3

文字列リテラルの上にマウスを置くとツールチップを表示する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ファイルをコンパイルして、カーソルが翻訳する必要のある文字列にカーソルを合わせているかどうかを計算する必要があります。

  • 「Hello」にカーソルを合わせると何も起こりません。
  • 「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ノードから、ソースコード(「Test.worldLabel」文字列)の位置170にある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);
}

縫い目は大丈夫ですか?それとも、より簡単な方法ですか、それともよりパフォーマンスの高い方法ですか?

4

1 に答える 1

1

1つの解決策は、オフセットロジックをまったく使用しないことです。ノードの親チェックを使用して、ソリューションを一般化できます。

サンプルコードは次のとおりです。

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;
    }
于 2013-02-19T14:33:46.523 に答える