diff options
11 files changed, 396 insertions, 3 deletions
diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF index ab3afbc20e0..ca272a0877e 100644 --- a/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF +++ b/codan/org.eclipse.cdt.codan.checkers.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: org.eclipse.cdt.codan.checkers.ui;singleton:=true -Bundle-Version: 3.2.2.qualifier +Bundle-Version: 3.2.3.qualifier Bundle-Activator: org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator Require-Bundle: org.eclipse.core.resources, org.eclipse.core.runtime, diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/plugin.xml b/codan/org.eclipse.cdt.codan.checkers.ui/plugin.xml index 073956ab06e..cf753037cb3 100644 --- a/codan/org.eclipse.cdt.codan.checkers.ui/plugin.xml +++ b/codan/org.eclipse.cdt.codan.checkers.ui/plugin.xml @@ -4,6 +4,14 @@ <extension point="org.eclipse.cdt.codan.ui.codanMarkerResolution"> <resolution + class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixAddDefaultSwitch" + problemId="com.baldapps.artemis.checkers.MissDefaultProblem"> + </resolution> + <resolution + class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixAddCaseSwitch" + problemId="com.baldapps.artemis.checkers.MissCaseProblem"> + </resolution> + <resolution class="org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixForFixit" messagePattern=".*"> </resolution> diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddCaseSwitch.java b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddCaseSwitch.java new file mode 100644 index 00000000000..5f02f1fc152 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddCaseSwitch.java @@ -0,0 +1,163 @@ +/******************************************************************************* + * Copyright (c) 2019 Marco Stornelli + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator; +import org.eclipse.cdt.codan.ui.AbstractAstRewriteQuickFix; +import org.eclipse.cdt.core.dom.ast.IASTBreakStatement; +import org.eclipse.cdt.core.dom.ast.IASTCaseStatement; +import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; +import org.eclipse.cdt.core.dom.ast.IASTExpression; +import org.eclipse.cdt.core.dom.ast.IASTIdExpression; +import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression; +import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTStatement; +import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IEnumeration; +import org.eclipse.cdt.core.dom.ast.IEnumerator; +import org.eclipse.cdt.core.dom.ast.INodeFactory; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPEnumeration; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.core.dom.parser.ValueFactory; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.CPPVisitor; +import org.eclipse.cdt.internal.core.dom.parser.cpp.semantics.SemanticUtil; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.ltk.core.refactoring.Change; + +@SuppressWarnings("restriction") +public class QuickFixAddCaseSwitch extends AbstractAstRewriteQuickFix { + + @Override + public String getLabel() { + return QuickFixMessages.QuickFixAddCaseSwitch_add_cases_to_switch; + } + + @Override + public void modifyAST(IIndex index, IMarker marker) { + IASTTranslationUnit ast; + try { + ITranslationUnit tu = getTranslationUnitViaEditor(marker); + ast = tu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS); + } catch (CoreException e) { + CheckersUiActivator.log(e); + return; + } + IASTNode astNode = null; + if (isCodanProblem(marker)) { + astNode = getASTNodeFromMarker(marker, ast); + } + if (astNode == null || !(astNode instanceof IASTSwitchStatement)) { + return; + } + ASTRewrite r = ASTRewrite.create(ast); + INodeFactory factory = ast.getASTNodeFactory(); + Map<String, Number> missingEnums = getMissingCases((IASTSwitchStatement) astNode); + Set<Number> existing = new HashSet<>(); + missingEnums = missingEnums.entrySet().stream().filter(entry -> existing.add(entry.getValue())) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + List<IASTCaseStatement> caseStatements = new ArrayList<>(); + for (Map.Entry<String, Number> e : missingEnums.entrySet()) { + IASTName newName = factory.newName(e.getKey()); + caseStatements.add(factory.newCaseStatement(factory.newIdExpression(newName))); + } + IASTBreakStatement breakStatement = factory.newBreakStatement(); + IASTNode[] children = astNode.getChildren(); + IASTCompoundStatement compound = null; + for (int i = 0; i < children.length; ++i) { + if (children[i] instanceof IASTCompoundStatement) { + compound = (IASTCompoundStatement) children[i]; + break; + } + } + if (compound == null) + return; + for (IASTCaseStatement caseStatement : caseStatements) + r.insertBefore(compound, null, caseStatement, null); + r.insertBefore(compound, null, breakStatement, null); + Change c = r.rewriteAST(); + try { + c.perform(new NullProgressMonitor()); + } catch (CoreException e) { + CheckersUiActivator.log(e); + return; + } + try { + marker.delete(); + } catch (CoreException e) { + CheckersUiActivator.log(e); + } + } + + private Map<String, Number> getMissingCases(IASTSwitchStatement statement) { + IASTExpression controller = statement.getControllerExpression(); + IASTStatement bodyStmt = statement.getBody(); + IType type = SemanticUtil.getUltimateType(controller.getExpressionType(), true); + Map<String, Number> enumValues = new HashMap<>(); + if (type instanceof IEnumeration) { + IEnumerator[] enums = ((IEnumeration) type).getEnumerators(); + String prefix = ""; + if (type instanceof ICPPEnumeration) { + String[] qualName = CPPVisitor.getQualifiedName((IEnumeration) type); + StringBuilder builder = new StringBuilder(); + for (int i = 0; i < qualName.length - 1; ++i) { + builder.append(qualName[i]); + builder.append("::"); + } + prefix = builder.toString(); + } + for (IEnumerator e : enums) { + enumValues.put(prefix + e.getName(), e.getValue().numberValue()); + } + } else + return enumValues; + final List<IASTStatement> statements; + if (bodyStmt instanceof IASTCompoundStatement) { + statements = Arrays.asList(((IASTCompoundStatement) bodyStmt).getStatements()); + } else { + statements = Collections.singletonList(bodyStmt); + } + for (IASTStatement s : statements) { + if (s instanceof IASTCaseStatement && ((IASTCaseStatement) s).getExpression() instanceof IASTIdExpression) { + IASTName name = ((IASTIdExpression) ((IASTCaseStatement) s).getExpression()).getName(); + IBinding binding = name.resolveBinding(); + if (binding instanceof IEnumerator) { + enumValues.entrySet().removeIf( + entry -> entry.getValue().equals(((IEnumerator) binding).getValue().numberValue())); + } + } else if (s instanceof IASTCaseStatement + && ((IASTCaseStatement) s).getExpression() instanceof IASTLiteralExpression) { + Number value = ValueFactory.getConstantNumericalValue(((IASTCaseStatement) s).getExpression()); + if (value != null) + enumValues.entrySet().removeIf(entry -> entry.getValue().equals(value)); + } + } + return enumValues; + } +} diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddDefaultSwitch.java b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddDefaultSwitch.java new file mode 100644 index 00000000000..468dc3eed2b --- /dev/null +++ b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddDefaultSwitch.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * Copyright (c) 2019 Marco Stornelli + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import org.eclipse.cdt.codan.internal.checkers.ui.CheckersUiActivator; +import org.eclipse.cdt.codan.ui.AbstractAstRewriteQuickFix; +import org.eclipse.cdt.core.dom.ast.IASTBreakStatement; +import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; +import org.eclipse.cdt.core.dom.ast.IASTDefaultStatement; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTSwitchStatement; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.INodeFactory; +import org.eclipse.cdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.ltk.core.refactoring.Change; + +public class QuickFixAddDefaultSwitch extends AbstractAstRewriteQuickFix { + + @Override + public String getLabel() { + return QuickFixMessages.QuickFixAddDefaultSwitch_add_default_to_switch; + } + + @Override + public void modifyAST(IIndex index, IMarker marker) { + IASTTranslationUnit ast; + try { + ITranslationUnit tu = getTranslationUnitViaEditor(marker); + ast = tu.getAST(index, ITranslationUnit.AST_SKIP_INDEXED_HEADERS); + } catch (CoreException e) { + CheckersUiActivator.log(e); + return; + } + IASTNode astNode = null; + if (isCodanProblem(marker)) { + astNode = getASTNodeFromMarker(marker, ast); + } + if (astNode == null || !(astNode instanceof IASTSwitchStatement)) { + return; + } + ASTRewrite r = ASTRewrite.create(ast); + INodeFactory factory = ast.getASTNodeFactory(); + IASTDefaultStatement defStatement = factory.newDefaultStatement(); + IASTBreakStatement breakStatement = factory.newBreakStatement(); + IASTNode[] children = astNode.getChildren(); + IASTCompoundStatement compound = null; + for (int i = 0; i < children.length; ++i) { + if (children[i] instanceof IASTCompoundStatement) { + compound = (IASTCompoundStatement) children[i]; + break; + } + } + if (compound == null) + return; + r.insertBefore(compound, null, defStatement, null); + r.insertBefore(compound, null, breakStatement, null); + Change c = r.rewriteAST(); + try { + c.perform(new NullProgressMonitor()); + } catch (CoreException e) { + CheckersUiActivator.log(e); + return; + } + try { + marker.delete(); + } catch (CoreException e) { + CheckersUiActivator.log(e); + } + } +} diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixMessages.java b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixMessages.java index a323dfa34b5..444a565aa6a 100644 --- a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixMessages.java +++ b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixMessages.java @@ -29,6 +29,8 @@ public class QuickFixMessages extends NLS { public static String QuickFixUseDotOperator_replace_ptr; public static String QuickFixForFixit_apply_fixit; public static String QuickFixSuppressProblem_Label; + public static String QuickFixAddDefaultSwitch_add_default_to_switch; + public static String QuickFixAddCaseSwitch_add_cases_to_switch; static { NLS.initializeMessages(QuickFixMessages.class.getName(), QuickFixMessages.class); diff --git a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixMessages.properties b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixMessages.properties index 9371535ca80..9c5486487c4 100644 --- a/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixMessages.properties +++ b/codan/org.eclipse.cdt.codan.checkers.ui/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixMessages.properties @@ -23,4 +23,6 @@ QuickFixAddSemicolon_add_semicolon=Add semicolon QuickFixUsePointer_replace_dot=Replace '.' with '->' QuickFixUseDotOperator_replace_ptr=Replace '->' with '.' QuickFixForFixit_apply_fixit=Apply compiler recommended fix-it -QuickFixSuppressProblem_Label=Suppress problem "%s"
\ No newline at end of file +QuickFixSuppressProblem_Label=Suppress problem "%s" +QuickFixAddDefaultSwitch_add_default_to_switch=Add default to switch +QuickFixAddCaseSwitch_add_cases_to_switch=Add missing cases to switch diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java index 9a0cb3e2399..52107633ac7 100644 --- a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/core/tests/AutomatedIntegrationSuite.java @@ -43,6 +43,8 @@ import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.CaseBreakQuickFixComm import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.CaseBreakQuickFixFallthroughAttributeTest; import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.CatchByReferenceQuickFixTest; import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.CreateLocalVariableQuickFixTest; +import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixAddCaseTest; +import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixAddDefaultTest; import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.QuickFixSuppressProblemTest; import org.eclipse.cdt.codan.internal.checkers.ui.quickfix.SuggestedParenthesisQuickFixTest; @@ -103,6 +105,8 @@ public class AutomatedIntegrationSuite extends TestSuite { suite.addTestSuite(CaseBreakQuickFixFallthroughAttributeTest.class); suite.addTestSuite(AssignmentInConditionQuickFixTest.class); suite.addTestSuite(QuickFixSuppressProblemTest.class); + suite.addTestSuite(QuickFixAddDefaultTest.class); + suite.addTestSuite(QuickFixAddCaseTest.class); return suite; } } diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddCaseTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddCaseTest.java new file mode 100644 index 00000000000..d20b41f9ede --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddCaseTest.java @@ -0,0 +1,53 @@ +/******************************************************************************* + * Copyright (c) 2019 Marco Stornelli + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Marco Stornelli - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import org.eclipse.cdt.codan.internal.checkers.SwitchCaseChecker; +import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution; + +public class QuickFixAddCaseTest extends QuickFixTestCase { + + @Override + protected AbstractCodanCMarkerResolution createQuickFix() { + return new QuickFixAddCaseSwitch(); + } + + @Override + public boolean isCpp() { + return true; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(SwitchCaseChecker.MISS_CASE_ID); + } + + //enum FRUIT { + // APPLE, PEAR, BANANA + //}; + //void func() { + // FRUIT f = APPLE; + // switch(f) { + // case APPLE: + // break; + // } + //} + public void testAddCase() throws Exception { + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("PEAR:", result); //$NON-NLS-1$ + assertContainedIn("BANANA:", result); //$NON-NLS-1$ + } +} diff --git a/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddDefaultTest.java b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddDefaultTest.java new file mode 100644 index 00000000000..45a0732bf38 --- /dev/null +++ b/codan/org.eclipse.cdt.codan.core.tests/src/org/eclipse/cdt/codan/internal/checkers/ui/quickfix/QuickFixAddDefaultTest.java @@ -0,0 +1,50 @@ +/******************************************************************************* + * Copyright (c) 2019 Marco Stornelli + * + * This program and the accompanying materials + * are made available under the terms of the Eclipse Public License 2.0 + * which accompanies this distribution, and is available at + * https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * Marco Stornelli - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.codan.internal.checkers.ui.quickfix; + +import org.eclipse.cdt.codan.internal.checkers.SwitchCaseChecker; +import org.eclipse.cdt.codan.ui.AbstractCodanCMarkerResolution; + +public class QuickFixAddDefaultTest extends QuickFixTestCase { + + @Override + protected AbstractCodanCMarkerResolution createQuickFix() { + return new QuickFixAddDefaultSwitch(); + } + + @Override + public boolean isCpp() { + return true; + } + + @Override + public void setUp() throws Exception { + super.setUp(); + enableProblems(SwitchCaseChecker.MISS_DEFAULT_ID); + } + + //void func() { + // int a = 0; + // switch(a) { + // case 0: + // break; + // } + //} + public void testAddDefault() throws Exception { + loadcode(getAboveComment()); + String result = runQuickFixOneFile(); + assertContainedIn("default:", result); //$NON-NLS-1$ + } + +} diff --git a/codan/org.eclipse.cdt.codan.ui.cxx/META-INF/MANIFEST.MF b/codan/org.eclipse.cdt.codan.ui.cxx/META-INF/MANIFEST.MF index 3a32f8dc6af..e27c2c661c1 100644 --- a/codan/org.eclipse.cdt.codan.ui.cxx/META-INF/MANIFEST.MF +++ b/codan/org.eclipse.cdt.codan.ui.cxx/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %Bundle-Name Bundle-SymbolicName: org.eclipse.cdt.codan.ui.cxx;singleton:=true -Bundle-Version: 3.4.1.qualifier +Bundle-Version: 3.5.0.qualifier Bundle-Activator: org.eclipse.cdt.codan.internal.ui.cxx.Activator Bundle-Vendor: %Bundle-Vendor Require-Bundle: org.eclipse.ui, diff --git a/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/AbstractCodanCMarkerResolution.java b/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/AbstractCodanCMarkerResolution.java index 4b15a25b03b..a4380223c53 100644 --- a/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/AbstractCodanCMarkerResolution.java +++ b/codan/org.eclipse.cdt.codan.ui.cxx/src/org/eclipse/cdt/codan/ui/AbstractCodanCMarkerResolution.java @@ -21,6 +21,7 @@ import org.eclipse.cdt.codan.internal.core.model.CodanProblemMarker; import org.eclipse.cdt.codan.internal.ui.CodanUIActivator; import org.eclipse.cdt.core.CCorePlugin; import org.eclipse.cdt.core.dom.ast.IASTName; +import org.eclipse.cdt.core.dom.ast.IASTNode; import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; import org.eclipse.cdt.core.index.IIndex; import org.eclipse.cdt.core.model.CModelException; @@ -309,4 +310,30 @@ public abstract class AbstractCodanCMarkerResolution implements ICodanMarkerReso public String getProblemMessage(IMarker marker) { return CodanProblemMarker.getMessage(marker); } + + /** + * Get the enclosing node using the input position + * @param ast The AST + * @param charStart Start position + * @param length Length + * @return The node or null + * @since 3.5 + */ + protected IASTNode getASTNodeFromPosition(IASTTranslationUnit ast, final int charStart, final int length) { + IASTNode node = ast.getNodeSelector(null).findEnclosingNode(charStart, length); + return node; + } + + /** + * Get the enclosing node using the input marker + * @param marker The marker + * @param ast The AST + * @return The node or null + * @since 3.5 + */ + protected IASTNode getASTNodeFromMarker(IMarker marker, IASTTranslationUnit ast) { + final int charStart = marker.getAttribute(IMarker.CHAR_START, -1); + final int length = marker.getAttribute(IMarker.CHAR_END, -1) - charStart; + return getASTNodeFromPosition(ast, charStart, length); + } } |