# HG changeset patch # Parent 9668265424036f56c1242fd96ab6cd58a1be233a diff -r 966826542403 -r 679fced0dff0 java.hints/src/org/netbeans/modules/java/hints/bugs/Bundle.properties --- a/java.hints/src/org/netbeans/modules/java/hints/bugs/Bundle.properties Thu Jan 26 22:35:21 2012 +0100 +++ b/java.hints/src/org/netbeans/modules/java/hints/bugs/Bundle.properties Mon Jan 30 15:28:04 2012 +0100 @@ -119,6 +119,6 @@ ERR_UnbalancedCollectionREAD=The collection is never added to ERR_UnbalancedCollectionWRITE=The collection is only added to, never read -DN_org.netbeans.modules.java.hints.bugs.CheckReturnValueHint=@CheckReturnValue -DESC_org.netbeans.modules.java.hints.bugs.CheckReturnValueHint=Verifies that a result of method marked with @CheckReturnValue is really checked. +#DN_org.netbeans.modules.java.hints.bugs.CheckReturnValueHint=@CheckReturnValue +#DESC_org.netbeans.modules.java.hints.bugs.CheckReturnValueHint=Verifies that a result of method marked with @CheckReturnValue is really checked. ERR_org.netbeans.modules.java.hints.bugs.CheckReturnValueHint=Should check the method return value diff -r 966826542403 -r 679fced0dff0 java.hints/src/org/netbeans/modules/java/hints/bugs/CheckReturnValueHint.java --- a/java.hints/src/org/netbeans/modules/java/hints/bugs/CheckReturnValueHint.java Thu Jan 26 22:35:21 2012 +0100 +++ b/java.hints/src/org/netbeans/modules/java/hints/bugs/CheckReturnValueHint.java Mon Jan 30 15:28:04 2012 +0100 @@ -59,7 +59,7 @@ * * @author lahvac */ -@Hint(category="bugs", suppressWarnings="ResultOfMethodCallIgnored") +@Hint(displayName="@CheckReturnValue", description="Verifies that a result of method marked with @CheckReturnValue is really checked.", category="bugs", suppressWarnings="ResultOfMethodCallIgnored") public class CheckReturnValueHint { @TriggerPattern("$method($params$);") diff -r 966826542403 -r 679fced0dff0 openide.util/nbproject/project.xml --- a/openide.util/nbproject/project.xml Thu Jan 26 22:35:21 2012 +0100 +++ b/openide.util/nbproject/project.xml Mon Jan 30 15:28:04 2012 +0100 @@ -81,6 +81,7 @@ org.openide org.openide.util org.openide.util.actions + org.openide.util.annotations org.openide.util.datatransfer org.openide.util.io org.openide.xml diff -r 966826542403 -r 679fced0dff0 openide.util/src/org/netbeans/modules/openide/util/NbBundleProcessor.java --- a/openide.util/src/org/netbeans/modules/openide/util/NbBundleProcessor.java Thu Jan 26 22:35:21 2012 +0100 +++ b/openide.util/src/org/netbeans/modules/openide/util/NbBundleProcessor.java Mon Jan 30 15:28:04 2012 +0100 @@ -73,17 +73,18 @@ import org.openide.util.EditableProperties; import org.openide.util.NbBundle; import org.openide.util.Utilities; +import org.openide.util.annotations.AbstractBundleProcessor; import org.openide.util.lookup.ServiceProvider; @ServiceProvider(service = Processor.class) @SupportedSourceVersion(SourceVersion.RELEASE_6) -public class NbBundleProcessor extends AbstractProcessor { +public class NbBundleProcessor extends AbstractBundleProcessor { public @Override Set getSupportedAnnotationTypes() { return Collections.singleton(NbBundle.Messages.class.getCanonicalName()); } - public @Override boolean process(Set annotations, RoundEnvironment roundEnv) { + protected @Override boolean handleProcess(Set annotations, RoundEnvironment roundEnv) { if (roundEnv.processingOver()) { return false; } @@ -149,10 +150,14 @@ String value = keyValue.substring(i + 1); pairs.put(key, value); compilationUnits.put(key, simplename); + String[] keyComments; if (!runningComments.isEmpty()) { - comments.put(key, runningComments.toArray(new String[runningComments.size()])); + comments.put(key, keyComments = runningComments.toArray(new String[runningComments.size()])); runningComments.clear(); + } else { + keyComments = new String[0]; } + setBundleKey(pkg, key, new Value(value, keyComments, new Element[] {e})); } if (!runningComments.isEmpty()) { processingEnv.getMessager().printMessage(Kind.ERROR, "Comments must precede keys", e); @@ -160,47 +165,47 @@ } Element[] elements = new HashSet(identifiers.values()).toArray(new Element[0]); try { - EditableProperties p = new EditableProperties(true); - // Load any preexisting bundle so we can just add our keys. - try { - InputStream is = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, pkg, "Bundle.properties").openInputStream(); - try { - p.load(is); - } finally { - is.close(); - } - } catch (IOException x) { - // OK, not there - } - for (String key : p.keySet()) { - if (pairs.containsKey(key)) { - processingEnv.getMessager().printMessage(Kind.ERROR, "Key " + key + " is a duplicate of one from Bundle.properties", identifiers.get(toIdentifier(key))); - } - } - // Also check class output for (1) incremental builds, (2) preexisting bundles from Maven projects. - try { - InputStream is = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, pkg, "Bundle.properties").openInputStream(); - try { - // do not use p.load(is) as the impl in EditableProperties does not currently handle duplicates properly - EditableProperties p2 = new EditableProperties(true); - p2.load(is); - p.putAll(p2); - } finally { - is.close(); - } - } catch (IOException x) { - // OK, not there - } - p.putAll(pairs); - for (Map.Entry entry2 : comments.entrySet()) { - p.setComment(entry2.getKey(), entry2.getValue(), false); - } - OutputStream os = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, pkg, "Bundle.properties", elements).openOutputStream(); - try { - p.store(os); - } finally { - os.close(); - } +// EditableProperties p = new EditableProperties(true); +// // Load any preexisting bundle so we can just add our keys. +// try { +// InputStream is = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, pkg, "Bundle.properties").openInputStream(); +// try { +// p.load(is); +// } finally { +// is.close(); +// } +// } catch (IOException x) { +// // OK, not there +// } +// for (String key : p.keySet()) { +// if (pairs.containsKey(key)) { +// processingEnv.getMessager().printMessage(Kind.ERROR, "Key " + key + " is a duplicate of one from Bundle.properties", identifiers.get(toIdentifier(key))); +// } +// } +// // Also check class output for (1) incremental builds, (2) preexisting bundles from Maven projects. +// try { +// InputStream is = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, pkg, "Bundle.properties").openInputStream(); +// try { +// // do not use p.load(is) as the impl in EditableProperties does not currently handle duplicates properly +// EditableProperties p2 = new EditableProperties(true); +// p2.load(is); +// p.putAll(p2); +// } finally { +// is.close(); +// } +// } catch (IOException x) { +// // OK, not there +// } +// p.putAll(pairs); +// for (Map.Entry entry2 : comments.entrySet()) { +// p.setComment(entry2.getKey(), entry2.getValue(), false); +// } +// OutputStream os = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, pkg, "Bundle.properties", elements).openOutputStream(); +// try { +// p.store(os); +// } finally { +// os.close(); +// } Map methods = new TreeMap(); for (Map.Entry entry2 : pairs.entrySet()) { String key = entry2.getKey(); diff -r 966826542403 -r 679fced0dff0 openide.util/src/org/openide/util/annotations/AbstractBundleProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/openide.util/src/org/openide/util/annotations/AbstractBundleProcessor.java Mon Jan 30 15:28:04 2012 +0100 @@ -0,0 +1,179 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.openide.util.annotations; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintWriter; +import java.io.Writer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.Diagnostic.Kind; +import javax.tools.StandardLocation; +import org.netbeans.modules.openide.util.NbBundleProcessor; +import org.openide.util.EditableProperties; + +/** + * + * @author lahvac + */ +public abstract class AbstractBundleProcessor extends AbstractProcessor { + + private Map> package2Keys2Values = new HashMap>(); + + @Override + public final boolean process(Set annotations, RoundEnvironment roundEnv) { + if (!roundEnv.processingOver()) { + return handleProcess(annotations, roundEnv); + } + + List totalElements = new ArrayList(); + + for (Entry> e : package2Keys2Values.entrySet()) { + String pkg = e.getKey(); + Map key2Value = e.getValue(); + + try { + EditableProperties p = new EditableProperties(true); + // Load any preexisting bundle so we can just add our keys. + try { + InputStream is = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, pkg, "Bundle.properties").openInputStream(); + try { + p.load(is); + } finally { + is.close(); + } + } catch (IOException x) { + // OK, not there + } + for (String key : p.keySet()) { + if (key2Value.containsKey(key)) { + Element[] originatingElements = key2Value.get(key).originatingElements; + if (originatingElements.length == 0) { + processingEnv.getMessager().printMessage(Kind.ERROR, "Key " + key + " is a duplicate of one from Bundle.properties"); + } else { + processingEnv.getMessager().printMessage(Kind.ERROR, "Key " + key + " is a duplicate of one from Bundle.properties", originatingElements[0]); + } + } + } + // Also check class output for (1) incremental builds, (2) preexisting bundles from Maven projects. + try { + InputStream is = processingEnv.getFiler().getResource(StandardLocation.CLASS_OUTPUT, pkg, "Bundle.properties").openInputStream(); + try { + // do not use p.load(is) as the impl in EditableProperties does not currently handle duplicates properly + EditableProperties p2 = new EditableProperties(true); + p2.load(is); + p.putAll(p2); + } finally { + is.close(); + } + } catch (IOException x) { + // OK, not there + } + + for (Entry valEntry : key2Value.entrySet()) { + p.put(valEntry.getKey(), valEntry.getValue().value); + p.setComment(valEntry.getKey(), valEntry.getValue().comments, false); + totalElements.addAll(Arrays.asList(valEntry.getValue().originatingElements)); + } + OutputStream os = processingEnv.getFiler().createResource(StandardLocation.CLASS_OUTPUT, pkg, "Bundle.properties", totalElements.toArray(new Element[0])).openOutputStream(); + try { + p.store(os); + } finally { + os.close(); + } + } catch (IOException x) { + if (totalElements.isEmpty()) { + processingEnv.getMessager().printMessage(Kind.ERROR, "Could not generate files: " + x); + } else { + processingEnv.getMessager().printMessage(Kind.ERROR, "Could not generate files: " + x, totalElements.get(0)); + } + } + } + + return true; + } + + protected abstract boolean handleProcess(Set annotations, RoundEnvironment roundEnv); + + protected final void setBundleKey(String pkg, String key, Value value) { + Map key2Value = package2Keys2Values.get(pkg); + + if (key2Value == null) { + package2Keys2Values.put(pkg, key2Value = new HashMap()); + } + + if (key2Value.containsKey(key)) { + throw new IllegalStateException("Key already exists: " + key); + } + + key2Value.put(key, value); + } + + public static final class Value { + private final String value; + private final String[] comments; + private final Element[] originatingElements; + + public Value(String value, String[] comments, Element[] originatingElements) { + this.value = value; + this.comments = comments; + this.originatingElements = originatingElements; + } + + } + +} diff -r 966826542403 -r 679fced0dff0 spi.java.hints/src/org/netbeans/modules/java/hints/providers/code/CodeHintProviderImpl.java --- a/spi.java.hints/src/org/netbeans/modules/java/hints/providers/code/CodeHintProviderImpl.java Thu Jan 26 22:35:21 2012 +0100 +++ b/spi.java.hints/src/org/netbeans/modules/java/hints/providers/code/CodeHintProviderImpl.java Mon Jan 30 15:28:04 2012 +0100 @@ -381,6 +381,16 @@ return EMPTY_OPTIONS; } + @Override + public String displayName() { + return ""; + } + + @Override + public String description() { + return ""; + } + } private static final class JComponentBasedCustomizerProvider implements CustomizerProvider { diff -r 966826542403 -r 679fced0dff0 spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/processor/BundleProcessor.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/processor/BundleProcessor.java Mon Jan 30 15:28:04 2012 +0100 @@ -0,0 +1,89 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2012 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2012 Sun Microsystems, Inc. + */ +package org.netbeans.modules.java.hints.spiimpl.processor; + +import java.util.Set; +import javax.annotation.processing.Processor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedAnnotationTypes; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.Element; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import org.netbeans.spi.java.hints.Hint; +import org.openide.util.annotations.AbstractBundleProcessor; +import org.openide.util.lookup.ServiceProvider; + +/** + * + * @author lahvac + */ +@SupportedSourceVersion(SourceVersion.RELEASE_6) +@SupportedAnnotationTypes("org.netbeans.spi.java.hints.Hint") +@ServiceProvider(service=Processor.class, position=150) +public class BundleProcessor extends AbstractBundleProcessor { + + @Override + protected boolean handleProcess(Set annotations, RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) return false; + + TypeElement hint = processingEnv.getElementUtils().getTypeElement(Hint.class.getName()); + + if (hint == null) return false; + + for (Element annotated : roundEnv.getElementsAnnotatedWith(hint)) { + String id = JavaHintsAnnotationProcessor.hintId(processingEnv, annotated); + PackageElement pe = processingEnv.getElementUtils().getPackageOf(annotated); + Hint hintObj = annotated.getAnnotation(Hint.class); + if (!hintObj.displayName().isEmpty()) { + setBundleKey(pe.getQualifiedName().toString(), "DN_" + id, new Value(hintObj.displayName(), new String[0], new Element[] {annotated})); + } + if (!hintObj.description().isEmpty()) { + setBundleKey(pe.getQualifiedName().toString(), "DESC_" + id, new Value(hintObj.description(), new String[0], new Element[] {annotated})); + } + } + + return false; + } + +} diff -r 966826542403 -r 679fced0dff0 spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/processor/JavaHintsAnnotationProcessor.java --- a/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/processor/JavaHintsAnnotationProcessor.java Thu Jan 26 22:35:21 2012 +0100 +++ b/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/processor/JavaHintsAnnotationProcessor.java Mon Jan 30 15:28:04 2012 +0100 @@ -60,6 +60,7 @@ import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; +import javax.annotation.processing.ProcessingEnvironment; import javax.annotation.processing.Processor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; @@ -242,9 +243,9 @@ return null; } - private T getAttributeValue(AnnotationMirror annotation, String attribute, Class clazz) { + private static T getAttributeValue(ProcessingEnvironment processingEnv, AnnotationMirror annotation, String attribute, Class clazz) { if (clazz.isArray()) { - Iterable attributes = getAttributeValueInternal(annotation, attribute, Iterable.class); + Iterable attributes = getAttributeValueInternal(processingEnv, annotation, attribute, Iterable.class); Collection coll = new ArrayList(); for (Object internal : NbCollections.iterable(NbCollections.checkedIteratorByFilter(attributes.iterator(), clazz.getComponentType(), false))) { @@ -253,11 +254,11 @@ return clazz.cast(coll.toArray((Object[]) Array.newInstance(clazz.getComponentType(), 0))); } else { - return getAttributeValueInternal(annotation, attribute, clazz); + return getAttributeValueInternal(processingEnv, annotation, attribute, clazz); } } - private T getAttributeValueInternal(AnnotationMirror annotation, String attribute, Class clazz) { + private static T getAttributeValueInternal(ProcessingEnvironment processingEnv, AnnotationMirror annotation, String attribute, Class clazz) { for (Entry e : processingEnv.getElementUtils().getElementValuesWithDefaults(annotation).entrySet()) { if (e.getKey().getSimpleName().contentEquals(attribute)) { Object value = e.getValue().getValue(); @@ -283,11 +284,11 @@ return null; } - private String hintId(Element hint) { + static String hintId(ProcessingEnvironment processingEnv, Element hint) { AnnotationMirror hintMirror = findAnnotation(hint.getAnnotationMirrors(), "org.netbeans.spi.java.hints.Hint"); if (hintMirror != null) { - String id = getAttributeValue(hintMirror, "id", String.class); + String id = getAttributeValue(processingEnv, hintMirror, "id", String.class); if (id != null && !id.isEmpty()) return id; } @@ -305,7 +306,7 @@ } private boolean verifyHintAnnotationAcceptable(Element hint) { - String id = hintId(hint); + String id = hintId(processingEnv, hint); if (id == null) { return false; @@ -320,8 +321,8 @@ FileObject bundle = processingEnv.getFiler().getResource(StandardLocation.SOURCE_PATH, ((PackageElement) hintPackage).getQualifiedName(), "Bundle.properties"); ResourceBundle rb = new PropertyResourceBundle(bundle.openInputStream()); - checkBundle(rb, "DN_" + id, hint); - checkBundle(rb, "DESC_" + id, hint); +// checkBundle(rb, "DN_" + id, hint); +// checkBundle(rb, "DESC_" + id, hint); } catch (IOException ex) { LOG.log(Level.FINE, null, ex); } catch (IllegalArgumentException ex) { @@ -396,11 +397,11 @@ am = findAnnotation(method.getAnnotationMirrors(), "org.netbeans.spi.java.hints.TriggerPatterns"); if (am != null) { - patternAnnotations.addAll(Arrays.asList(getAttributeValue(am, "value", AnnotationMirror[].class))); + patternAnnotations.addAll(Arrays.asList(getAttributeValue(processingEnv, am, "value", AnnotationMirror[].class))); } for (AnnotationMirror patternDescription : patternAnnotations) { - String pattern = getAttributeValue(patternDescription, "value", String.class); + String pattern = getAttributeValue(processingEnv, patternDescription, "value", String.class); if (pattern == null) continue; @@ -411,9 +412,9 @@ variables.add(m.group(0)); } - for (AnnotationMirror constraint : getAttributeValue(patternDescription, "constraints", AnnotationMirror[].class)) { - String variable = getAttributeValue(constraint, "variable", String.class); - String type = getAttributeValue(constraint, "type", String.class); + for (AnnotationMirror constraint : getAttributeValue(processingEnv, patternDescription, "constraints", AnnotationMirror[].class)) { + String variable = getAttributeValue(processingEnv, constraint, "variable", String.class); + String type = getAttributeValue(processingEnv, constraint, "type", String.class); if (variable == null || type == null) continue; diff -r 966826542403 -r 679fced0dff0 spi.java.hints/src/org/netbeans/spi/java/hints/Hint.java --- a/spi.java.hints/src/org/netbeans/spi/java/hints/Hint.java Thu Jan 26 22:35:21 2012 +0100 +++ b/spi.java.hints/src/org/netbeans/spi/java/hints/Hint.java Mon Jan 30 15:28:04 2012 +0100 @@ -63,6 +63,8 @@ * from previous version. Id will be generated automatically is not specified. */ public String id() default ""; + public String displayName() default ""; + public String description() default ""; /**Category where the hint belongs. */ public String category();