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

Bug 372551. Fixed semantics of ErrorParserManager (e.g.

getErrorParserAvailableIds()) get by removing knowledge of
contexts from internal data structures (introduced in previous change
set).

Change-Id: Ia1ff68841f3b494a209e8cdf45325d640fd74ddf
Reviewed-on: https://git.eclipse.org/r/5656
Reviewed-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
IP-Clean: Sergey Prigogin <eclipse.sprigogin@gmail.com>
Tested-by: Sergey Prigogin <eclipse.sprigogin@gmail.com>
This commit is contained in:
Alex Ruiz 2012-04-25 13:28:06 -07:00 committed by Sergey Prigogin
parent bde03774f2
commit ba5775f033
6 changed files with 114 additions and 191 deletions

View file

@ -10,8 +10,6 @@
*******************************************************************************/
package org.eclipse.cdt.codan.core.cxx.externaltool;
import static org.eclipse.cdt.core.ErrorParserContext.CODAN;
import java.net.URI;
import org.eclipse.cdt.codan.core.CodanRuntime;
@ -127,7 +125,7 @@ public abstract class AbstractExternalToolBasedChecker extends AbstractCheckerWi
private ErrorParserManager createErrorParserManager(InvocationParameters parameters) {
IProject project = parameters.getActualFile().getProject();
URI workingDirectory = URIUtil.toURI(parameters.getWorkingDirectory());
return new ErrorParserManager(project, workingDirectory, this, getParserIDs(), CODAN);
return new ErrorParserManager(project, workingDirectory, this, getParserIDs());
}
/**

View file

@ -153,24 +153,18 @@
<documentation>
Use this element to specify the context where an error parser can be used. If none is specified, a default context type will be &quot;build&quot;.
An error parser can be assigned to more than one context type. For example, an error parser can have two &quot;context&quot; elements, one for &quot;build&quot; and one for &quot;codan&quot;.
An example of context type is &quot;build&quot;. Only error parsers in this context are used to parse build output. You can see these error parsers in the &quot;C/C++&quot; &gt; &quot;Build&quot; &gt; &quot;Settings&quot; preference page.
An error parser can be assigned to more than one context type. Clients contributing error parsers are free to define their own context types.
</documentation>
</annotation>
<complexType>
<attribute name="type" use="required">
<attribute name="type" type="string" use="required">
<annotation>
<documentation>
The type of context where an error parser can be used. Valid values are &quot;build&quot; and &quot;codan&quot;.
The type of context where an error parser can be used.
</documentation>
</annotation>
<simpleType>
<restriction base="string">
<enumeration value="build">
</enumeration>
<enumeration value="codan">
</enumeration>
</restriction>
</simpleType>
</attribute>
</complexType>
</element>

View file

@ -1,32 +0,0 @@
/*******************************************************************************
* Copyright (c) 2012 Google, 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:
* Alex Ruiz (Google) - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core;
/**
* Indicates the context in which <code>{@link org.eclipse.cdt.core.IErrorParser}</code>s can be
* used.
*
* @since 5.4
*/
public class ErrorParserContext {
public static final int BUILD = 1 << 0;
public static final int CODAN = 1 << 1;
public static int getValue(String text) {
if ("build".equals(text)) { //$NON-NLS-1$
return BUILD;
}
if ("codan".equals(text)) { //$NON-NLS-1$
return CODAN;
}
throw new IllegalArgumentException("Unknown context value: " + text); //$NON-NLS-1$
}
}

View file

@ -11,11 +11,10 @@
* James Blackburn (Broadcom) - Bug 247838
* Andrew Gvozdev (Quoin Inc)
* Dmitry Kozlov (CodeSourcery) - Build error highlighting and navigation
* Alex Ruiz (Google)
*******************************************************************************/
package org.eclipse.cdt.core;
import static org.eclipse.cdt.core.ErrorParserContext.BUILD;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
@ -68,6 +67,11 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser,
*/
public final static char ERROR_PARSER_DELIMITER = ';';
/**
* @since 5.4
*/
public static final String BUILD_CONTEXT = "build"; //$NON-NLS-1$
private int nOpens;
private int lineCounter=0;
@ -75,7 +79,7 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser,
private final IMarkerGenerator fMarkerGenerator;
private Map<String, IErrorParser[]> fErrorParsers;
private final ArrayList<ProblemMarkerInfo> fErrors;
private final List<ProblemMarkerInfo> fErrors;
private final Vector<URI> fDirectoryStack;
private final URI fBaseDirectoryURI;
@ -149,28 +153,11 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser,
* @since 5.1
*/
public ErrorParserManager(IProject project, URI baseDirectoryURI, IMarkerGenerator markerGenerator, String[] parsersIDs) {
this(project, baseDirectoryURI, markerGenerator, parsersIDs, BUILD);
}
/**
* URI based constructor.
*
* @param project - project being built.
* @param baseDirectoryURI - absolute location URI of working directory of where the build is performed.
* @param markerGenerator - marker generator able to create markers.
* @param parsersIDs - array of error parsers' IDs.
* @param context - context where the error parser will be used. Valid values are defined by
* <code>{@link ErrorParserContext}</code>.
* @see ErrorParserContext
* @since 5.4
*/
public ErrorParserManager(IProject project, URI baseDirectoryURI,
IMarkerGenerator markerGenerator, String[] parsersIDs, int context) {
fProject = project;
fMarkerGenerator = markerGenerator;
fDirectoryStack = new Vector<URI>();
fErrors = new ArrayList<ProblemMarkerInfo>();
enableErrorParsers(parsersIDs, context);
enableErrorParsers(parsersIDs);
if (baseDirectoryURI != null) {
fBaseDirectoryURI = baseDirectoryURI;
@ -182,13 +169,13 @@ public class ErrorParserManager extends OutputStream implements IConsoleParser,
}
}
private void enableErrorParsers(String[] parsersIDs, int context) {
if (parsersIDs == null) {
parsersIDs = ErrorParserExtensionManager.getDefaultErrorParserIds();
private void enableErrorParsers(String[] parserIDs) {
if (parserIDs == null) {
parserIDs = ErrorParserExtensionManager.getDefaultErrorParserIds();
}
fErrorParsers = new LinkedHashMap<String, IErrorParser[]>(parsersIDs.length);
for (String parsersID : parsersIDs) {
IErrorParser errorParser = getErrorParserCopy(parsersID, context);
fErrorParsers = new LinkedHashMap<String, IErrorParser[]>(parserIDs.length);
for (String parsersID : parserIDs) {
IErrorParser errorParser = getErrorParserCopy(parsersID);
if (errorParser!=null) {
fErrorParsers.put(parsersID, new IErrorParser[] {errorParser} );
}
@ -375,7 +362,7 @@ outer:
} catch (Exception e){
String id = ""; //$NON-NLS-1$
if (parser instanceof IErrorParserNamed) {
id = ((IErrorParserNamed)parser).getId();
id = ((IErrorParserNamed) parser).getId();
}
@SuppressWarnings("nls")
String message = "Errorparser " + id + " failed parsing line [" + lineToParse + "]";
@ -832,6 +819,16 @@ outer:
return ErrorParserExtensionManager.getErrorParserAvailableIds();
}
/**
* @param context - indicates the context in which an error parser can be used.
* @return available error parsers ID, which include contributed through extension and user-
* defined ones from workspace, that can be used in the given context.
* @since 5.4
*/
public static String[] getErrorParserAvailableIdsInContext(String context) {
return ErrorParserExtensionManager.getErrorParserAvailableIdsInContext(context);
}
/**
* @return IDs of error parsers contributed through error parser extension point.
* @since 5.2
@ -870,20 +867,6 @@ outer:
return ErrorParserExtensionManager.getErrorParserCopy(id, false);
}
/**
* @param id - ID of error parser
* @param context - context where the error parser will be used. Valid values are defined by
* <code>{@link ErrorParserContext}</code>.
* @return cloned copy of error parser or {@code null}.
* Note that {@link ErrorParserNamedWrapper} returns shallow copy with the same instance
* of underlying error parser.
* @see ErrorParserContext
* @since 5.4
*/
public static IErrorParserNamed getErrorParserCopy(String id, int context) {
return ErrorParserExtensionManager.getErrorParserCopy(id, false, context);
}
/**
* @param id - ID of error parser
* @return cloned copy of error parser as defined by its extension point or {@code null}.

View file

@ -11,12 +11,14 @@
*******************************************************************************/
package org.eclipse.cdt.internal.errorparsers;
import static org.eclipse.cdt.core.ErrorParserContext.BUILD;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -25,7 +27,6 @@ import java.util.Set;
import java.util.TreeSet;
import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.ErrorParserContext;
import org.eclipse.cdt.core.ErrorParserManager;
import org.eclipse.cdt.core.IErrorParser;
import org.eclipse.cdt.core.IErrorParserNamed;
@ -33,7 +34,6 @@ 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.Pair;
import org.eclipse.cdt.internal.core.XmlUtil;
import org.eclipse.core.filesystem.URIUtil;
import org.eclipse.core.runtime.CoreException;
@ -71,7 +71,6 @@ public class ErrorParserExtensionManager {
private static final String ATTR_POINT = "point"; //$NON-NLS-1$
private static final String ATTR_TYPE = "type"; //$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$
@ -85,10 +84,9 @@ public class ErrorParserExtensionManager {
private static final String ATTR_VALUE_INFO = "Info"; //$NON-NLS-1$
private static final String ATTR_VALUE_IGNORE = "Ignore"; //$NON-NLS-1$
// Key: error parser id. Value: pair of error parser and contexts value
private static final LinkedHashMap<String, Pair<IErrorParserNamed, Integer>> fExtensionErrorParsers = new LinkedHashMap<String, Pair<IErrorParserNamed, Integer>>();
// Key: error parser id. Value: pair of error parser and contexts value
private static final LinkedHashMap<String, Pair<IErrorParserNamed, Integer>> fAvailableErrorParsers = new LinkedHashMap<String, Pair<IErrorParserNamed, Integer>>();
private static final LinkedHashMap<String, IErrorParserNamed> fExtensionErrorParsers = new LinkedHashMap<String, IErrorParserNamed>();
private static final LinkedHashMap<String, IErrorParserNamed> fAvailableErrorParsers = new LinkedHashMap<String, IErrorParserNamed>();
private static final Map<String, Set<String>> fErrorParserContexts = new HashMap<String, Set<String>>();
private static LinkedHashMap<String, IErrorParserNamed> fUserDefinedErrorParsers = null;
private static List<String> fDefaultErrorParserIds = null;
@ -121,18 +119,6 @@ public class ErrorParserExtensionManager {
}
}
private static class ErrorParserAndContextComparator implements Comparator<Pair<IErrorParserNamed, Integer>> {
private static final ErrorParserComparator DELEGATE = new ErrorParserComparator();
@Override
public int compare(Pair<IErrorParserNamed, Integer> pair1,
Pair<IErrorParserNamed, Integer> pair2) {
IErrorParserNamed parser1 = pair1.first;
IErrorParserNamed parser2 = pair2.first;
return DELEGATE.compare(parser1, parser2);
}
}
static {
loadUserDefinedErrorParsers();
loadDefaultErrorParserIds();
@ -223,13 +209,12 @@ public class ErrorParserExtensionManager {
* @noreference This method is not intended to be referenced by clients.
*/
synchronized public static void loadErrorParserExtensions() {
Set<Pair<IErrorParserNamed, Integer>> sortedErrorParsers =
new TreeSet<Pair<IErrorParserNamed, Integer>>(new ErrorParserAndContextComparator());
Set<IErrorParserNamed> sortedErrorParsers = new TreeSet<IErrorParserNamed>(new ErrorParserComparator());
loadErrorParserExtensions(Platform.getExtensionRegistry(), sortedErrorParsers);
fExtensionErrorParsers.clear();
for (Pair<IErrorParserNamed, Integer> pair : sortedErrorParsers) {
fExtensionErrorParsers.put(pair.first.getId(), pair);
for (IErrorParserNamed errorParser : sortedErrorParsers) {
fExtensionErrorParsers.put(errorParser.getId(), errorParser);
}
recalculateAvailableErrorParsers();
}
@ -240,8 +225,7 @@ public class ErrorParserExtensionManager {
* @param registry - extension registry
* @param errorParsers - resulting set of error parsers
*/
private static void loadErrorParserExtensions(IExtensionRegistry registry,
Set<Pair<IErrorParserNamed, Integer>> errorParsers) {
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) {
@ -255,9 +239,8 @@ public class ErrorParserExtensionManager {
if (cfgEl.getName().equals(ELEM_ERRORPARSER)) {
IErrorParserNamed errorParser = createErrorParserCarcass(oldStyleId, oldStyleName, cfgEl);
if (errorParser!=null) {
Pair<IErrorParserNamed, Integer> configured =
configureErrorParser(errorParser, cfgEl);
errorParsers.add(configured);
configureErrorParser(errorParser, cfgEl);
errorParsers.add(errorParser);
}
}
}
@ -278,50 +261,42 @@ public class ErrorParserExtensionManager {
List<String> ids = new ArrayList<String>();
if (fDefaultErrorParserIds!=null) {
for (String id : fDefaultErrorParserIds) {
Pair<IErrorParserNamed, Integer> pair = null;
IErrorParserNamed errorParser = null;
if (fUserDefinedErrorParsers!=null) {
errorParser = fUserDefinedErrorParsers.get(id);
}
if (errorParser != null) {
pair = errorParserForBuild(errorParser);
} else {
pair = fExtensionErrorParsers.get(id);
if (errorParser==null) {
errorParser = fExtensionErrorParsers.get(id);
}
if (pair != null) {
fAvailableErrorParsers.put(id, pair);
if (errorParser!=null) {
fAvailableErrorParsers.put(id, errorParser);
ids.add(id);
}
}
}
// then the rest in the order defined by comparator
Set<Pair<IErrorParserNamed, Integer>> sortedErrorParsers =
new TreeSet<Pair<IErrorParserNamed, Integer>>(new ErrorParserAndContextComparator());
Set<IErrorParserNamed> sortedErrorParsers = new TreeSet<IErrorParserNamed>(new ErrorParserComparator());
if (fUserDefinedErrorParsers!=null) {
for (String id : fUserDefinedErrorParsers.keySet()) {
if (!ids.contains(id)) {
IErrorParserNamed errorParser = fUserDefinedErrorParsers.get(id);
sortedErrorParsers.add(errorParserForBuild(errorParser));
sortedErrorParsers.add(errorParser);
}
}
}
for (String id : fExtensionErrorParsers.keySet()) {
if (!ids.contains(id)) {
Pair<IErrorParserNamed, Integer> pair = fExtensionErrorParsers.get(id);
sortedErrorParsers.add(pair);
IErrorParserNamed errorParser = fExtensionErrorParsers.get(id);
sortedErrorParsers.add(errorParser);
}
}
for (Pair<IErrorParserNamed, Integer> pairs : sortedErrorParsers) {
fAvailableErrorParsers.put(pairs.first.getId(), pairs);
for (IErrorParserNamed errorParser : sortedErrorParsers) {
fAvailableErrorParsers.put(errorParser.getId(), errorParser);
}
}
private static Pair<IErrorParserNamed, Integer> errorParserForBuild(IErrorParserNamed errorParser) {
return new Pair<IErrorParserNamed, Integer>(errorParser, ErrorParserContext.BUILD);
}
/**
* Serialize error parsers in workspace level storage.
*
@ -576,8 +551,7 @@ public class ErrorParserExtensionManager {
* @param cfgEl - extension configuration element
* @throws CoreException
*/
private static Pair<IErrorParserNamed, Integer> configureErrorParser(
IErrorParserNamed errorParser, IConfigurationElement cfgEl) 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);
@ -602,33 +576,39 @@ public class ErrorParserExtensionManager {
}
}
}
int contexts = contextTypes(cfgEl);
return new Pair<IErrorParserNamed, Integer>(errorParser, contexts);
findContexts(id, cfgEl);
}
/**
* Returns a bit mask of contexts where an error parser can be used. Valid values for context
* are defined in <code>{@link ErrorParserContext}</code>.
* Finds the contexts where an error parser can be used. Clients determine whether the found
* context values are valid.
*
* @param errorParserId the error parser id.
* @param errorParserElement represents an "errorparser" element in the extension point
* "org.eclipse.cdt.core.ErrorParser".
* @return the contexts in which an error parser can be used, or
* <code>{@link ErrorParserContext#BUILD BUILD}</code> is none is specified.
* @see ErrorParserContext
*/
private static int contextTypes(IConfigurationElement errorParserElement) {
private static void findContexts(String errorParserId, IConfigurationElement errorParserElement) {
Set<String> contexts = fErrorParserContexts.get(errorParserId);
IConfigurationElement[] contextElements = errorParserElement.getChildren(ELEM_CONTEXT);
if (contextElements.length == 0) {
return BUILD;
return;
}
boolean newContextCreated = false;
if (contexts == null) {
contexts = new HashSet<String>();
newContextCreated = true;
}
int contexts = 0;
for (IConfigurationElement contextElement : contextElements) {
String contextType = contextElement.getAttribute(ATTR_TYPE);
contexts = contexts | ErrorParserContext.getValue(contextType);
String context = contextElement.getAttribute(ATTR_TYPE);
if (context != null) {
contexts.add(context);
}
}
if (newContextCreated && !contexts.isEmpty()) {
fErrorParserContexts.put(errorParserId, contexts);
}
return contexts;
}
/**
* Return error parser as stored in internal list.
*
@ -639,8 +619,7 @@ public class ErrorParserExtensionManager {
* @return internal instance of error parser
*/
public static IErrorParser getErrorParserInternal(String id) {
Pair<IErrorParserNamed, Integer> pair = fAvailableErrorParsers.get(id);
IErrorParserNamed errorParser = pair.first;
IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
if (errorParser instanceof ErrorParserNamedWrapper)
return ((ErrorParserNamedWrapper) errorParser).getErrorParser();
return errorParser;
@ -685,25 +664,14 @@ public class ErrorParserExtensionManager {
* from workspace
*/
public static String[] getErrorParserAvailableIds() {
return getErrorParserIds(fAvailableErrorParsers, BUILD);
return fAvailableErrorParsers.keySet().toArray(new String[fAvailableErrorParsers.size()]);
}
/**
* @return IDs of error parsers contributed through error parser extension point.
*/
public static String[] getErrorParserExtensionIds() {
return getErrorParserIds(fExtensionErrorParsers, BUILD);
}
private static String[] getErrorParserIds(
Map<String, Pair<IErrorParserNamed, Integer>> parsers, int context) {
List<String> ids = new ArrayList<String>();
for (Map.Entry<String, Pair<IErrorParserNamed, Integer>> entry : parsers.entrySet()) {
if (isInContext(entry.getValue(), context)) {
ids.add(entry.getKey());
}
}
return ids.toArray(new String[ids.size()]);
return fExtensionErrorParsers.keySet().toArray(new String[fExtensionErrorParsers.size()]);
}
/**
@ -748,7 +716,7 @@ public class ErrorParserExtensionManager {
*/
public static String[] getDefaultErrorParserIds() {
if (fDefaultErrorParserIds == null) {
return getErrorParserIds(fAvailableErrorParsers, BUILD);
return fAvailableErrorParsers.keySet().toArray(new String[fAvailableErrorParsers.size()]);
}
return fDefaultErrorParserIds.toArray(new String[fDefaultErrorParserIds.size()]);
}
@ -760,26 +728,8 @@ public class ErrorParserExtensionManager {
* shallow copy with the same instance of underlying error parser.
*/
public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension) {
return getErrorParserCopy(id, isExtension, BUILD);
}
IErrorParserNamed errorParser = isExtension ? fExtensionErrorParsers.get(id) : fAvailableErrorParsers.get(id);
/**
* @param id - ID of error parser
* @param isExtension - if {@code true} get unmodified copy of error parser defined as extension
* @param context - context where the error parser will be used. Valid values are defined by
* <code>{@link ErrorParserContext}</code>.
* @return cloned copy of error parser. Note that {@link ErrorParserNamedWrapper} returns
* shallow copy with the same instance of underlying error parser.
* @see ErrorParserContext
*/
public static IErrorParserNamed getErrorParserCopy(String id, boolean isExtension,
int context) {
Pair<IErrorParserNamed, Integer> pair =
isExtension ? fExtensionErrorParsers.get(id) : fAvailableErrorParsers.get(id);
if (pair == null || !isInContext(pair, context)) {
return null;
}
IErrorParserNamed errorParser = pair.first;
try {
if (errorParser instanceof RegexErrorParser) {
return (RegexErrorParser) ((RegexErrorParser) errorParser).clone();
@ -791,8 +741,38 @@ public class ErrorParserExtensionManager {
}
return errorParser;
}
private static boolean isInContext(Pair<IErrorParserNamed, Integer> pair, int context) {
return (pair.second & context) != 0;
/**
* @param context - indicates the context in which an error parser can be used.
* @return available error parsers ID, which include contributed through extension and user-
* defined ones from workspace, that can be used in the given context.
*/
public static String[] getErrorParserAvailableIdsInContext(String context) {
List<String> ids = new ArrayList<String>();
for (String id : fAvailableErrorParsers.keySet()) {
if (getErrorParserContexts(id).contains(context)) {
ids.add(id);
}
}
return ids.toArray(new String[ids.size()]);
}
/**
* Returns all the contexts of the error parser with the given ID. Contexts are {@code String}
* values belonging to an error parser, defined as part the "errorparser" extension point
* element.
* <p>
* If an error parser does not have an explicit context, it is assumed that the error parser
* can be used in the "build" context.
* </p>
* @param id the id of the error parser.
* @return the contexts of the error parser with the given ID.
*/
private static Collection<String> getErrorParserContexts(String id) {
Set<String> contexts = fErrorParserContexts.get(id);
if (contexts == null) {
return Collections.singletonList(ErrorParserManager.BUILD_CONTEXT);
}
return contexts;
}
}

View file

@ -244,7 +244,7 @@ public class ErrorParsTab extends AbstractCPropertyTab {
}
fAvailableErrorParsers.clear();
fOptionsPageMap.clear();
for (String id : ErrorParserManager.getErrorParserAvailableIds()) {
for (String id : ErrorParserManager.getErrorParserAvailableIdsInContext(ErrorParserManager.BUILD_CONTEXT)) {
IErrorParserNamed errorParser = ErrorParserManager.getErrorParserCopy(id);
fAvailableErrorParsers.put(id, errorParser);
initializeOptionsPage(id);