Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Gvozdev2009-09-11 02:09:38 +0000
committerAndrew Gvozdev2009-09-11 02:09:38 +0000
commitdbbdbd8f95d06a6f008c5f066d1161bfc4e86a62 (patch)
tree9c125a727d3aa1c50dcae06431e6afe0b8bb841c /core/org.eclipse.cdt.core
parent64a0f77fafae191bbacd572be2223df88ee64219 (diff)
downloadorg.eclipse.cdt-dbbdbd8f95d06a6f008c5f066d1161bfc4e86a62.tar.gz
org.eclipse.cdt-dbbdbd8f95d06a6f008c5f066d1161bfc4e86a62.tar.xz
org.eclipse.cdt-dbbdbd8f95d06a6f008c5f066d1161bfc4e86a62.zip
bug 109139: Generic Error parser
(RegexErrorParser)
Diffstat (limited to 'core/org.eclipse.cdt.core')
-rw-r--r--core/org.eclipse.cdt.core/plugin.properties1
-rw-r--r--core/org.eclipse.cdt.core/plugin.xml19
-rw-r--r--core/org.eclipse.cdt.core/schema/ErrorParser.exsd102
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java56
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java118
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IErrorParserNamed.java40
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/ErrorParserNamedWrapper.java109
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorParser.java179
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorPattern.java385
-rw-r--r--core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java726
10 files changed, 1690 insertions, 45 deletions
diff --git a/core/org.eclipse.cdt.core/plugin.properties b/core/org.eclipse.cdt.core/plugin.properties
index 02fe04af25c..63f637feb3b 100644
--- a/core/org.eclipse.cdt.core/plugin.properties
+++ b/core/org.eclipse.cdt.core/plugin.properties
@@ -48,6 +48,7 @@ CDTGNUAssemblerErrorParser.name=CDT GNU Assembler Error Parser
CDTGNULinkerErrorParser.name=CDT GNU Linker Error Parser
CDTGNUMakeErrorParser.name=CDT GNU Make Error Parser
CDTVisualCErrorParser.name=CDT Visual C Error Parser
+CDTRegexErrorParser.name=CDT Regular Expression Error Parser
PathEntryContainerInitializer=Path Entry Container Initializer
diff --git a/core/org.eclipse.cdt.core/plugin.xml b/core/org.eclipse.cdt.core/plugin.xml
index 6174b57e379..1af203884e5 100644
--- a/core/org.eclipse.cdt.core/plugin.xml
+++ b/core/org.eclipse.cdt.core/plugin.xml
@@ -144,6 +144,8 @@
name="%CDTGNUMakeErrorParser.name"
point="org.eclipse.cdt.core.ErrorParser">
<errorparser
+ id="org.eclipse.cdt.core.MakeErrorParser"
+ name="%CDTGNUMakeErrorParser.name"
class="org.eclipse.cdt.internal.errorparsers.MakeErrorParser">
</errorparser>
</extension>
@@ -152,6 +154,8 @@
name="%CDTGNUCErrorParser.name"
point="org.eclipse.cdt.core.ErrorParser">
<errorparser
+ id="org.eclipse.cdt.core.GCCErrorParser"
+ name="%CDTGNUCErrorParser.name"
class="org.eclipse.cdt.internal.errorparsers.GCCErrorParser">
</errorparser>
</extension>
@@ -160,6 +164,8 @@
name="%CDTGNUAssemblerErrorParser.name"
point="org.eclipse.cdt.core.ErrorParser">
<errorparser
+ id="org.eclipse.cdt.core.GASErrorParser"
+ name="%CDTGNUAssemblerErrorParser.name"
class="org.eclipse.cdt.internal.errorparsers.GASErrorParser">
</errorparser>
</extension>
@@ -168,6 +174,8 @@
name="%CDTGNULinkerErrorParser.name"
point="org.eclipse.cdt.core.ErrorParser">
<errorparser
+ id="org.eclipse.cdt.core.GLDErrorParser"
+ name="%CDTGNULinkerErrorParser.name"
class="org.eclipse.cdt.internal.errorparsers.GLDErrorParser">
</errorparser>
</extension>
@@ -176,9 +184,20 @@
name="%CDTVisualCErrorParser.name"
point="org.eclipse.cdt.core.ErrorParser">
<errorparser
+ id="org.eclipse.cdt.core.VCErrorParser"
+ name="%CDTVisualCErrorParser.name"
class="org.eclipse.cdt.internal.errorparsers.VCErrorParser">
</errorparser>
</extension>
+ <extension
+ id="RegexErrorParser"
+ name="%CDTRegexErrorParser.name"
+ point="org.eclipse.cdt.core.ErrorParser">
+ <errorparser
+ id="org.eclipse.cdt.core.RegexErrorParser"
+ name="%CDTRegexErrorParser.name">
+ </errorparser>
+ </extension>
<!-- =================================================================================== -->
<!-- CDT customized problem markers: C Problem markers -->
<!-- =================================================================================== -->
diff --git a/core/org.eclipse.cdt.core/schema/ErrorParser.exsd b/core/org.eclipse.cdt.core/schema/ErrorParser.exsd
index a4ce450e13c..0ab67eae5a2 100644
--- a/core/org.eclipse.cdt.core/schema/ErrorParser.exsd
+++ b/core/org.eclipse.cdt.core/schema/ErrorParser.exsd
@@ -23,14 +23,14 @@
<attribute name="id" type="string" use="required">
<annotation>
<documentation>
-
+ ID of the extension point (Simple ID)
</documentation>
</annotation>
</attribute>
<attribute name="name" type="string" use="required">
<annotation>
<documentation>
-
+ Name of the extension point
</documentation>
</annotation>
</attribute>
@@ -46,19 +46,107 @@
<element name="errorparser">
<complexType>
- <attribute name="class" type="string" use="required">
+ <sequence>
+ <element ref="pattern" minOccurs="0" maxOccurs="unbounded"/>
+ </sequence>
+ <attribute name="id" type="string">
+ <annotation>
+ <documentation>
+ ID of the error parser. If attribute is missing error parser ID is constructed appending Simple ID of extension to plugin ID.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="name" type="string">
+ <annotation>
+ <documentation>
+ Name of the error parser. If this attribute is missing extension name is taken.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="class" type="string" use="default" value="org.eclipse.cdt.core.errorparsers.RegexErrorParser">
<annotation>
<documentation>
a fully qualified name of the Java class that implements &lt;samp&gt;org.eclipse.cdt.core.IErrorParser&lt;/samp&gt; interface.
</documentation>
<appInfo>
- <meta.attribute kind="java" basedOn=":org.eclipse.cdt.core.IErrorParser"/>
+ <meta.attribute kind="java" basedOn=":org.eclipse.cdt.core.errorparsers.IErrorParser"/>
</appInfo>
</annotation>
</attribute>
</complexType>
</element>
+ <element name="pattern">
+ <annotation>
+ <documentation>
+ Use element &quot;pattern&quot; to configure RegexErrorParser.
+ </documentation>
+ </annotation>
+ <complexType>
+ <attribute name="severity" use="required">
+ <annotation>
+ <documentation>
+ Attribute &quot;severity&quot; specifies which severity should be used to display the marker in Problems View. There are 3 levels of severity, &quot;Error&quot;, &quot;Warning&quot; and &quot;Info&quot;. &quot;Ignore&quot; lets stop evaluating the line by the rest of patterns without showing up in Problems View.
+ </documentation>
+ </annotation>
+ <simpleType>
+ <restriction base="string">
+ <enumeration value="Error">
+ </enumeration>
+ <enumeration value="Warning">
+ </enumeration>
+ <enumeration value="Info">
+ </enumeration>
+ <enumeration value="Ignore">
+ </enumeration>
+ </restriction>
+ </simpleType>
+ </attribute>
+ <attribute name="regex" type="string" use="default" value="(.*)">
+ <annotation>
+ <documentation>
+ Java regular expression to define capturing groups for file-expr, line-expr and description-expr.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="file-expr" type="string">
+ <annotation>
+ <documentation>
+ &quot;Replacement&quot; expression composed from capturing groups defined in regex to define the file.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="line-expr" type="string">
+ <annotation>
+ <documentation>
+ &quot;Replacement&quot; expression composed from capturing groups defined in regex to define the line in file.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="description-expr" type="string" use="default" value="$1">
+ <annotation>
+ <documentation>
+ &quot;Replacement&quot; expression composed from capturing groups defined in regex to define the description (i.e. &quot;$1: $2&quot;). It is possible to specify more than one capturing group in such expression.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="variable-expr" type="string">
+ <annotation>
+ <documentation>
+ &quot;Replacement&quot; expression composed from capturing groups defined in regex to define variable. The value will be assigned to marker attributes but is not used by CDT currently.
+ </documentation>
+ </annotation>
+ </attribute>
+ <attribute name="eat-processed-line" type="boolean" use="required">
+ <annotation>
+ <documentation>
+ The attribute defines if a line matched by the pattern is prevented or allowed to be processed by the rest of patterns. &quot;No&quot; allows several patterns to evaluate one line.
+ </documentation>
+ </annotation>
+ </attribute>
+ </complexType>
+ </element>
+
<annotation>
<appInfo>
<meta.section type="since"/>
@@ -107,7 +195,8 @@ public class SampleErrorParser extends AbstractErrorParser {&lt;br/&gt;
<documentation>
Plug-ins that want to extend this extension point must implement &lt;samp&gt;org.eclipse.cdt.core.IErrorParser&lt;/samp&gt; interface.
&lt;br/&gt;
-It is recommended to extend &lt;samp&gt;org.eclipse.cdt.core.errorparsers.AbstractErrorParser&lt;/samp&gt; for most cases.
+For most cases it is sufficient to configure RegexErrorParser which is provided by default.
+Another good choice is to extend &lt;samp&gt;org.eclipse.cdt.core.errorparsers.AbstractErrorParser&lt;/samp&gt; as done in the example.
&lt;br/&gt;
ErrorParsers dealing with multi-line messages should implement &lt;samp&gt;org.eclipse.cdt.core.IErrorParser2&lt;/samp&gt; interface.
</documentation>
@@ -132,8 +221,7 @@ All rights reserved. This program and the accompanying materials&lt;br/&gt;
are made available under the terms of the Eclipse Public License v1.0&lt;br/&gt;
which accompanies this distribution, and is available at&lt;br/&gt;
http://www.eclipse.org/legal/epl-v10.html&lt;br/&gt;
-
</documentation>
</annotation>
-</schema> \ No newline at end of file
+</schema>
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
index e73c0eefb19..b3627d36a99 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/CCorePlugin.java
@@ -19,7 +19,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.List;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
@@ -60,6 +59,7 @@ import org.eclipse.cdt.internal.core.pdom.PDOMManager;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
import org.eclipse.cdt.internal.core.settings.model.CProjectDescriptionManager;
import org.eclipse.cdt.internal.core.settings.model.ExceptionFactory;
+import org.eclipse.cdt.internal.errorparsers.ErrorParserExtensionManager;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.resources.IResource;
@@ -118,7 +118,13 @@ public class CCorePlugin extends Plugin {
public static final String PREF_INDEXER = "indexer"; //$NON-NLS-1$
public static final String DEFAULT_INDEXER = IPDOMManager.ID_FAST_INDEXER;
+ /**
+ * Name of the extension point for contributing an error parser
+ */
public final static String ERROR_PARSER_SIMPLE_ID = "ErrorParser"; //$NON-NLS-1$
+ /**
+ * Full unique name of the extension point for contributing an error parser
+ */
public final static String ERROR_PARSER_UNIQ_ID = PLUGIN_ID + "." + ERROR_PARSER_SIMPLE_ID; //$NON-NLS-1$
// default store for pathentry
@@ -886,41 +892,29 @@ public class CCorePlugin extends Plugin {
}
/**
- * Array of error parsers ids.
+ * @deprecated since CDT 6.1. Use {@link ErrorParserManager#getErrorParserAvailableIds()} instead
+ * @return array of error parsers ids
*/
+ @Deprecated
public String[] getAllErrorParsersIDs() {
- IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, ERROR_PARSER_SIMPLE_ID);
- String[] empty = new String[0];
- if (extension != null) {
- IExtension[] extensions = extension.getExtensions();
- ArrayList<String> list = new ArrayList<String>(extensions.length);
- for (IExtension e : extensions)
- list.add(e.getUniqueIdentifier());
- return list.toArray(empty);
- }
- return empty;
+ ErrorParserExtensionManager.loadErrorParserExtensions();
+ return ErrorParserExtensionManager.getErrorParserAvailableIds();
}
-
+
+ /**
+ * @deprecated since CDT 6.1. Use {@link ErrorParserManager#getErrorParserCopy(String)} instead
+ * @param id - id of error parser
+ * @return array of error parsers
+ */
+ @Deprecated
public IErrorParser[] getErrorParser(String id) {
- IErrorParser[] empty = new IErrorParser[0];
- try {
- IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(CCorePlugin.PLUGIN_ID, ERROR_PARSER_SIMPLE_ID);
- if (extension != null) {
- IExtension[] extensions = extension.getExtensions();
- List<IErrorParser> list = new ArrayList<IErrorParser>(extensions.length);
- for (IExtension e : extensions) {
- String parserID = e.getUniqueIdentifier();
- if ((id == null && parserID != null) || (id != null && id.equals(parserID))) {
- for (IConfigurationElement ce : e.getConfigurationElements())
- list.add((IErrorParser)ce.createExecutableExtension("class")); //$NON-NLS-1$
- }
- }
- return list.toArray(empty);
- }
- } catch (CoreException e) {
- log(e);
+ ErrorParserExtensionManager.loadErrorParserExtensions();
+ IErrorParser errorParser = ErrorParserExtensionManager.getErrorParserInternal(id);
+ if (errorParser == null) {
+ return new IErrorParser[] {};
+ } else {
+ return new IErrorParser[] { errorParser };
}
- return empty;
}
public IScannerInfoProvider getScannerInfoProvider(IProject project) {
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java
index 115752d03ae..bbf08b37f46 100644
--- a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/ErrorParserManager.java
@@ -23,8 +23,10 @@ import java.util.List;
import java.util.Map;
import java.util.Vector;
+import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper;
import org.eclipse.cdt.core.resources.ACBuilder;
import org.eclipse.cdt.internal.core.resources.ResourceLookup;
+import org.eclipse.cdt.internal.errorparsers.ErrorParserExtensionManager;
import org.eclipse.cdt.utils.CygPath;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
@@ -36,6 +38,7 @@ import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.URIUtil;
+import org.osgi.service.prefs.BackingStoreException;
/**
* The purpose of ErrorParserManager is to delegate the work of error parsing
@@ -46,10 +49,22 @@ import org.eclipse.core.runtime.URIUtil;
* @noextend This class is not intended to be subclassed by clients.
*/
public class ErrorParserManager extends OutputStream {
+ /**
+ * The list of error parsers stored in .project for 3.X projects
+ * as key/value pair with key="org.eclipse.cdt.core.errorOutputParser"
+ * @deprecated since CDT 4.0.
+ */
+ @Deprecated
+ public final static String PREF_ERROR_PARSER = CCorePlugin.PLUGIN_ID + ".errorOutputParser"; //$NON-NLS-1$
+
+ /**
+ * Delimiter for error parsers presented in one string.
+ * @since 5.2
+ */
+ public final static char ERROR_PARSER_DELIMITER = ';';
private int nOpens;
-
- public final static String PREF_ERROR_PARSER = CCorePlugin.PLUGIN_ID + ".errorOutputParser"; //$NON-NLS-1$
+ private int lineCounter=0;
private final IProject fProject;
private final IMarkerGenerator fMarkerGenerator;
@@ -143,12 +158,14 @@ public class ErrorParserManager extends OutputStream {
private void enableErrorParsers(String[] parsersIDs) {
if (parsersIDs == null) {
- parsersIDs = CCorePlugin.getDefault().getAllErrorParsersIDs();
+ parsersIDs = ErrorParserExtensionManager.getDefaultErrorParserIds();
}
fErrorParsers = new LinkedHashMap<String, IErrorParser[]>(parsersIDs.length);
for (String parsersID : parsersIDs) {
- IErrorParser[] parsers = CCorePlugin.getDefault().getErrorParser(parsersID);
- fErrorParsers.put(parsersID, parsers);
+ IErrorParser errorParser = ErrorParserExtensionManager.getErrorParserCopy(parsersID);
+ if (errorParser!=null) {
+ fErrorParsers.put(parsersID, new IErrorParser[] {errorParser} );
+ }
}
}
@@ -169,7 +186,7 @@ public class ErrorParserManager extends OutputStream {
}
/**
- * Return the current URI location where the build is being performed
+ * @return the current URI location where the build is being performed
* @since 5.1
*/
public URI getWorkingDirectoryURI() {
@@ -292,9 +309,14 @@ public class ErrorParserManager extends OutputStream {
String lineTrimmed = line.trim();
+ lineCounter++;
for (IErrorParser[] parsers : fErrorParsers.values()) {
- for (IErrorParser curr : parsers) {
+ for (IErrorParser parser : parsers) {
+ IErrorParser curr = parser;
+ if (parser instanceof ErrorParserNamedWrapper) {
+ curr = ((ErrorParserNamedWrapper)parser).getErrorParser();
+ }
int types = IErrorParser2.NONE;
if (curr instanceof IErrorParser2) {
types = ((IErrorParser2) curr).getProcessLineBehaviour();
@@ -324,6 +346,14 @@ public class ErrorParserManager extends OutputStream {
}
}
}
+
+ /**
+ * @return counter counting processed lines of output
+ * @since 5.2
+ */
+ public int getLineCounter() {
+ return lineCounter;
+ }
/**
* Returns the file with the given (partial) location if that file can be uniquely identified.
@@ -693,4 +723,78 @@ public class ErrorParserManager extends OutputStream {
public boolean hasErrors() {
return hasErrors;
}
+
+ /**
+ * Set and store in workspace area user defined error parsers.
+ *
+ * @param errorParsers - array of user defined error parsers
+ * @throws CoreException in case of problems
+ * @since 5.2
+ */
+ public static void setUserDefinedErrorParsers(IErrorParserNamed[] errorParsers) throws CoreException {
+ ErrorParserExtensionManager.setUserDefinedErrorParsers(errorParsers);
+ }
+
+ /**
+ * @return available error parsers IDs which include contributed through extension + user defined ones
+ * from workspace
+ * @since 5.2
+ */
+ public static String[] getErrorParserAvailableIds() {
+ return ErrorParserExtensionManager.getErrorParserAvailableIds();
+ }
+
+ /**
+ * @return IDs of error parsers contributed through error parser extension point.
+ * @since 5.2
+ */
+ public static String[] getErrorParserExtensionIds() {
+ return ErrorParserExtensionManager.getErrorParserExtensionIds();
+ }
+
+ /**
+ * Set and store default error parsers IDs to be used if error parser list is empty.
+ *
+ * @param ids - default error parsers IDs
+ * @throws BackingStoreException in case of problem with storing
+ * @since 5.2
+ */
+ public static void setDefaultErrorParserIds(String[] ids) throws BackingStoreException {
+ ErrorParserExtensionManager.setDefaultErrorParserIds(ids);
+ }
+
+ /**
+ * @return default error parsers IDs to be used if error parser list is empty.
+ * @since 5.2
+ */
+ public static String[] getDefaultErrorParserIds() {
+ return ErrorParserExtensionManager.getDefaultErrorParserIds();
+ }
+
+ /**
+ * @param id - ID of error parser
+ * @return cloned copy of error parser. Note that {@link ErrorParserNamedWrapper} returns
+ * shallow copy with the same instance of underlying error parser.
+ * @since 5.2
+ */
+ public static IErrorParserNamed getErrorParserCopy(String id) {
+ return ErrorParserExtensionManager.getErrorParserCopy(id);
+ }
+
+ /**
+ * @param ids - array of error parser IDs
+ * @return error parser IDs delimited with error parser delimiter ";"
+ * @since 5.2
+ */
+ public static String toDelimitedString(String[] ids) {
+ String result=""; //$NON-NLS-1$
+ for (String id : ids) {
+ if (result.length()==0) {
+ result = id;
+ } else {
+ result += ERROR_PARSER_DELIMITER + id;
+ }
+ }
+ return result;
+ }
}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IErrorParserNamed.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IErrorParserNamed.java
new file mode 100644
index 00000000000..462d58b4281
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/IErrorParserNamed.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Andrew Gvozdev (Quoin Inc.) 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
+ *
+ * Contributors:
+ * Andrew Gvozdev (Quoin Inc.) - Initial API and implementation
+ *******************************************************************************/
+package org.eclipse.cdt.core;
+
+/**
+ * Extension of IErrorParser interface to attach id and names to an error parser.
+ * Clients must implement {@link Object#clone} and {@link Object#equals} methods to avoid slicing.
+ * @since 5.2
+ */
+public interface IErrorParserNamed extends IErrorParser, Cloneable {
+ /**
+ * Set error parser ID.
+ * @param id of error parser
+ */
+ public void setId(String id);
+
+ /**
+ * Set error parser name.
+ * @param name of error parser
+ */
+ public void setName(String name);
+
+ /**
+ * @return id of error parser
+ */
+ public String getId();
+
+ /**
+ * @return name of error parser
+ */
+ public String getName();
+}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/ErrorParserNamedWrapper.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/ErrorParserNamedWrapper.java
new file mode 100644
index 00000000000..bf43ffb47a6
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/ErrorParserNamedWrapper.java
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2009 Andrew Gvozdev (Quoin Inc.) 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
+ *
+ * Contributors:
+ * Andrew Gvozdev (Quoin Inc.) - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.core.errorparsers;
+
+import org.eclipse.cdt.core.ErrorParserManager;
+import org.eclipse.cdt.core.IErrorParser;
+import org.eclipse.cdt.core.IErrorParserNamed;
+import org.eclipse.core.runtime.Assert;
+
+/**
+ * Class to wrap any {@link IErrorParser} to {@link IErrorParserNamed}.
+ * @since 5.2
+ */
+public class ErrorParserNamedWrapper implements IErrorParserNamed {
+ private String fId;
+ private String fName;
+ private final IErrorParser fErrorParser;
+
+ /**
+ * Constructor.
+ *
+ * @param id - assigned ID
+ * @param name - assigned name.
+ * @param errorParser - error parser to assign name and ID.
+ */
+ public ErrorParserNamedWrapper(String id, String name, IErrorParser errorParser) {
+ Assert.isNotNull(errorParser);
+
+ this.fId = id;
+ this.fName = name;
+ this.fErrorParser = errorParser;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IErrorParser#processLine(java.lang.String, org.eclipse.cdt.core.ErrorParserManager)
+ */
+ public boolean processLine(String line, ErrorParserManager epm) {
+ return fErrorParser.processLine(line, epm);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IErrorParserNamed#getId()
+ */
+ public String getId() {
+ return fId;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IErrorParserNamed#getName()
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * @return original error parser which is being wrapped
+ */
+ public IErrorParser getErrorParser() {
+ return fErrorParser;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IErrorParserNamed#setId(java.lang.String)
+ */
+ public void setId(String id) {
+ this.fId = id;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.core.IErrorParserNamed#setName(java.lang.String)
+ */
+ public void setName(String name) {
+ this.fName = name;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof ErrorParserNamedWrapper) {
+ ErrorParserNamedWrapper that = (ErrorParserNamedWrapper)o;
+ return this.fId.equals(that.fId)
+ && this.fName.equals(that.fName)
+ // can't be more specific than that since IErrorParser may not implement equals()...
+ && this.getClass()==that.getClass();
+ }
+ return false;
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ // shallow copy since IErrorParser is not {@link Cloneable} in general.
+ return new ErrorParserNamedWrapper(fId, fName, fErrorParser);
+ }
+}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorParser.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorParser.java
new file mode 100644
index 00000000000..e1852d7e7fd
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorParser.java
@@ -0,0 +1,179 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2009 Andrew Gvozdev (Quoin Inc.) 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
+ *
+ * Contributors:
+ * Andrew Gvozdev (Quoin Inc.) - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.core.errorparsers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.ErrorParserManager;
+import org.eclipse.cdt.core.IErrorParser;
+import org.eclipse.cdt.core.IErrorParserNamed;
+
+/**
+ * {@code RegexerrorParser} is an error parser designed to use regular expressions in order
+ * to parse build output to produce Errors, Warnings or Infos in Problems View.
+ *
+ * Clients may extend this class. As it implements {@link Cloneable} interface those clients
+ * must implement {@link Object#clone} and {@link Object#equals} methods to avoid slicing.
+ * Hint to implementers: if you want to extend it with customized {@link RegexErrorPattern}
+ * it is possible to inject it in {@link #addPattern(RegexErrorPattern)}.
+ *
+ * @see IErrorParser
+ * @since 5.2
+ */
+public class RegexErrorParser implements IErrorParserNamed, Cloneable {
+ private String fId;
+ private String fName;
+ private final List<RegexErrorPattern> fPatterns= new ArrayList<RegexErrorPattern>();
+
+ /**
+ * Default constructor will initialize the error parser with the name of the class
+ * using reflection mechanism.
+ */
+ public RegexErrorParser() {
+ fName = this.getClass().getSimpleName();
+ fId = this.getClass().getCanonicalName();
+ }
+
+ /**
+ * Constructor to initialize ID and name of the error parser.
+ *
+ * @param id - ID of the error parser.
+ * @param name - name of the error parser.
+ */
+ public RegexErrorParser(String id, String name) {
+ fName = name;
+ fId = id;
+ }
+
+ /**
+ * Set error parser ID.
+ *
+ * @param id of error parser
+ */
+ public void setId(String id) {
+ fId = id;
+ }
+
+ /**
+ * Set error parser name.
+ *
+ * @param name of error parser
+ */
+ public void setName(String name) {
+ fName = name;
+ }
+
+ /**
+ * Add new {@link RegexErrorPattern}.
+ *
+ * @param pattern - new pattern
+ */
+ public void addPattern(RegexErrorPattern pattern) {
+ fPatterns.add(pattern);
+ }
+
+ /**
+ * Remove error pattern from processing.
+ *
+ * @param pattern - error pattern to remove
+ */
+ public void removePattern(RegexErrorPattern pattern) {
+ fPatterns.remove(pattern);
+ }
+
+ /**
+ * Remove all error patterns.
+ */
+ public void clearPatterns() {
+ fPatterns.clear();
+ }
+
+ /**
+ * Method toString() for debugging purposes.
+ */
+ @Override
+ public String toString() {
+ return "id="+fId+", name="+fName; //$NON-NLS-1$//$NON-NLS-2$
+ }
+
+ /**
+ * @return id of error parser
+ */
+ public String getId() {
+ return fId;
+ }
+
+ /**
+ * @return name of error parser
+ */
+ public String getName() {
+ return fName;
+ }
+
+ /**
+ * @return array of error patterns of this error parser.
+ */
+ public RegexErrorPattern[] getPatterns() {
+ return fPatterns.toArray(new RegexErrorPattern[0]);
+ }
+
+
+ /**
+ * Parse a line of build output and register errors/warnings/infos for
+ * Problems view in internal list of {@link ErrorParserManager}.
+ *
+ * @param line - line of the input
+ * @param epManager - error parsers manager
+ * @return true if error parser recognized and accepted line, false otherwise
+ */
+ public boolean processLine(String line, ErrorParserManager epManager) {
+ for (RegexErrorPattern pattern : fPatterns)
+ try {
+ if (pattern.processLine(line, epManager))
+ return true;
+ } catch (Exception e){
+ String message = "Error parsing line [" + line + "]"; //$NON-NLS-1$//$NON-NLS-2$
+ CCorePlugin.log(message, e);
+ }
+
+ return false;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof RegexErrorParser) {
+ RegexErrorParser that = (RegexErrorParser)o;
+ return this.fId.equals(that.fId)
+ && this.fName.equals(that.fName)
+ && this.fPatterns.equals(that.fPatterns);
+ }
+ return false;
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ RegexErrorParser that = new RegexErrorParser(fId, fName);
+ for (RegexErrorPattern pattern : fPatterns) {
+ that.addPattern((RegexErrorPattern)pattern.clone());
+ }
+ return that;
+ }
+}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorPattern.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorPattern.java
new file mode 100644
index 00000000000..95cc485fea7
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/core/errorparsers/RegexErrorPattern.java
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2009 Andrew Gvozdev (Quoin Inc.) 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
+ *
+ * Contributors:
+ * Andrew Gvozdev (Quoin Inc.) - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.core.errorparsers;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.cdt.core.ErrorParserManager;
+import org.eclipse.cdt.core.IMarkerGenerator;
+import org.eclipse.cdt.utils.CygPath;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+
+/**
+ * <p>RegexErrorPattern specifies a regular expression and rules how to create markers for
+ * Problems View. It is used by {@link RegexErrorParser} to process build output.
+ *
+ * <p>Regex pattern used by this class is Java regular expression and defines capturing groups.
+ * Those capturing groups are used in file, line, description expressions to get the values.
+ * <p>For example: pattern <b>"(../../..) (.*):(\d*): (Error:.*)"</b> could go along with
+ * file-expression <b>"$2"</b>, line-expression <b>"$3"</b> and description-expression <b>"$1 $4"</b>.
+ *
+ * <p>Note: variable name is being stored in marker tag. However currently it is not being used.
+ *
+ * <p>Severity could be one of:
+ * <br> - {@link IMarkerGenerator#SEVERITY_INFO},
+ * <br> - {@link IMarkerGenerator#SEVERITY_WARNING},
+ * <br> - {@link IMarkerGenerator#SEVERITY_ERROR_RESOURCE},
+ * <br> - {@link IMarkerGenerator#SEVERITY_ERROR_BUILD}
+ * <br> - {@link RegexErrorPattern#SEVERITY_SKIP}
+ * <br/>{@code SEVERITY_SKIP} means that output line is checked to match the pattern
+ * but won't be parsed to create a marker. It is useful with conjunction with
+ * {@code eatProcessedLine=true} to filter out certain lines.
+ *
+ * <p>{@code eatProcessedLine} specifies if the current output line is being passed
+ * to the rest of patterns for further processing or consumed by the pattern.
+ *
+ * <p>Clients may extend this class. As it implements {@link Cloneable} interface those clients
+ * must implement {@link Object#clone} and {@link Object#equals} methods to avoid slicing.
+ * @since 5.2
+ */
+public class RegexErrorPattern implements Cloneable {
+ /**
+ * Additional "severity" flag which tells if qualified output line should be ignored.
+ */
+ public static final int SEVERITY_SKIP = -1;
+ private static final String EMPTY_STR=""; //$NON-NLS-1$
+
+ private Pattern pattern;
+ private String fileExpression;
+ private String lineExpression;
+ private String descriptionExpression;
+ private String varNameExpression;
+ private int severity;
+ private boolean eatProcessedLine;
+
+ private static boolean isCygwin = true;
+
+ /**
+ * Constructor.
+ *
+ * @param pattern - regular expression describing the capturing groups
+ * @param fileExpression - capturing group expression defining file name
+ * @param lineExpression - capturing group expression defining line number
+ * @param descriptionExpression - capturing group expression defining description
+ * @param varNameExpression -capturing group expression defining variable name
+ * @param severity - severity, one of
+ * <br>{@link IMarkerGenerator#SEVERITY_INFO},
+ * <br>{@link IMarkerGenerator#SEVERITY_WARNING},
+ * <br>{@link IMarkerGenerator#SEVERITY_ERROR_RESOURCE},
+ * <br>{@link IMarkerGenerator#SEVERITY_ERROR_BUILD}
+ * <br>{@link RegexErrorPattern#SEVERITY_SKIP}
+ * @param eat - defines whether to consume output line avoiding further processing by other patterns
+ *
+ * <p>See general description for this class {@link RegexErrorPattern} for more details.
+ */
+ public RegexErrorPattern(String pattern,
+ String fileExpression,
+ String lineExpression,
+ String descriptionExpression,
+ String varNameExpression,
+ int severity,
+ boolean eat) {
+ this.pattern = Pattern.compile(pattern!=null ? pattern : EMPTY_STR);
+ this.fileExpression = fileExpression!=null ? fileExpression : EMPTY_STR;
+ this.lineExpression = lineExpression!=null ? lineExpression : EMPTY_STR;
+ this.descriptionExpression = descriptionExpression!=null ? descriptionExpression : EMPTY_STR;
+ this.varNameExpression = varNameExpression!=null ? varNameExpression : EMPTY_STR;
+ this.severity = severity;
+ this.eatProcessedLine = eat;
+ }
+
+ /**
+ * @return regular expression pattern
+ */
+ public String getPattern() {
+ return pattern.toString();
+ }
+
+ /**
+ * @return expression defining file name
+ */
+ public String getFileExpression() {
+ return fileExpression;
+ }
+
+ /**
+ * @return expression defining line number
+ */
+ public String getLineExpression() {
+ return lineExpression;
+ }
+
+ /**
+ * @return expression defining description
+ */
+ public String getDescriptionExpression() {
+ return descriptionExpression;
+ }
+
+ /**
+ * @return expression defining variable name
+ */
+ public String getVarNameExpression() {
+ return varNameExpression;
+ }
+
+ /**
+ * @return severity of the marker, one of:
+ * <br>{@link IMarkerGenerator#SEVERITY_INFO},
+ * <br>{@link IMarkerGenerator#SEVERITY_WARNING},
+ * <br>{@link IMarkerGenerator#SEVERITY_ERROR_RESOURCE},
+ * <br>{@link IMarkerGenerator#SEVERITY_ERROR_BUILD}
+ */
+ public int getSeverity() {
+ return severity;
+ }
+
+ /**
+ * @return whether output line is consumed and not processed further by other patterns
+ */
+ public boolean isEatProcessedLine() {
+ return eatProcessedLine;
+ }
+
+ /**
+ * @param pattern - regular expression pattern describing the capturing groups
+ */
+ public void setPattern(String pattern) {
+ this.pattern = Pattern.compile(pattern);
+ }
+
+ /**
+ * @param fileExpression - capturing group expression defining file name
+ */
+ public void setFileExpression(String fileExpression) {
+ this.fileExpression = fileExpression;
+ }
+
+ /**
+ * @param lineExpression - capturing group expression defining line number
+ */
+ public void setLineExpression(String lineExpression) {
+ this.lineExpression = lineExpression;
+ }
+
+ /**
+ * @param descriptionExpression - capturing group expression defining description
+ */
+ public void setDescriptionExpression(String descriptionExpression) {
+ this.descriptionExpression = descriptionExpression;
+ }
+
+ /**
+ * @param varNameExpression -capturing group expression defining variable name
+ */
+ public void setVarNameExpression(String varNameExpression) {
+ this.varNameExpression = varNameExpression;
+ }
+
+ /**
+ * @param severity - severity, one of
+ * <br>{@link IMarkerGenerator#SEVERITY_INFO},
+ * <br>{@link IMarkerGenerator#SEVERITY_WARNING},
+ * <br>{@link IMarkerGenerator#SEVERITY_ERROR_RESOURCE},
+ * <br>{@link IMarkerGenerator#SEVERITY_ERROR_BUILD}
+ * <br>{@link RegexErrorPattern#SEVERITY_SKIP}
+ */
+ public void setSeverity(int severity) {
+ this.severity = severity;
+ }
+
+ /**
+ * @param eatProcessedLine - whether to consume output line avoiding further processing by other patterns
+ */
+ public void setEatProcessedLine(boolean eatProcessedLine) {
+ this.eatProcessedLine = eatProcessedLine;
+ }
+
+ /**
+ * @param input - input line.
+ * @return matcher to interpret the input line.
+ */
+ private Matcher getMatcher(CharSequence input) {
+ return pattern.matcher(input);
+ }
+
+ private String parseStr(Matcher matcher, String str) {
+ if (str!=null)
+ return matcher.replaceAll(str);
+ return null;
+ }
+ /**
+ * @param matcher - matcher to parse the input line.
+ * @return parsed file name or {@code null}.
+ */
+ protected String getFileName(Matcher matcher) {
+ return parseStr(matcher, fileExpression);
+ }
+
+ /**
+ * @param matcher - matcher to parse the input line.
+ * @return parsed line number or {@code 0}.
+ */
+ protected int getLineNum(Matcher matcher) {
+ if (lineExpression != null)
+ try {
+ return Integer.valueOf(matcher.replaceAll(lineExpression)).intValue();
+ } catch (NumberFormatException e) {
+ }
+ return 0;
+ }
+
+ /**
+ * @param matcher - matcher to parse the input line.
+ * @return parsed description or {@code null}.
+ */
+ protected String getDesc(Matcher matcher) {
+ return parseStr(matcher, descriptionExpression);
+ }
+
+ /**
+ * @param matcher - matcher to parse the input line.
+ * @return parsed variable name or {@code null}.
+ */
+ protected String getVarName(Matcher matcher) {
+ return parseStr(matcher, varNameExpression);
+ }
+
+ /**
+ * @param matcher - matcher to parse the input line.
+ * @return severity of the problem.
+ */
+ protected int getSeverity(Matcher matcher) {
+ return severity;
+ }
+
+ /**
+ * Parse a line of build output and register error/warning for
+ * Problems view.
+ *
+ * @param line - one line of output.
+ * @param eoParser - {@link ErrorParserManager}.
+ * @return {@code true} if error/warning/info problem was found.
+ */
+ public boolean processLine(String line, ErrorParserManager eoParser) {
+ Matcher matcher = getMatcher(line);
+ if (!matcher.find())
+ return false;
+
+ recordError(matcher, eoParser);
+ return eatProcessedLine;
+ }
+
+ /**
+ * Register the error in {@link ErrorParserManager}.
+ *
+ * @param matcher - matcher to parse the input line.
+ * @param eoParser - {@link ErrorParserManager}.
+ * @return {@code true} indicating that error was found.
+ */
+ protected boolean recordError(Matcher matcher, ErrorParserManager eoParser) {
+ int severity = getSeverity(matcher);
+ if (severity == SEVERITY_SKIP)
+ return true;
+
+ String fileName = getFileName(matcher);
+ int lineNum = getLineNum(matcher);
+ String desc = getDesc(matcher);
+ String varName = getVarName(matcher);
+ IPath externalPath = null ;
+
+ IResource file = null;
+ if (fileName != null) {
+ file = eoParser.findFileName(fileName);
+
+ if (file == null) {
+ // If the file is not found in the workspace we attach the problem to the project
+ // and add the external path to the file.
+ file = eoParser.getProject();
+ externalPath = getLocation(fileName);
+ }
+ }
+
+ eoParser.generateExternalMarker(file, lineNum, desc, severity, varName, externalPath);
+ return true;
+ }
+
+ /**
+ * If the file designated by filename exists, return the IPath representation of the filename
+ * If it does not exist, try cygpath translation
+ *
+ * @param filename - file name
+ * @return location (outside of the workspace).
+ */
+ private IPath getLocation(String filename) {
+ IPath path = new Path(filename);
+ File file = path.toFile() ;
+ if (!file.exists() && isCygwin && path.isAbsolute()) {
+ CygPath cygpath = null ;
+ try {
+ cygpath = new CygPath("cygpath"); //$NON-NLS-1$
+ String cygfilename = cygpath.getFileName(filename);
+ IPath convertedPath = new Path(cygfilename);
+ file = convertedPath.toFile() ;
+ if (file.exists()) {
+ path = convertedPath;
+ }
+ } catch (UnsupportedOperationException e) {
+ isCygwin = false;
+ } catch (IOException e) {
+ } finally {
+ if (null!=cygpath) {
+ cygpath.dispose();
+ }
+ }
+ }
+ return path ;
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof RegexErrorPattern) {
+ RegexErrorPattern that = (RegexErrorPattern)o;
+ return this.pattern.toString().equals(that.pattern.toString())
+ && this.fileExpression.equals(that.fileExpression)
+ && this.lineExpression.equals(that.lineExpression)
+ && this.descriptionExpression.equals(that.descriptionExpression)
+ && this.varNameExpression.equals(that.varNameExpression)
+ && this.severity==that.severity
+ && this.eatProcessedLine==that.eatProcessedLine;
+ }
+ return false;
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#clone()
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return new RegexErrorPattern(pattern.toString(),
+ fileExpression,
+ lineExpression,
+ descriptionExpression,
+ varNameExpression,
+ severity,
+ eatProcessedLine);
+ }
+}
diff --git a/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java
new file mode 100644
index 00000000000..d2e4ba56b9b
--- /dev/null
+++ b/core/org.eclipse.cdt.core/src/org/eclipse/cdt/internal/errorparsers/ErrorParserExtensionManager.java
@@ -0,0 +1,726 @@
+/*******************************************************************************
+ * Copyright (c) 2009, 2009 Andrew Gvozdev (Quoin Inc.) 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
+ *
+ * Contributors:
+ * Andrew Gvozdev (Quoin Inc.) - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.cdt.internal.errorparsers;
+
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.Map.Entry;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.eclipse.cdt.core.CCorePlugin;
+import org.eclipse.cdt.core.ErrorParserManager;
+import org.eclipse.cdt.core.IErrorParser;
+import org.eclipse.cdt.core.IErrorParserNamed;
+import org.eclipse.cdt.core.IMarkerGenerator;
+import org.eclipse.cdt.core.errorparsers.ErrorParserNamedWrapper;
+import org.eclipse.cdt.core.errorparsers.RegexErrorParser;
+import org.eclipse.cdt.core.errorparsers.RegexErrorPattern;
+import org.eclipse.cdt.internal.core.XmlUtil;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.osgi.service.prefs.BackingStoreException;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
+
+/**
+ * ErrorParserExtensionManager manages error parser extensions, serialization and preferences
+ *
+ */
+public class ErrorParserExtensionManager {
+ private static final String STORAGE_ERRORPARSER_EXTENSIONS = "model.extensions.xml"; //$NON-NLS-1$
+ private static final String PREFERENCE_ERRORPARSER_DEFAULT_IDS = "errorparser.default.ids"; //$NON-NLS-1$
+ private static final String NONE = ""; //$NON-NLS-1$
+
+ private static final String EXTENSION_POINT_ERROR_PARSER = "org.eclipse.cdt.core.ErrorParser"; //$NON-NLS-1$
+ private static final String ELEM_PLUGIN = "plugin"; //$NON-NLS-1$
+ private static final String ELEM_EXTENSION = "extension"; //$NON-NLS-1$
+ private static final String ELEM_ERRORPARSER = "errorparser"; //$NON-NLS-1$
+ private static final String ELEM_PATTERN = "pattern"; //$NON-NLS-1$
+ private static final String ATTR_CLASS = "class"; //$NON-NLS-1$
+ private static final String ATTR_ID = "id"; //$NON-NLS-1$
+ private static final String ATTR_NAME = "name"; //$NON-NLS-1$
+ private static final String ATTR_POINT = "point"; //$NON-NLS-1$
+
+ private static final String ATTR_REGEX = "regex"; //$NON-NLS-1$
+ private static final String ATTR_SEVERITY = "severity"; //$NON-NLS-1$
+ private static final String ATTR_FILE = "file-expr"; //$NON-NLS-1$
+ private static final String ATTR_LINE = "line-expr"; //$NON-NLS-1$
+ private static final String ATTR_DESCRIPTION = "description-expr"; //$NON-NLS-1$
+ private static final String ATTR_VARIABLE = "variable-expr"; //$NON-NLS-1$
+ private static final String ATTR_EAT_LINE = "eat-processed-line"; //$NON-NLS-1$
+
+ private static final String ATTR_VALUE_WARNING = "Warning"; //$NON-NLS-1$
+ private static final String ATTR_VALUE_ERROR = "Error"; //$NON-NLS-1$
+ private static final String ATTR_VALUE_INFO = "Info"; //$NON-NLS-1$
+ private static final String ATTR_VALUE_IGNORE = "Ignore"; //$NON-NLS-1$
+
+ private static final LinkedHashMap<String, IErrorParserNamed> fExtensionErrorParsers = new LinkedHashMap<String, IErrorParserNamed>();
+ private static final LinkedHashMap<String, IErrorParserNamed> fAvailableErrorParsers = new LinkedHashMap<String, IErrorParserNamed>();
+ private static LinkedHashMap<String, IErrorParserNamed> fUserDefinedErrorParsers = null;
+ private static List<String> fDefaultErrorParserIds = null;
+
+ static {
+ loadUserDefinedErrorParsers();
+ loadDefaultErrorParserIds();
+ loadErrorParserExtensions();
+ }
+
+ /**
+ * Load user defined error parsers from workspace preference storage.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ synchronized public static void loadUserDefinedErrorParsers() {
+ fUserDefinedErrorParsers = null;
+ Document doc = null;
+ try {
+ doc = loadXml(getStoreLocation(STORAGE_ERRORPARSER_EXTENSIONS));
+ } catch (Exception e) {
+ CCorePlugin.log("Can't load preferences from file "+STORAGE_ERRORPARSER_EXTENSIONS, e); //$NON-NLS-1$
+ }
+
+ if (doc!=null) {
+ Set<IErrorParserNamed> errorParsers = new LinkedHashSet<IErrorParserNamed>();
+ loadErrorParserExtensions(doc, errorParsers);
+
+ if (errorParsers.size()>0) {
+ fUserDefinedErrorParsers = new LinkedHashMap<String, IErrorParserNamed>();
+ for (IErrorParserNamed errorParser : errorParsers) {
+ fUserDefinedErrorParsers.put(errorParser.getId(), errorParser);
+ }
+ }
+ }
+ recalculateAvailableErrorParsers();
+ }
+
+ /**
+ * Load XML from file to DOM Document.
+ *
+ * @param location - location of XML file
+ * @return new loaded XML Document or {@code null} if file does not exist
+ * @throws ParserConfigurationException
+ * @throws SAXException
+ * @throws IOException
+ */
+ private static Document loadXml(IPath location) throws ParserConfigurationException, SAXException, IOException {
+ java.io.File storeFile = location.toFile();
+ if (storeFile.exists()) {
+ InputStream xmlStream = new FileInputStream(storeFile);
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ return builder.parse(xmlStream);
+ }
+ return null;
+ }
+
+ /**
+ * Parse error parser contributed extensions from XML document.
+ *
+ * @param doc - source XML
+ * @param errorParsers - resulting list of error parsers
+ */
+ private static void loadErrorParserExtensions(Document doc, Set<IErrorParserNamed> errorParsers) {
+ errorParsers.clear();
+ NodeList extentionNodes = doc.getElementsByTagName(ELEM_EXTENSION);
+ for (int iext=0;iext<extentionNodes.getLength();iext++) {
+ Node extentionNode = extentionNodes.item(iext);
+ if(extentionNode.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ NodeList errorparserNodes = extentionNode.getChildNodes();
+ for (int ierp=0;ierp<errorparserNodes.getLength();ierp++) {
+ Node errorparserNode = errorparserNodes.item(ierp);
+ if(errorparserNode.getNodeType() != Node.ELEMENT_NODE || ! ELEM_ERRORPARSER.equals(errorparserNode.getNodeName()))
+ continue;
+
+ NamedNodeMap errorParserAttributes = errorparserNode.getAttributes();
+ String className = determineNodeValue(errorParserAttributes.getNamedItem(ATTR_CLASS));
+
+ try {
+ IErrorParserNamed errorParser = createErrorParserCarcass(className, Platform.getExtensionRegistry());
+ if (errorParser!=null) {
+ configureErrorParser(errorParser, errorparserNode);
+ errorParsers.add(errorParser);
+ }
+ } catch (Exception e) {
+ CCorePlugin.log("Can't create class ["+className+"] while trying to load error parser extension", e); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+ }
+ }
+ }
+
+ /**
+ * Load workspace default error parser IDs to be used if no error parsers specified.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ synchronized public static void loadDefaultErrorParserIds() {
+ fDefaultErrorParserIds = null;
+ IEclipsePreferences preferences = new InstanceScope().getNode(CCorePlugin.PLUGIN_ID);
+ String ids = preferences.get(PREFERENCE_ERRORPARSER_DEFAULT_IDS, NONE);
+ if (ids.equals(NONE)) {
+ return;
+ }
+
+ fDefaultErrorParserIds = Arrays.asList(ids.split(String.valueOf(ErrorParserManager.ERROR_PARSER_DELIMITER)));
+ }
+
+ /**
+ * Load error parser contributed extensions.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ synchronized public static void loadErrorParserExtensions() {
+ // sort by name - for the error parsers taken from platform extensions
+ Set<IErrorParserNamed> sortedErrorParsers = new TreeSet<IErrorParserNamed>(new Comparator<IErrorParserNamed>() {
+ public int compare(IErrorParserNamed errorParser1, IErrorParserNamed errorParser2) {
+ return errorParser1.getName().compareTo(errorParser2.getName());
+ }
+ });
+
+ loadErrorParserExtensions(Platform.getExtensionRegistry(), sortedErrorParsers);
+
+ fExtensionErrorParsers.clear();
+ for (IErrorParserNamed errorParser : sortedErrorParsers) {
+ fExtensionErrorParsers.put(errorParser.getId(), errorParser);
+ }
+ recalculateAvailableErrorParsers();
+ }
+
+ /**
+ * Load error parser contributed extensions from extension registry.
+ *
+ * @param registry - extension registry
+ * @param errorParsers - resulting set of error parsers
+ */
+ private static void loadErrorParserExtensions(IExtensionRegistry registry, Set<IErrorParserNamed> errorParsers) {
+ errorParsers.clear();
+ IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.ERROR_PARSER_SIMPLE_ID);
+ if (extension != null) {
+ IExtension[] extensions = extension.getExtensions();
+ for (IExtension ext : extensions) {
+ try {
+ String extensionID = ext.getUniqueIdentifier();
+ String oldStyleId = extensionID;
+ String oldStyleName = ext.getLabel();
+ for (IConfigurationElement cfgEl : ext.getConfigurationElements()) {
+ if (cfgEl.getName().equals(ELEM_ERRORPARSER)) {
+ IErrorParserNamed errorParser = createErrorParserCarcass(oldStyleId, oldStyleName, cfgEl);
+ if (errorParser!=null) {
+ configureErrorParser(errorParser, cfgEl);
+ errorParsers.add(errorParser);
+ }
+ }
+ }
+ } catch (Exception e) {
+ CCorePlugin.log("Cannot load ErrorParser extension " + ext.getUniqueIdentifier(), e); //$NON-NLS-1$
+ }
+ }
+ }
+ }
+
+ /**
+ * Populate the list of available error parsers where workspace level user defined parsers
+ * overwrite contributed through error parser extension point.
+ */
+ private static void recalculateAvailableErrorParsers() {
+ fAvailableErrorParsers.clear();
+ if (fUserDefinedErrorParsers!=null) {
+ fAvailableErrorParsers.putAll(fUserDefinedErrorParsers);
+ }
+ for (IErrorParserNamed errorParser : fExtensionErrorParsers.values()) {
+ String id = errorParser.getId();
+ if (!fAvailableErrorParsers.containsKey(id)) {
+ fAvailableErrorParsers.put(id, errorParser);
+ }
+ }
+ }
+
+ /**
+ * Serialize error parsers in workspace level storage.
+ *
+ * @throws CoreException if something goes wrong
+ */
+ public static void serializeUserDefinedErrorParsers() throws CoreException {
+ try {
+ DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
+ Document doc = builder.newDocument();
+ Element elementPlugin = doc.createElement(ELEM_PLUGIN);
+ doc.appendChild(elementPlugin);
+
+ if (fUserDefinedErrorParsers!=null) {
+ for (Entry<String, IErrorParserNamed> entry: fUserDefinedErrorParsers.entrySet()) {
+ IErrorParserNamed errorParser = entry.getValue();
+ addErrorParserExtension(elementPlugin, errorParser);
+ }
+ }
+
+ serializeXml(doc, getStoreLocation(STORAGE_ERRORPARSER_EXTENSIONS));
+
+ } catch (Exception e) {
+ throw new CoreException(new Status(IStatus.ERROR, "Failed serializing to file " + STORAGE_ERRORPARSER_EXTENSIONS, CCorePlugin.PLUGIN_ID, e)); //$NON-NLS-1$
+ }
+ }
+
+ /**
+ * Utility method to convert severity to string for the purpose of serializing in XML.
+ *
+ * @param severity - severity
+ * @return string representation
+ */
+ private static String severityToString(int severity) {
+ switch (severity) {
+ case IMarkerGenerator.SEVERITY_INFO:
+ return ATTR_VALUE_INFO;
+ case IMarkerGenerator.SEVERITY_WARNING:
+ return ATTR_VALUE_WARNING;
+ case IMarkerGenerator.SEVERITY_ERROR_BUILD:
+ case IMarkerGenerator.SEVERITY_ERROR_RESOURCE:
+ return ATTR_VALUE_ERROR;
+ }
+ return ATTR_VALUE_IGNORE;
+ }
+
+ /**
+ * Utility method to de-serialize severity from XML.
+ *
+ * @param attrSeverity - string representation of the severity
+ * @return severity
+ */
+ private static int stringToSeverity(String attrSeverity) {
+ if (ATTR_VALUE_ERROR.equals(attrSeverity))
+ return IMarkerGenerator.SEVERITY_ERROR_RESOURCE;
+ if (ATTR_VALUE_WARNING.equals(attrSeverity))
+ return IMarkerGenerator.SEVERITY_WARNING;
+ if (ATTR_VALUE_INFO.equals(attrSeverity))
+ return IMarkerGenerator.SEVERITY_INFO;
+
+ return RegexErrorPattern.SEVERITY_SKIP;
+ }
+
+ /**
+ * Add error parser extension to XML fragment, normally under <plugin/> element.
+ *
+ * @param elementPlugin - element where to add error parser extension
+ * @param errorParserNamed - error parser to add
+ */
+ private static void addErrorParserExtension(Element elementPlugin, IErrorParserNamed errorParserNamed) {
+ String id = errorParserNamed.getId();
+ String name = errorParserNamed.getName();
+ String simpleId = getSimpleId(id);
+
+ IErrorParser errorParser = errorParserNamed;
+ if (errorParser instanceof ErrorParserNamedWrapper)
+ errorParser = ((ErrorParserNamedWrapper)errorParser).getErrorParser();
+
+ Document doc = elementPlugin.getOwnerDocument();
+
+ // <extension/>
+ Element elementExtension = doc.createElement(ELEM_EXTENSION);
+ elementExtension.setAttribute(ATTR_ID, simpleId);
+ elementExtension.setAttribute(ATTR_NAME, name);
+ elementExtension.setAttribute(ATTR_POINT, EXTENSION_POINT_ERROR_PARSER);
+
+ elementPlugin.appendChild(elementExtension);
+
+ // <errorparser/>
+ Element elementErrorParser = doc.createElement(ELEM_ERRORPARSER);
+ elementErrorParser.setAttribute(ATTR_ID, id);
+ elementErrorParser.setAttribute(ATTR_NAME, name);
+ elementErrorParser.setAttribute(ATTR_CLASS, errorParser.getClass().getCanonicalName());
+
+ elementExtension.appendChild(elementErrorParser);
+
+ if (errorParserNamed instanceof RegexErrorParser) {
+ RegexErrorParser regexErrorParser = (RegexErrorParser)errorParserNamed;
+ RegexErrorPattern[] patterns = regexErrorParser.getPatterns();
+
+ for (RegexErrorPattern pattern : patterns) {
+ // <pattern/>
+ Element elementPattern = doc.createElement(ELEM_PATTERN);
+ elementPattern.setAttribute(ATTR_SEVERITY, severityToString(pattern.getSeverity()));
+ elementPattern.setAttribute(ATTR_REGEX, pattern.getPattern());
+ elementPattern.setAttribute(ATTR_FILE, pattern.getFileExpression());
+ elementPattern.setAttribute(ATTR_LINE, pattern.getLineExpression());
+ elementPattern.setAttribute(ATTR_DESCRIPTION, pattern.getDescriptionExpression());
+ elementPattern.setAttribute(ATTR_EAT_LINE, String.valueOf(pattern.isEatProcessedLine()));
+
+ elementErrorParser.appendChild(elementPattern);
+ }
+
+ }
+ }
+
+ /**
+ * Determine simple ID of error parser as last segment of full or unique ID.
+ *
+ * @param uniqueId - full ID of error parser
+ * @return simple ID of error parser
+ */
+ private static String getSimpleId(String uniqueId) {
+ String simpleId = uniqueId;
+ int dot = uniqueId.lastIndexOf('.');
+ if (dot>=0) {
+ simpleId = uniqueId.substring(dot+1);
+ }
+ return simpleId;
+ }
+
+ /**
+ * Serialize XML Document in a file.
+ *
+ * @param doc - XML to serialize
+ * @param location - location of the file
+ * @throws IOException in case of problems with file I/O
+ * @throws TransformerException in case of problems with XML output
+ */
+ synchronized private static void serializeXml(Document doc, IPath location) throws IOException, TransformerException {
+
+ java.io.File storeFile = location.toFile();
+ if (!storeFile.exists()) {
+ storeFile.createNewFile();
+ }
+ OutputStream fileStream = new FileOutputStream(storeFile);
+
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ transformer.setOutputProperty(OutputKeys.METHOD, "xml"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); //$NON-NLS-1$
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes"); //$NON-NLS-1$
+
+ XmlUtil.prettyFormat(doc);
+ DOMSource source = new DOMSource(doc);
+ StreamResult result = new StreamResult(new FileOutputStream(storeFile));
+ transformer.transform(source, result);
+
+ fileStream.close();
+ }
+
+ /**
+ * Save the list of default error parsers in preferences.
+ *
+ * @throws BackingStoreException in case of problem storing
+ */
+ public static void serializeDefaultErrorParserIds() throws BackingStoreException {
+ IEclipsePreferences preferences = new InstanceScope().getNode(CCorePlugin.PLUGIN_ID);
+ String ids = NONE;
+ if (fDefaultErrorParserIds!=null) {
+ ids = ErrorParserManager.toDelimitedString(fDefaultErrorParserIds.toArray(new String[0]));
+ }
+
+ preferences.put(PREFERENCE_ERRORPARSER_DEFAULT_IDS, ids);
+ preferences.flush();
+ }
+
+ /**
+ * @param store - name of the store
+ * @return location of the store in the plug-in state area
+ */
+ private static IPath getStoreLocation(String store) {
+ return CCorePlugin.getDefault().getStateLocation().append(store);
+ }
+
+ /**
+ * Creates empty non-configured error parser from extension point definition looking at "class" attribute.
+ * ID and name of error parser are assigned from first extension point encountered.
+ *
+ * @param className - full qualified class name of error parser.
+ * @param registry - extension registry
+ * @return new non-configured error parser
+ */
+ private static IErrorParserNamed createErrorParserCarcass(String className, IExtensionRegistry registry) {
+ if (className==null || className.length()==0 || className.equals(RegexErrorParser.class.getName()))
+ return new RegexErrorParser();
+
+ try {
+ IExtensionPoint extension = registry.getExtensionPoint(CCorePlugin.PLUGIN_ID, CCorePlugin.ERROR_PARSER_SIMPLE_ID);
+ if (extension != null) {
+ IExtension[] extensions = extension.getExtensions();
+ for (IExtension ext : extensions) {
+ String extensionID = ext.getUniqueIdentifier();
+ String oldStyleId = extensionID;
+ String oldStyleName = ext.getLabel();
+ for (IConfigurationElement cfgEl : ext.getConfigurationElements()) {
+ if (cfgEl.getName().equals(ELEM_ERRORPARSER) && className.equals(cfgEl.getAttribute(ATTR_CLASS))) {
+ return createErrorParserCarcass(oldStyleId, oldStyleName, cfgEl);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ CCorePlugin.log("Error creating error parser", e); //$NON-NLS-1$
+ }
+ return null;
+ }
+
+ /**
+ * Creates empty non-configured error parser as executable extension from extension point definition.
+ * If "class" attribute is empty RegexErrorParser is created.
+ *
+ * @param initialId - nominal ID of error parser
+ * @param initialName - nominal name of error parser
+ * @param ce - configuration element with error parser definition
+ * @return new non-configured error parser
+ * @throws CoreException in case of failure
+ */
+ private static IErrorParserNamed createErrorParserCarcass(String initialId, String initialName, IConfigurationElement ce) throws CoreException {
+ IErrorParserNamed errorParser = null;
+ if (ce.getAttribute(ATTR_CLASS)!=null) {
+ IErrorParser ep = (IErrorParser)ce.createExecutableExtension(ATTR_CLASS);
+ if (ep instanceof IErrorParserNamed) {
+ errorParser = (IErrorParserNamed)ep;
+ errorParser.setId(initialId);
+ errorParser.setName(initialName);
+ } else if (ep!=null) {
+ errorParser = new ErrorParserNamedWrapper(initialId, initialName, ep);
+ }
+ }
+ if (errorParser==null) {
+ errorParser = new RegexErrorParser(initialId, initialName);
+ }
+ return errorParser;
+ }
+
+ /**
+ * Configure error parser from XML error parser node.
+ *
+ * @param errorParser - error parser to configure
+ * @param errorparserNode - XML error parser node
+ */
+ private static void configureErrorParser(IErrorParserNamed errorParser, Node errorparserNode) {
+ NamedNodeMap errorParserAttributes = errorparserNode.getAttributes();
+ String id = determineNodeValue(errorParserAttributes.getNamedItem(ATTR_ID));
+ String name = determineNodeValue(errorParserAttributes.getNamedItem(ATTR_NAME));
+ errorParser.setId(id);
+ errorParser.setName(name);
+ if (errorParser instanceof RegexErrorParser) {
+ RegexErrorParser regexErrorParser = (RegexErrorParser)errorParser;
+
+ NodeList patternNodes = errorparserNode.getChildNodes();
+ for (int ipat=0;ipat<patternNodes.getLength();ipat++) {
+ Node patternNode = patternNodes.item(ipat);
+ if(patternNode.getNodeType() != Node.ELEMENT_NODE || ! ELEM_PATTERN.equals(patternNode.getNodeName()))
+ continue;
+
+ NamedNodeMap patternAttributes = patternNode.getAttributes();
+ String attrSeverity = determineNodeValue(patternAttributes.getNamedItem(ATTR_SEVERITY));
+ String regex = determineNodeValue(patternAttributes.getNamedItem(ATTR_REGEX));
+ String fileExpr = determineNodeValue(patternAttributes.getNamedItem(ATTR_FILE));
+ String lineExpr = determineNodeValue(patternAttributes.getNamedItem(ATTR_LINE));
+ String DescExpr = determineNodeValue(patternAttributes.getNamedItem(ATTR_DESCRIPTION));
+ String attrEatLine = determineNodeValue(patternAttributes.getNamedItem(ATTR_EAT_LINE));
+
+ int severity = stringToSeverity(attrSeverity);
+
+ boolean eatLine = ! Boolean.FALSE.toString().equals(attrEatLine); // if null default to true
+ regexErrorParser.addPattern(new RegexErrorPattern(regex, fileExpr, lineExpr, DescExpr, null,
+ severity, eatLine));
+ }
+ }
+ }
+
+ /**
+ * @param node
+ * @return node value or {@code null}
+ */
+ private static String determineNodeValue(Node node) {
+ return node!=null ? node.getNodeValue() : null;
+ }
+
+ /**
+ * Configure error parser from extension configuration element.
+ *
+ * @param errorParser - error parser to configure
+ * @param cfgEl - extension configuration element
+ * @throws CoreException
+ */
+ private static void configureErrorParser(IErrorParserNamed errorParser, IConfigurationElement cfgEl) throws CoreException {
+ String id = cfgEl.getAttribute(ATTR_ID);
+ if (id!=null && id.length()>0)
+ errorParser.setId(id);
+ String name = cfgEl.getAttribute(ATTR_NAME);
+ if (name!=null && name.length()>0)
+ errorParser.setName(name);
+
+ if (errorParser instanceof RegexErrorParser) {
+ RegexErrorParser regexErrorParser = (RegexErrorParser)errorParser;
+
+ for (IConfigurationElement cepat : cfgEl.getChildren()) {
+ if (cepat.getName().equals(ELEM_PATTERN)) {
+
+ boolean eat = ! Boolean.FALSE.toString().equals(cepat.getAttribute(ATTR_EAT_LINE));
+ regexErrorParser.addPattern(new RegexErrorPattern(cepat.getAttribute(ATTR_REGEX),
+ cepat.getAttribute(ATTR_FILE),
+ cepat.getAttribute(ATTR_LINE),
+ cepat.getAttribute(ATTR_DESCRIPTION),
+ cepat.getAttribute(ATTR_VARIABLE),
+ stringToSeverity(cepat.getAttribute(ATTR_SEVERITY)),
+ eat));
+ }
+ }
+ }
+ }
+
+ /**
+ * Return error parser as stored in internal list.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ * Use {@link #getErrorParserCopy(String)} instead.
+ *
+ * @param id - ID of error parser
+ * @return internal instance of error parser
+ */
+ public static IErrorParser getErrorParserInternal(String id) {
+ IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
+ if (errorParser instanceof ErrorParserNamedWrapper)
+ return ((ErrorParserNamedWrapper)errorParser).getErrorParser();
+ return errorParser;
+ }
+
+ /**
+ * Set and store in workspace area user defined error parsers.
+ *
+ * @param errorParsers - array of user defined error parsers
+ * @throws CoreException in case of problems
+ */
+ public static void setUserDefinedErrorParsers(IErrorParserNamed[] errorParsers) throws CoreException {
+ setUserDefinedErrorParsersInternal(errorParsers);
+ serializeUserDefinedErrorParsers();
+ }
+
+ /**
+ * Internal method to set user defined error parsers in memory.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ * Use {@link #setUserDefinedErrorParsers(IErrorParserNamed[])}.
+ *
+ * @param errorParsers - array of user defined error parsers
+ */
+ public static void setUserDefinedErrorParsersInternal(IErrorParserNamed[] errorParsers) {
+ if (errorParsers==null) {
+ fUserDefinedErrorParsers = null;
+ } else {
+ fUserDefinedErrorParsers= new LinkedHashMap<String, IErrorParserNamed>();
+ // set customized list
+ for (IErrorParserNamed errorParser : errorParsers) {
+ fUserDefinedErrorParsers.put(errorParser.getId(), errorParser);
+ }
+ }
+ recalculateAvailableErrorParsers();
+ }
+
+ /**
+ * @return available error parsers IDs which include contributed through extension + user defined ones
+ * from workspace
+ */
+ public static String[] getErrorParserAvailableIds() {
+ return fAvailableErrorParsers.keySet().toArray(new String[0]);
+ }
+
+ /**
+ * @return IDs of error parsers contributed through error parser extension point.
+ */
+ public static String[] getErrorParserExtensionIds() {
+ return fExtensionErrorParsers.keySet().toArray(new String[0]);
+ }
+
+ /**
+ * Set and store default error parsers IDs to be used if error parser list is empty.
+ *
+ * @param ids - default error parsers IDs
+ * @throws BackingStoreException in case of problem with storing
+ */
+ public static void setDefaultErrorParserIds(String[] ids) throws BackingStoreException {
+ setDefaultErrorParserIdsInternal(ids);
+ serializeDefaultErrorParserIds();
+ }
+
+ /**
+ * Set default error parsers IDs in internal list.
+ *
+ * @noreference This method is not intended to be referenced by clients.
+ * Use {@link #setDefaultErrorParserIds(String[])}.
+ *
+ * @param ids - default error parsers IDs
+ */
+ public static void setDefaultErrorParserIdsInternal(String[] ids) {
+ if (ids==null) {
+ fDefaultErrorParserIds = null;
+ } else {
+ fDefaultErrorParserIds = new ArrayList<String>(Arrays.asList(ids));
+ }
+ }
+
+ /**
+ * @return default error parsers IDs to be used if error parser list is empty.
+ */
+ public static String[] getDefaultErrorParserIds() {
+ if (fDefaultErrorParserIds==null) {
+ return fAvailableErrorParsers.keySet().toArray(new String[0]);
+ }
+ return fDefaultErrorParserIds.toArray(new String[0]);
+ }
+
+ /**
+ * @param id - ID of error parser
+ * @return cloned copy of error parser. Note that {@link ErrorParserNamedWrapper} returns
+ * shallow copy with the same instance of underlying error parser.
+ */
+ public static IErrorParserNamed getErrorParserCopy(String id) {
+ IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
+
+ try {
+ if (errorParser instanceof RegexErrorParser) {
+ return (RegexErrorParser) ((RegexErrorParser)errorParser).clone();
+ } else if (errorParser instanceof ErrorParserNamedWrapper) {
+ return (ErrorParserNamedWrapper) ((ErrorParserNamedWrapper)errorParser).clone();
+ }
+ } catch (CloneNotSupportedException e) {
+ CCorePlugin.log(e);
+ }
+ return errorParser;
+ }
+
+
+}

Back to the top