我需要创建一个 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 文件来计算光标是否悬停在需要翻译的字符串上。
- 悬停“你好”不会有任何作用。
- 悬停“Test.worldLabel”将显示我的工具提示,因为该文字包含在 Translator.get() 方法调用中。
起初我用这个(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 处的 StringLiteral 的 ASTNode(“Test.worldLabel”字符串)?
额外的问题:我选择了正确的解决方案吗?在性能的基础上。
编辑: 嗯,这是我找到的解决方案:
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);
}
接缝好吗?还是一种更简单的方法或更高效的方法?