mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-23 06:32:10 +02:00
bug 109139: Generic Error parser
(RegexErrorParser)
This commit is contained in:
parent
64a0f77faf
commit
dbbdbd8f95
26 changed files with 4130 additions and 195 deletions
|
@ -35,6 +35,11 @@ CommandTargetBuild.description=Invoke a make target build for the selected conta
|
|||
CommandTargetCreate.name=Create Make Target
|
||||
CommandTargetCreate.description=Create a new make build target for the selected container.
|
||||
|
||||
# Build Settings Preference page
|
||||
PreferenceBuildSettings.name=Build Settings
|
||||
ErrorParsersTab.name=Error Parsers
|
||||
ErrorParsersTab.tooltip=Error Parsers scan build output and report errors in Problems view
|
||||
|
||||
PreferenceMakeProject.name=New Make Projects
|
||||
PreferenceMake.name=Make
|
||||
PreferenceMakefileEditor.name=Makefile Editor
|
||||
|
|
|
@ -175,6 +175,12 @@
|
|||
</extension>
|
||||
<extension
|
||||
point="org.eclipse.ui.preferencePages">
|
||||
<page
|
||||
name="%PreferenceBuildSettings.name"
|
||||
category="org.eclipse.cdt.ui.preferences.CPluginPreferencePage"
|
||||
class="org.eclipse.cdt.make.internal.ui.preferences.BuildSettingsPreferencePage"
|
||||
id="org.eclipse.cdt.make.ui.preferences.BuildSettings">
|
||||
</page>
|
||||
<page
|
||||
name="%PreferenceMake.name"
|
||||
category="org.eclipse.cdt.ui.preferences.CPluginPreferencePage"
|
||||
|
@ -428,8 +434,8 @@
|
|||
profileId="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"/>
|
||||
</extension>
|
||||
|
||||
<extension
|
||||
point="org.eclipse.cdt.ui.cPropertyTab">
|
||||
<extension
|
||||
point="org.eclipse.cdt.ui.cPropertyTab">
|
||||
|
||||
<!-- exported from CORE -->
|
||||
<tab
|
||||
|
@ -448,7 +454,16 @@
|
|||
helpId="cdt_u_prop_pns_sym"
|
||||
parent="org.eclipse.cdt.make.internal.ui.properties.PathAndSymbolPage"
|
||||
tooltip="%Symbols.tooltip"/>
|
||||
</extension>
|
||||
<tab
|
||||
class="org.eclipse.cdt.ui.newui.ErrorParsTab"
|
||||
helpId="cdt_u_prop_build_setting_errparser"
|
||||
icon="icons/obj16/error_obj.gif"
|
||||
name="%ErrorParsersTab.name"
|
||||
parent="org.eclipse.cdt.make.internal.ui.preferences.BuildSettingsPreferencePage"
|
||||
tooltip="%ErrorParsersTab.tooltip"
|
||||
weight="020">
|
||||
</tab>
|
||||
</extension>
|
||||
|
||||
<extension
|
||||
point="org.eclipse.ui.propertyPages">
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 Andrew Gvozdev 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 - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.make.internal.ui.preferences;
|
||||
|
||||
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
|
||||
import org.eclipse.cdt.ui.newui.AbstractPrefPage;
|
||||
import org.eclipse.cdt.ui.newui.ICPropertyTab;
|
||||
|
||||
/**
|
||||
* Preference page for Build Settings.
|
||||
*
|
||||
*/
|
||||
public class BuildSettingsPreferencePage extends AbstractPrefPage {
|
||||
|
||||
@Override
|
||||
protected String getHeader() {
|
||||
return MakefilePreferencesMessages.getString("BuildPreferencePage.description"); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/*
|
||||
* All affected settings are stored in preferences. Tabs are responsible for
|
||||
* saving, after OK signal. No need to affect Project Description somehow.
|
||||
*/
|
||||
@Override
|
||||
public boolean performOk() {
|
||||
forEach(ICPropertyTab.OK, null);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ICResourceDescription getResDesc() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSingle() {
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
###############################################################################
|
||||
# Copyright (c) 2000, 2006 IBM Corporation and others.
|
||||
# Copyright (c) 2000, 2009 IBM Corporation 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
|
||||
|
@ -9,6 +9,8 @@
|
|||
# IBM Corporation - initial API and implementation
|
||||
###############################################################################
|
||||
|
||||
BuildPreferencePage.description=These settings are global to the entire workspace. They are overridden by project-specific settings.
|
||||
|
||||
MakefileEditorPreferencePage.description=Makefile Editor settings:
|
||||
MakefileEditorPreferencePage.invalid_input_print_margin= Invalid print margin column specified
|
||||
MakefileEditorPreferencePage.empty_input_print_margin= No print margin column specified
|
||||
|
|
|
@ -26,6 +26,7 @@ public class ErrorParserTests {
|
|||
suite.addTest(ErrorParserManagerTest.suite());
|
||||
suite.addTest(ErrorParserFileMatchingTest.suite());
|
||||
suite.addTest(ErrorParserEfsFileMatchingTest.suite());
|
||||
suite.addTest(RegexErrorParserTests.suite());
|
||||
return suite;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,689 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 Andrew Gvozdev 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 - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.core.internal.errorparsers.tests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
|
||||
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.ProblemMarkerInfo;
|
||||
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.errorparsers.ErrorParserExtensionManager;
|
||||
import org.eclipse.cdt.internal.errorparsers.GCCErrorParser;
|
||||
import org.eclipse.core.resources.IMarker;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IResource;
|
||||
|
||||
/**
|
||||
* Test cases testing RegexErrorParser functionality
|
||||
*/
|
||||
public class RegexErrorParserTests extends TestCase {
|
||||
// These should match id and name of extension point defined in plugin.xml
|
||||
private static final String REGEX_ERRORPARSER_ID = "org.eclipse.cdt.core.tests.RegexErrorParserId";
|
||||
private static final String REGEX_ERRORPARSER_NAME = "Test Plugin RegexErrorParser";
|
||||
private static final String GCC_ERRORPARSER_ID = "org.eclipse.cdt.core.GCCErrorParser";
|
||||
|
||||
private static final String TEST_PROJECT_NAME = "RegexErrorParserTests";
|
||||
|
||||
private IProject fProject = null;
|
||||
private ArrayList<ProblemMarkerInfo> errorList;
|
||||
|
||||
private final IMarkerGenerator markerGenerator = new IMarkerGenerator() {
|
||||
// deprecated
|
||||
public void addMarker(IResource file, int lineNumber, String errorDesc, int severity, String errorVar) {}
|
||||
|
||||
public void addMarker(ProblemMarkerInfo problemMarkerInfo) {
|
||||
errorList.add(problemMarkerInfo);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Dummy error parser
|
||||
*/
|
||||
public static class DummyErrorParser implements IErrorParser {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public DummyErrorParser() {
|
||||
}
|
||||
|
||||
public boolean processLine(String line, ErrorParserManager eoParser) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param name - name of the test.
|
||||
*/
|
||||
public RegexErrorParserTests(String name) {
|
||||
super(name);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
fProject = ResourceHelper.createCDTProject(TEST_PROJECT_NAME);
|
||||
assertNotNull(fProject);
|
||||
errorList = new ArrayList<ProblemMarkerInfo>();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
ResourceHelper.cleanUp();
|
||||
fProject = null;
|
||||
|
||||
ErrorParserManager.setUserDefinedErrorParsers(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return - new TestSuite.
|
||||
*/
|
||||
public static TestSuite suite() {
|
||||
return new TestSuite(RegexErrorParserTests.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* main function of the class.
|
||||
*
|
||||
* @param args - arguments
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
junit.textui.TestRunner.run(suite());
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if error pattern can be added/deleted.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testRegexErrorParserAddDeletePattern() throws Exception {
|
||||
RegexErrorParser regexErrorParser = new RegexErrorParser();
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("pattern 1",
|
||||
null, null, null, null, RegexErrorPattern.SEVERITY_SKIP, true));
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("delete me",
|
||||
null, null, null, null, RegexErrorPattern.SEVERITY_SKIP, true));
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("pattern 3",
|
||||
null, null, null, null, RegexErrorPattern.SEVERITY_SKIP, true));
|
||||
|
||||
// adding patterns
|
||||
RegexErrorPattern[] patternsBefore = regexErrorParser.getPatterns();
|
||||
assertEquals(3, patternsBefore.length);
|
||||
assertEquals("delete me", patternsBefore[1].getPattern());
|
||||
RegexErrorPattern next = patternsBefore[2];
|
||||
|
||||
// delete pattern test
|
||||
regexErrorParser.removePattern(patternsBefore[1]);
|
||||
|
||||
RegexErrorPattern[] patternsAfter = regexErrorParser.getPatterns();
|
||||
assertEquals(2, patternsAfter.length);
|
||||
assertEquals(next, patternsAfter[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure the order of patterns is preserved.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testRegexErrorParserPatternOrder() throws Exception {
|
||||
final int ERR=IMarkerGenerator.SEVERITY_ERROR_RESOURCE;
|
||||
RegexErrorParser regexErrorParser = new RegexErrorParser();
|
||||
RegexErrorPattern removable = new RegexErrorPattern("CCC", null, null, null, null, ERR, true);
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("AAA", null, null, null, null, ERR, true));
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("BBB", null, null, null, null, ERR, true));
|
||||
regexErrorParser.addPattern(removable);
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("DDD", null, null, null, null, ERR, true));
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("ZZZ", null, null, null, null, ERR, true));
|
||||
|
||||
{
|
||||
RegexErrorPattern[] patterns = regexErrorParser.getPatterns();
|
||||
assertEquals("AAA", patterns[0].getPattern());
|
||||
assertEquals("BBB", patterns[1].getPattern());
|
||||
assertEquals("CCC", patterns[2].getPattern());
|
||||
assertEquals("DDD", patterns[3].getPattern());
|
||||
assertEquals("ZZZ", patterns[4].getPattern());
|
||||
}
|
||||
|
||||
regexErrorParser.removePattern(removable);
|
||||
|
||||
{
|
||||
RegexErrorPattern[] patterns = regexErrorParser.getPatterns();
|
||||
assertEquals("AAA", patterns[0].getPattern());
|
||||
assertEquals("BBB", patterns[1].getPattern());
|
||||
assertEquals("DDD", patterns[2].getPattern());
|
||||
assertEquals("ZZZ", patterns[3].getPattern());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check how RegexErrorParser parses output.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testRegexErrorParserParseOutput() throws Exception {
|
||||
RegexErrorParser regexErrorParser = new RegexErrorParser();
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("(.*)#(.*)#(.*)#(.*)",
|
||||
"$1", "$2", "$3 $4", "var=$4", IMarkerGenerator.SEVERITY_ERROR_RESOURCE, true));
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("(.*)!(skip me)!(.*)!(.*)",
|
||||
null, null, null, null, RegexErrorPattern.SEVERITY_SKIP, true));
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("(.*)!(Description)!(.*)!(.*)",
|
||||
"$4", "$3", "$2", "$1", IMarkerGenerator.SEVERITY_WARNING, /*eat-line*/ false));
|
||||
// broken pattern
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("(.*)!(.*)",
|
||||
"$6", "$7", "$8", "$9", IMarkerGenerator.SEVERITY_WARNING, true));
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("(.*)!(.*)!(.*)!(.*)",
|
||||
null, null, null, null, IMarkerGenerator.SEVERITY_INFO, true));
|
||||
|
||||
String fileName = "RegexErrorParser.c";
|
||||
ResourceHelper.createFile(fProject, fileName);
|
||||
|
||||
ErrorParserManager epManager = new ErrorParserManager(fProject, markerGenerator, new String[0]);
|
||||
boolean result;
|
||||
ProblemMarkerInfo problemMarkerInfo;
|
||||
|
||||
// Regular pattern
|
||||
regexErrorParser.processLine(fileName+"#10#Description#Variable", epManager);
|
||||
// This should get ignored
|
||||
regexErrorParser.processLine("Variable!skip me!10!"+fileName, epManager);
|
||||
// Eat-line=false + qualifying next pattern (nulls), i.e. generates 2 problems
|
||||
regexErrorParser.processLine("Variable!Description!10!"+fileName, epManager);
|
||||
|
||||
errorList.clear();
|
||||
epManager.reportProblems();
|
||||
assertEquals(3, errorList.size());
|
||||
|
||||
// Regular
|
||||
problemMarkerInfo = errorList.get(0);
|
||||
assertEquals(IMarkerGenerator.SEVERITY_ERROR_RESOURCE, problemMarkerInfo.severity);
|
||||
assertEquals("L/"+TEST_PROJECT_NAME+"/"+fileName, problemMarkerInfo.file.toString());
|
||||
assertEquals(fileName, problemMarkerInfo.file.getName());
|
||||
assertEquals(10, problemMarkerInfo.lineNumber);
|
||||
assertEquals("Description Variable",problemMarkerInfo.description);
|
||||
assertEquals("var=Variable",problemMarkerInfo.variableName);
|
||||
|
||||
// Eat-line
|
||||
problemMarkerInfo = errorList.get(1);
|
||||
assertEquals(IMarkerGenerator.SEVERITY_WARNING, problemMarkerInfo.severity);
|
||||
assertEquals("L/"+TEST_PROJECT_NAME+"/"+fileName, problemMarkerInfo.file.toString());
|
||||
assertEquals(fileName, problemMarkerInfo.file.getName());
|
||||
assertEquals(10, problemMarkerInfo.lineNumber);
|
||||
assertEquals("Description",problemMarkerInfo.description);
|
||||
assertEquals("Variable",problemMarkerInfo.variableName);
|
||||
|
||||
// Nulls
|
||||
problemMarkerInfo = errorList.get(2);
|
||||
assertEquals(IMarkerGenerator.SEVERITY_INFO, problemMarkerInfo.severity);
|
||||
assertEquals("P/"+TEST_PROJECT_NAME, problemMarkerInfo.file.toString());
|
||||
assertEquals(0, problemMarkerInfo.lineNumber);
|
||||
assertEquals("",problemMarkerInfo.description);
|
||||
assertEquals("",problemMarkerInfo.variableName);
|
||||
|
||||
// clone & equals
|
||||
RegexErrorParser cloned = (RegexErrorParser)regexErrorParser.clone();
|
||||
assertTrue(cloned!=regexErrorParser);
|
||||
assertEquals(regexErrorParser, cloned);
|
||||
assertTrue(cloned.getPatterns()!=regexErrorParser.getPatterns());
|
||||
assertEquals(cloned.getPatterns().length, regexErrorParser.getPatterns().length);
|
||||
for (int i=0; i<regexErrorParser.getPatterns().length; i++) {
|
||||
// Checking deep copy
|
||||
assertTrue(cloned.getPatterns()[i]!=regexErrorParser.getPatterns()[i]);
|
||||
assertEquals(cloned.getPatterns()[i],regexErrorParser.getPatterns()[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if compatibility with CCorePlugin methods from CDT 6.0 was not violated.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testCompatibility() throws Exception {
|
||||
final CCorePlugin cCorePlugin = CCorePlugin.getDefault();
|
||||
|
||||
// CCorePlugin.getAllErrorParsersIDs()
|
||||
String all = ErrorParserManager.toDelimitedString(cCorePlugin.getAllErrorParsersIDs());
|
||||
assertTrue(all.contains(GCC_ERRORPARSER_ID));
|
||||
|
||||
// CCorePlugin.getErrorParser(id)
|
||||
IErrorParser[] gccErrorParserArray = cCorePlugin.getErrorParser(GCC_ERRORPARSER_ID);
|
||||
assertNotNull(gccErrorParserArray);
|
||||
assertEquals(1, gccErrorParserArray.length);
|
||||
assertTrue(gccErrorParserArray[0] instanceof GCCErrorParser);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that regular error parser extension defined in plugin.xml is accessible.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testExtension() throws Exception {
|
||||
// ErrorParserManager.getErrorParser
|
||||
{
|
||||
IErrorParserNamed errorParser = ErrorParserManager.getErrorParserCopy(REGEX_ERRORPARSER_ID);
|
||||
assertNotNull(errorParser);
|
||||
assertEquals(REGEX_ERRORPARSER_NAME, errorParser.getName());
|
||||
|
||||
assertTrue(errorParser instanceof RegexErrorParser);
|
||||
RegexErrorParser regexErrorParser = (RegexErrorParser)errorParser;
|
||||
assertEquals(REGEX_ERRORPARSER_ID, regexErrorParser.getId());
|
||||
assertEquals(REGEX_ERRORPARSER_NAME, regexErrorParser.getName());
|
||||
|
||||
RegexErrorPattern[] patterns = regexErrorParser.getPatterns();
|
||||
assertEquals(1, patterns.length);
|
||||
|
||||
RegexErrorPattern pattern = patterns[0];
|
||||
assertEquals(IMarker.SEVERITY_ERROR, pattern.getSeverity());
|
||||
assertEquals(true, pattern.isEatProcessedLine());
|
||||
assertEquals("(.*):(.*):regex (.*)", pattern.getPattern());
|
||||
assertEquals("$1", pattern.getFileExpression());
|
||||
assertEquals("$2", pattern.getLineExpression());
|
||||
assertEquals("$3", pattern.getDescriptionExpression());
|
||||
assertEquals("", pattern.getVarNameExpression());
|
||||
}
|
||||
|
||||
// ErrorParserManager.getErrorParsers
|
||||
{
|
||||
IErrorParser errorParser = ErrorParserManager.getErrorParserCopy(REGEX_ERRORPARSER_ID);
|
||||
assertTrue(errorParser instanceof RegexErrorParser);
|
||||
|
||||
RegexErrorParser regexErrorParser = (RegexErrorParser)errorParser;
|
||||
assertEquals(REGEX_ERRORPARSER_ID, regexErrorParser.getId());
|
||||
assertEquals(REGEX_ERRORPARSER_NAME, regexErrorParser.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure extensions contributed through extension point are sorted by name.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testExtensionsSorting() throws Exception {
|
||||
{
|
||||
String[] ids = ErrorParserManager.getErrorParserExtensionIds();
|
||||
String lastName="";
|
||||
// error parsers created from extensions are to be sorted by names
|
||||
for (String id : ids) {
|
||||
String name = ErrorParserManager.getErrorParserCopy(id).getName();
|
||||
assertTrue(lastName.compareTo(name)<=0);
|
||||
lastName = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting/retrieval of error parsers and their IDs.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testAvailableErrorParsers() throws Exception {
|
||||
final String TESTING_ID = "org.eclipse.cdt.core.test.errorparser";
|
||||
final String TESTING_NAME = "An error parser";
|
||||
|
||||
final String[] availableParserIds = ErrorParserManager.getErrorParserAvailableIds();
|
||||
assertNotNull(availableParserIds);
|
||||
assertTrue(availableParserIds.length>0);
|
||||
final String firstId = ErrorParserManager.getErrorParserAvailableIds()[0];
|
||||
final IErrorParserNamed firstErrorParser = ErrorParserManager.getErrorParserCopy(firstId);
|
||||
assertNotNull(firstErrorParser);
|
||||
assertEquals(firstId, firstErrorParser.getId());
|
||||
final String firstName = firstErrorParser.getName();
|
||||
// Preconditions
|
||||
{
|
||||
String all = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
assertEquals(false, all.contains(TESTING_ID));
|
||||
assertEquals(true, all.contains(firstId));
|
||||
|
||||
assertNull(ErrorParserManager.getErrorParserCopy(TESTING_ID));
|
||||
|
||||
IErrorParserNamed retrieved2 = ErrorParserManager.getErrorParserCopy(firstId);
|
||||
assertNotNull(retrieved2);
|
||||
assertEquals(firstErrorParser, retrieved2);
|
||||
}
|
||||
|
||||
// set available parsers
|
||||
{
|
||||
IErrorParser dummy1 = new DummyErrorParser();
|
||||
IErrorParser dummy2 = new DummyErrorParser();
|
||||
ErrorParserManager.setUserDefinedErrorParsers(new IErrorParserNamed[] {
|
||||
// add brand new one
|
||||
new ErrorParserNamedWrapper(TESTING_ID, TESTING_NAME, dummy1),
|
||||
// override extension with another one
|
||||
new ErrorParserNamedWrapper(firstId, firstName, dummy2),
|
||||
});
|
||||
String all = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
assertEquals(true, all.contains(TESTING_ID));
|
||||
assertEquals(true, all.contains(firstId));
|
||||
|
||||
IErrorParserNamed retrieved1 = ErrorParserManager.getErrorParserCopy(TESTING_ID);
|
||||
assertNotNull(retrieved1);
|
||||
assertEquals(TESTING_NAME, retrieved1.getName());
|
||||
assertTrue(retrieved1 instanceof ErrorParserNamedWrapper);
|
||||
assertEquals(dummy1, ((ErrorParserNamedWrapper)retrieved1).getErrorParser());
|
||||
|
||||
IErrorParserNamed retrieved2 = ErrorParserManager.getErrorParserCopy(firstId);
|
||||
assertNotNull(retrieved2);
|
||||
assertEquals(firstName, retrieved2.getName());
|
||||
assertTrue(retrieved2 instanceof ErrorParserNamedWrapper);
|
||||
assertEquals(dummy2, ((ErrorParserNamedWrapper)retrieved2).getErrorParser());
|
||||
}
|
||||
// reset available parsers
|
||||
{
|
||||
ErrorParserManager.setUserDefinedErrorParsers(null);
|
||||
|
||||
String all = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
assertEquals(false, all.contains(TESTING_ID));
|
||||
assertEquals(true, all.contains(firstId));
|
||||
|
||||
assertNull(ErrorParserManager.getErrorParserCopy(TESTING_ID));
|
||||
|
||||
IErrorParserNamed retrieved2 = ErrorParserManager.getErrorParserCopy(firstId);
|
||||
assertNotNull(retrieved2);
|
||||
assertEquals(firstErrorParser, retrieved2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting/retrieval of user defined error parsers.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testUserDefinedErrorParsers() throws Exception {
|
||||
final String TESTING_ID = "org.eclipse.cdt.core.test.errorparser";
|
||||
final String TESTING_NAME = "An error parser";
|
||||
// reset parsers
|
||||
{
|
||||
ErrorParserManager.setUserDefinedErrorParsers(null);
|
||||
String all = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
String extensions = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserExtensionIds());
|
||||
assertEquals(all, extensions);
|
||||
}
|
||||
{
|
||||
ErrorParserManager.setUserDefinedErrorParsers(new IErrorParserNamed[] {
|
||||
new ErrorParserNamedWrapper(TESTING_ID, TESTING_NAME, new DummyErrorParser()),
|
||||
});
|
||||
String all = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
String extensions = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserExtensionIds());
|
||||
assertFalse(all.equals(extensions));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test setting/retrieval of default error parser IDs preferences.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testDefaultErrorParserIds() throws Exception {
|
||||
final String[] availableParserIds = ErrorParserManager.getErrorParserAvailableIds();
|
||||
assertNotNull(availableParserIds);
|
||||
final String[] initialDefaultErrorParserIds = ErrorParserManager.getDefaultErrorParserIds();
|
||||
|
||||
// preconditions
|
||||
{
|
||||
String[] defaultErrorParserIds = ErrorParserManager.getDefaultErrorParserIds();
|
||||
assertNotNull(defaultErrorParserIds);
|
||||
assertEquals(ErrorParserManager.toDelimitedString(availableParserIds),
|
||||
ErrorParserManager.toDelimitedString(defaultErrorParserIds));
|
||||
}
|
||||
// setDefaultErrorParserIds
|
||||
{
|
||||
String[] newDefaultErrorParserIds = {
|
||||
"org.eclipse.cdt.core.test.errorparser0",
|
||||
"org.eclipse.cdt.core.test.errorparser1",
|
||||
"org.eclipse.cdt.core.test.errorparser2",
|
||||
};
|
||||
ErrorParserManager.setDefaultErrorParserIds(newDefaultErrorParserIds);
|
||||
String[] defaultErrorParserIds = ErrorParserManager.getDefaultErrorParserIds();
|
||||
assertNotNull(defaultErrorParserIds);
|
||||
assertEquals(ErrorParserManager.toDelimitedString(newDefaultErrorParserIds),
|
||||
ErrorParserManager.toDelimitedString(defaultErrorParserIds));
|
||||
}
|
||||
|
||||
// reset
|
||||
{
|
||||
ErrorParserManager.setDefaultErrorParserIds(null);
|
||||
String[] defaultErrorParserIds = ErrorParserManager.getDefaultErrorParserIds();
|
||||
assertNotNull(defaultErrorParserIds);
|
||||
assertEquals(ErrorParserManager.toDelimitedString(availableParserIds),
|
||||
ErrorParserManager.toDelimitedString(defaultErrorParserIds));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of user defined error parsers.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testSerializeErrorParser() throws Exception {
|
||||
final String TESTING_ID = "org.eclipse.cdt.core.test.errorparser";
|
||||
final String TESTING_NAME = "An error parser";
|
||||
|
||||
{
|
||||
// Create error parser
|
||||
IErrorParser errorParser = new GCCErrorParser();
|
||||
// Add to available parsers
|
||||
ErrorParserExtensionManager.setUserDefinedErrorParsersInternal(new IErrorParserNamed[] {new ErrorParserNamedWrapper(TESTING_ID, TESTING_NAME, errorParser)});
|
||||
assertNotNull(ErrorParserManager.getErrorParserCopy(TESTING_ID));
|
||||
assertEquals(TESTING_NAME, ErrorParserManager.getErrorParserCopy(TESTING_ID).getName());
|
||||
// Serialize in persistent storage
|
||||
ErrorParserExtensionManager.serializeUserDefinedErrorParsers();
|
||||
}
|
||||
{
|
||||
// Remove from available parsers
|
||||
ErrorParserExtensionManager.setUserDefinedErrorParsersInternal(null);
|
||||
assertNull(ErrorParserManager.getErrorParserCopy(TESTING_ID));
|
||||
}
|
||||
|
||||
{
|
||||
// Re-load from persistent storage and check it out
|
||||
ErrorParserExtensionManager.loadUserDefinedErrorParsers();
|
||||
IErrorParserNamed errorParser = ErrorParserManager.getErrorParserCopy(TESTING_ID);
|
||||
assertNotNull(errorParser);
|
||||
assertEquals(TESTING_NAME, errorParser.getName());
|
||||
assertTrue(errorParser instanceof ErrorParserNamedWrapper);
|
||||
assertTrue(((ErrorParserNamedWrapper)errorParser).getErrorParser() instanceof GCCErrorParser);
|
||||
}
|
||||
{
|
||||
// Remove from available parsers as clean-up
|
||||
ErrorParserExtensionManager.setUserDefinedErrorParsersInternal(null);
|
||||
assertNull(ErrorParserManager.getErrorParserCopy(TESTING_ID));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test serialization of user defined RegexErrorParser.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testSerializeRegexErrorParser() throws Exception {
|
||||
|
||||
final String TESTING_ID = "org.eclipse.cdt.core.test.regexerrorparser";
|
||||
final String TESTING_NAME = "Regex Error Parser";
|
||||
final String ALL_IDS = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
{
|
||||
// Create error parser with the same id as in eclipse registry
|
||||
RegexErrorParser regexErrorParser = new RegexErrorParser(TESTING_ID, TESTING_NAME);
|
||||
regexErrorParser.addPattern(new RegexErrorPattern("Pattern-Y",
|
||||
"line-Y", "file-Y", "description-Y", null, IMarkerGenerator.SEVERITY_WARNING, false));
|
||||
|
||||
// Add to available parsers
|
||||
ErrorParserExtensionManager.setUserDefinedErrorParsersInternal(new IErrorParserNamed[] {regexErrorParser});
|
||||
assertNotNull(ErrorParserManager.getErrorParserCopy(TESTING_ID));
|
||||
// And serialize in persistent storage
|
||||
ErrorParserExtensionManager.serializeUserDefinedErrorParsers();
|
||||
}
|
||||
|
||||
{
|
||||
// Remove from available parsers
|
||||
ErrorParserExtensionManager.setUserDefinedErrorParsersInternal(null);
|
||||
assertNull(ErrorParserManager.getErrorParserCopy(TESTING_ID));
|
||||
}
|
||||
|
||||
{
|
||||
// Re-load from persistent storage and check it out
|
||||
ErrorParserExtensionManager.loadUserDefinedErrorParsers();
|
||||
String all = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
assertTrue(all.contains(TESTING_ID));
|
||||
|
||||
IErrorParser errorParser = ErrorParserManager.getErrorParserCopy(TESTING_ID);
|
||||
assertNotNull(errorParser);
|
||||
assertTrue(errorParser instanceof RegexErrorParser);
|
||||
RegexErrorParser regexErrorParser = (RegexErrorParser)errorParser;
|
||||
assertEquals(TESTING_ID, regexErrorParser.getId());
|
||||
assertEquals(TESTING_NAME, regexErrorParser.getName());
|
||||
|
||||
RegexErrorPattern[] errorPatterns = regexErrorParser.getPatterns();
|
||||
assertEquals(1, errorPatterns.length);
|
||||
assertEquals("Pattern-Y", errorPatterns[0].getPattern());
|
||||
}
|
||||
|
||||
{
|
||||
// Remove from available parsers and serialize
|
||||
ErrorParserExtensionManager.setUserDefinedErrorParsersInternal(null);
|
||||
ErrorParserExtensionManager.serializeUserDefinedErrorParsers();
|
||||
|
||||
// Re-load from persistent storage and check it out
|
||||
ErrorParserExtensionManager.loadUserDefinedErrorParsers();
|
||||
String all = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
assertEquals(ALL_IDS, all);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure special characters are serialized properly.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testSerializeRegexErrorParserSpecialCharacters() throws Exception {
|
||||
|
||||
final String TESTING_ID = "org.eclipse.cdt.core.test.regexerrorparser";
|
||||
final String TESTING_NAME = "<>\"'\\& Error Parser";
|
||||
final String TESTING_REGEX = "Pattern-<>\"'\\&";
|
||||
final String ALL_IDS = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
{
|
||||
// Create error parser with the same id as in eclipse registry
|
||||
RegexErrorParser regexErrorParser = new RegexErrorParser(TESTING_ID, TESTING_NAME);
|
||||
regexErrorParser.addPattern(new RegexErrorPattern(TESTING_REGEX,
|
||||
"line-<>\"'\\&", "file-<>\"'\\&", "description-<>\"'\\&", null, IMarkerGenerator.SEVERITY_WARNING, false));
|
||||
|
||||
// Add to available parsers
|
||||
ErrorParserExtensionManager.setUserDefinedErrorParsersInternal(new IErrorParserNamed[] {regexErrorParser});
|
||||
assertNotNull(ErrorParserManager.getErrorParserCopy(TESTING_ID));
|
||||
// And serialize in persistent storage
|
||||
ErrorParserExtensionManager.serializeUserDefinedErrorParsers();
|
||||
}
|
||||
|
||||
{
|
||||
// Re-load from persistent storage and check it out
|
||||
ErrorParserExtensionManager.loadUserDefinedErrorParsers();
|
||||
String all = ErrorParserManager.toDelimitedString(ErrorParserManager.getErrorParserAvailableIds());
|
||||
assertTrue(all.contains(TESTING_ID));
|
||||
|
||||
IErrorParser errorParser = ErrorParserManager.getErrorParserCopy(TESTING_ID);
|
||||
assertNotNull(errorParser);
|
||||
assertTrue(errorParser instanceof RegexErrorParser);
|
||||
RegexErrorParser regexErrorParser = (RegexErrorParser)errorParser;
|
||||
assertEquals(TESTING_ID, regexErrorParser.getId());
|
||||
assertEquals(TESTING_NAME, regexErrorParser.getName());
|
||||
|
||||
RegexErrorPattern[] errorPatterns = regexErrorParser.getPatterns();
|
||||
assertEquals(1, errorPatterns.length);
|
||||
assertEquals(TESTING_REGEX, errorPatterns[0].getPattern());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that default parser IDs are stored properly.
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testSerializeDefaultErrorParserIds() throws Exception {
|
||||
final String[] testingDefaultErrorParserIds = {
|
||||
"org.eclipse.cdt.core.test.errorparser0",
|
||||
"org.eclipse.cdt.core.test.errorparser1",
|
||||
"org.eclipse.cdt.core.test.errorparser2",
|
||||
};
|
||||
final String TESTING_IDS = ErrorParserManager.toDelimitedString(testingDefaultErrorParserIds);
|
||||
final String DEFAULT_IDS = ErrorParserManager.toDelimitedString(ErrorParserManager.getDefaultErrorParserIds());
|
||||
|
||||
{
|
||||
// setDefaultErrorParserIds
|
||||
ErrorParserExtensionManager.setDefaultErrorParserIdsInternal(testingDefaultErrorParserIds);
|
||||
|
||||
String[] defaultErrorParserIds = ErrorParserManager.getDefaultErrorParserIds();
|
||||
assertNotNull(defaultErrorParserIds);
|
||||
assertEquals(TESTING_IDS, ErrorParserManager.toDelimitedString(defaultErrorParserIds));
|
||||
|
||||
// serialize them
|
||||
ErrorParserExtensionManager.serializeDefaultErrorParserIds();
|
||||
}
|
||||
|
||||
{
|
||||
// Remove from internal list
|
||||
ErrorParserExtensionManager.setDefaultErrorParserIdsInternal(null);
|
||||
assertEquals(DEFAULT_IDS, ErrorParserManager.toDelimitedString(ErrorParserManager.getDefaultErrorParserIds()));
|
||||
}
|
||||
|
||||
{
|
||||
// Re-load from persistent storage and check it out
|
||||
ErrorParserExtensionManager.loadDefaultErrorParserIds();
|
||||
|
||||
String[] defaultErrorParserIds = ErrorParserManager.getDefaultErrorParserIds();
|
||||
assertNotNull(defaultErrorParserIds);
|
||||
assertEquals(TESTING_IDS, ErrorParserManager.toDelimitedString(defaultErrorParserIds));
|
||||
}
|
||||
|
||||
{
|
||||
// Reset IDs and serialize
|
||||
ErrorParserExtensionManager.setDefaultErrorParserIdsInternal(null);
|
||||
ErrorParserExtensionManager.serializeDefaultErrorParserIds();
|
||||
|
||||
// Check that default IDs are loaded
|
||||
ErrorParserExtensionManager.loadDefaultErrorParserIds();
|
||||
String[] defaultErrorParserIds = ErrorParserManager.getDefaultErrorParserIds();
|
||||
assertNotNull(defaultErrorParserIds);
|
||||
assertEquals(DEFAULT_IDS, ErrorParserManager.toDelimitedString(defaultErrorParserIds));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test retrieval of error parser, clone() and equals().
|
||||
*
|
||||
* @throws Exception...
|
||||
*/
|
||||
public void testGetErrorParserCopy() throws Exception {
|
||||
{
|
||||
IErrorParserNamed clone1 = ErrorParserManager.getErrorParserCopy(REGEX_ERRORPARSER_ID);
|
||||
IErrorParserNamed clone2 = ErrorParserManager.getErrorParserCopy(REGEX_ERRORPARSER_ID);
|
||||
assertEquals(clone1, clone2);
|
||||
assertNotSame(clone1, clone2);
|
||||
}
|
||||
{
|
||||
IErrorParserNamed clone1 = ErrorParserManager.getErrorParserCopy(GCC_ERRORPARSER_ID);
|
||||
IErrorParserNamed clone2 = ErrorParserManager.getErrorParserCopy(GCC_ERRORPARSER_ID);
|
||||
assertEquals(clone1, clone2);
|
||||
assertNotSame(clone1, clone2);
|
||||
|
||||
assertTrue(clone1 instanceof ErrorParserNamedWrapper);
|
||||
assertTrue(clone2 instanceof ErrorParserNamedWrapper);
|
||||
IErrorParser gccClone1 = ((ErrorParserNamedWrapper)clone1).getErrorParser();
|
||||
IErrorParser gccClone2 = ((ErrorParserNamedWrapper)clone2).getErrorParser();
|
||||
assertNotSame(clone1, clone2);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -159,4 +159,21 @@
|
|||
</run>
|
||||
</filesystem>
|
||||
</extension>
|
||||
<extension
|
||||
id="RegexErrorParserId"
|
||||
name="Test Plugin RegexErrorParser"
|
||||
point="org.eclipse.cdt.core.ErrorParser">
|
||||
<errorparser
|
||||
id="org.eclipse.cdt.core.tests.RegexErrorParserId"
|
||||
name="Test Plugin RegexErrorParser">
|
||||
<pattern
|
||||
description-expr="$3"
|
||||
eat-processed-line="true"
|
||||
file-expr="$1"
|
||||
line-expr="$2"
|
||||
regex="(.*):(.*):regex (.*)"
|
||||
severity="Error">
|
||||
</pattern>
|
||||
</errorparser>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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 -->
|
||||
<!-- =================================================================================== -->
|
||||
|
|
|
@ -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 <samp>org.eclipse.cdt.core.IErrorParser</samp> 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 "pattern" to configure RegexErrorParser.
|
||||
</documentation>
|
||||
</annotation>
|
||||
<complexType>
|
||||
<attribute name="severity" use="required">
|
||||
<annotation>
|
||||
<documentation>
|
||||
Attribute "severity" specifies which severity should be used to display the marker in Problems View. There are 3 levels of severity, "Error", "Warning" and "Info". "Ignore" 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>
|
||||
"Replacement" expression composed from capturing groups defined in regex to define the file.
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="line-expr" type="string">
|
||||
<annotation>
|
||||
<documentation>
|
||||
"Replacement" 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>
|
||||
"Replacement" expression composed from capturing groups defined in regex to define the description (i.e. "$1: $2"). It is possible to specify more than one capturing group in such expression.
|
||||
</documentation>
|
||||
</annotation>
|
||||
</attribute>
|
||||
<attribute name="variable-expr" type="string">
|
||||
<annotation>
|
||||
<documentation>
|
||||
"Replacement" 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. "No" 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 {<br/>
|
|||
<documentation>
|
||||
Plug-ins that want to extend this extension point must implement <samp>org.eclipse.cdt.core.IErrorParser</samp> interface.
|
||||
<br/>
|
||||
It is recommended to extend <samp>org.eclipse.cdt.core.errorparsers.AbstractErrorParser</samp> for most cases.
|
||||
For most cases it is sufficient to configure RegexErrorParser which is provided by default.
|
||||
Another good choice is to extend <samp>org.eclipse.cdt.core.errorparsers.AbstractErrorParser</samp> as done in the example.
|
||||
<br/>
|
||||
ErrorParsers dealing with multi-line messages should implement <samp>org.eclipse.cdt.core.IErrorParser2</samp> interface.
|
||||
</documentation>
|
||||
|
@ -132,7 +221,6 @@ All rights reserved. This program and the accompanying materials<br/>
|
|||
are made available under the terms of the Eclipse Public License v1.0<br/>
|
||||
which accompanies this distribution, and is available at<br/>
|
||||
http://www.eclipse.org/legal/epl-v10.html<br/>
|
||||
|
||||
</documentation>
|
||||
</annotation>
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
@ -325,6 +347,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.
|
||||
* Otherwise returns {@code null}.
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2009 Andrew Gvozdev 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 - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.ui.dialogs;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
|
||||
/**
|
||||
* The IInputStatusValidator is the interface for IStatus validators.
|
||||
*/
|
||||
public interface IInputStatusValidator {
|
||||
/**
|
||||
* Validates the given string. Returns the status with an error/warning/info message to display if the new
|
||||
* text fails validation.
|
||||
*
|
||||
* @param newText
|
||||
* the text to check for validity
|
||||
*
|
||||
* @return {@link IStatus} object. For the purpose of validation severity and message are considered.
|
||||
* <li/>{@link Status#OK_STATUS} or any {@link IStatus#OK} to indicate no error.
|
||||
* <li/>{@link IStatus#ERROR} indicates an error.
|
||||
* <li/>{@link IStatus#WARNING} indicates a warning.
|
||||
* <li/>{@link IStatus#INFO} indicates an informational message.
|
||||
*/
|
||||
public IStatus isValid(String newText);
|
||||
}
|
|
@ -0,0 +1,208 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2009 Andrew Gvozdev 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 - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.internal.ui.dialogs;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.jface.dialogs.IDialogConstants;
|
||||
import org.eclipse.jface.dialogs.StatusDialog;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.ModifyEvent;
|
||||
import org.eclipse.swt.events.ModifyListener;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Label;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.swt.widgets.Text;
|
||||
|
||||
/**
|
||||
* An input dialog for soliciting an input string from the user.
|
||||
* The string can be validated. In case of problem error/warning/info message
|
||||
* is shown in status line and decorated with appropriate status icon.
|
||||
* <p>
|
||||
* This concrete dialog class can be instantiated as is, or further subclassed as required.
|
||||
* </p>
|
||||
*/
|
||||
public class InputStatusDialog extends StatusDialog {
|
||||
/**
|
||||
* The title of the dialog.
|
||||
*/
|
||||
private String title;
|
||||
|
||||
/**
|
||||
* The message to display, or <code>null</code> if none.
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* The input value; the empty string by default.
|
||||
*/
|
||||
private String value = "";//$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* The input validator, or <code>null</code> if none.
|
||||
*/
|
||||
private IInputStatusValidator validator;
|
||||
|
||||
/**
|
||||
* Input text widget.
|
||||
*/
|
||||
private Text text;
|
||||
|
||||
/**
|
||||
* Creates an input dialog with OK and Cancel buttons. Note that the dialog
|
||||
* will have no visual representation (no widgets) until it is told to open.
|
||||
* <p>
|
||||
* Note that the <code>open</code> method blocks for input dialogs.
|
||||
* </p>
|
||||
*
|
||||
* @param parentShell
|
||||
* the parent shell, or <code>null</code> to create a top-level
|
||||
* shell
|
||||
* @param dialogTitle
|
||||
* the dialog title, or <code>null</code> if none
|
||||
* @param dialogMessage
|
||||
* the dialog message, or <code>null</code> if none
|
||||
* @param initialValue
|
||||
* the initial input value, or <code>null</code> if none
|
||||
* (equivalent to the empty string)
|
||||
* @param validator
|
||||
* an input validator, or <code>null</code> if none
|
||||
* For a validator, following return statuses are recognized:
|
||||
* <li/>{@link Status#OK_STATUS} or any {@link IStatus#OK} to indicate no error.
|
||||
* <li/>{@link IStatus#ERROR} indicates an error.
|
||||
* <li/>{@link IStatus#WARNING} indicates a warning.
|
||||
* <li/>{@link IStatus#INFO} indicates an informational message
|
||||
*/
|
||||
public InputStatusDialog(Shell parentShell, String dialogTitle, String dialogMessage,
|
||||
String initialValue, IInputStatusValidator validator) {
|
||||
super(parentShell);
|
||||
this.title = dialogTitle;
|
||||
if (dialogMessage == null) {
|
||||
this.message = ""; //$NON-NLS-1$
|
||||
} else {
|
||||
this.message = dialogMessage;
|
||||
}
|
||||
if (initialValue == null) {
|
||||
this.value = ""; //$NON-NLS-1$
|
||||
} else {
|
||||
this.value = initialValue;
|
||||
}
|
||||
this.validator = validator;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc) Method declared on Dialog.
|
||||
*/
|
||||
@Override
|
||||
protected void buttonPressed(int buttonId) {
|
||||
if (buttonId == IDialogConstants.OK_ID) {
|
||||
value = text.getText();
|
||||
} else {
|
||||
value = null;
|
||||
}
|
||||
super.buttonPressed(buttonId);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
|
||||
*/
|
||||
@Override
|
||||
protected void configureShell(Shell shell) {
|
||||
super.configureShell(shell);
|
||||
if (title != null) {
|
||||
shell.setText(title);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Control createDialogArea(Composite parent) {
|
||||
Composite composite = (Composite) super.createDialogArea(parent);
|
||||
|
||||
Label label = new Label(composite, SWT.WRAP);
|
||||
label.setText(message);
|
||||
GridData data = new GridData(GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL
|
||||
| GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_CENTER);
|
||||
data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
|
||||
label.setLayoutData(data);
|
||||
label.setFont(parent.getFont());
|
||||
|
||||
text = new Text(composite, getInputTextStyle());
|
||||
text.setLayoutData(new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL));
|
||||
text.addModifyListener(new ModifyListener() {
|
||||
public void modifyText(ModifyEvent e) {
|
||||
validateInput();
|
||||
}
|
||||
});
|
||||
text.setFocus();
|
||||
if (value != null) {
|
||||
text.setText(value);
|
||||
text.selectAll();
|
||||
}
|
||||
|
||||
applyDialogFont(composite);
|
||||
|
||||
return composite;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the text area.
|
||||
*
|
||||
* @return the text area
|
||||
*/
|
||||
protected Text getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the validator.
|
||||
*
|
||||
* @return the validator
|
||||
*/
|
||||
protected IInputStatusValidator getValidator() {
|
||||
return validator;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the input.
|
||||
* <p>
|
||||
* The default implementation of this framework method delegates the request to the supplied input
|
||||
* validator object; if it finds the input invalid, the error message is displayed in the dialog's message
|
||||
* line. This hook method is called whenever the text changes in the input field.
|
||||
* </p>
|
||||
*/
|
||||
protected void validateInput() {
|
||||
IStatus status = Status.OK_STATUS;
|
||||
if (validator != null) {
|
||||
status = validator.isValid(text.getText());
|
||||
}
|
||||
updateStatus(status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the style bits that should be used for the input text field. Defaults to a single line entry.
|
||||
* Subclasses may override.
|
||||
*
|
||||
* @return the integer style bits that should be used when creating the input text
|
||||
*
|
||||
*/
|
||||
protected int getInputTextStyle() {
|
||||
return SWT.SINGLE | SWT.BORDER;
|
||||
}
|
||||
|
||||
}
|
|
@ -57,6 +57,52 @@ public class DialogsMessages extends NLS {
|
|||
public static String DocCommentOwnerBlock_SelectDocToolDescription;
|
||||
public static String DocCommentOwnerCombo_None;
|
||||
public static String DocCommentOwnerComposite_DocumentationToolGroupTitle;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_ConsumeNo;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_ConsumeYes;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_DescriptionColumn;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_EatColumn;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_FileColumn;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_LineColumn;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_LinkToPreferencesMessage;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_Pattern_Column;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_SeverityColumn;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_SeverityError;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_SeverityIgnore;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_SeverityInfo;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_SeverityWarning;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_Title;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_TooltipConsume;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_TooltipDescription;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_TooltipFile;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_TooltipLine;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_TooltipPattern;
|
||||
/** @since 5.2 */
|
||||
public static String RegexErrorParserOptionPage_TooltipSeverity;
|
||||
/** @since 5.2 */
|
||||
public static String RegularExpression_EmptyPattern;
|
||||
/** @since 5.2 */
|
||||
public static String RegularExpression_Validate;
|
||||
/** @since 5.2 */
|
||||
public static String RegularExpression_Enter;
|
||||
|
||||
static {
|
||||
// initialize resource bundle
|
||||
|
|
|
@ -41,3 +41,26 @@ IndexerStrategyBlock_immediateUpdate=Update index immediately after every file-s
|
|||
IndexerStrategyBlock_buildConfigGroup=Build configuration for the indexer
|
||||
IndexerStrategyBlock_activeBuildConfig=Use active build configuration
|
||||
IndexerStrategyBlock_specificBuildConfig=Use the build configuration specified in the project's indexer settings
|
||||
RegexErrorParserOptionPage_ConsumeNo=No
|
||||
RegexErrorParserOptionPage_ConsumeYes=
|
||||
RegexErrorParserOptionPage_DescriptionColumn=Description
|
||||
RegexErrorParserOptionPage_EatColumn=Consume
|
||||
RegexErrorParserOptionPage_FileColumn=File
|
||||
RegexErrorParserOptionPage_LineColumn=Line
|
||||
RegexErrorParserOptionPage_LinkToPreferencesMessage=These options are workspace-wide and can be changed in <a href="workspace">Workspace Settings</a>.
|
||||
RegexErrorParserOptionPage_Pattern_Column=Pattern
|
||||
RegexErrorParserOptionPage_SeverityColumn=Severity
|
||||
RegexErrorParserOptionPage_SeverityError=Error
|
||||
RegexErrorParserOptionPage_SeverityIgnore=Ignore
|
||||
RegexErrorParserOptionPage_SeverityInfo=Info
|
||||
RegexErrorParserOptionPage_SeverityWarning=Warning
|
||||
RegexErrorParserOptionPage_Title=Error Parser Options
|
||||
RegexErrorParserOptionPage_TooltipConsume=Use ''{0}'' to allow to re-process matching input line by other patterns
|
||||
RegexErrorParserOptionPage_TooltipDescription=Description as replacement expression (i.e. $3)
|
||||
RegexErrorParserOptionPage_TooltipFile=File as replacement expression (i.e. $1)
|
||||
RegexErrorParserOptionPage_TooltipLine=Line as replacement expression (i.e. $2)
|
||||
RegexErrorParserOptionPage_TooltipPattern=Java regular expression specifying capturing groups for 'File', 'Line' and 'Description'
|
||||
RegexErrorParserOptionPage_TooltipSeverity=Severity of marker
|
||||
RegularExpression_EmptyPattern=Empty pattern
|
||||
RegularExpression_Validate=Validate Regular Expression
|
||||
RegularExpression_Enter=Enter regular expression (use Ctrl+Space for content assist):
|
||||
|
|
|
@ -0,0 +1,752 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009, 2009 Andrew Gvozdev 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 - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.ui.dialogs;
|
||||
|
||||
import org.eclipse.core.resources.IMarker;
|
||||
import org.eclipse.core.runtime.Assert;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.jface.dialogs.Dialog;
|
||||
import org.eclipse.jface.resource.JFaceResources;
|
||||
import org.eclipse.jface.text.FindReplaceDocumentAdapterContentProposalProvider;
|
||||
import org.eclipse.jface.viewers.ArrayContentProvider;
|
||||
import org.eclipse.jface.viewers.CellEditor;
|
||||
import org.eclipse.jface.viewers.ColumnLabelProvider;
|
||||
import org.eclipse.jface.viewers.ColumnWeightData;
|
||||
import org.eclipse.jface.viewers.ComboBoxCellEditor;
|
||||
import org.eclipse.jface.viewers.EditingSupport;
|
||||
import org.eclipse.jface.viewers.TableLayout;
|
||||
import org.eclipse.jface.viewers.TableViewer;
|
||||
import org.eclipse.jface.viewers.TableViewerColumn;
|
||||
import org.eclipse.jface.viewers.TextCellEditor;
|
||||
import org.eclipse.jface.window.Window;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.graphics.Image;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Button;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Event;
|
||||
import org.eclipse.swt.widgets.Group;
|
||||
import org.eclipse.swt.widgets.Link;
|
||||
import org.eclipse.swt.widgets.Listener;
|
||||
import org.eclipse.swt.widgets.Table;
|
||||
import org.eclipse.swt.widgets.TableItem;
|
||||
import org.eclipse.ui.ISharedImages;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.dialogs.PreferencesUtil;
|
||||
import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter;
|
||||
|
||||
import com.ibm.icu.text.MessageFormat;
|
||||
|
||||
import org.eclipse.cdt.core.ErrorParserManager;
|
||||
import org.eclipse.cdt.core.IErrorParserNamed;
|
||||
import org.eclipse.cdt.core.IMarkerGenerator;
|
||||
import org.eclipse.cdt.core.errorparsers.RegexErrorParser;
|
||||
import org.eclipse.cdt.core.errorparsers.RegexErrorPattern;
|
||||
import org.eclipse.cdt.ui.newui.AbstractCPropertyTab;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.dialogs.MessageLine;
|
||||
import org.eclipse.cdt.internal.ui.util.PixelConverter;
|
||||
import org.eclipse.cdt.internal.ui.util.SWTUtil;
|
||||
import org.eclipse.cdt.internal.ui.util.TableLayoutComposite;
|
||||
|
||||
/**
|
||||
* Options page for RegexErrorParser in Error Parsers Tab of properties/preferences.
|
||||
*
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
* @since 5.2
|
||||
*/
|
||||
public final class RegexErrorParserOptionPage extends AbstractCOptionPage {
|
||||
|
||||
private static final String WORKSPACE_PREFERENCE_PAGE = "org.eclipse.cdt.make.ui.preferences.BuildSettings"; //$NON-NLS-1$
|
||||
|
||||
private static final int BUTTON_ADD = 0;
|
||||
private static final int BUTTON_DELETE = 1;
|
||||
private static final int BUTTON_MOVEUP = 2;
|
||||
private static final int BUTTON_MOVEDOWN = 3;
|
||||
|
||||
private static final String[] BUTTONS = new String[] {
|
||||
AbstractCPropertyTab.ADD_STR,
|
||||
AbstractCPropertyTab.DEL_STR,
|
||||
AbstractCPropertyTab.MOVEUP_STR,
|
||||
AbstractCPropertyTab.MOVEDOWN_STR,
|
||||
};
|
||||
|
||||
private static final String OOPS = "OOPS"; //$NON-NLS-1$
|
||||
|
||||
private Table fTable;
|
||||
private TableViewer fTableViewer;
|
||||
private Button[] fButtons = null;
|
||||
|
||||
private RegexErrorParser fErrorParser;
|
||||
private boolean fEditable;
|
||||
|
||||
/**
|
||||
* Provides generic implementation for overridden methods.
|
||||
* One purpose is to make it easier for subclasses to operate with {@link RegexErrorPattern},
|
||||
* another is to provide content assist.
|
||||
*
|
||||
*/
|
||||
private abstract class RegexPatternEditingSupport extends EditingSupport {
|
||||
private final TableViewer tableViewer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param viewer - table viewer where to provide editing support.
|
||||
* @param isFindStyle - if "find" or "replace" style for potential content assist,
|
||||
* see {@link FindReplaceDocumentAdapterContentProposalProvider}.
|
||||
*/
|
||||
public RegexPatternEditingSupport(TableViewer viewer, boolean isFindStyle) {
|
||||
super(viewer);
|
||||
tableViewer = viewer;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.jface.viewers.EditingSupport#canEdit(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected boolean canEdit(Object element) {
|
||||
return fEditable;
|
||||
}
|
||||
|
||||
/**
|
||||
* The intention of RegexPatternEditingSupport is to provide Regex content assist
|
||||
* during in-table editing. However having problems with mouse selection and
|
||||
* {@link ContentAssistCommandAdapter} using {@link FindReplaceDocumentAdapterContentProposalProvider}
|
||||
* is removed for time being. See bug 288982 for more details.
|
||||
*
|
||||
* @see org.eclipse.jface.viewers.EditingSupport#getCellEditor(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected CellEditor getCellEditor(Object element) {
|
||||
CellEditor editor = new TextCellEditor(tableViewer.getTable());
|
||||
return editor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value from {@link RegexErrorPattern}. This is column-specific value.
|
||||
*
|
||||
* @param regexErrorPattern - pattern to query.
|
||||
* @return retrieved value
|
||||
*/
|
||||
abstract protected Object getFromPattern(RegexErrorPattern regexErrorPattern);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.jface.viewers.EditingSupport#getValue(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Object getValue(Object element) {
|
||||
if (element instanceof RegexErrorPattern) {
|
||||
RegexErrorPattern regexErrorPattern = (RegexErrorPattern) element;
|
||||
return getFromPattern(regexErrorPattern);
|
||||
}
|
||||
return OOPS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set value into one of the pattern's field. Which field - it's column-specific.
|
||||
*
|
||||
* @param regexErrorPattern - pattern to set the field
|
||||
* @param value - value to set
|
||||
*/
|
||||
abstract protected void setToPattern(RegexErrorPattern regexErrorPattern, String value);
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.jface.viewers.EditingSupport#setValue(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected void setValue(Object element, Object value) {
|
||||
if (element instanceof RegexErrorPattern && (value instanceof String)) {
|
||||
String stringValue = (String) value;
|
||||
RegexErrorPattern errorPattern = (RegexErrorPattern) element;
|
||||
setToPattern(errorPattern, stringValue);
|
||||
tableViewer.update(element, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param errorparser - regex error parser for which to display options.
|
||||
* @param editable - if error parser is editable and allowed to change its patterns
|
||||
*/
|
||||
public RegexErrorParserOptionPage(RegexErrorParser errorparser, boolean editable) {
|
||||
fErrorParser = errorparser;
|
||||
fEditable = editable;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
|
||||
*/
|
||||
@Override
|
||||
public void createControl(Composite parent) {
|
||||
Group group = new Group(parent, SWT.SHADOW_ETCHED_IN);
|
||||
group.setText(DialogsMessages.RegexErrorParserOptionPage_Title);
|
||||
|
||||
GridLayout gridLayout = new GridLayout(2, true);
|
||||
gridLayout.makeColumnsEqualWidth = false;
|
||||
gridLayout.marginRight = -10;
|
||||
gridLayout.marginLeft = -4;
|
||||
group.setLayout(gridLayout);
|
||||
group.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
||||
|
||||
Composite composite = new Composite(group, SWT.NONE);
|
||||
GridLayout layout = new GridLayout();
|
||||
layout.numColumns = 2;
|
||||
layout.marginWidth = 1;
|
||||
layout.marginHeight = 1;
|
||||
layout.marginRight = 1;
|
||||
composite.setLayout(layout);
|
||||
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||
Dialog.applyDialogFont(composite);
|
||||
|
||||
if (!fEditable)
|
||||
createLinkToPreferences(composite);
|
||||
|
||||
createPatternsTable(group, composite);
|
||||
|
||||
if (fEditable) {
|
||||
createButtons(composite);
|
||||
|
||||
// TODO: remove the warning before 6.1
|
||||
MessageLine errorImageLabel = new MessageLine(composite, SWT.NONE);
|
||||
errorImageLabel.setImage(JFaceResources.getImage(Dialog.DLG_IMG_MESSAGE_WARNING));
|
||||
errorImageLabel.setText("Error Parser Options user entries may be lost on CDT update as persistence will be finalized with CDT 6.1 final release.");
|
||||
}
|
||||
|
||||
setControl(group);
|
||||
group.update();
|
||||
}
|
||||
|
||||
private void createLinkToPreferences(final Composite parent) {
|
||||
// must not be editable as error parser gets desynchronized with ErrorParsTab
|
||||
Assert.isTrue(!fEditable);
|
||||
|
||||
Link link = new Link(parent, SWT.NONE);
|
||||
link.setText(DialogsMessages.RegexErrorParserOptionPage_LinkToPreferencesMessage);
|
||||
|
||||
link.addListener(SWT.Selection, new Listener() {
|
||||
public void handleEvent(Event event) {
|
||||
// Use event.text to tell which link was used
|
||||
PreferencesUtil.createPreferenceDialogOn(parent.getShell(), WORKSPACE_PREFERENCE_PAGE, null, null).open();
|
||||
|
||||
IErrorParserNamed errorParser = ErrorParserManager.getErrorParserCopy(fErrorParser.getId());
|
||||
if (errorParser instanceof RegexErrorParser)
|
||||
fErrorParser = (RegexErrorParser) errorParser;
|
||||
else
|
||||
fErrorParser = null;
|
||||
|
||||
initializeTable();
|
||||
}
|
||||
});
|
||||
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.BOTTOM, true, false);
|
||||
gridData.horizontalSpan = 2;
|
||||
link.setLayoutData(gridData);
|
||||
}
|
||||
|
||||
private static RegexErrorPattern newDummyPattern() {
|
||||
return new RegexErrorPattern(null, null, null, null, null, IMarker.SEVERITY_ERROR, true);
|
||||
}
|
||||
|
||||
private static String severityToString(int severity) {
|
||||
switch (severity) {
|
||||
case IMarkerGenerator.SEVERITY_INFO:
|
||||
return DialogsMessages.RegexErrorParserOptionPage_SeverityInfo;
|
||||
case IMarkerGenerator.SEVERITY_WARNING:
|
||||
return DialogsMessages.RegexErrorParserOptionPage_SeverityWarning;
|
||||
case IMarkerGenerator.SEVERITY_ERROR_BUILD:
|
||||
case IMarkerGenerator.SEVERITY_ERROR_RESOURCE:
|
||||
return DialogsMessages.RegexErrorParserOptionPage_SeverityError;
|
||||
}
|
||||
return DialogsMessages.RegexErrorParserOptionPage_SeverityIgnore;
|
||||
}
|
||||
|
||||
private void initializeTable() {
|
||||
RegexErrorPattern[] errorParserPatterns = fErrorParser!=null
|
||||
? errorParserPatterns = fErrorParser.getPatterns()
|
||||
: new RegexErrorPattern[0];
|
||||
|
||||
int len = errorParserPatterns.length;
|
||||
int newLen = len;
|
||||
|
||||
RegexErrorPattern[] tablePatterns = new RegexErrorPattern[newLen];
|
||||
System.arraycopy(errorParserPatterns, 0, tablePatterns, 0, len);
|
||||
|
||||
fTableViewer.setInput(tablePatterns);
|
||||
fTableViewer.refresh();
|
||||
}
|
||||
|
||||
private void createPatternsTable(Group group, Composite parent) {
|
||||
TableLayoutComposite tableLayouter = new TableLayoutComposite(parent, SWT.NONE);
|
||||
tableLayouter.addColumnData(new ColumnWeightData(10, true)); // severity
|
||||
tableLayouter.addColumnData(new ColumnWeightData(40, true)); // pattern
|
||||
tableLayouter.addColumnData(new ColumnWeightData(10, true)); // file
|
||||
tableLayouter.addColumnData(new ColumnWeightData(10, true)); // line
|
||||
tableLayouter.addColumnData(new ColumnWeightData(15, true)); // description
|
||||
tableLayouter.addColumnData(new ColumnWeightData(10, true)); // eat line
|
||||
|
||||
int style= SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER;
|
||||
if (fEditable) {
|
||||
style = style | SWT.FULL_SELECTION;
|
||||
}
|
||||
fTable = new Table(tableLayouter, style);
|
||||
fTable.setHeaderVisible(true);
|
||||
fTable.setLinesVisible(true);
|
||||
fTable.setEnabled(fEditable);
|
||||
|
||||
GridData gridData = new GridData(GridData.FILL_BOTH);
|
||||
gridData.heightHint = SWTUtil.getTableHeightHint(fTable, 10);
|
||||
gridData.widthHint = new PixelConverter(group).convertWidthInCharsToPixels(100);
|
||||
tableLayouter.setLayoutData(gridData);
|
||||
fTable.setLayout(new TableLayout());
|
||||
|
||||
fTable.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
updateButtons();
|
||||
}
|
||||
});
|
||||
|
||||
fTableViewer = new TableViewer(fTable);
|
||||
fTableViewer.setUseHashlookup(true);
|
||||
fTableViewer.setContentProvider(new ArrayContentProvider());
|
||||
|
||||
createSeverityColumn();
|
||||
createPatternColumn();
|
||||
createFileColumn();
|
||||
createLineColumn();
|
||||
createDescriptionColumn();
|
||||
createEatLineColumn();
|
||||
|
||||
initializeTable();
|
||||
}
|
||||
|
||||
private void createSeverityColumn() {
|
||||
TableViewerColumn columnViewer = new TableViewerColumn(fTableViewer, SWT.NONE);
|
||||
columnViewer.getColumn().setText(DialogsMessages.RegexErrorParserOptionPage_SeverityColumn);
|
||||
columnViewer.getColumn().setResizable(true);
|
||||
columnViewer.getColumn().setToolTipText(DialogsMessages.RegexErrorParserOptionPage_TooltipSeverity);
|
||||
columnViewer.setLabelProvider(new ColumnLabelProvider() {
|
||||
final ISharedImages images = PlatformUI.getWorkbench().getSharedImages();
|
||||
|
||||
@Override
|
||||
public Image getImage(Object element) {
|
||||
if (element instanceof RegexErrorPattern) {
|
||||
RegexErrorPattern regexErrorPattern = (RegexErrorPattern) element;
|
||||
switch (regexErrorPattern.getSeverity()) {
|
||||
case IMarkerGenerator.SEVERITY_INFO:
|
||||
return images.getImage(ISharedImages.IMG_OBJS_INFO_TSK);
|
||||
case IMarkerGenerator.SEVERITY_WARNING:
|
||||
return images.getImage(ISharedImages.IMG_OBJS_WARN_TSK);
|
||||
case IMarkerGenerator.SEVERITY_ERROR_BUILD:
|
||||
case IMarkerGenerator.SEVERITY_ERROR_RESOURCE:
|
||||
return images.getImage(ISharedImages.IMG_OBJS_ERROR_TSK);
|
||||
case RegexErrorPattern.SEVERITY_SKIP:
|
||||
return images.getImage(ISharedImages.IMG_ELCL_REMOVE_DISABLED);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText(Object element) {
|
||||
if (element instanceof RegexErrorPattern) {
|
||||
RegexErrorPattern regex = (RegexErrorPattern) element;
|
||||
return severityToString(regex.getSeverity());
|
||||
}
|
||||
return severityToString(RegexErrorPattern.SEVERITY_SKIP);
|
||||
}
|
||||
});
|
||||
columnViewer.setEditingSupport(new EditingSupport(fTableViewer) {
|
||||
final String[] severityComboBoxArray = new String[] {
|
||||
severityToString(IMarkerGenerator.SEVERITY_ERROR_RESOURCE),
|
||||
severityToString(IMarkerGenerator.SEVERITY_WARNING),
|
||||
severityToString(IMarkerGenerator.SEVERITY_INFO),
|
||||
severityToString(RegexErrorPattern.SEVERITY_SKIP),
|
||||
};
|
||||
|
||||
private int severityToIndex(int severity) {
|
||||
String strSeverity = severityToString(severity);
|
||||
for (int i = 0; i < severityComboBoxArray.length; i++) {
|
||||
if (strSeverity.equals(severityComboBoxArray[i]))
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int indexToSeverity(int index) {
|
||||
String strCombo = severityComboBoxArray[index];
|
||||
for (int i = 0; i < severityComboBoxArray.length; i++) {
|
||||
if (severityToString(i).equals(strCombo))
|
||||
return i;
|
||||
}
|
||||
return RegexErrorPattern.SEVERITY_SKIP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canEdit(Object element) {
|
||||
return (element instanceof RegexErrorPattern) && fEditable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CellEditor getCellEditor(Object element) {
|
||||
return new ComboBoxCellEditor(fTableViewer.getTable(), severityComboBoxArray, SWT.READ_ONLY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getValue(Object element) {
|
||||
if (element instanceof RegexErrorPattern)
|
||||
return severityToIndex(((RegexErrorPattern) element).getSeverity());
|
||||
return RegexErrorPattern.SEVERITY_SKIP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setValue(Object element, Object value) {
|
||||
if (element instanceof RegexErrorPattern && (value instanceof Integer)) {
|
||||
((RegexErrorPattern) element).setSeverity(indexToSeverity(((Integer) value).intValue()));
|
||||
fTableViewer.update(element, null);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void createPatternColumn() {
|
||||
TableViewerColumn columnViewer = new TableViewerColumn(fTableViewer, SWT.NONE);
|
||||
columnViewer.getColumn().setText(DialogsMessages.RegexErrorParserOptionPage_Pattern_Column);
|
||||
columnViewer.getColumn().setResizable(true);
|
||||
columnViewer.getColumn().setToolTipText(DialogsMessages.RegexErrorParserOptionPage_TooltipPattern);
|
||||
columnViewer.setLabelProvider(new ColumnLabelProvider() {
|
||||
|
||||
@Override
|
||||
public String getText(Object element) {
|
||||
if (element instanceof RegexErrorPattern) {
|
||||
RegexErrorPattern regex = (RegexErrorPattern) element;
|
||||
String pattern = regex.getPattern();
|
||||
return pattern;
|
||||
}
|
||||
return OOPS;
|
||||
}
|
||||
});
|
||||
|
||||
columnViewer.setEditingSupport(new RegexPatternEditingSupport(fTableViewer, true) {
|
||||
@Override
|
||||
protected Object getFromPattern(RegexErrorPattern regexErrorPattern) {
|
||||
return regexErrorPattern.getPattern();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setToPattern(RegexErrorPattern regexErrorPattern, String value) {
|
||||
if (!fEditable)
|
||||
return;
|
||||
try{
|
||||
regexErrorPattern.setPattern(value);
|
||||
} catch (Exception e) {
|
||||
// to avoid recursive edits. the dialog is needed to ensure valid pattern on losing focus.
|
||||
// this looks ugly and likely incorrect
|
||||
fEditable = false;
|
||||
RegularExpressionStatusDialog dialog= new RegularExpressionStatusDialog(getShell(), value);
|
||||
if (dialog.open() == Window.OK) {
|
||||
regexErrorPattern.setPattern(dialog.getValue());
|
||||
}
|
||||
fEditable = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createFileColumn() {
|
||||
TableViewerColumn columnViewer = new TableViewerColumn(fTableViewer, SWT.NONE);
|
||||
columnViewer.getColumn().setText(DialogsMessages.RegexErrorParserOptionPage_FileColumn);
|
||||
columnViewer.getColumn().setToolTipText(DialogsMessages.RegexErrorParserOptionPage_TooltipFile);
|
||||
columnViewer.getColumn().setResizable(true);
|
||||
columnViewer.setLabelProvider(new ColumnLabelProvider() {
|
||||
|
||||
@Override
|
||||
public String getText(Object element) {
|
||||
if (element instanceof RegexErrorPattern) {
|
||||
RegexErrorPattern regex = (RegexErrorPattern) element;
|
||||
return regex.getFileExpression();
|
||||
}
|
||||
return OOPS;
|
||||
}
|
||||
});
|
||||
columnViewer.setEditingSupport(new RegexPatternEditingSupport(fTableViewer, false) {
|
||||
@Override
|
||||
protected Object getFromPattern(RegexErrorPattern regexErrorPattern) {
|
||||
return regexErrorPattern.getFileExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setToPattern(RegexErrorPattern regexErrorPattern, String value) {
|
||||
regexErrorPattern.setFileExpression(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createLineColumn() {
|
||||
TableViewerColumn columnViewer = new TableViewerColumn(fTableViewer, SWT.NONE);
|
||||
columnViewer.getColumn().setText(DialogsMessages.RegexErrorParserOptionPage_LineColumn);
|
||||
columnViewer.getColumn().setResizable(true);
|
||||
columnViewer.getColumn().setToolTipText(DialogsMessages.RegexErrorParserOptionPage_TooltipLine);
|
||||
columnViewer.setLabelProvider(new ColumnLabelProvider() {
|
||||
|
||||
@Override
|
||||
public String getText(Object element) {
|
||||
if (element instanceof RegexErrorPattern) {
|
||||
RegexErrorPattern regex = (RegexErrorPattern) element;
|
||||
return regex.getLineExpression();
|
||||
}
|
||||
return OOPS;
|
||||
}
|
||||
});
|
||||
columnViewer.setEditingSupport(new RegexPatternEditingSupport(fTableViewer, false) {
|
||||
@Override
|
||||
protected Object getFromPattern(RegexErrorPattern regexErrorPattern) {
|
||||
return regexErrorPattern.getLineExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setToPattern(RegexErrorPattern regexErrorPattern, String value) {
|
||||
regexErrorPattern.setLineExpression(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createDescriptionColumn() {
|
||||
TableViewerColumn columnViewer = new TableViewerColumn(fTableViewer, SWT.NONE);
|
||||
columnViewer.getColumn().setText(DialogsMessages.RegexErrorParserOptionPage_DescriptionColumn);
|
||||
columnViewer.getColumn().setResizable(true);
|
||||
columnViewer.getColumn().setToolTipText(DialogsMessages.RegexErrorParserOptionPage_TooltipDescription);
|
||||
columnViewer.setLabelProvider(new ColumnLabelProvider() {
|
||||
|
||||
@Override
|
||||
public String getText(Object element) {
|
||||
if (element instanceof RegexErrorPattern) {
|
||||
RegexErrorPattern regex = (RegexErrorPattern) element;
|
||||
return regex.getDescriptionExpression();
|
||||
}
|
||||
return OOPS;
|
||||
}
|
||||
});
|
||||
columnViewer.setEditingSupport(new RegexPatternEditingSupport(fTableViewer, false) {
|
||||
@Override
|
||||
protected Object getFromPattern(RegexErrorPattern regexErrorPattern) {
|
||||
return regexErrorPattern.getDescriptionExpression();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setToPattern(RegexErrorPattern regexErrorPattern, String value) {
|
||||
regexErrorPattern.setDescriptionExpression(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void createEatLineColumn() {
|
||||
final String EAT_NO = DialogsMessages.RegexErrorParserOptionPage_ConsumeNo;
|
||||
final String EAT_YES = DialogsMessages.RegexErrorParserOptionPage_ConsumeYes;
|
||||
|
||||
final String[] eatLineComboBoxArray = new String[] { EAT_YES, EAT_NO, };
|
||||
final int EAT_YES_INDEX = 0;
|
||||
final int EAT_NO_INDEX = 1;
|
||||
|
||||
TableViewerColumn columnViewer = new TableViewerColumn(fTableViewer, SWT.NONE);
|
||||
columnViewer.getColumn().setText(DialogsMessages.RegexErrorParserOptionPage_EatColumn);
|
||||
columnViewer.getColumn().setResizable(true);
|
||||
|
||||
String message = MessageFormat.format(DialogsMessages.RegexErrorParserOptionPage_TooltipConsume, new Object[] { EAT_NO });
|
||||
columnViewer.getColumn().setToolTipText(message);
|
||||
columnViewer.setLabelProvider(new ColumnLabelProvider() {
|
||||
|
||||
@Override
|
||||
public String getText(Object element) {
|
||||
if (element instanceof RegexErrorPattern) {
|
||||
RegexErrorPattern regex = (RegexErrorPattern) element;
|
||||
if (!regex.isEatProcessedLine())
|
||||
return EAT_NO;
|
||||
}
|
||||
return EAT_YES;
|
||||
}
|
||||
});
|
||||
columnViewer.setEditingSupport(new EditingSupport(fTableViewer) {
|
||||
@Override
|
||||
protected boolean canEdit(Object element) {
|
||||
return (element instanceof RegexErrorPattern) && fEditable;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CellEditor getCellEditor(Object element) {
|
||||
return new ComboBoxCellEditor(fTableViewer.getTable(), eatLineComboBoxArray, SWT.READ_ONLY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object getValue(Object element) {
|
||||
if (element instanceof RegexErrorPattern)
|
||||
if (!((RegexErrorPattern) element).isEatProcessedLine())
|
||||
return EAT_NO_INDEX;
|
||||
return EAT_YES_INDEX;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setValue(Object element, Object value) {
|
||||
if ((element instanceof RegexErrorPattern) && (value instanceof Integer)) {
|
||||
((RegexErrorPattern) element).setEatProcessedLine((Integer) value != EAT_NO_INDEX);
|
||||
fTableViewer.update(element, null);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
private void createButtons(Composite parent) {
|
||||
Composite composite = new Composite(parent, SWT.NONE);
|
||||
composite.setLayoutData(new GridData(GridData.FILL_VERTICAL));
|
||||
composite.setLayout(new GridLayout(1, false));
|
||||
|
||||
fButtons = new Button[BUTTONS.length];
|
||||
for (int i = 0; i < BUTTONS.length; i++) {
|
||||
fButtons[i] = new Button(composite, SWT.PUSH);
|
||||
GridData gridData = new GridData(SWT.FILL, SWT.CENTER, false, false);
|
||||
gridData.minimumWidth = 80;
|
||||
|
||||
if (BUTTONS[i] != null) {
|
||||
fButtons[i].setText(BUTTONS[i]);
|
||||
fButtons[i].setEnabled(false);
|
||||
} else {
|
||||
// no button, but placeholder
|
||||
fButtons[i].setVisible(false);
|
||||
fButtons[i].setEnabled(false);
|
||||
gridData.heightHint = 10;
|
||||
}
|
||||
|
||||
fButtons[i].setLayoutData(gridData);
|
||||
fButtons[i].addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent event) {
|
||||
for (int i=0; i<fButtons.length; i++) {
|
||||
if (fButtons[i].equals(event.widget)) {
|
||||
buttonPressed(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
private void updateButtons() {
|
||||
if (fButtons!=null) {
|
||||
int pos = fTable.getSelectionIndex();
|
||||
int count = fTable.getItemCount();
|
||||
int last = count-1;
|
||||
boolean selected = pos>=0 && pos<=last;
|
||||
|
||||
fButtons[BUTTON_ADD].setEnabled(true);
|
||||
fButtons[BUTTON_DELETE].setEnabled(selected);
|
||||
fButtons[BUTTON_MOVEUP].setEnabled(selected && pos != 0);
|
||||
fButtons[BUTTON_MOVEDOWN].setEnabled(selected && pos != last);
|
||||
}
|
||||
}
|
||||
|
||||
private void buttonPressed (int button) {
|
||||
switch (button) {
|
||||
case BUTTON_ADD:
|
||||
addErrorPattern();
|
||||
break;
|
||||
case BUTTON_DELETE:
|
||||
deleteErrorPattern();
|
||||
break;
|
||||
case BUTTON_MOVEUP:
|
||||
moveItem(true);
|
||||
break;
|
||||
case BUTTON_MOVEDOWN:
|
||||
moveItem(false);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
private void addErrorPattern() {
|
||||
int pos = fTable.getSelectionIndex();
|
||||
int last = fTable.getItemCount()-1;
|
||||
if (pos<0 || pos>last)
|
||||
pos = last;
|
||||
|
||||
int newPos = pos + 1;
|
||||
fTableViewer.insert(newDummyPattern(), newPos);
|
||||
fTable.setSelection(newPos);
|
||||
}
|
||||
|
||||
private void deleteErrorPattern() {
|
||||
int pos = fTable.getSelectionIndex();
|
||||
int last = fTable.getItemCount()-1;
|
||||
|
||||
if (pos>=0 && pos<=last) {
|
||||
fTableViewer.remove(fTableViewer.getElementAt(pos));
|
||||
fTable.setSelection(pos);
|
||||
}
|
||||
}
|
||||
|
||||
private void moveItem(boolean up) {
|
||||
int pos = fTable.getSelectionIndex();
|
||||
int count = fTable.getItemCount();
|
||||
int last = count-1;
|
||||
boolean selected = pos>=0 && pos<=last;
|
||||
|
||||
if (!selected || (up && pos==0) || (!up && pos==last))
|
||||
return;
|
||||
|
||||
Object item = fTableViewer.getElementAt(pos);
|
||||
fTableViewer.remove(item);
|
||||
int newPos = up ? pos-1 : pos+1;
|
||||
fTableViewer.insert(item, newPos);
|
||||
fTable.setSelection(newPos);
|
||||
}
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.cdt.ui.dialogs.ICOptionPage#performApply(org.eclipse.core.runtime.IProgressMonitor)
|
||||
*/
|
||||
@Override
|
||||
public void performApply(IProgressMonitor monitor) throws CoreException {
|
||||
if (fErrorParser!=null && fEditable) {
|
||||
fErrorParser.clearPatterns();
|
||||
for (TableItem tableItem : fTable.getItems()) {
|
||||
Object item = tableItem.getData();
|
||||
if (item instanceof RegexErrorPattern) {
|
||||
fErrorParser.addPattern((RegexErrorPattern)item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.eclipse.cdt.ui.dialogs.ICOptionPage#performDefaults()
|
||||
*/
|
||||
@Override
|
||||
public void performDefaults() {
|
||||
// ErrorParsTas.performDefaults() will do all the work
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009,2009 Andrew Gvozdev 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 - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
|
||||
package org.eclipse.cdt.ui.dialogs;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.jface.fieldassist.TextContentAdapter;
|
||||
import org.eclipse.jface.text.FindReplaceDocumentAdapterContentProposalProvider;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Control;
|
||||
import org.eclipse.swt.widgets.Shell;
|
||||
import org.eclipse.ui.fieldassist.ContentAssistCommandAdapter;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.dialogs.IInputStatusValidator;
|
||||
import org.eclipse.cdt.internal.ui.dialogs.InputStatusDialog;
|
||||
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
|
||||
|
||||
/**
|
||||
* Input Dialog for validating regular expression syntax.
|
||||
*
|
||||
* @since 5.2
|
||||
*/
|
||||
public class RegularExpressionStatusDialog extends InputStatusDialog {
|
||||
private static final IInputStatusValidator fValidator = new IInputStatusValidator() {
|
||||
public IStatus isValid(String newText) {
|
||||
StatusInfo status = new StatusInfo();
|
||||
if (newText.length() == 0) {
|
||||
status.setWarning(DialogsMessages.RegularExpression_EmptyPattern);
|
||||
} else {
|
||||
try {
|
||||
Pattern.compile(newText);
|
||||
} catch (Exception e) {
|
||||
// only first line of PatternSyntaxException is really descriptive
|
||||
status.setError(e.getMessage().split("[\n\r]", 2)[0]); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param shell - the parent shell, or <code>null</code> to create a top-level shell
|
||||
* @param initialValue the initial input value, or <code>null</code> if none
|
||||
* (equivalent to the empty string)
|
||||
*/
|
||||
public RegularExpressionStatusDialog(Shell shell, String initialValue) {
|
||||
super(shell, DialogsMessages.RegularExpression_Validate,
|
||||
DialogsMessages.RegularExpression_Enter,
|
||||
initialValue, fValidator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param shell - the parent shell, or <code>null</code> to create a top-level shell
|
||||
* @param dialogTitle - the dialog title, or <code>null</code> if none
|
||||
* @param dialogMessage - the dialog message, or <code>null</code> if none
|
||||
* @param initialValue the initial input value, or <code>null</code> if none
|
||||
* (equivalent to the empty string)
|
||||
*/
|
||||
public RegularExpressionStatusDialog(Shell shell, String dialogTitle, String dialogMessage, String initialValue) {
|
||||
super(shell, dialogTitle, dialogMessage, initialValue, fValidator);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.internal.ui.dialogs.InputStatusDialog#createDialogArea(org.eclipse.swt.widgets.Composite)
|
||||
*/
|
||||
@Override
|
||||
protected Control createDialogArea(Composite parent) {
|
||||
Control control = super.createDialogArea(parent);
|
||||
|
||||
new ContentAssistCommandAdapter(
|
||||
getText(),
|
||||
new TextContentAdapter(),
|
||||
new FindReplaceDocumentAdapterContentProposalProvider(true),
|
||||
null,
|
||||
null,
|
||||
true);
|
||||
|
||||
|
||||
setHelpAvailable(false);
|
||||
return control;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.jface.dialogs.StatusDialog#create()
|
||||
*/
|
||||
@Override
|
||||
public void create() {
|
||||
super.create();
|
||||
if (getValue().length()>0)
|
||||
validateInput();
|
||||
}
|
||||
}
|
|
@ -339,7 +339,7 @@ implements
|
|||
GridData gd;
|
||||
parentComposite = new Composite(c, SWT.NONE);
|
||||
parentComposite.setLayoutData(gd= new GridData(GridData.FILL_BOTH));
|
||||
gd.widthHint= 200;
|
||||
gd.widthHint= 800;
|
||||
itabs.clear();
|
||||
if (!isSingle()) {
|
||||
parentComposite.setLayout(new FillLayout());
|
||||
|
|
|
@ -7,234 +7,568 @@
|
|||
*
|
||||
* Contributors:
|
||||
* Intel Corporation - Initial API and implementation
|
||||
* Andrew Gvozdev (Quoin Inc.) - Regular expression error parsers
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.ui.newui;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.core.runtime.IExtension;
|
||||
import org.eclipse.core.runtime.IExtensionPoint;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Assert;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.NullProgressMonitor;
|
||||
import org.eclipse.jface.dialogs.MessageDialog;
|
||||
import org.eclipse.jface.viewers.CheckStateChangedEvent;
|
||||
import org.eclipse.jface.viewers.CheckboxTableViewer;
|
||||
import org.eclipse.jface.viewers.ICheckStateListener;
|
||||
import org.eclipse.jface.viewers.IStructuredContentProvider;
|
||||
import org.eclipse.jface.viewers.LabelProvider;
|
||||
import org.eclipse.jface.viewers.Viewer;
|
||||
import org.eclipse.jface.window.Window;
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.custom.SashForm;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.layout.FillLayout;
|
||||
import org.eclipse.swt.layout.GridData;
|
||||
import org.eclipse.swt.layout.GridLayout;
|
||||
import org.eclipse.swt.widgets.Composite;
|
||||
import org.eclipse.swt.widgets.Table;
|
||||
import org.eclipse.swt.widgets.TableItem;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.osgi.service.prefs.BackingStoreException;
|
||||
|
||||
import org.eclipse.cdt.core.CCorePlugin;
|
||||
import com.ibm.icu.text.MessageFormat;
|
||||
|
||||
import org.eclipse.cdt.core.ErrorParserManager;
|
||||
import org.eclipse.cdt.core.IErrorParserNamed;
|
||||
import org.eclipse.cdt.core.errorparsers.RegexErrorParser;
|
||||
import org.eclipse.cdt.core.settings.model.ICConfigurationDescription;
|
||||
import org.eclipse.cdt.core.settings.model.ICMultiConfigDescription;
|
||||
import org.eclipse.cdt.core.settings.model.ICResourceDescription;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
import org.eclipse.cdt.ui.dialogs.ICOptionPage;
|
||||
import org.eclipse.cdt.ui.dialogs.RegexErrorParserOptionPage;
|
||||
import org.eclipse.cdt.utils.ui.controls.TabFolderLayout;
|
||||
|
||||
import org.eclipse.cdt.internal.ui.ICHelpContextIds;
|
||||
import org.eclipse.cdt.internal.ui.dialogs.IInputStatusValidator;
|
||||
import org.eclipse.cdt.internal.ui.dialogs.InputStatusDialog;
|
||||
import org.eclipse.cdt.internal.ui.dialogs.StatusInfo;
|
||||
import org.eclipse.cdt.internal.ui.util.PixelConverter;
|
||||
|
||||
|
||||
/**
|
||||
* This class represents Error Parser Tab in Project Properties or workspace Preferences
|
||||
*
|
||||
* @noextend This class is not intended to be subclassed by clients.
|
||||
*/
|
||||
public class ErrorParsTab extends AbstractCPropertyTab {
|
||||
private HashMap<String, String> mapParsers = new HashMap<String, String>();
|
||||
private Table table;
|
||||
private CheckboxTableViewer tv;
|
||||
private ICConfigurationDescription cfgd;
|
||||
private static final int DEFAULT_HEIGHT = 130;
|
||||
private static final int BUTTON_ADD = 0;
|
||||
private static final int BUTTON_EDIT = 1;
|
||||
private static final int BUTTON_DELETE = 2;
|
||||
// there is a separator instead of button = 3
|
||||
private static final int BUTTON_MOVEUP = 4;
|
||||
private static final int BUTTON_MOVEDOWN = 5;
|
||||
|
||||
private static final String[] BUTTONS = new String[] {
|
||||
ADD_STR,
|
||||
EDIT_STR,
|
||||
DEL_STR,
|
||||
null,
|
||||
MOVEUP_STR,
|
||||
MOVEDOWN_STR,
|
||||
};
|
||||
|
||||
private static final String OOPS = "OOPS"; //$NON-NLS-1$
|
||||
|
||||
private Table fTable;
|
||||
private CheckboxTableViewer fTableViewer;
|
||||
private ICConfigurationDescription fCfgDesc;
|
||||
|
||||
private final Map<String, IErrorParserNamed> fAvailableErrorParsers = new LinkedHashMap<String, IErrorParserNamed>();
|
||||
private final Map<String, ICOptionPage> fOptionsPageMap = new HashMap<String, ICOptionPage>();
|
||||
private ICOptionPage fCurrentOptionsPage = null;
|
||||
|
||||
private Composite fCompositeForOptionsPage;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#createControls(org.eclipse.swt.widgets.Composite)
|
||||
*/
|
||||
@Override
|
||||
public void createControls(Composite parent) {
|
||||
|
||||
super.createControls(parent);
|
||||
usercomp.setLayout(new FillLayout());
|
||||
table = new Table(usercomp, SWT.BORDER | SWT.CHECK | SWT.SINGLE);
|
||||
table.addSelectionListener(new SelectionAdapter() {
|
||||
PlatformUI.getWorkbench().getHelpSystem().setHelp(usercomp, ICHelpContextIds.ERROR_PARSERS_PAGE);
|
||||
|
||||
usercomp.setLayout(new GridLayout(1, false));
|
||||
|
||||
// SashForm
|
||||
SashForm sashForm = new SashForm(usercomp, SWT.NONE);
|
||||
sashForm.setBackground(sashForm.getDisplay().getSystemColor(SWT.COLOR_GRAY));
|
||||
sashForm.setOrientation(SWT.VERTICAL);
|
||||
sashForm.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||
|
||||
GridLayout layout = new GridLayout(2, false);
|
||||
layout.marginHeight = 5;
|
||||
sashForm.setLayout(layout);
|
||||
|
||||
// table
|
||||
Composite compositeSashForm = new Composite(sashForm, SWT.NONE);
|
||||
compositeSashForm.setLayout(new GridLayout(2, false));
|
||||
fTable = new Table(compositeSashForm, SWT.BORDER | SWT.CHECK | SWT.SINGLE);
|
||||
fTable.setLayoutData(new GridData(GridData.FILL_BOTH));
|
||||
fTable.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
displaySelectedOptionPage();
|
||||
updateButtons();
|
||||
}});
|
||||
tv = new CheckboxTableViewer(table);
|
||||
tv.setContentProvider(new IStructuredContentProvider() {
|
||||
fTableViewer = new CheckboxTableViewer(fTable);
|
||||
fTableViewer.setContentProvider(new IStructuredContentProvider() {
|
||||
public Object[] getElements(Object inputElement) {
|
||||
return (Object[])inputElement;
|
||||
}
|
||||
public void dispose() {}
|
||||
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
|
||||
});
|
||||
|
||||
tv.addCheckStateListener(new ICheckStateListener() {
|
||||
public void checkStateChanged(CheckStateChangedEvent e) {
|
||||
saveChecked();
|
||||
fTableViewer.setLabelProvider(new LabelProvider() {
|
||||
@Override
|
||||
public String getText(Object element) {
|
||||
if (element instanceof String) {
|
||||
String id = (String)element;
|
||||
IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
|
||||
if (errorParser!=null) {
|
||||
String name = errorParser.getName();
|
||||
if (name!=null && name.length()>0) {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return UIMessages.getFormattedString("ErrorParsTab.error.NonAccessibleID", id); //$NON-NLS-1$
|
||||
}
|
||||
return OOPS;
|
||||
}
|
||||
});
|
||||
|
||||
initButtons(new String[] {
|
||||
MOVEUP_STR, MOVEDOWN_STR, null,
|
||||
UIMessages.getString("ErrorParsTab.0"), //$NON-NLS-1$
|
||||
UIMessages.getString("ErrorParsTab.1") //$NON-NLS-1$
|
||||
});
|
||||
fTableViewer.addCheckStateListener(new ICheckStateListener() {
|
||||
public void checkStateChanged(CheckStateChangedEvent e) {
|
||||
saveChecked();
|
||||
}});
|
||||
|
||||
// Buttons
|
||||
Composite compositeButtons = new Composite(compositeSashForm, SWT.NONE);
|
||||
compositeButtons.setLayoutData(new GridData(GridData.END));
|
||||
initButtons(compositeButtons, BUTTONS);
|
||||
|
||||
fCompositeForOptionsPage = new Composite(sashForm, SWT.NULL);
|
||||
GridData gd = new GridData();
|
||||
fCompositeForOptionsPage.setLayout(new TabFolderLayout());
|
||||
|
||||
PixelConverter converter = new PixelConverter(parent);
|
||||
gd.heightHint = converter.convertHorizontalDLUsToPixels(DEFAULT_HEIGHT);
|
||||
|
||||
gd.horizontalAlignment = GridData.FILL;
|
||||
gd.grabExcessHorizontalSpace = true;
|
||||
gd.grabExcessVerticalSpace = true;
|
||||
gd.horizontalSpan = 2;
|
||||
fCompositeForOptionsPage.setLayoutData(gd);
|
||||
|
||||
sashForm.setWeights(new int[] {50, 50});
|
||||
|
||||
// init data
|
||||
ICResourceDescription resDecs = getResDesc();
|
||||
fCfgDesc = resDecs!=null ? resDecs.getConfiguration() : null;
|
||||
initMapParsers();
|
||||
updateData(getResDesc());
|
||||
}
|
||||
|
||||
protected void initMapParsers() {
|
||||
mapParsers.clear();
|
||||
IExtensionPoint point = Platform.getExtensionRegistry().getExtensionPoint(
|
||||
CCorePlugin.PLUGIN_ID,
|
||||
CCorePlugin.ERROR_PARSER_SIMPLE_ID
|
||||
);
|
||||
if (point != null) {
|
||||
IExtension[] exts = point.getExtensions();
|
||||
for (IExtension ext : exts) {
|
||||
if (ext.getConfigurationElements().length > 0) {
|
||||
mapParsers.put(ext.getUniqueIdentifier(), ext.getLabel());
|
||||
private void initMapParsers() {
|
||||
fAvailableErrorParsers.clear();
|
||||
fOptionsPageMap.clear();
|
||||
for (String id : ErrorParserManager.getErrorParserAvailableIds()) {
|
||||
IErrorParserNamed errorParser = ErrorParserManager.getErrorParserCopy(id);
|
||||
fAvailableErrorParsers.put(id, errorParser);
|
||||
initializeOptionsPage(id);
|
||||
}
|
||||
|
||||
String ids[];
|
||||
if (fCfgDesc!=null) {
|
||||
ICConfigurationDescription srcCfgDesc = fCfgDesc.getConfiguration();
|
||||
if (srcCfgDesc instanceof ICMultiConfigDescription) {
|
||||
String[][] ss = ((ICMultiConfigDescription)srcCfgDesc).getErrorParserIDs();
|
||||
ids = CDTPrefUtil.getStrListForDisplay(ss);
|
||||
} else {
|
||||
ids = srcCfgDesc.getBuildSetting().getErrorParserIDs();
|
||||
}
|
||||
Set<String> setIds = new LinkedHashSet<String>(Arrays.asList(ids));
|
||||
setIds.addAll(fAvailableErrorParsers.keySet());
|
||||
fTableViewer.setInput(setIds.toArray(new String[0]));
|
||||
} else {
|
||||
fTableViewer.setInput(fAvailableErrorParsers.keySet().toArray(new String[0]));
|
||||
ids = ErrorParserManager.getDefaultErrorParserIds();
|
||||
}
|
||||
fTableViewer.setCheckedElements(ids);
|
||||
|
||||
displaySelectedOptionPage();
|
||||
}
|
||||
|
||||
private void initializeOptionsPage(String id) {
|
||||
IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
|
||||
if (errorParser!=null) {
|
||||
String name = errorParser.getName();
|
||||
if (name!=null && name.length()>0) {
|
||||
// RegexErrorParser has an Options page
|
||||
if (errorParser instanceof RegexErrorParser) {
|
||||
// allow to edit only for Build Settings Preference Page (where cfgd==null)
|
||||
RegexErrorParserOptionPage optionsPage = new RegexErrorParserOptionPage((RegexErrorParser) errorParser, isErrorParsersEditable());
|
||||
fOptionsPageMap.put(id, optionsPage);
|
||||
optionsPage.setContainer(page);
|
||||
optionsPage.createControl(fCompositeForOptionsPage);
|
||||
optionsPage.setVisible(false);
|
||||
fCompositeForOptionsPage.layout(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void displaySelectedOptionPage() {
|
||||
if (fCurrentOptionsPage != null)
|
||||
fCurrentOptionsPage.setVisible(false);
|
||||
|
||||
int pos = fTable.getSelectionIndex();
|
||||
if (pos<0)
|
||||
return;
|
||||
|
||||
String parserId = (String)fTable.getItem(pos).getData();
|
||||
ICOptionPage optionsPage = fOptionsPageMap.get(parserId);
|
||||
if (optionsPage != null) {
|
||||
optionsPage.setVisible(true);
|
||||
}
|
||||
fCurrentOptionsPage = optionsPage;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#buttonPressed(int)
|
||||
*/
|
||||
@Override
|
||||
public void buttonPressed (int n) {
|
||||
switch (n) {
|
||||
case 0: // up
|
||||
case BUTTON_ADD:
|
||||
addErrorParser();
|
||||
break;
|
||||
case BUTTON_EDIT:
|
||||
editErrorParser();
|
||||
break;
|
||||
case BUTTON_DELETE:
|
||||
deleteErrorParser();
|
||||
break;
|
||||
case BUTTON_MOVEUP:
|
||||
moveItem(true);
|
||||
break;
|
||||
case 1: // down
|
||||
case BUTTON_MOVEDOWN:
|
||||
moveItem(false);
|
||||
break;
|
||||
case 2: // do nothing - it's not a button
|
||||
break;
|
||||
|
||||
case 3: // check all
|
||||
tv.setAllChecked(true);
|
||||
saveChecked();
|
||||
break;
|
||||
case 4: // uncheck all
|
||||
tv.setAllChecked(false);
|
||||
saveChecked();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
// Move item up / down
|
||||
private void moveItem(boolean up) {
|
||||
int n = table.getSelectionIndex();
|
||||
if (n < 0 ||
|
||||
(up && n == 0) ||
|
||||
(!up && n+1 == table.getItemCount()))
|
||||
int n = fTable.getSelectionIndex();
|
||||
if (n < 0 || (up && n == 0) || (!up && n+1 == fTable.getItemCount()))
|
||||
return;
|
||||
TableData d = (TableData)tv.getElementAt(n);
|
||||
boolean checked = tv.getChecked(d);
|
||||
tv.remove(d);
|
||||
n = up ? n - 1 : n + 1;
|
||||
tv.insert(d, n);
|
||||
tv.setChecked(d, checked);
|
||||
table.setSelection(n);
|
||||
|
||||
String id = (String)fTableViewer.getElementAt(n);
|
||||
boolean checked = fTableViewer.getChecked(id);
|
||||
fTableViewer.remove(id);
|
||||
n = up ? n-1 : n+1;
|
||||
fTableViewer.insert(id, n);
|
||||
fTableViewer.setChecked(id, checked);
|
||||
fTable.setSelection(n);
|
||||
|
||||
saveChecked();
|
||||
}
|
||||
|
||||
class TableData {
|
||||
String key;
|
||||
String value;
|
||||
public TableData (String _key, String _value) {
|
||||
key = _key;
|
||||
value = _value;
|
||||
}
|
||||
@Override
|
||||
public String toString() { return value; }
|
||||
private String makeId(String name) {
|
||||
return CUIPlugin.PLUGIN_ID+'.'+name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateData(ICResourceDescription _cfgd) {
|
||||
cfgd = _cfgd.getConfiguration();
|
||||
if (mapParsers == null) return;
|
||||
|
||||
String[] ss = null;
|
||||
if (page.isMultiCfg()) {
|
||||
String[][] ids = ((ICMultiConfigDescription)cfgd).getErrorParserIDs();
|
||||
ss = CDTPrefUtil.getStrListForDisplay(ids);
|
||||
} else {
|
||||
ss = cfgd.getBuildSetting().getErrorParserIDs();
|
||||
}
|
||||
|
||||
ArrayList<TableData> data = new ArrayList<TableData>(mapParsers.size());
|
||||
ArrayList<TableData> checked = new ArrayList<TableData>(ss.length);
|
||||
HashMap<String, String> cloneMap = new HashMap<String, String>(mapParsers);
|
||||
// add checked elements
|
||||
for (String element : ss) {
|
||||
String s = cloneMap.get(element);
|
||||
if (s != null) {
|
||||
TableData d = new TableData(element,s);
|
||||
data.add(d);
|
||||
checked.add(d);
|
||||
cloneMap.remove(element);
|
||||
private void addErrorParser() {
|
||||
IInputStatusValidator inputValidator = new IInputStatusValidator() {
|
||||
public IStatus isValid(String newText) {
|
||||
StatusInfo status = new StatusInfo();
|
||||
if (newText.trim().length() == 0) {
|
||||
status.setError(UIMessages.getString("ErrorParsTab.error.NonEmptyName")); //$NON-NLS-1$
|
||||
} else if (newText.indexOf(ErrorParserManager.ERROR_PARSER_DELIMITER)>=0) {
|
||||
String message = MessageFormat.format( UIMessages.getString("ErrorParsTab.error.IllegalCharacter"), //$NON-NLS-1$
|
||||
new Object[] { ErrorParserManager.ERROR_PARSER_DELIMITER });
|
||||
status.setError(message);
|
||||
} else if (fAvailableErrorParsers.containsKey(makeId(newText))) {
|
||||
status.setError(UIMessages.getString("ErrorParsTab.error.NonUniqueID")); //$NON-NLS-1$
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
};
|
||||
InputStatusDialog addDialog = new InputStatusDialog(usercomp.getShell(),
|
||||
UIMessages.getString("ErrorParsTab.title.Add"), //$NON-NLS-1$
|
||||
UIMessages.getString("ErrorParsTab.label.EnterName"), //$NON-NLS-1$
|
||||
UIMessages.getString("ErrorParsTab.label.DefaultRegexErrorParserName"), //$NON-NLS-1$
|
||||
inputValidator);
|
||||
addDialog.setHelpAvailable(false);
|
||||
|
||||
if (addDialog.open() == Window.OK) {
|
||||
String newName = addDialog.getValue();
|
||||
String newId = makeId(newName);
|
||||
IErrorParserNamed errorParser = new RegexErrorParser(newId, newName);
|
||||
fAvailableErrorParsers.put(newId, errorParser);
|
||||
|
||||
fTableViewer.add(newId);
|
||||
fTableViewer.setChecked(newId, true);
|
||||
fTable.setSelection(fTable.getItemCount()-1);
|
||||
|
||||
initializeOptionsPage(newId);
|
||||
displaySelectedOptionPage();
|
||||
updateButtons();
|
||||
}
|
||||
// add remaining parsers (unchecked)
|
||||
Iterator<String> it = cloneMap.keySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
String s = it.next();
|
||||
data.add(new TableData(s, cloneMap.get(s)));
|
||||
}
|
||||
|
||||
private void editErrorParser() {
|
||||
int n = fTable.getSelectionIndex();
|
||||
Assert.isTrue(n>=0);
|
||||
|
||||
String id = (String)fTableViewer.getElementAt(n);
|
||||
IErrorParserNamed errorParser = fAvailableErrorParsers.get(id);
|
||||
|
||||
IInputStatusValidator inputValidator = new IInputStatusValidator() {
|
||||
public IStatus isValid(String newText) {
|
||||
StatusInfo status = new StatusInfo();
|
||||
if (newText.trim().length() == 0) {
|
||||
status.setError(UIMessages.getString("ErrorParsTab.error.NonEmptyName")); //$NON-NLS-1$
|
||||
} else if (newText.indexOf(ErrorParserManager.ERROR_PARSER_DELIMITER)>=0) {
|
||||
String message = MessageFormat.format( UIMessages.getString("ErrorParsTab.error.IllegalCharacter"), //$NON-NLS-1$
|
||||
new Object[] { ErrorParserManager.ERROR_PARSER_DELIMITER });
|
||||
status.setError(message);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
};
|
||||
InputStatusDialog addDialog = new InputStatusDialog(usercomp.getShell(),
|
||||
UIMessages.getString("ErrorParsTab.title.Edit"), //$NON-NLS-1$
|
||||
UIMessages.getString("ErrorParsTab.label.EnterName"), //$NON-NLS-1$
|
||||
errorParser.getName(),
|
||||
inputValidator);
|
||||
addDialog.setHelpAvailable(false);
|
||||
|
||||
if (addDialog.open() == Window.OK) {
|
||||
errorParser.setName(addDialog.getValue());
|
||||
fTableViewer.refresh(id);
|
||||
}
|
||||
tv.setInput(data.toArray());
|
||||
tv.setCheckedElements(checked.toArray());
|
||||
}
|
||||
|
||||
private void deleteErrorParser() {
|
||||
int n = fTable.getSelectionIndex();
|
||||
if (n < 0)
|
||||
return;
|
||||
|
||||
fTableViewer.remove(fTableViewer.getElementAt(n));
|
||||
|
||||
int last = fTable.getItemCount() - 1;
|
||||
if (n>last)
|
||||
n = last;
|
||||
if (n>=0)
|
||||
fTable.setSelection(n);
|
||||
|
||||
saveChecked();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#updateData(org.eclipse.cdt.core.settings.model.ICResourceDescription)
|
||||
*/
|
||||
@Override
|
||||
public void updateData(ICResourceDescription resDecs) {
|
||||
ICConfigurationDescription oldCfgDesc = fCfgDesc;
|
||||
fCfgDesc = resDecs!=null ? resDecs.getConfiguration() : null;
|
||||
if (oldCfgDesc!=fCfgDesc) {
|
||||
initMapParsers();
|
||||
}
|
||||
displaySelectedOptionPage();
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateButtons() {
|
||||
int cnt = table.getItemCount();
|
||||
int pos = table.getSelectionIndex();
|
||||
buttonSetEnabled(0, pos > 0);
|
||||
buttonSetEnabled(1, pos != -1 && pos < (cnt - 1));
|
||||
buttonSetEnabled(3, cnt > 0);
|
||||
buttonSetEnabled(4, cnt > 0);
|
||||
private static boolean isExtensionId(String id) {
|
||||
for (String extId : ErrorParserManager.getErrorParserExtensionIds()) {
|
||||
if (extId.equals(id)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#updateButtons()
|
||||
*/
|
||||
@Override
|
||||
public void updateButtons() {
|
||||
int pos = fTable.getSelectionIndex();
|
||||
int count = fTable.getItemCount();
|
||||
int last = count - 1;
|
||||
boolean selected = pos >= 0 && pos <= last;
|
||||
String id = (String)fTableViewer.getElementAt(pos);
|
||||
|
||||
buttonSetEnabled(BUTTON_ADD, isErrorParsersEditable());
|
||||
buttonSetEnabled(BUTTON_EDIT, isErrorParsersEditable() && selected);
|
||||
buttonSetEnabled(BUTTON_DELETE, isErrorParsersEditable() && selected && !isExtensionId(id));
|
||||
buttonSetEnabled(BUTTON_MOVEUP, selected && pos != 0);
|
||||
buttonSetEnabled(BUTTON_MOVEDOWN, selected && pos != last);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#performApply(org.eclipse.cdt.core.settings.model.ICResourceDescription, org.eclipse.cdt.core.settings.model.ICResourceDescription)
|
||||
*/
|
||||
@Override
|
||||
protected void performApply(ICResourceDescription src, ICResourceDescription dst) {
|
||||
ICConfigurationDescription sd = src.getConfiguration();
|
||||
ICConfigurationDescription dd = dst.getConfiguration();
|
||||
String[] s = null;
|
||||
if (sd instanceof ICMultiConfigDescription) {
|
||||
String[][] ss = ((ICMultiConfigDescription)sd).getErrorParserIDs();
|
||||
s = CDTPrefUtil.getStrListForDisplay(ss);
|
||||
} else {
|
||||
s = sd.getBuildSetting().getErrorParserIDs();
|
||||
performOK();
|
||||
|
||||
if (!page.isForPrefs()) {
|
||||
ICConfigurationDescription sd = src.getConfiguration();
|
||||
ICConfigurationDescription dd = dst.getConfiguration();
|
||||
String[] s = null;
|
||||
if (sd instanceof ICMultiConfigDescription) {
|
||||
String[][] ss = ((ICMultiConfigDescription)sd).getErrorParserIDs();
|
||||
s = CDTPrefUtil.getStrListForDisplay(ss);
|
||||
} else {
|
||||
s = sd.getBuildSetting().getErrorParserIDs();
|
||||
}
|
||||
if (dd instanceof ICMultiConfigDescription)
|
||||
((ICMultiConfigDescription)dd).setErrorParserIDs(s);
|
||||
else
|
||||
dd.getBuildSetting().setErrorParserIDs(s);
|
||||
initMapParsers();
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#performOK()
|
||||
*/
|
||||
@Override
|
||||
protected void performOK() {
|
||||
informPages(true);
|
||||
|
||||
if (page.isForPrefs()) {
|
||||
if (fCfgDesc==null) {
|
||||
// Build Settings page
|
||||
try {
|
||||
IErrorParserNamed[] errorParsers = new IErrorParserNamed[fTable.getItemCount()];
|
||||
int i=0;
|
||||
for (TableItem item : fTable.getItems()) {
|
||||
if (item.getData() instanceof String) {
|
||||
String id = (String) item.getData();
|
||||
errorParsers[i] = fAvailableErrorParsers.get(id);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
Object[] checkedElements = fTableViewer.getCheckedElements();
|
||||
String[] checkedErrorParserIds = new String[checkedElements.length];
|
||||
System.arraycopy(checkedElements, 0, checkedErrorParserIds, 0, checkedElements.length);
|
||||
|
||||
ErrorParserManager.setUserDefinedErrorParsers(errorParsers);
|
||||
ErrorParserManager.setDefaultErrorParserIds(checkedErrorParserIds);
|
||||
} catch (BackingStoreException e) {
|
||||
CUIPlugin.log(UIMessages.getString("ErrorParsTab.error.OnApplyingSettings"), e); //$NON-NLS-1$
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.log(UIMessages.getString("ErrorParsTab.error.OnApplyingSettings"), e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
initMapParsers();
|
||||
}
|
||||
if (dd instanceof ICMultiConfigDescription)
|
||||
((ICMultiConfigDescription)dd).setErrorParserIDs(s);
|
||||
else
|
||||
dd.getBuildSetting().setErrorParserIDs(s);
|
||||
}
|
||||
|
||||
private void saveChecked() {
|
||||
Object[] objs = tv.getCheckedElements();
|
||||
ArrayList<String> lst = new ArrayList<String>();
|
||||
if (objs != null) {
|
||||
for (Object ob : objs)
|
||||
lst.add(((TableData)ob).key);
|
||||
if (fCfgDesc!=null) {
|
||||
Object[] objs = fTableViewer.getCheckedElements();
|
||||
String[] ids = new String[objs.length];
|
||||
System.arraycopy(objs, 0, ids, 0, objs.length);
|
||||
|
||||
if (fCfgDesc instanceof ICMultiConfigDescription)
|
||||
((ICMultiConfigDescription)fCfgDesc).setErrorParserIDs(ids);
|
||||
else
|
||||
fCfgDesc.getBuildSetting().setErrorParserIDs(ids);
|
||||
}
|
||||
String[] s = lst.toArray(new String[lst.size()]);
|
||||
if (cfgd instanceof ICMultiConfigDescription)
|
||||
((ICMultiConfigDescription)cfgd).setErrorParserIDs(s);
|
||||
else
|
||||
cfgd.getBuildSetting().setErrorParserIDs(s);
|
||||
}
|
||||
// This page can be displayed for project only
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#canBeVisible()
|
||||
*/
|
||||
@Override
|
||||
public boolean canBeVisible() {
|
||||
return page.isForProject() || page.isForPrefs();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if the error parsers are allowed to be editable,
|
||||
* i.e. Add/Edit/Delete buttons are enabled and Options page edits enabled.
|
||||
* This will evaluate to {@code true} for Preference Build Settings page but
|
||||
* not for Preference New CDT Project Wizard/Makefile Project.
|
||||
*/
|
||||
private boolean isErrorParsersEditable() {
|
||||
return fCfgDesc==null;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.ui.newui.AbstractCPropertyTab#performDefaults()
|
||||
*/
|
||||
@Override
|
||||
protected void performDefaults() {
|
||||
if (cfgd instanceof ICMultiConfigDescription)
|
||||
((ICMultiConfigDescription)cfgd).setErrorParserIDs(null);
|
||||
else
|
||||
cfgd.getBuildSetting().setErrorParserIDs(null);
|
||||
updateData(getResDesc());
|
||||
if (isErrorParsersEditable()) {
|
||||
// Must be Build Settings Preference Page
|
||||
if (MessageDialog.openQuestion(usercomp.getShell(),
|
||||
UIMessages.getString(UIMessages.getString("ErrorParsTab.title.ConfirmReset")), //$NON-NLS-1$
|
||||
UIMessages.getString(UIMessages.getString("ErrorParsTab.message.ConfirmReset")))) { //$NON-NLS-1$
|
||||
|
||||
try {
|
||||
ErrorParserManager.setUserDefinedErrorParsers(null);
|
||||
ErrorParserManager.setDefaultErrorParserIds(null);
|
||||
} catch (BackingStoreException e) {
|
||||
CUIPlugin.log(UIMessages.getString("ErrorParsTab.error.OnRestoring"), e); //$NON-NLS-1$
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.log(UIMessages.getString("ErrorParsTab.error.OnRestoring"), e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (fCfgDesc instanceof ICMultiConfigDescription)
|
||||
((ICMultiConfigDescription) fCfgDesc).setErrorParserIDs(null);
|
||||
else
|
||||
fCfgDesc.getBuildSetting().setErrorParserIDs(null);
|
||||
}
|
||||
initMapParsers();
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
private void informPages(boolean apply) {
|
||||
Collection<ICOptionPage> pages = fOptionsPageMap.values();
|
||||
for (ICOptionPage dynamicPage : pages) {
|
||||
if (dynamicPage!=null && dynamicPage.isValid() && dynamicPage.getControl() != null) {
|
||||
try {
|
||||
if (apply)
|
||||
dynamicPage.performApply(new NullProgressMonitor());
|
||||
else
|
||||
dynamicPage.performDefaults();
|
||||
} catch (CoreException e) {
|
||||
CUIPlugin.log(UIMessages.getString("ErrorParsTab.error.OnApplyingSettings"), e); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -443,8 +443,18 @@ ConfigDescriptionTab.0=Project Description
|
|||
ConfigDescriptionTab.1=Configuration Description
|
||||
ConfigDescriptionTab.2=Resource Description
|
||||
BinaryParsTab.0=Binary parser:
|
||||
ErrorParsTab.0=Check all
|
||||
ErrorParsTab.1=Uncheck all
|
||||
ErrorParsTab.error.NonEmptyName=Specify non empty name
|
||||
ErrorParsTab.error.NonUniqueID=Error parser ID is not unique, specify different name
|
||||
ErrorParsTab.error.OnApplyingSettings=Error applying Error Parser Tab settings
|
||||
ErrorParsTab.error.OnRestoring=Error restoring default Error Parser Tab settings
|
||||
ErrorParsTab.error.NonAccessibleID=[ Not accessible id={0} ]
|
||||
ErrorParsTab.error.IllegalCharacter=Special character ''{0}'' is not allowed
|
||||
ErrorParsTab.label.EnterName=Enter name of new error parser:
|
||||
ErrorParsTab.label.DefaultRegexErrorParserName=Regex Error Parser
|
||||
ErrorParsTab.message.ConfirmReset=Are you sure you want to delete all customized error parsers?
|
||||
ErrorParsTab.title.Add=Add Regex Error Parser
|
||||
ErrorParsTab.title.ConfirmReset=Confirm Resetting Error Parsers
|
||||
ErrorParsTab.title.Edit=Edit Regex Error Parser name
|
||||
StructureTreeTab.0=Level:
|
||||
StructureTreeTab.1=Maximal tree nesting
|
||||
StructureTreeTab.2=Long
|
||||
|
|
Loading…
Add table
Reference in a new issue