我将鼠标悬停在String文字上时,需要创建一个显示工具提示的Eclipse插件。
但仅当该字符串文字是特殊方法的第一个参数时。
这是我用来测试插件的Test.java文件:
package test;
public class Test {
public static void main(String[] args) {
String hello = "Hello";
String world = Translator.get("Test.worldLabel");
System.out.println(hello + " " + world);
}
}
我创建了一个实现IJavaEditorTextHover的类,并且需要编译当前编辑的Java文件以计算光标是否悬停在需要翻译的String上。
最初,我使用了这个(170位于“Test.worldLabel”内部):
ITypeRoot typeRoot = (ITypeRoot)
JavaUI.getEditorInputJavaElement(editorPart.getEditorInput());
JavaElement foundElement = (JavaElement) typeRoot.getElementAt(170);
但是foundElement包含整个main()方法:它的粒度不够细。
然后,我认为正确的方法是:
private static ASTNode parse(ICompilationUnit unit, int position) {
ASTParser parser = ASTParser.newParser(AST.JLS3);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setSource(unit);
parser.setResolveBindings(true);
parser.setIgnoreMethodBodies(false);
// TODO Future optimisation: parser.setFocalPosition(position);
return parser.createAST((IProgressMonitor) null); // parse
}
在我的IJavaEditorTextHover.getHoverInfo(...)实现中:
ICompilationUnit compilationUnit = (ICompilationUnit)
JavaUI.getEditorInputJavaElement(editor.getEditorInput())
int position = 170/*hoverRegion.getOffset()*/;
ASTNode ast = parse(compilationUnit, position);
现在,这是我的问题:
如何从这个ast节点获取如何在源代码中的位置170(“Test.worldLabel”字符串)上表示StringLiteral的ASTNode?
奖励问题:我选择了正确的解决方案吗?基于性能。
编辑:
好吧,这是我找到的解决方案:
private StringLiteral findStringLiteralAtPosition(final ASTNode parent, final int position) {
final List<StringLiteral> stringLiterals = new ArrayList<StringLiteral>();
parent.accept(new ASTVisitor() {
@Override
public boolean visit(StringLiteral stringLiteral) {
int start = stringLiteral.getStartPosition();
int end = start + stringLiteral.getLength();
if (start <= position && position <= end) {
stringLiterals.add(stringLiteral);
}
return super.visit(stringLiteral);
}
});
return (stringLiterals.size() > 0 ? stringLiterals.get(0) : null);
}
可以接缝吗?
还是更简单或更高效的方法?
最佳答案
一种解决方案将根本不使用偏移逻辑。
您可以使用节点父检查来概括解决方案。
这是一个示例代码:
public boolean visit(StringLiteral stringLiteral) {
// Check if parent is a method inovacation.
if (stringLiteral.getParent().getNodeType() == ASTNode.METHOD_INVOCATION) {
// get the parent method inovacation.
MethodInvocation miNode = (MethodInvocation) stringLiteral.getParent();
//To do: null and empty check on argument list.
// Check if is the special method and this is the 1st argument
if (miNode.getName().toString().equals("SpecialMethod")
&& miNode.arguments().get(0).toString().equals(stringLiteral.toString())) {
System.out.println("Found it : " + stringLiteral.toString());
}
}
return true;
}