3

Мне нужно создать плагин Eclipse, который отображает всплывающую подсказку, когда я наводил указатель мыши на строковый литерал. Но только если этот строковый литерал является первым параметром специального метода.Как перейти к StringLiterals с Eclipse AST?

Вот файл 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 содержит метод весь основной(): это не достаточно мелкозернистая.

Тогда правильный путь, я думаю:

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); 

И теперь, вот мой вопрос:

Как, с этого узла, я получаю ASTNode, выдающий StringLiteral в позиции 170 в исходном коде («Test.worldLabel» St кольцо)?

Бонус вопрос: я выбрал правильное решение? На основе результатов.


Edit: Ну, вот решение, которое я нашел:

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); 
} 

ли шов ОК? Или это более простой способ или более эффективный?

ответ

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; 
    } 

 Смежные вопросы

  • Нет связанных вопросов^_^