mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-04-29 19:45:01 +02:00
Bug 355174 - Added quickfix for miss cases/default
Change-Id: I4c815bd55e55d81456efa796453dd2f69a7c876a Signed-off-by: Marco Stornelli <marco.stornelli@gmail.com>
This commit is contained in:
parent
a009b41021
commit
3890eec7b7
11 changed files with 396 additions and 3 deletions
|
@ -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,
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
<plugin>
|
||||
<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=".*">
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
|
@ -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"
|
||||
QuickFixSuppressProblem_Label=Suppress problem "%s"
|
||||
QuickFixAddDefaultSwitch_add_default_to_switch=Add default to switch
|
||||
QuickFixAddCaseSwitch_add_cases_to_switch=Add missing cases to switch
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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$
|
||||
}
|
||||
}
|
|
@ -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$
|
||||
}
|
||||
|
||||
}
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue