diff -r 8205d68aead0 apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/UseNbBundleMessages.java --- a/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/UseNbBundleMessages.java Fri Sep 09 10:21:12 2011 +0200 +++ b/apisupport.refactoring/src/org/netbeans/modules/apisupport/hints/UseNbBundleMessages.java Fri Sep 09 10:21:28 2011 +0200 @@ -89,6 +89,7 @@ import com.sun.source.tree.Tree.Kind; import com.sun.source.util.SourcePositions; import com.sun.source.util.TreePath; +import org.netbeans.api.java.source.TreePathHandle; public class UseNbBundleMessages extends AbstractHint { @@ -225,163 +226,198 @@ return warning(UseNbBundleMessages_no_such_key(key), span, compilationInfo); } } - return Collections.singletonList(ErrorDescriptionFactory.createErrorDescription(getSeverity().toEditorSeverity(), UseNbBundleMessages_error_text(), Collections.singletonList(new Fix() { - public @Override String getText() { - return UseNbBundleMessages_displayName(); + return Collections.singletonList(ErrorDescriptionFactory.createErrorDescription(getSeverity().toEditorSeverity(), UseNbBundleMessages_error_text(), Collections.singletonList(new MyFix(src, key, TreePathHandle.create(treePath, compilationInfo), isAlreadyRegistered, ep, bundleProperties)), compilationInfo.getFileObject(), span[0], span[1])); + } + + private static class MyFix implements Fix { + + final private FileObject src; + final String key; + final private TreePathHandle treePathHandle; + final boolean isAlreadyRegistered; + final EditableProperties ep; + final FileObject bundleProperties; + + private MyFix(FileObject src, String key, TreePathHandle treePathHandle, boolean isAlreadyRegistered, EditableProperties ep, FileObject bundleProperties) { + this.src = src; + this.key = key; + this.treePathHandle = treePathHandle; + this.isAlreadyRegistered = isAlreadyRegistered; + this.ep = ep; + this.bundleProperties = bundleProperties; + } + + public @Override String getText() { + return UseNbBundleMessages_displayName(); + } + public @Override ChangeInfo implement() throws Exception { + JavaSource js = JavaSource.forFileObject(src); + if (js == null) { + throw new Exception("No source info for " + src); } - public @Override ChangeInfo implement() throws Exception { - JavaSource js = JavaSource.forFileObject(src); - if (js == null) { - throw new Exception("No source info for " + src); - } - js.runModificationTask(new Task() { - public @Override void run(WorkingCopy wc) throws Exception { - wc.toPhase(JavaSource.Phase.RESOLVED); - TreeMaker make = wc.getTreeMaker(); - if (mit != null) { - CompilationUnitTree cut = wc.getCompilationUnit(); - boolean imported = false; - String importBundleStar = cut.getPackageName() + ".Bundle.*"; - for (ImportTree it : cut.getImports()) { - if (it.isStatic() && it.getQualifiedIdentifier().toString().equals(importBundleStar)) { - imported = true; - break; - } - } - if (!imported) { - wc.rewrite(cut, make.addCompUnitImport(cut, make.Import(make.Identifier(importBundleStar), true))); - } - List args = mit.getArguments(); - List params; - if (args.size() == 3 && args.get(2).getKind() == Kind.NEW_ARRAY) { - params = ((NewArrayTree) args.get(2)).getInitializers(); - } else { - params = args.subList(2, args.size()); - } - wc.rewrite(mit, make.MethodInvocation(Collections.emptyList(), make.Identifier(toIdentifier(key)), params)); - } // else annotation value, nothing to change - if (!isAlreadyRegistered) { - Tree enclosing = findEnclosingElement(wc, treePath); - Tree modifiers; - if (enclosing.getKind() == Kind.METHOD) { - modifiers = ((MethodTree) enclosing).getModifiers(); - } else if (enclosing.getKind() == Kind.COMPILATION_UNIT) { - modifiers = enclosing; - } else { - modifiers = ((ClassTree) enclosing).getModifiers(); - } - List lines = new ArrayList(); - for (String comment : ep.getComment(key)) { - lines.add(make.Literal(comment)); - } - lines.add(make.Literal(key + '=' + ep.remove(key))); - wc.rewrite(modifiers, addMessage(wc, modifiers, lines)); - } - // XXX remove NbBundle import if now unused - } - // borrowed from FindBugsHint: - private Tree addMessage(WorkingCopy wc, /*Modifiers|CompilationUnit*/Tree original, List lines) throws Exception { - TreeMaker make = wc.getTreeMaker(); - // First try to insert into a value list for an existing annotation: - List anns; - if (original.getKind() == Kind.COMPILATION_UNIT) { - anns = ((CompilationUnitTree) original).getPackageAnnotations(); - } else { - anns = ((ModifiersTree) original).getAnnotations(); - } - for (int i = 0; i < anns.size(); i++) { - AnnotationTree ann = anns.get(i); - Tree annotationType = ann.getAnnotationType(); - // XXX clumsy and imprecise, but how to find the FQN of the annotation type given a Tree? Want a TypeMirror for it. - if (annotationType.toString().matches("((org[.]openide[.]util[.])?NbBundle[.])?Messages")) { - List args = ann.getArguments(); - if (args.size() != 1) { - throw new Exception("expecting just one arg for @Messages"); - } - AssignmentTree assign = (AssignmentTree) args.get(0); - if (!assign.getVariable().toString().equals("value")) { - throw new Exception("expected value=... for @Messages"); - } - ExpressionTree arg = assign.getExpression(); - NewArrayTree arr; - if (arg.getKind() == Tree.Kind.STRING_LITERAL) { - arr = make.NewArray(null, Collections.emptyList(), Collections.singletonList(arg)); - } else if (arg.getKind() == Tree.Kind.NEW_ARRAY) { - arr = (NewArrayTree) arg; - } else { - throw new Exception("unknown arg kind " + arg.getKind() + ": " + arg); - } - for (ExpressionTree line : lines) { - arr = make.addNewArrayInitializer(arr, line); - } - ann = make.Annotation(annotationType, Collections.singletonList(arr)); - if (original.getKind() == Kind.COMPILATION_UNIT) { - CompilationUnitTree cut = (CompilationUnitTree) original; - List newAnns = new ArrayList(anns); - newAnns.set(i, ann); - return make.CompilationUnit(newAnns, cut.getPackageName(), cut.getImports(), cut.getTypeDecls(), cut.getSourceFile()); - } else { - return make.insertModifiersAnnotation(make.removeModifiersAnnotation((ModifiersTree) original, i), i, ann); - } + js.runModificationTask(new Task() { + public @Override void run(WorkingCopy wc) throws Exception { + wc.toPhase(JavaSource.Phase.RESOLVED); + TreeMaker make = wc.getTreeMaker(); + final TreePath treePath = treePathHandle.resolve(wc); + final MethodInvocationTree mit = treePath.getLeaf().getKind() == Tree.Kind.METHOD_INVOCATION ? (MethodInvocationTree)treePath.getLeaf() : null; + if (mit != null) { + CompilationUnitTree cut = wc.getCompilationUnit(); + boolean imported = false; + String importBundleStar = cut.getPackageName() + ".Bundle.*"; + for (ImportTree it : cut.getImports()) { + if (it.isStatic() && it.getQualifiedIdentifier().toString().equals(importBundleStar)) { + imported = true; + break; } } - // Not found, so create a new annotation: - List values; - if (lines.size() > 1) { // @Messages({"# ...", "k=v"}) - values = Collections.singletonList(make.NewArray(null, Collections.emptyList(), lines)); - } else { // @Messages("k=v") - values = lines; + if (!imported) { + wc.rewrite(cut, make.addCompUnitImport(cut, make.Import(make.Identifier(importBundleStar), true))); } - AnnotationTree atMessages = make.Annotation(make.QualIdent("org.openide.util.NbBundle.Messages"), values); - Tree result; - if (original.getKind() == Kind.COMPILATION_UNIT) { - CompilationUnitTree cut = (CompilationUnitTree) original; - List newAnns = new ArrayList(anns); - newAnns.add(atMessages); - result = make.CompilationUnit(newAnns, cut.getPackageName(), cut.getImports(), cut.getTypeDecls(), cut.getSourceFile()); + List args = mit.getArguments(); + List params; + if (args.size() == 3 && args.get(2).getKind() == Kind.NEW_ARRAY) { + params = ((NewArrayTree) args.get(2)).getInitializers(); } else { - result = make.addModifiersAnnotation((ModifiersTree) original, atMessages); + params = args.subList(2, args.size()); } - return GeneratorUtilities.get(wc).importFQNs(result); + wc.rewrite(mit, make.MethodInvocation(Collections.emptyList(), make.Identifier(toIdentifier(key)), params)); + } // else annotation value, nothing to change + if (!isAlreadyRegistered) { + Tree enclosing = findEnclosingElement(wc, treePath); + Tree modifiers; + if (enclosing.getKind() == Kind.METHOD) { + modifiers = ((MethodTree) enclosing).getModifiers(); + } else if (enclosing.getKind() == Kind.COMPILATION_UNIT) { + modifiers = enclosing; + } else { + modifiers = ((ClassTree) enclosing).getModifiers(); + } + List lines = new ArrayList(); + for (String comment : ep.getComment(key)) { + lines.add(make.Literal(comment)); + } + lines.add(make.Literal(key + '=' + ep.remove(key))); + wc.rewrite(modifiers, addMessage(wc, modifiers, lines)); } - private Tree findEnclosingElement(WorkingCopy wc, TreePath treePath) { - Tree leaf = treePath.getLeaf(); - Kind kind = leaf.getKind(); - switch (kind) { - case CLASS: - case ENUM: - case INTERFACE: - case ANNOTATION_TYPE: - case METHOD: // (or constructor) - Element e = wc.getTrees().getElement(treePath); - if (e != null) { - TypeElement type = kind == Kind.METHOD ? wc.getElementUtilities().enclosingTypeElement(e) : (TypeElement) e; - if (type == null || !wc.getElementUtilities().isLocal(type)) { - return leaf; - } // else part of an inner class + // XXX remove NbBundle import if now unused + } + // borrowed from FindBugsHint: + private Tree addMessage(WorkingCopy wc, /*Modifiers|CompilationUnit*/Tree original, List lines) throws Exception { + TreeMaker make = wc.getTreeMaker(); + // First try to insert into a value list for an existing annotation: + List anns; + if (original.getKind() == Kind.COMPILATION_UNIT) { + anns = ((CompilationUnitTree) original).getPackageAnnotations(); + } else { + anns = ((ModifiersTree) original).getAnnotations(); + } + for (int i = 0; i < anns.size(); i++) { + AnnotationTree ann = anns.get(i); + Tree annotationType = ann.getAnnotationType(); + // XXX clumsy and imprecise, but how to find the FQN of the annotation type given a Tree? Want a TypeMirror for it. + if (annotationType.toString().matches("((org[.]openide[.]util[.])?NbBundle[.])?Messages")) { + List args = ann.getArguments(); + if (args.size() != 1) { + throw new Exception("expecting just one arg for @Messages"); } - break; - case COMPILATION_UNIT: - return leaf; + AssignmentTree assign = (AssignmentTree) args.get(0); + if (!assign.getVariable().toString().equals("value")) { + throw new Exception("expected value=... for @Messages"); + } + ExpressionTree arg = assign.getExpression(); + NewArrayTree arr; + if (arg.getKind() == Tree.Kind.STRING_LITERAL) { + arr = make.NewArray(null, Collections.emptyList(), Collections.singletonList(arg)); + } else if (arg.getKind() == Tree.Kind.NEW_ARRAY) { + arr = (NewArrayTree) arg; + } else { + throw new Exception("unknown arg kind " + arg.getKind() + ": " + arg); + } + for (ExpressionTree line : lines) { + arr = make.addNewArrayInitializer(arr, line); + } + ann = make.Annotation(annotationType, Collections.singletonList(arr)); + if (original.getKind() == Kind.COMPILATION_UNIT) { + CompilationUnitTree cut = (CompilationUnitTree) original; + List newAnns = new ArrayList(anns); + newAnns.set(i, ann); + return make.CompilationUnit(newAnns, cut.getPackageName(), cut.getImports(), cut.getTypeDecls(), cut.getSourceFile()); + } else { + return make.insertModifiersAnnotation(make.removeModifiersAnnotation((ModifiersTree) original, i), i, ann); + } } - TreePath parentPath = treePath.getParentPath(); - if (parentPath == null) { - return null; + } + // Not found, so create a new annotation: + List values; + if (lines.size() > 1) { // @Messages({"# ...", "k=v"}) + values = Collections.singletonList(make.NewArray(null, Collections.emptyList(), lines)); + } else { // @Messages("k=v") + values = lines; + } + AnnotationTree atMessages = make.Annotation(make.QualIdent("org.openide.util.NbBundle.Messages"), values); + Tree result; + if (original.getKind() == Kind.COMPILATION_UNIT) { + CompilationUnitTree cut = (CompilationUnitTree) original; + List newAnns = new ArrayList(anns); + newAnns.add(atMessages); + result = make.CompilationUnit(newAnns, cut.getPackageName(), cut.getImports(), cut.getTypeDecls(), cut.getSourceFile()); + } else { + result = make.addModifiersAnnotation((ModifiersTree) original, atMessages); + } + return GeneratorUtilities.get(wc).importFQNs(result); + } + private Tree findEnclosingElement(WorkingCopy wc, TreePath treePath) { + Tree leaf = treePath.getLeaf(); + Kind kind = leaf.getKind(); + switch (kind) { + case CLASS: + case ENUM: + case INTERFACE: + case ANNOTATION_TYPE: + case METHOD: // (or constructor) + Element e = wc.getTrees().getElement(treePath); + if (e != null) { + TypeElement type = kind == Kind.METHOD ? wc.getElementUtilities().enclosingTypeElement(e) : (TypeElement) e; + if (type == null || !wc.getElementUtilities().isLocal(type)) { + return leaf; + } // else part of an inner class } - return findEnclosingElement(wc, parentPath); + break; + case COMPILATION_UNIT: + return leaf; } - }).commit(); - if (!isAlreadyRegistered) { - OutputStream os = bundleProperties.getOutputStream(); - try { - ep.store(os); - } finally { - os.close(); + TreePath parentPath = treePath.getParentPath(); + if (parentPath == null) { + return null; } + return findEnclosingElement(wc, parentPath); } - return null; + }).commit(); + if (!isAlreadyRegistered) { + OutputStream os = bundleProperties.getOutputStream(); + try { + ep.store(os); + } finally { + os.close(); + } } - }), compilationInfo.getFileObject(), span[0], span[1])); + return null; + } + + // Copied from NbBundleProcessor + private String toIdentifier(String key) { + if (Utilities.isJavaIdentifier(key)) { + return key; + } else { + String i = key.replaceAll("[^\\p{javaJavaIdentifierPart}]+", "_"); + if (Utilities.isJavaIdentifier(i)) { + return i; + } else { + return "_" + i; + } + } + } } private List warning(String text, int[] span, CompilationInfo compilationInfo) { @@ -392,20 +428,6 @@ // Probably nothing to do. } - // Copied from NbBundleProcessor - private String toIdentifier(String key) { - if (Utilities.isJavaIdentifier(key)) { - return key; - } else { - String i = key.replaceAll("[^\\p{javaJavaIdentifierPart}]+", "_"); - if (Utilities.isJavaIdentifier(i)) { - return i; - } else { - return "_" + i; - } - } - } - private static boolean isAlreadyRegistered(TreePath treePath, String key) { ModifiersTree modifiers; Tree tree = treePath.getLeaf();