1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-04-29 19:45:01 +02:00

Bug 425538 - Syntax errors in QML reported as "C/C++ Problems" because errors from Qt Linguist

The problem is solved by allowing to ignore duplicated markers in case
there is already loaded a plugin that could handle QML files

The ProblemMarkerFilter extension point allows to filter out unneeded
problem markers. For example during building of Qt base project with QML
files tool Qt Linguist could report syntax errors in some qml file.
These errors are presented as "C/C++ Problems" in qml files because they
match format CDT expects for errors. If there is already installed plug-in
that handles QML files it is a wise to ignore such errors because they
are already reported as "QML Problems" with more meaningful descriptions.

Change-Id: I3a0a1b58e9690bed9c2774e4328760c695d54a54
Signed-off-by: Daniel Pesch <dpesch@blackberry.com>
Reviewed-on: https://git.eclipse.org/r/20581
Tested-by: Hudson CI
Reviewed-by: Andrew Eidsness <eclipse@jfront.com>
Reviewed-by: Doug Schaefer <dschaefer@qnx.com>
IP-Clean: Doug Schaefer <dschaefer@qnx.com>
This commit is contained in:
Daniel Pesch 2014-01-16 09:39:12 +01:00 committed by Doug Schaefer
parent 93c60329b8
commit eb5c0c8a55
7 changed files with 450 additions and 0 deletions

View file

@ -138,3 +138,5 @@ uncPathConverter.name = UNC Path Converter
ScannerInfoExtensionLanguageSettingsProvider.name=Contributed ScannerInfo Entries
PathEntryScannerInfoLanguageSettingsProvider.name=Contributed PathEntry Containers
ReferencedProjectsLanguageSettingsProvider.name=Exported Entries from Referenced Projects
problemMarkerFilter.name=Problem Marker Filter

View file

@ -675,6 +675,7 @@
<extension-point id="RefreshExclusionFactory" name="%refreshExclusionFactory.name" schema="schema/RefreshExclusionFactory.exsd"/>
<extension-point id="LanguageSettingsProvider" name="%LanguageSettingsProvider.name" schema="schema/LanguageSettingsProvider.exsd"/>
<extension-point id="UNCPathConverter" name="%uncPathConverter.name" schema="schema/UNCPathConverter.exsd"/>
<extension-point id="ProblemMarkerFilter" name="%problemMarkerFilter.name" schema="schema/ProblemMarkerFilter.exsd"/>
<extension
point="org.eclipse.cdt.core.templateProcessTypes">

View file

@ -0,0 +1,135 @@
<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="org.eclipse.cdt.core" xmlns="http://www.w3.org/2001/XMLSchema">
<annotation>
<appInfo>
<meta.schema plugin="org.eclipse.cdt.core" id="ProblemMarkerFilter" name="Problem Marker Filter"/>
</appInfo>
<documentation>
This extension point allows to filter out unneeded problem markers.
For example during building of Qt base project with QML files tool Qt Linguist
could report syntax errors in some qml file. These errors are presented as
"C/C++ Problems" in qml files because they match format CDT expects for errors.
If there is already installed plug-in that handles QML files it is a wise to ignore such
errors because they are already reported as "QML Problems" with more meaningful descriptions.
</documentation>
</annotation>
<include schemaLocation="schema://org.eclipse.core.expressions/schema/expressionLanguage.exsd"/>
<element name="extension">
<annotation>
<appInfo>
<meta.element />
</appInfo>
</annotation>
<complexType>
<sequence>
<element ref="problemMarkerFilter" minOccurs="1" maxOccurs="unbounded"/>
</sequence>
<attribute name="point" type="string" use="required">
<annotation>
<documentation>
a fully qualified identifier of the target extension point
</documentation>
</annotation>
</attribute>
<attribute name="id" type="string">
<annotation>
<documentation>
an optional identifier of the extension instance
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string">
<annotation>
<documentation>
an optional name of the extension instance
</documentation>
<appInfo>
<meta.attribute translatable="true"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
<element name="problemMarkerFilter">
<complexType>
<sequence>
<element ref="enablement" minOccurs="0" maxOccurs="1"/>
</sequence>
<attribute name="class" type="string" use="required">
<annotation>
<documentation>
Implementation of Problem Marker Filter that allows to filter out unneded or duplicit problem markers.
</documentation>
<appinfo>
<meta.attribute kind="java" basedOn=":org.eclipse.cdt.core.IProblemMarkerFilter"/>
</appinfo>
</annotation>
</attribute>
</complexType>
</element>
<annotation>
<appInfo>
<meta.section type="since"/>
</appInfo>
<documentation>
8.3
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="examples"/>
</appInfo>
<documentation>
The following is an example of a qmakeEnvProvider contribution:
&lt;p&gt;
&lt;pre&gt;
&lt;extension
point=&quot;org.eclipse.cdt.core.ProblemMarkerFilter&quot;
id=&quot;example&quot;
name=&quot;Example QMake Env Provider Extension&quot;&gt;
&lt;problemMarkerFilter
class=&quot;com.example.internal.ProblemMarkerFilter&quot;&gt;
&lt;enablement&gt;
&lt;with variable=&quot;projectNatures&quot;&gt;
&lt;iterate operator=&quot;or&quot;&gt;
&lt;equals value=&quot;com.example.my-nature&quot;/&gt;
&lt;/iterate&gt;
&lt;/with&gt;
&lt;/enablement&gt;
&lt;/problemMarkerFilter&gt;
&lt;/extension&gt;
&lt;/pre&gt;
&lt;/p&gt;
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="apiinfo"/>
</appInfo>
<documentation>
The contributed class must implement &lt;code&gt;org.eclipse.cdt.core.IProblemMarkerFilter&lt;/code&gt;.
</documentation>
</annotation>
<annotation>
<appInfo>
<meta.section type="implementation"/>
</appInfo>
<documentation>
Copyright (c) 2014 BlackBerry Limited and others.
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
</documentation>
</annotation>
</schema>

View file

@ -30,6 +30,7 @@ import org.eclipse.cdt.core.language.settings.providers.IWorkingDirectoryTracker
import org.eclipse.cdt.core.resources.ACBuilder;
import org.eclipse.cdt.internal.core.Cygwin;
import org.eclipse.cdt.internal.core.IErrorMarkeredOutputStream;
import org.eclipse.cdt.internal.core.ProblemMarkerFilterManager;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
import org.eclipse.cdt.internal.errorparsers.ErrorParserExtensionManager;
import org.eclipse.cdt.utils.EFSExtensionManager;
@ -588,6 +589,8 @@ outer:
* @since 5.4
*/
public void addProblemMarker(ProblemMarkerInfo problemMarkerInfo){
if ( ! ProblemMarkerFilterManager.getInstance().acceptMarker(problemMarkerInfo) )
return;
fErrors.add(problemMarkerInfo);
fMarkerGenerator.addMarker(problemMarkerInfo);
if (problemMarkerInfo.severity == IMarkerGenerator.SEVERITY_ERROR_RESOURCE) {

View file

@ -0,0 +1,25 @@
/*
* Copyright (c) 2014 BlackBerry Limited and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.cdt.core;
/**
* The purpose of IProblemMarkerFilter is to provide filtering function for problem markers.
* ProblemMarkerFilter extension point are required to implements this interface.
*
* @since 5.6
*/
public interface IProblemMarkerFilter {
/**
* Decide if a problem marker should be reported or ignored.
*
* @param markerInfo description of the problem marker that is going to be reported
* @return true if markers should be reported, false if should be ignored
*/
boolean acceptMarker(ProblemMarkerInfo markerInfo);
}

View file

@ -0,0 +1,160 @@
/*
* Copyright (c) 2014 BlackBerry Limited and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.cdt.internal.core;
import java.util.Arrays;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.IProblemMarkerFilter;
import org.eclipse.cdt.core.ProblemMarkerInfo;
import org.eclipse.core.expressions.EvaluationContext;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionConverter;
import org.eclipse.core.expressions.ExpressionTagNames;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
/**
* The purpose of ProblemMarkerFilterDesc is to manage information about
* one instance ProblemMarkerFilter extension point.
*/
class ProblemMarkerFilterDesc {
/**
* XML attribute for name of class that implements this extension point
*/
private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
/**
* Variable name for projectNatures for enablement expression
*/
private static final String VAR_PROJECTNATURES = "projectNatures"; //$NON-NLS-1$
/**
* Configuration element for this extension point
*/
private final IConfigurationElement element;
/**
* Expression that allows conditionally enable/disable extension point
*/
private final Expression enablementExpression;
/**
* Status of this extension point.
* False = disabled because of expression error
* True = enabled because of missing enablementExpression
* null = evaluate the expression for particular project
*/
private Boolean fStatus = null;
/**
* Unique id of this extension point
*/
private String id;
/**
*
*/
private IProblemMarkerFilter filter;
/**
* Filter that accept any marker.
*
*/
private static final IProblemMarkerFilter NULL_FILTER = new IProblemMarkerFilter() {
@Override
public boolean acceptMarker(ProblemMarkerInfo markerInfo) {
return true;
}
};
/**
* Constructor
*
* @param element configuration element with optional enablementExpression
*/
ProblemMarkerFilterDesc(IConfigurationElement element) {
this.element = element;
Expression expr = null;
IConfigurationElement[] children = element.getChildren(ExpressionTagNames.ENABLEMENT);
switch (children.length) {
case 0:
fStatus = Boolean.TRUE;
break;
case 1:
try {
ExpressionConverter parser = ExpressionConverter.getDefault();
expr = parser.perform(children[0]);
} catch (CoreException e) {
CCorePlugin.log("Error in enablement expression of " + id, e); //$NON-NLS-1$
fStatus = Boolean.FALSE;
}
break;
default:
CCorePlugin.log("Too many enablement expressions for " + id); //$NON-NLS-1$
fStatus = Boolean.FALSE;
break;
}
enablementExpression = expr;
}
/**
* Evaluate enablement expression
*
* @param project project for which we had to evaluate the expression
* @return value of enablement expression
*/
public boolean matches(IProject project) {
// If the enablement expression is missing or structurally invalid, then return immediately
if (fStatus != null)
return fStatus.booleanValue();
if (enablementExpression != null)
try {
EvaluationContext evalContext = new EvaluationContext(null, project);
String[] natures = project.getDescription().getNatureIds();
evalContext.addVariable(VAR_PROJECTNATURES, Arrays.asList(natures));
return enablementExpression.evaluate(evalContext) == EvaluationResult.TRUE;
} catch (CoreException e) {
CCorePlugin.log("Error while evaluating enablement expression for " + id, e); //$NON-NLS-1$
}
return false;
}
/**
* Return filter interface
* @return Filter interface or NULL_FILER if filter could not be created
*/
IProblemMarkerFilter getFilter() {
if (filter == null)
synchronized (this) {
if (filter == null) {
try {
filter = (IProblemMarkerFilter) element.createExecutableExtension(ATTR_CLASS);
} catch (CoreException e) {
String id = element.getDeclaringExtension().getNamespaceIdentifier() + '.'
+ element.getDeclaringExtension().getSimpleIdentifier();
CCorePlugin.log("Error in class attribute of " + id, e); //$NON-NLS-1$
// mark the filter with an empty implementation to prevent future load attempts
filter = NULL_FILTER;
}
}
}
return filter;
}
}

View file

@ -0,0 +1,124 @@
/*
* Copyright (c) 2014 BlackBerry Limited and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.cdt.internal.core;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.IProblemMarkerFilter;
import org.eclipse.cdt.core.ProblemMarkerInfo;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
/**
* The purpose of ProblemMarkerFilterManager is to manage ProblemMarkerFilter extension points.
* {@link ErrorParserManager} use this manager to filter out unnecessary problem markers
*
* @noextend This class is not intended to be subclassed by clients.
*/
public class ProblemMarkerFilterManager {
/**
* Name of ProblemMarkerFilter extension point
*/
private final static String EXTENSION_POINT = "ProblemMarkerFilter"; //$NON-NLS-1$
/**
* Singleton instance of ProblemMarkerFilterManager
*/
private final static ProblemMarkerFilterManager INSTANCE = new ProblemMarkerFilterManager();
/**
* List of all executable extension registered in Extension Registry
*/
private final List<ProblemMarkerFilterDesc> filters = new ArrayList<ProblemMarkerFilterDesc>();
/**
* Cache of active filters for known projects.
* This cache allow to skip evaluation of enablementExpression for every marker.
*/
private final Map<IProject, List<ProblemMarkerFilterDesc>> filtersCache = new WeakHashMap<IProject, List<ProblemMarkerFilterDesc>>();
/**
* Return singleton instance of ProblemMarkerFilterManager
*
* @return singleton instance of ProblemMarkerFilterManager
*/
public static ProblemMarkerFilterManager getInstance() {
return INSTANCE;
}
/**
* Constructor.
*
* Creates instances of executable extension for ProblemMarkerFilter extension point
*
*/
private ProblemMarkerFilterManager() {
IExtensionRegistry reg = Platform.getExtensionRegistry();
IConfigurationElement[] extensions = reg
.getConfigurationElementsFor(CCorePlugin.PLUGIN_ID, EXTENSION_POINT);
for (int i = 0; i < extensions.length; i++) {
IConfigurationElement element = extensions[i];
ProblemMarkerFilterDesc filterDesc = new ProblemMarkerFilterDesc(element);
filters.add(filterDesc);
}
}
/**
* Called by {@link ErrorParserManager#addProblemMarker(ProblemMarkerInfo)} to filter out unnecessary problem markers
*
* Problem marker is ignored if any plug-in that implements ProblemMarkerFilter extension point rejects it.
*
* @see IProblemMarkerFilter#acceptMarker(ProblemMarkerInfo)
*
* @param markerInfo description of the problem marker that is going to be added
* @return true if markers should be reported, false if should be ignored
*/
public boolean acceptMarker(ProblemMarkerInfo markerInfo) {
IProject project = markerInfo.file.getProject();
if (project == null || !project.isOpen())
return true;
List<ProblemMarkerFilterDesc> enabledFilters = findEnabledFilters(project);
for (ProblemMarkerFilterDesc filterDesc: enabledFilters) {
if ( ! filterDesc.getFilter().acceptMarker(markerInfo) ) {
return false;
}
}
return true;
}
/**
* Try to find enabled filter for project and cache results
* @param project project for which we want know enabled filters
* @return list of enabled filters
*/
private List<ProblemMarkerFilterDesc> findEnabledFilters(IProject project) {
synchronized (filtersCache) {
List<ProblemMarkerFilterDesc> result = filtersCache.get(project);
if (result == null) {
result = new ArrayList<ProblemMarkerFilterDesc>();
for (ProblemMarkerFilterDesc filterDesc: filters) {
if ( filterDesc.matches(project) ) {
result.add(filterDesc);
}
}
filtersCache.put(project, result);
}
return result;
}
}
}