From a50552b0a0e68cc43c0d241e7d460cf8791108df Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 10 Oct 2025 09:14:11 +0200 Subject: [PATCH 1/2] External (Java) annotations. --- .../java/hints/bugs/MagicConstantHint.java | 132 +++ .../modules/java/hints/bugs/NPECheck.java | 10 +- .../hints/bugs/MagicConstantHintTest.java | 135 +++ java/java.kit/nbproject/project.xml | 6 + .../nbproject/project.properties | 2 +- java/java.source.base/nbproject/project.xml | 8 + .../api/java/source/ElementUtilities.java | 16 + .../netbeans/api/java/source/SourceUtils.java | 5 + .../annotations/AugmentedAnnotations.java | 839 ++++++++++++++++++ .../annotations/AugmentedAnnotationsTest.java | 384 ++++++++ .../GenerateExternalAnnotationsMetadata.java | 444 +++++++++ java/libs.jdkannotations/build.xml | 31 + java/libs.jdkannotations/external/.gitignore | 1 + ...fdc7364be735ec4953f172db31130b-license.txt | 209 +++++ ...9fdc7364be735ec4953f172db31130b-notice.txt | 3 + .../external/binaries-list | 66 ++ java/libs.jdkannotations/manifest.mf | 7 + .../nbproject/project.properties | 19 + .../libs.jdkannotations/nbproject/project.xml | 31 + .../libs/jdkannotations/Bundle.properties | 18 + .../netbeans/libs/jdkannotations/layer.xml | 202 +++++ nbbuild/cluster.properties | 1 + 22 files changed, 2559 insertions(+), 10 deletions(-) create mode 100644 java/java.hints/src/org/netbeans/modules/java/hints/bugs/MagicConstantHint.java create mode 100644 java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/MagicConstantHintTest.java create mode 100644 java/java.source.base/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotations.java create mode 100644 java/java.source.base/test/unit/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotationsTest.java create mode 100644 java/libs.jdkannotations/GenerateExternalAnnotationsMetadata.java create mode 100644 java/libs.jdkannotations/build.xml create mode 100644 java/libs.jdkannotations/external/.gitignore create mode 100644 java/libs.jdkannotations/external/annotations-73943d0839fdc7364be735ec4953f172db31130b-license.txt create mode 100644 java/libs.jdkannotations/external/annotations-73943d0839fdc7364be735ec4953f172db31130b-notice.txt create mode 100644 java/libs.jdkannotations/external/binaries-list create mode 100644 java/libs.jdkannotations/manifest.mf create mode 100644 java/libs.jdkannotations/nbproject/project.properties create mode 100644 java/libs.jdkannotations/nbproject/project.xml create mode 100644 java/libs.jdkannotations/src/org/netbeans/libs/jdkannotations/Bundle.properties create mode 100644 java/libs.jdkannotations/src/org/netbeans/libs/jdkannotations/layer.xml diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/MagicConstantHint.java b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/MagicConstantHint.java new file mode 100644 index 000000000000..48e3c6f10fe8 --- /dev/null +++ b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/MagicConstantHint.java @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.hints.bugs; + +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.NewClassTree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.util.TreePath; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.util.ElementFilter; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.spi.editor.hints.ErrorDescription; +import org.netbeans.spi.java.hints.ErrorDescriptionFactory; +import org.netbeans.spi.java.hints.Hint; +import org.netbeans.spi.java.hints.HintContext; +import org.netbeans.spi.java.hints.TriggerTreeKind; +import org.openide.util.NbBundle.Messages; +import org.openide.util.NbCollections; + +@Hint(displayName="Magic Constant", description="Verifies magic constants", category="bugs") +public class MagicConstantHint { + + @TriggerTreeKind({Kind.METHOD_INVOCATION, Kind.NEW_CLASS}) + @Messages({ + "# {0} - the list of valid values", + "ERR_NotAValidValue=Not a valid value, expected one of: {0}" + }) + public static List hint(HintContext ctx) { + Element el = ctx.getInfo().getTrees().getElement(ctx.getPath()); + + if (el == null || (el.getKind() != ElementKind.METHOD && el.getKind() != ElementKind.CONSTRUCTOR)) return null; + + List result = new ArrayList(); + List arguments = ctx.getPath().getLeaf().getKind() == Kind.METHOD_INVOCATION ? + ((MethodInvocationTree) ctx.getPath().getLeaf()).getArguments() : + ((NewClassTree) ctx.getPath().getLeaf()).getArguments(); + int parameterIndex = 0; + + for (VariableElement param : ((ExecutableElement) el).getParameters()) { + int currentParam = parameterIndex++; + + List annotations = ctx.getInfo().getElementUtilities().getAugmentedAnnotationMirrors(param); + List validValues = new ArrayList(); + + for (AnnotationMirror am : annotations) { + if (!((TypeElement) am.getAnnotationType().asElement()).getQualifiedName().contentEquals("org.intellij.lang.annotations.MagicConstant")) continue; + + //TODO: caching(!) + for (Entry e : am.getElementValues().entrySet()) { + boolean isFlagsFromClass = e.getKey().getSimpleName().contentEquals("flagsFromClass"); + boolean isValuesFromClass = e.getKey().getSimpleName().contentEquals("valuesFromClass"); + if ((isFlagsFromClass || isValuesFromClass) && e.getValue().getValue() instanceof DeclaredType) { + for (VariableElement flag : ElementFilter.fieldsIn(((TypeElement) ((DeclaredType) e.getValue().getValue()).asElement()).getEnclosedElements())) { + if (!flag.getModifiers().contains(Modifier.STATIC)) continue; + + validValues.add(flag); + } + + break; + } + if (e.getKey().getSimpleName().contentEquals("intValues") && e.getValue().getValue() instanceof Collection) { + for (AnnotationValue field : NbCollections.iterable(NbCollections.checkedIteratorByFilter(((Collection) e.getValue().getValue()).iterator(), AnnotationValue.class, false))) { + if (!(field.getValue() instanceof String)) continue; + Element foundField = lookupField(ctx.getInfo(), (String) field.getValue()); + if (foundField == null || foundField.getKind() != ElementKind.FIELD) continue; + + validValues.add((VariableElement) foundField); + } + + break; + } + } + } + + if (validValues.isEmpty()) continue; + + Element resolved = ctx.getInfo().getTrees().getElement(new TreePath(ctx.getPath(), arguments.get(currentParam))); + + //TODO: "values" vs. "flags": + if (!validValues.contains(resolved)) { + result.add(ErrorDescriptionFactory.forTree(ctx, arguments.get(currentParam), Bundle.ERR_NotAValidValue(validValues.stream().map(ve -> ctx.getInfo().getElementUtilities().getElementName(ve, false)).collect(Collectors.joining(", "))))); + } + } + + return result; + } + + //should be replaced with ElementUtilities.findElement when the platform is NB7.4+: + private static Element lookupField(CompilationInfo info, String field) { + int lastDot = field.lastIndexOf('.'); + if (lastDot == (-1)) return null; + TypeElement clazz = info.getElements().getTypeElement(field.substring(0, lastDot)); + if (clazz == null) return null; + String simpleName = field.substring(lastDot + 1); + for (VariableElement var : ElementFilter.fieldsIn(clazz.getEnclosedElements())) { + if (var.getSimpleName().contentEquals(simpleName)) + return var; + } + return null; + } + +} diff --git a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/NPECheck.java b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/NPECheck.java index 3beeb9bedd5a..b57adfc3922d 100644 --- a/java/java.hints/src/org/netbeans/modules/java/hints/bugs/NPECheck.java +++ b/java/java.hints/src/org/netbeans/modules/java/hints/bugs/NPECheck.java @@ -540,14 +540,10 @@ private static State getStateFromAnnotations(CompilationInfo info, Element e) { return getStateFromAnnotations(info, e, State.POSSIBLE_NULL); } - private static final AnnotationMirrorGetter OVERRIDE_ANNOTATIONS = Lookup.getDefault().lookup(AnnotationMirrorGetter.class); - private static State getStateFromAnnotations(CompilationInfo info, Element e, State def) { if (e == null) return def; - Iterable mirrors = OVERRIDE_ANNOTATIONS != null ? OVERRIDE_ANNOTATIONS.getAnnotationMirrors(info, e) : null; - - if (mirrors == null) mirrors = e.getAnnotationMirrors(); + Iterable mirrors = info.getElementUtilities().getAugmentedAnnotationMirrors(e); for (AnnotationMirror am : mirrors) { String simpleName = ((TypeElement) am.getAnnotationType().asElement()).getSimpleName().toString(); @@ -568,10 +564,6 @@ private static State getStateFromAnnotations(CompilationInfo info, Element e, St return def; } - public interface AnnotationMirrorGetter { - public Iterable getAnnotationMirrors(CompilationInfo info, Element el); - } - private static final class VisitorImpl extends CancellableTreeScanner { private final HintContext ctx; diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/MagicConstantHintTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/MagicConstantHintTest.java new file mode 100644 index 000000000000..075c9f35d3e7 --- /dev/null +++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/MagicConstantHintTest.java @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.hints.bugs; + +import java.io.IOException; +import org.junit.Test; +import org.netbeans.modules.java.hints.test.api.HintTest; +import org.netbeans.modules.java.source.annotations.AugmentedAnnotations; + +public class MagicConstantHintTest { + + @Test + public void testFlagsFromClass() throws Exception { + writeAnnotations("\n" + + "\n" + + "" + + "" + + " " + + "\n" + + "\n" + + "\n"); + + HintTest.create() + .input("package test;\n" + + "public class Test {\n" + + " public void test(int i) {\n" + + " test(java.awt.event.InputEvent.META_MASK);\n" + + " }\n" + + "}\n") + .run(MagicConstantHint.class) + .assertWarnings("3:13-3:48:verifier:" + Bundle.ERR_NotAValidValue()); + + HintTest.create() + .input("package test;\n" + + "public class Test {\n" + + " public void test(int i) {\n" + + " test(java.lang.reflect.Modifier.PUBLIC);\n" + + " }\n" + + "}\n") + .run(MagicConstantHint.class) + .assertWarnings(); + } + + @Test + public void testIntValues() throws Exception { + writeAnnotations("\n" + + "\n" + + "" + + "" + + " " + + "\n" + + "\n" + + "\n"); + + HintTest.create() + .input("package test;\n" + + "public class Test {\n" + + " public void test(int i) {\n" + + " test(java.lang.reflect.Modifier.PRIVATE);\n" + + " }\n" + + "}\n") + .run(MagicConstantHint.class) + .assertWarnings("3:13-3:47:verifier:" + Bundle.ERR_NotAValidValue()); + + HintTest.create() + .input("package test;\n" + + "public class Test {\n" + + " public void test(int i) {\n" + + " test(java.lang.reflect.Modifier.PUBLIC);\n" + + " }\n" + + "}\n") + .run(MagicConstantHint.class) + .assertWarnings(); + } + + @Test + public void testConstructorAndValuesFromClass() throws Exception { + writeAnnotations("\n" + + "\n" + + "" + + "" + + " " + + "\n" + + "\n" + + "\n"); + + HintTest.create() + .input("package test;\n" + + "public class Test {\n" + + " public static final int V = 1;\n" + + " public Test(int i) {\n" + + " new Test(V);\n" + + " }\n" + + "}\n" + + "class Values {\n" + + " public static final int V = 0;\n" + + "}\n") + .run(MagicConstantHint.class) + .assertWarnings("4:17-4:18:verifier:" + Bundle.ERR_NotAValidValue()); + + HintTest.create() + .input("package test;\n" + + "public class Test {\n" + + " public Test(int i) {\n" + + " new Test(Values.V);\n" + + " }\n" + + "}\n" + + "class Values {\n" + + " public static final int V = 0;\n" + + "}\n") + .run(MagicConstantHint.class) + .assertWarnings(); + } + + private static void writeAnnotations(String content) throws IOException { + AugmentedAnnotations.setAugmentedAnnotationsForTests(content); + } + +} diff --git a/java/java.kit/nbproject/project.xml b/java/java.kit/nbproject/project.xml index cbc93c33361c..b13935def250 100644 --- a/java/java.kit/nbproject/project.xml +++ b/java/java.kit/nbproject/project.xml @@ -41,6 +41,12 @@ 1.0 + + org.netbeans.libs.jdkannotations + + 1.0 + + org.netbeans.modules.ant.kit diff --git a/java/java.source.base/nbproject/project.properties b/java/java.source.base/nbproject/project.properties index 55e004633df1..2995d90f4932 100644 --- a/java/java.source.base/nbproject/project.properties +++ b/java/java.source.base/nbproject/project.properties @@ -23,7 +23,7 @@ javadoc.name=Java Source Base javadoc.title=Java Source Base javadoc.arch=${basedir}/arch.xml javadoc.apichanges=${basedir}/apichanges.xml -spec.version.base=2.80.0 +spec.version.base=2.81.0 test.qa-functional.cp.extra=${refactoring.java.dir}/modules/ext/nb-javac-api.jar test.unit.run.cp.extra=${o.n.core.dir}/core/core.jar:\ ${o.n.core.dir}/lib/boot.jar:\ diff --git a/java/java.source.base/nbproject/project.xml b/java/java.source.base/nbproject/project.xml index cd71868b2ee5..20e1bdb4a53e 100644 --- a/java/java.source.base/nbproject/project.xml +++ b/java/java.source.base/nbproject/project.xml @@ -292,6 +292,14 @@ 8.0 + + org.openide.util.ui + + + + 9.39 + + diff --git a/java/java.source.base/src/org/netbeans/api/java/source/ElementUtilities.java b/java/java.source.base/src/org/netbeans/api/java/source/ElementUtilities.java index 558af0d37806..9af02fae95a7 100644 --- a/java/java.source.base/src/org/netbeans/api/java/source/ElementUtilities.java +++ b/java/java.source.base/src/org/netbeans/api/java/source/ElementUtilities.java @@ -64,6 +64,7 @@ import java.util.logging.Level; import java.util.logging.Logger; +import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; @@ -90,6 +91,7 @@ import org.netbeans.api.annotations.common.CheckForNull; import org.netbeans.api.annotations.common.NonNull; import org.netbeans.api.annotations.common.NullAllowed; +import org.netbeans.modules.java.source.annotations.AugmentedAnnotations; import org.netbeans.modules.java.source.builder.ElementsService; import org.netbeans.modules.java.source.base.SourceLevelUtils; import org.openide.util.Pair; @@ -1131,6 +1133,20 @@ private ExecutableElement recordCanonicalConstructor(TypeElement recordType) { return exported; } + /** + * Get any annotations which with the given {@code Element} has been annotated, + * as if by calling {@link Element#getAnnotationMirrors()}, and add any externally + * defined annotations for the {@code Element}. + * + * @param e the {@code Element} for which the annotations should be retrieved + * @return the annotations with which the given {@code Element} has been + * annotated and any externally attached annotations. + * @since 2.81 + */ + public List getAugmentedAnnotationMirrors(Element e) { + return AugmentedAnnotations.getAugmentedAnnotationMirrors(info, e); + } + // private implementation -------------------------------------------------- private static final Set NOT_OVERRIDABLE = EnumSet.of(Modifier.STATIC, Modifier.FINAL, Modifier.PRIVATE); diff --git a/java/java.source.base/src/org/netbeans/api/java/source/SourceUtils.java b/java/java.source.base/src/org/netbeans/api/java/source/SourceUtils.java index c725dbd1d699..73f6236f9468 100644 --- a/java/java.source.base/src/org/netbeans/api/java/source/SourceUtils.java +++ b/java/java.source.base/src/org/netbeans/api/java/source/SourceUtils.java @@ -96,6 +96,7 @@ import org.netbeans.modules.java.source.ElementUtils; import org.netbeans.modules.java.source.JavadocHelper; import org.netbeans.modules.java.source.ModuleNames; +import org.netbeans.modules.java.source.annotations.AugmentedAnnotations; import org.netbeans.modules.java.source.indexing.FQN2Files; import org.netbeans.modules.java.source.indexing.JavaCustomIndexer; import org.netbeans.modules.java.source.parsing.ClassParser; @@ -1531,4 +1532,8 @@ public static String classNameFor(ClasspathInfo info, String relativePath, Neste return className; } } + + public static boolean attachAnnotation(CompilationInfo info, Element e, String annotationFQN) { + return AugmentedAnnotations.attachAnnotation(info, e, annotationFQN); + } } diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotations.java b/java/java.source.base/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotations.java new file mode 100644 index 000000000000..0953d3af7e56 --- /dev/null +++ b/java/java.source.base/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotations.java @@ -0,0 +1,839 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.source.annotations; + +import com.sun.source.tree.AnnotationTree; +import com.sun.source.tree.AssignmentTree; +import com.sun.source.tree.BlockTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.LiteralTree; +import com.sun.source.tree.StatementTree; +import com.sun.source.tree.Tree.Kind; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.SourcePositions; +import com.sun.source.util.Trees; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.annotation.Annotation; +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.net.MalformedURLException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.IdentityHashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.WeakHashMap; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.AnnotationValueVisitor; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ElementVisitor; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.Name; +import javax.lang.model.element.NestingKind; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.type.ArrayType; +import javax.lang.model.type.DeclaredType; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.type.TypeVisitor; +import javax.lang.model.util.Elements; +import javax.tools.JavaFileObject; +import org.netbeans.api.annotations.common.CheckForNull; +import org.netbeans.api.java.source.ClasspathInfo.PathKind; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.api.java.source.CompilationInfo.CacheClearPolicy; +import org.netbeans.api.project.FileOwnerQuery; +import org.netbeans.api.project.Project; +import org.netbeans.api.project.ProjectUtils; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.filesystems.URLMapper; +import org.openide.modules.Places; +import org.openide.util.*; +import org.openide.xml.XMLUtil; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + +public class AugmentedAnnotations { + + private static final Logger LOG = Logger.getLogger(AugmentedAnnotations.class.getName()); //-J-Dorg.netbeans.modules.java.source.annotations.AugmentedAnnotations.level=0 + public static final String NS = "http://www.netbeans.org/ns/external-annotations-java/1"; + + private static byte[] augmentedAnnotationsOverride = null; + + //package->encoded element+DOM + private static final Map> hardCodedAnnotations2DOMCache = new WeakHashMap<>(); + //root->encoded element+DOM + private static final Map> userAnnotations2DOMCache = new WeakHashMap<>(); + + public static List getAugmentedAnnotationMirrors(CompilationInfo info, Element e) { + ParsedAnnotationsXML parsedAnnotations = findParsedAnnotations(info, e); + + if (parsedAnnotations == null || parsedAnnotations.encodedElement2DOMElement.isEmpty()) { + return e.getAnnotationMirrors(); + } + + String serializedElement = serialize(e); + org.w3c.dom.Element externalAnnotation = parsedAnnotations.encodedElement2DOMElement.get(serializedElement); + + if (externalAnnotation == null) return e.getAnnotationMirrors(); + + List augmented = new ArrayList(e.getAnnotationMirrors()); + + augmented.addAll(mirror(info, externalAnnotation)); + + return augmented; + } + + public static boolean attachAnnotation(CompilationInfo info, Element e, String annotation) { + FileObject root = binaryRootFor(info, e); + + if (root == null) return false; + + ParsedAnnotationsXML parsedAnnotations = findAugmentElementAnnotationsRoot(info, root); + org.w3c.dom.Element annotations = parsedAnnotations.root; + String serialized = serialize(e); + org.w3c.dom.Element elementsElement; + Document document; + + document = parsedAnnotations.root.getOwnerDocument(); + elementsElement = parsedAnnotations.encodedElement2DOMElement.computeIfAbsent(serialized, s -> { + org.w3c.dom.Element nue = document.createElementNS(NS, "item"); + nue.setAttribute("name", serialized); + annotations.appendChild(nue); + return nue; + }); + + StatementTree st = info.getTreeUtilities().parseStatement("{ " + annotation + " int i; }", new SourcePositions[1]); + + if (st.getKind() != Kind.BLOCK) { + //error + return false; + } + + BlockTree bt = (BlockTree) st; + + if (bt.getStatements().size() != 1) { + //error + return false; + } + + st = bt.getStatements().get(0); + + if (st.getKind() != Kind.VARIABLE) { + //error + return false; + } + + for (AnnotationTree at : ((VariableTree) st).getModifiers().getAnnotations()) { + org.w3c.dom.Element annot = document.createElement("annotation"); + + annot.setAttribute("name", at.getAnnotationType().toString()); + for (ExpressionTree attribute : at.getArguments()) { + String attributeName; + ExpressionTree attributeValue; + if (attribute.getKind() == Kind.ASSIGNMENT) { + AssignmentTree assign = (AssignmentTree) attribute; + attributeName = assign.getVariable().toString(); + attributeValue = assign.getExpression(); + } else { + attributeName = "value"; + attributeValue = attribute; + } + AttributeDescription desc = AttributeDescription.create(attributeValue); + + org.w3c.dom.Element val = document.createElement("val"); + + val.setAttribute("name", attributeName); + val.setAttribute("val", desc.toString()); + + annot.appendChild(val); + } + + elementsElement.appendChild(annot); + } + + writeAugmentElementAnnotationsRoot(info, root, annotations); + + return true; + } + + private static ParsedAnnotationsXML findAugmentElementAnnotationsRoot(CompilationInfo info, FileObject elementRoot) { + Reference cachedRef = userAnnotations2DOMCache.get(elementRoot); + ParsedAnnotationsXML cached = cachedRef != null ? cachedRef.get() : null; + if (cached != null) { + return cached; + } + Project prj = FileOwnerQuery.getOwner(elementRoot); + org.w3c.dom.Element parsed = null; + if (prj != null) { + parsed = ProjectUtils.getAuxiliaryConfiguration(prj).getConfigurationFragment("annotations", AugmentedAnnotations.NS, true); + } + if (parsed == null) { + try { + byte[] annotations = (byte[]) getAugmentedAnnotations(elementRoot); + if (annotations != null) { + InputSource input = new InputSource(new ByteArrayInputStream(annotations)); + parsed = XMLUtil.parse(input, false, true, /*XXX*/null, null).getDocumentElement(); + } + } catch (IOException | SAXException ex) { + LOG.log(Level.WARNING, null, ex); + } + } + if (parsed == null) { + parsed = XMLUtil.createDocument("annotations", NS, null, null).getDocumentElement(); + } + ParsedAnnotationsXML result = new ParsedAnnotationsXML(parsed); + userAnnotations2DOMCache.put(elementRoot, new SoftReference<>(result)); + return result; + } + + private static void writeAugmentElementAnnotationsRoot(CompilationInfo info, FileObject elementRoot, org.w3c.dom.Element annotations) { + Project prj = FileOwnerQuery.getOwner(elementRoot); + if (prj != null) { + ProjectUtils.getAuxiliaryConfiguration(prj).putConfigurationFragment(annotations, true); + return ; + } + try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { + XMLUtil.write(annotations.getOwnerDocument(), out, "UTF-8"); + setAugmentedAnnotations(elementRoot, out.toByteArray()); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + + static byte[] getAugmentedAnnotations(FileObject elementRoot) throws IOException { + if (augmentedAnnotationsOverride != null) { + return augmentedAnnotationsOverride; + } + return (byte[]) augmentedDataHolder().getAttribute(AugmentedAnnotations.class.getName() + "-" + elementRoot.toURI()); + } + + static void setAugmentedAnnotations(FileObject elementRoot, byte[] data) throws IOException { + augmentedDataHolder().setAttribute(AugmentedAnnotations.class.getName() + "-" + elementRoot.toURI(), data); + userAnnotations2DOMCache.remove(elementRoot); + } + + public static void setAugmentedAnnotationsForTests(String annotations) { + augmentedAnnotationsOverride = annotations.getBytes(StandardCharsets.UTF_8); + } + + private static FileObject augmentedDataHolder() { + File c = Places.getCacheSubfile("var/cache/javaAugmentedAnnotations"); + if (!c.exists()) { + try { + return FileUtil.createData(c); + } catch (IOException ex) { + Exceptions.printStackTrace(ex); + } + } + return FileUtil.toFileObject(c); + } + + private static class AttributeDescription { + enum Kind { + STRING; + } + final Kind kind; + final Object value; + + public AttributeDescription(Kind kind, Object value) { + this.kind = kind; + this.value = value; + } + + public static AttributeDescription create(ExpressionTree from) { + switch (from.getKind()) { + case STRING_LITERAL: return new AttributeDescription(Kind.STRING, ((LiteralTree) from).getValue()); + default: throw new IllegalArgumentException("Unknown expression: " + from.getKind()); + } + } + + @Override + public String toString() { + switch (kind) { + case STRING: return String.valueOf(value); + default: throw new IllegalStateException(); + } + } + } + + private static @CheckForNull ParsedAnnotationsXML findParsedAnnotations(CompilationInfo info, Element e) { + String packageName = info.getElements().getPackageOf(e).getQualifiedName().toString(); + + FileObject data = FileUtil.getConfigFile("java/annotations/external/" + packageName.replace('.', '/') + "/annotations.xml"); + + if (data != null) { + Reference cachedDOMRef = hardCodedAnnotations2DOMCache.get(data); + ParsedAnnotationsXML cachedDOM = cachedDOMRef != null ? cachedDOMRef.get() : null; + + if (cachedDOM == null) { + try (InputStream in = data.getInputStream()) { + cachedDOM = new ParsedAnnotationsXML(XMLUtil.parse(new InputSource(in), false, false, null, null).getDocumentElement()); + hardCodedAnnotations2DOMCache.put(data, new SoftReference(cachedDOM)); //TODO: clearing reference? + } catch (IOException | SAXException ex) { + Exceptions.printStackTrace(ex); + } + } + + return cachedDOM; + } + + FileObject binaryRoot = binaryRootFor(info, e); + + if (binaryRoot == null) { + return null; + } + + return findAugmentElementAnnotationsRoot(info, binaryRoot); + } + + + private static final class ParsedAnnotationsXML { + private static final ParsedAnnotationsXML EMPTY = new ParsedAnnotationsXML(); + private final org.w3c.dom.Element root; + private final Map encodedElement2DOMElement; + public ParsedAnnotationsXML() { + this.root = null; + this.encodedElement2DOMElement = new HashMap(); + } + public ParsedAnnotationsXML(org.w3c.dom.Element root) { + this.root = root; + this.encodedElement2DOMElement = new HashMap(); + NodeList itemsList = root.getChildNodes(); + + for (int i = 0; i < itemsList.getLength(); i++) { + Node current = itemsList.item(i); + + if (!(current instanceof org.w3c.dom.Element)) continue; + + org.w3c.dom.Element currentElement = (org.w3c.dom.Element) current; + + this.encodedElement2DOMElement.put(currentElement.getAttribute("name"), currentElement); + } + } + } + + private static String serialize(Element e) { + switch (e.getKind()) { + case PARAMETER: { + ExecutableElement method = (ExecutableElement) e.getEnclosingElement(); + + return serialize(method) + " " + method.getParameters().indexOf(e); + } + case CONSTRUCTOR: + case METHOD: + ExecutableElement method = (ExecutableElement) e; + StringBuilder result = new StringBuilder(); + + result.append(serialize(e.getEnclosingElement())); + result.append(" "); + if (e.getKind() == ElementKind.METHOD) { + result.append(method.getReturnType().toString()); + result.append(" "); + result.append(method.getSimpleName().toString()); + } else { + result.append(method.getEnclosingElement().getSimpleName().toString()); + } + result.append("("); + for (Iterator it = method.getParameters().iterator(); it.hasNext();) { + VariableElement param = it.next(); + if (it.hasNext() || !method.isVarArgs()) { + result.append(param.asType().toString()); + } else { + result.append(((ArrayType) param.asType()).getComponentType().toString()); + result.append("..."); + } + if (it.hasNext()) { + result.append(", "); + } + } + result.append(")"); + return result.toString(); + case ANNOTATION_TYPE: case CLASS: + case ENUM: case INTERFACE: + return ((TypeElement) e).getQualifiedName().toString(); + default: + return ""; + } + } + + private static List mirror(CompilationInfo info, org.w3c.dom.Element el) { + NodeList annotationDOM = el.getChildNodes(); + List result = new ArrayList(); + + for (int i = 0; i < annotationDOM.getLength(); i++) { + Node ann = annotationDOM.item(i); + + if (ann instanceof org.w3c.dom.Element && "annotation".equals(((org.w3c.dom.Element) ann).getNodeName())) { + result.add(singleAnnotationMirror(info, (org.w3c.dom.Element) ann)); + } + } + + return result; + } + + private static AnnotationMirror singleAnnotationMirror(CompilationInfo info, org.w3c.dom.Element annotation) { + String typeName = annotation.getAttribute("name"); + + NodeList valueDOM = annotation.getChildNodes(); + Map values = new IdentityHashMap(); + + for (int i = 0; i < valueDOM.getLength(); i++) { + Node ann = valueDOM.item(i); + + if (ann instanceof org.w3c.dom.Element && "val".equals(((org.w3c.dom.Element) ann).getNodeName())) { + Pair value = singleValueMirror(info, (org.w3c.dom.Element) ann); + values.put(value.first(), value.second()); + } + } + + return new FakeAnnotationMirror(declaredTypeForName(info, typeName), values); + } + + private static Pair singleValueMirror(CompilationInfo info, org.w3c.dom.Element val) { + String methodName = val.getAttribute("name"); + String value = val.getAttribute("val"); + + return Pair.of(new FakeAttributeElement(info.getElements().getName(methodName)), mirrorValueFromString(info, value)); + } + + private static AnnotationValue mirrorValueFromString(CompilationInfo info, String value) { + Object realValue; + + //TODO: .class and { escaped? Good idea anyway? Need to actually know the types? + if (value.endsWith(".class")) { + realValue = declaredTypeForName(info, value.substring(0, value.length() - ".class".length())); + } else if (value.startsWith("{") && value.endsWith("}")) { + value = value.substring(1, value.length() - 1); + + List result = new ArrayList(); + + for (String element : value.split(", ")) { + result.add(mirrorValueFromString(info, element)); + } + + realValue = result; + } else { + realValue = value; + } + + return new FakeAnnotationValue(realValue); + } + + private static FileObject binaryRootFor(CompilationInfo info, Element forElement) { + TypeElement topLevel = info.getElementUtilities().outermostTypeElement(forElement); + + if (topLevel == null || topLevel.asType().getKind() == TypeKind.ERROR) { + return null; + } + + record RootHolder(FileObject root) {} + + Map binaryRootCache = (Map) info.getCachedValue(AugmentedAnnotations.class); + + if (binaryRootCache == null) { + info.putCachedValue(AugmentedAnnotations.class, binaryRootCache = new HashMap<>(), CacheClearPolicy.ON_SIGNATURE_CHANGE); + } + + return binaryRootCache.computeIfAbsent(topLevel, te -> { + long s = System.nanoTime(); + try { + JavaFileObject origin = info.getElements().getFileObjectOf(topLevel); + + if (origin == null) { + return null; + } + + FileObject originFO; + + try { + originFO = URLMapper.findFileObject(origin.toUri().toURL()); + } catch (MalformedURLException ex) { + LOG.log(Level.FINE, null, ex); + return null; + } + + if (originFO == null) { + return null; + } + + while (topLevel.getEnclosingElement() != null && topLevel.getEnclosingElement().getKind() == ElementKind.PACKAGE && originFO != null) { + originFO = originFO.getParent(); + } + return new RootHolder(originFO); + } finally { + if (LOG.isLoggable(Level.FINE)) { + Trees trees = info.getTrees(); + long time = System.nanoTime() - s; + synchronized (rootComputationCummulativePerJavac) { + WeakJavacReference found = null; + + for (WeakJavacReference ref : rootComputationCummulativePerJavac) { + if (ref.get() == trees) { + found = ref; + } + } + if (found == null) { + rootComputationCummulativePerJavac.add(found = new WeakJavacReference(trees)); + } + + found.cummulativeTime += time; + } + } + } + }).root(); + } + + private static DeclaredType declaredTypeForName(CompilationInfo info, String fqn) { + TypeElement element = info.getElements().getTypeElement(fqn); + + return element != null ? (DeclaredType) element.asType() : new FakeDeclaredType(new FakeTypeElement(info.getElements(), fqn)); + } + + private static final class FakeTypeElement implements TypeElement { + + private final Name fqn; + private final Name simpleName; + + public FakeTypeElement(Elements elements, String fqn) { + this.fqn = elements.getName(fqn); + + int lastDot = fqn.lastIndexOf('.'); + + if (lastDot > (-1)) this.simpleName = elements.getName(fqn.substring(lastDot + 1)); + else this.simpleName = this.fqn; + } + + @Override public List getEnclosedElements() { + return Collections.emptyList();//TODO: can be made better? + } + + @Override public NestingKind getNestingKind() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override public Name getQualifiedName() { + return fqn; + } + + @Override public Name getSimpleName() { + return simpleName; + } + + @Override + public TypeMirror getSuperclass() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getInterfaces() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getTypeParameters() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Element getEnclosingElement() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public TypeMirror asType() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public ElementKind getKind() { + return ElementKind.ANNOTATION_TYPE; + } + + @Override + public List getAnnotationMirrors() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Set getModifiers() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitType(this, p); + } + + @Override + public A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException("Not supported yet."); + } + + } + + private static final class FakeDeclaredType implements DeclaredType { + + private final TypeElement forType; + + public FakeDeclaredType(TypeElement forType) { + this.forType = forType; + } + + @Override + public Element asElement() { + return forType; + } + + @Override + public TypeMirror getEnclosingType() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getTypeArguments() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public TypeKind getKind() { + return TypeKind.DECLARED; + } + + @Override + public R accept(TypeVisitor v, P p) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public String toString() { + return forType.getQualifiedName().toString(); + } + + @Override + public List getAnnotationMirrors() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException("Not supported yet."); + } + + } + + private static final class FakeAttributeElement implements ExecutableElement { + + private final Name simpleName; + + public FakeAttributeElement(Name simpleName) { + this.simpleName = simpleName; + } + + @Override + public List getTypeParameters() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public TypeMirror getReturnType() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getParameters() { + return Collections.emptyList(); + } + + @Override + public boolean isVarArgs() { + return false; + } + + @Override + public List getThrownTypes() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public AnnotationValue getDefaultValue() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Name getSimpleName() { + return simpleName; + } + + @Override + public TypeMirror asType() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public ElementKind getKind() { + return ElementKind.METHOD; + } + + @Override + public List getAnnotationMirrors() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public A getAnnotation(Class annotationType) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Set getModifiers() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public Element getEnclosingElement() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public List getEnclosedElements() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public R accept(ElementVisitor v, P p) { + return v.visitExecutable(this, p); + } + + @Override + public TypeMirror getReceiverType() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean isDefault() { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public A[] getAnnotationsByType(Class annotationType) { + throw new UnsupportedOperationException("Not supported yet."); + } + + } + + private static final class FakeAnnotationMirror implements AnnotationMirror { + + private final DeclaredType annotationType; + private final Map elementValues; + + public FakeAnnotationMirror(DeclaredType annotationType, Map elementValues) { + this.annotationType = annotationType; + this.elementValues = elementValues; + } + + @Override + public DeclaredType getAnnotationType() { + return annotationType; + } + + @Override + public Map getElementValues() { + return elementValues; + } + + } + + private static final class FakeAnnotationValue implements AnnotationValue { + + private final Object value; + + public FakeAnnotationValue(Object value) { + this.value = value; + } + + @Override + public Object getValue() { + return value; + } + + @Override + public R accept(AnnotationValueVisitor v, P p) { + throw new UnsupportedOperationException("Not supported yet."); + } + + } + + //statistics: + private static final Set rootComputationCummulativePerJavac = Collections.newSetFromMap(new IdentityHashMap<>()); + + private static final class WeakJavacReference extends WeakReference implements Runnable { + + private long cummulativeTime; + + public WeakJavacReference(Trees trees) { + super(trees, Utilities.activeReferenceQueue()); + } + + @Override + public void run() { + long timeToReport; + + synchronized (rootComputationCummulativePerJavac) { + timeToReport = cummulativeTime; + rootComputationCummulativePerJavac.remove(this); + } + + LOG.log(Level.FINE, "Cummulative time spend searching for binary roots for javac instance: {0}ms", timeToReport / 1000 / 1000.); + } + + } + +} diff --git a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotationsTest.java b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotationsTest.java new file mode 100644 index 000000000000..3b7386704810 --- /dev/null +++ b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotationsTest.java @@ -0,0 +1,384 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.netbeans.modules.java.source.annotations; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; +import javax.lang.model.element.Element; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.type.TypeKind; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.ElementFilter; +import javax.swing.text.Document; +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; +import static junit.framework.TestCase.assertTrue; +import org.netbeans.api.java.lexer.JavaTokenId; +import org.netbeans.api.java.source.ClasspathInfo.PathKind; +import org.netbeans.api.java.source.CompilationInfo; +import org.netbeans.api.java.source.JavaSource; +import org.netbeans.api.java.source.JavaSource.Phase; +import org.netbeans.api.java.source.SourceUtilsTestUtil; +import org.netbeans.api.java.source.TestUtilities; +import org.netbeans.api.lexer.Language; +import org.netbeans.junit.NbTestCase; +import org.openide.cookies.EditorCookie; +import org.openide.filesystems.FileObject; +import org.openide.filesystems.FileUtil; +import org.openide.loaders.DataObject; + +public class AugmentedAnnotationsTest extends NbTestCase { + + private static final String JAVA_BASE_AUGMENTED = "\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + + public AugmentedAnnotationsTest(String testName) { + super(testName); + } + + public void testGetAugmentedAnnotationMirrors1() throws Exception { + prepareTest("test/Test.java", + "package test;\n" + + "public class Test {\n" + + "}\n"); + + TypeElement jlClass = info.getElements().getTypeElement("java.lang.Class"); + + assertNotNull(jlClass); + + ExecutableElement toString = null; + + for (ExecutableElement ee : ElementFilter.methodsIn(jlClass.getEnclosedElements())) { + if (ee.getSimpleName().contentEquals("toString") && ee.getParameters().isEmpty()) { + toString = ee; + } + } + + assertNotNull(toString); + + String result = serializeAugmentedAnnotations(toString); + + assertEquals("@test.Test(clazz=TypeMirror:java.util.List, clazz-array=array:[TypeMirror:java.util.List, TypeMirror:java.util.ArrayList], string=String:test-value1, string-array=array:[String:value1, String:value2])\n", result); + } + + public void testGetAugmentedAnnotationMirrors2() throws Exception { + prepareTest("test/Test.java", + "package test;\n" + + "public class Test {\n" + + "}\n"); + + TypeElement jlClass = info.getElements().getTypeElement("java.lang.Class"); + + assertNotNull(jlClass); + + ExecutableElement forName = null; + + for (ExecutableElement ee : ElementFilter.methodsIn(jlClass.getEnclosedElements())) { + if (ee.getSimpleName().contentEquals("forName") && ee.getParameters().size() == 1) { + forName = ee; + } + } + + assertNotNull(forName); + + String result = serializeAugmentedAnnotations(forName.getParameters().get(0)); + + assertEquals("@test.Test(string=String:test-value2)\n", result); + } + + public void testGetAugmentedAnnotationMirrorsConstructor() throws Exception { + prepareTest("test/Test.java", + "package test;\n" + + "public class Test {\n" + + "}\n"); + + TypeElement jlClass = info.getElements().getTypeElement("java.lang.StringBuilder"); + + assertNotNull(jlClass); + + ExecutableElement forName = null; + + for (ExecutableElement ee : ElementFilter.constructorsIn(jlClass.getEnclosedElements())) { + if (ee.getParameters().size() == 1 && ee.getParameters().get(0).asType().getKind() == TypeKind.INT) { + forName = ee; + break; + } + } + + assertNotNull(forName); + + String result = serializeAugmentedAnnotations(forName.getParameters().get(0)); + + assertEquals("@test.Test(string=String:test-value4)\n", result); + } + + public void testGetAugmentedAnnotationMirrors3() throws Exception { + prepareTest("test/Test.java", + "package test;\n" + + "public class Test {\n" + + "}\n"); + + TypeElement jlClass = info.getElements().getTypeElement("java.lang.Class"); + + assertNotNull(jlClass); + + ExecutableElement forName = null; + + for (ExecutableElement ee : ElementFilter.methodsIn(jlClass.getEnclosedElements())) { + if (ee.getSimpleName().contentEquals("getMethod") && ee.getParameters().size() == 2) { + forName = ee; + } + } + + assertNotNull(forName); + + String result = serializeAugmentedAnnotations(forName.getParameters().get(0)); + + assertEquals("@test.Test(string=String:test-value3)\n", result); + } + + public void testNPEForPackage() throws Exception { + prepareTest("test/Test.java", + "package test;\n" + + "public class Test {\n" + + "}\n"); + + PackageElement jl = info.getElements().getPackageElement("java.lang"); + + assertNotNull(jl); + + String result = serializeAugmentedAnnotations(jl); + + assertEquals("", result); + } + + public void testAddAnnotation() throws Exception { + prepareTest("test/Test.java", + "package test;\n" + + "public class Test {\n" + + "}\n"); + + TypeElement tTest = info.getElements().getTypeElement("test.Test"); + + assertNotNull(tTest); + + assertTrue(AugmentedAnnotations.attachAnnotation(info, tTest, "@test.NonNull")); + assertEquals("@test.NonNull()\n", + serializeAugmentedAnnotations(tTest)); + + String augmentedAnnotations = new String(AugmentedAnnotations.getAugmentedAnnotations(sourceRoot), StandardCharsets.UTF_8); + + assertEquals("\n" + + "\n" + + " \n" + + " \n" + + " \n" + + "\n", + augmentedAnnotations); + } + + public void testAddAnnotation2() throws Exception { + prepareTest("test/Test.java", + "package test;\n" + + "public class Test {\n" + + "}\n"); + + TypeElement tTest = info.getElements().getTypeElement("test.Test"); + + assertNotNull(tTest); + + assertTrue(AugmentedAnnotations.attachAnnotation(info, tTest, "@test.Language(value=\"java\")")); + assertEquals("@test.Language(value=String:java)\n", + serializeAugmentedAnnotations(tTest)); + + String augmentedAnnotations = new String(AugmentedAnnotations.getAugmentedAnnotations(sourceRoot), StandardCharsets.UTF_8); + + assertEquals("\n" + + "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + "\n", + augmentedAnnotations); + } + + @Override + protected void setUp() throws Exception { + super.setUp(); + SourceUtilsTestUtil.prepareTest(new String[0], new Object[0]); + clearWorkDir(); + + FileUtil.refreshFor(File.listRoots()); + } + + protected void prepareTest(String fileName, String code) throws Exception { + FileObject workFO = FileUtil.createFolder(getWorkDir()); + + assertNotNull(workFO); + + workFO.refresh(); + + sourceRoot = workFO.createFolder("src"); + FileObject buildRoot = workFO.createFolder("build"); + FileObject cache = workFO.createFolder("cache"); + + FileObject data = FileUtil.createData(sourceRoot, fileName); + File dataFile = FileUtil.toFile(data); + + assertNotNull(dataFile); + + TestUtilities.copyStringToFile(dataFile, code); + + SourceUtilsTestUtil.prepareTest(sourceRoot, buildRoot, cache); + + DataObject od = DataObject.find(data); + EditorCookie ec = od.getLookup().lookup(EditorCookie.class); + + assertNotNull(ec); + + doc = ec.openDocument(); + doc.putProperty(Language.class, JavaTokenId.language()); + + JavaSource js = JavaSource.forFileObject(data); + + assertNotNull(js); + + info = SourceUtilsTestUtil.getCompilationInfo(js, Phase.RESOLVED); + + assertNotNull(info); + + setAugmentedAnnotations(JAVA_BASE_AUGMENTED); + } + + private void setAugmentedAnnotations(String annotations) throws IOException { + FileObject jlObject = info.getClasspathInfo().getClassPath(PathKind.MODULE_BOOT).findResource("java/lang/Object.class"); + FileObject root = info.getClasspathInfo().getClassPath(PathKind.MODULE_BOOT).findOwnerRoot(jlObject); + + AugmentedAnnotations.setAugmentedAnnotations(root, annotations.getBytes(StandardCharsets.UTF_8)); + } + + protected FileObject sourceRoot; + protected CompilationInfo info; + protected Document doc; + + private String serializeAugmentedAnnotations(Element forElement) { + StringBuilder result = new StringBuilder(); + + for (AnnotationMirror am : AugmentedAnnotations.getAugmentedAnnotationMirrors(info, forElement)) { + result.append("@"); + result.append(((TypeElement) am.getAnnotationType().asElement()).getQualifiedName()); + result.append("("); + + boolean first = true; + + List attributes = new ArrayList(am.getElementValues().keySet()); + + Collections.sort(attributes, new Comparator() { + @Override public int compare(ExecutableElement o1, ExecutableElement o2) { + return o1.getSimpleName().toString().compareTo(o2.getSimpleName().toString()); + } + }); + + for (ExecutableElement attr : attributes) { + if (!first) result.append(", "); + + first = false; + + result.append(attr.getSimpleName()); + result.append("="); + result.append(dumpAnnotationValue(info, am.getElementValues().get(attr))); + } + + result.append(")\n"); + } + return result.toString(); + } + + private String dumpAnnotationValue(CompilationInfo info, AnnotationValue valueMirror) { + StringBuilder result = new StringBuilder(); + Object value = valueMirror.getValue(); + + if (value instanceof TypeMirror) { + result.append("TypeMirror"); + result.append(":"); + result.append(info.getTypes().erasure((TypeMirror) value).toString()); + } else if (value instanceof String) { + result.append("String"); + result.append(":"); + result.append(value.toString()); + } else if (value instanceof Collection) { + result.append("array:["); + + boolean first = true; + + for (Object obj : (Collection) value) { + if (!first) result.append(", "); + first = false; + result.append(dumpAnnotationValue(info, (AnnotationValue) obj)); + } + + result.append("]"); + + return result.toString(); + } else { + result.append("UNKNOWN_TYPE"); + result.append(":"); + result.append(value.toString()); + } + + return result.toString(); + } + +} diff --git a/java/libs.jdkannotations/GenerateExternalAnnotationsMetadata.java b/java/libs.jdkannotations/GenerateExternalAnnotationsMetadata.java new file mode 100644 index 000000000000..8a5ae36aa3be --- /dev/null +++ b/java/libs.jdkannotations/GenerateExternalAnnotationsMetadata.java @@ -0,0 +1,444 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +*/ +package generate.external.annotations.metadata; + +import java.io.File; +import java.io.IOException; +import java.io.Writer; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.util.Arrays; + +/** + * Generate the binaries-list, license file and FS layer for annotation files, + * based on a given hash: + * $ cd java/libs.jdkannotations + * $ java GenerateExternalAnnotationsMetadata.java + */ +public class GenerateExternalAnnotationsMetadata { + + public static void main(String[] args) throws IOException { + String hash = args[0]; + Path libraryModule = new File(System.getProperty("user.dir")).toPath(); + Path checkout = cloneRepository(hash, libraryModule); + generate(hash, + checkout, + libraryModule); + } + + private static Path cloneRepository(String hash, Path libraryModule) throws IOException { + Path buildCheckout = libraryModule.resolve("build/checkout"); + + Files.createDirectories(buildCheckout); + run(buildCheckout, "git", "init", "."); + run(buildCheckout, "git", "remote", "add", "origin", "https://github.com/JetBrains/intellij-community"); + run(buildCheckout, "git", "config", "core.sparseCheckout", "true"); + Path sparseCheckout = buildCheckout.resolve(".git/info/sparse-checkout"); + try (Writer sparseCheckoutWriter = Files.newBufferedWriter(sparseCheckout)) { + sparseCheckoutWriter.write("java/jdkAnnotations/\n"); + } + run(buildCheckout, "git", "pull", "--depth=1", "origin", hash); + return buildCheckout; + } + + private static void run(Path wd, String... command) throws IOException { + try { + Process p = new ProcessBuilder(command).directory(wd.toFile()).inheritIO().start(); + int result = p.waitFor(); + + if (result != 0) { + throw new IOException("Incorrect result: " + result); + } + } catch (InterruptedException ex) { + throw new IOException(ex); + } + } + + private static void generate(String hash, Path checkout, Path libraryModule) throws IOException { + String urlPrefix = "https://raw.githubusercontent.com/JetBrains/intellij-community/" + hash + "/"; + StringBuilder fileList = new StringBuilder(); + try (Writer binariesList = Files.newBufferedWriter(libraryModule.resolve("external/binaries-list")); + Writer layer = Files.newBufferedWriter(libraryModule.resolve("src/org/netbeans/libs/jdkannotations/layer.xml"))) { + binariesList.write(BINARIES_LIST_PREFIX); + layer.write(LAYER_PREFIX); + Path jdkAnnotations = checkout.resolve("java/jdkAnnotations"); + Files.walkFileTree(jdkAnnotations, new FileVisitor() { + int indent = 4; + private String indent() { + char[] spaces = new char[indent]; + + Arrays.fill(spaces, ' '); + + return new String(spaces); + } + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + if (jdkAnnotations.equals(dir)) { + for (String layerDir : LAYER_DIRECTORIES) { + layer.write(indent() + "\n"); + indent += 4; + } + } else { + layer.write(indent() + "\n"); + indent += 4; + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + String annotationFileName = jdkAnnotations.relativize(file).toString().replace('/', '.'); + binariesList.write(computeSha1(file)); + binariesList.write(" "); + binariesList.write(urlPrefix + checkout.relativize(file)); + binariesList.write(" "); + binariesList.write(annotationFileName); + binariesList.write("\n"); + layer.write(indent() + "\n"); + if (!fileList.isEmpty()) { + fileList.append(" "); + } + fileList.append(annotationFileName); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + throw exc; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + if (jdkAnnotations.equals(dir)) { + for (String layerDir : LAYER_DIRECTORIES) { + indent -= 4; + layer.write("\n"); + } + } else { + indent -= 4; + layer.write(indent() + "\n"); + } + return FileVisitResult.CONTINUE; + } + }); + layer.write(LAYER_SUFFIX); + } + Path licenseFile = libraryModule.resolve("external/annotations-" + hash + "-license.txt"); + try (Writer w = Files.newBufferedWriter(licenseFile)) { + w.write("Name: JDK External Annotations\n"); + w.write("Description: External Annotations for JDK\n"); + w.write("Origin: JetBrains, IntelliJ Community\n"); + w.write("License: Apache-2.0\n"); + w.write("Version: " + hash + "\n"); + w.write("URL: " + urlPrefix + "java/jdkAnnotations\n"); + w.write("Files: " + fileList + "\n\n"); + w.write(APACHE_LICENSE); + } + Path noticeFile = libraryModule.resolve("external/annotations-" + hash + "-notice.txt"); + try (Writer w = Files.newBufferedWriter(noticeFile)) { + w.write(APACHE_NOTICE); + } + } + + private static String computeSha1(Path forFile) throws IOException { + try { + MessageDigest md = MessageDigest.getInstance("SHA1"); + md.update(Files.readAllBytes(forFile)); + StringBuilder sha1 = new StringBuilder(); + for (byte b : md.digest()) { + sha1.append(String.format("%02X", b)); + } + return sha1.toString(); + } catch (NoSuchAlgorithmException ex) { + throw new IOException(ex); + } + } + + private static final String BINARIES_LIST_PREFIX = + """ + # Licensed to the Apache Software Foundation (ASF) under one + # or more contributor license agreements. See the NOTICE file + # distributed with this work for additional information + # regarding copyright ownership. The ASF licenses this file + # to you under the Apache License, Version 2.0 (the + # "License"); you may not use this file except in compliance + # with the License. You may obtain a copy of the License at + # + # http://www.apache.org/licenses/LICENSE-2.0 + # + # Unless required by applicable law or agreed to in writing, + # software distributed under the License is distributed on an + # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + # KIND, either express or implied. See the License for the + # specific language governing permissions and limitations + # under the License. + """; + + private static final String LAYER_PREFIX = + """ + + + + + """; + + private static final String LAYER_SUFFIX = + """ + + """; + + private static final String APACHE_LICENSE = + """ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + """; + private static final String APACHE_NOTICE = + """ + This software includes code from IntelliJ IDEA Community Edition + Copyright (C) JetBrains s.r.o. + https://www.jetbrains.com/idea/ + """; + + private static final String[] LAYER_DIRECTORIES = new String[] { + "java", "annotations", "external" + }; +} diff --git a/java/libs.jdkannotations/build.xml b/java/libs.jdkannotations/build.xml new file mode 100644 index 000000000000..55139961c053 --- /dev/null +++ b/java/libs.jdkannotations/build.xml @@ -0,0 +1,31 @@ + + + + Builds, tests, and runs the project org.netbeans.libs.jdkannotations + + + + + + + + diff --git a/java/libs.jdkannotations/external/.gitignore b/java/libs.jdkannotations/external/.gitignore new file mode 100644 index 000000000000..6722cd96e785 --- /dev/null +++ b/java/libs.jdkannotations/external/.gitignore @@ -0,0 +1 @@ +*.xml diff --git a/java/libs.jdkannotations/external/annotations-73943d0839fdc7364be735ec4953f172db31130b-license.txt b/java/libs.jdkannotations/external/annotations-73943d0839fdc7364be735ec4953f172db31130b-license.txt new file mode 100644 index 000000000000..cd1bd8db6b06 --- /dev/null +++ b/java/libs.jdkannotations/external/annotations-73943d0839fdc7364be735ec4953f172db31130b-license.txt @@ -0,0 +1,209 @@ +Name: JDK External Annotations +Description: External Annotations for JDK +Origin: JetBrains, IntelliJ Community +License: Apache-2.0 +Version: 73943d0839fdc7364be735ec4953f172db31130b +URL: https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations +Files: java.beans.annotations.xml java.awt.geom.annotations.xml java.awt.im.annotations.xml java.awt.dnd.annotations.xml java.awt.event.annotations.xml java.awt.datatransfer.annotations.xml java.awt.annotations.xml java.text.annotations.xml java.time.format.annotations.xml java.time.annotations.xml java.security.annotations.xml java.util.jar.annotations.xml java.util.zip.annotations.xml java.util.stream.annotations.xml java.util.regex.annotations.xml java.util.function.annotations.xml java.util.concurrent.locks.annotations.xml java.util.concurrent.atomic.annotations.xml java.util.concurrent.annotations.xml java.util.annotations.xml java.lang.ref.annotations.xml java.lang.reflect.annotations.xml java.lang.annotations.xml java.lang.invoke.annotations.xml java.nio.file.spi.annotations.xml java.nio.file.annotations.xml java.nio.charset.annotations.xml java.nio.channels.annotations.xml java.nio.annotations.xml java.math.annotations.xml java.sql.annotations.xml java.io.annotations.xml java.net.annotations.xml javax.annotation.processing.annotations.xml javax.naming.event.annotations.xml javax.accessibility.annotations.xml javax.tools.annotations.xml javax.swing.text.html.annotations.xml javax.swing.tree.annotations.xml javax.swing.plaf.basic.annotations.xml javax.swing.plaf.annotations.xml javax.swing.event.annotations.xml javax.swing.annotations.xml javax.swing.table.annotations.xml javax.swing.border.annotations.xml javax.xml.bind.annotation.annotations.xml org.w3c.dom.annotations.xml com.sun.jdi.event.annotations.xml com.sun.jdi.request.annotations.xml com.sun.jdi.annotations.xml + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/java/libs.jdkannotations/external/annotations-73943d0839fdc7364be735ec4953f172db31130b-notice.txt b/java/libs.jdkannotations/external/annotations-73943d0839fdc7364be735ec4953f172db31130b-notice.txt new file mode 100644 index 000000000000..d9f5e1dfc3b2 --- /dev/null +++ b/java/libs.jdkannotations/external/annotations-73943d0839fdc7364be735ec4953f172db31130b-notice.txt @@ -0,0 +1,3 @@ +This software includes code from IntelliJ IDEA Community Edition +Copyright (C) JetBrains s.r.o. +https://www.jetbrains.com/idea/ diff --git a/java/libs.jdkannotations/external/binaries-list b/java/libs.jdkannotations/external/binaries-list new file mode 100644 index 000000000000..9615def9ef81 --- /dev/null +++ b/java/libs.jdkannotations/external/binaries-list @@ -0,0 +1,66 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +EC5C1E409E56B27121E41668759C7D106D01EFB4 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/beans/annotations.xml java.beans.annotations.xml +CB211119803740EC62C4A6C3F3357EC303CA2CE9 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/awt/geom/annotations.xml java.awt.geom.annotations.xml +926E2B21E0E712B3607EEB6D84F43417B2896127 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/awt/im/annotations.xml java.awt.im.annotations.xml +35E3224FCBD3E1AF306F2B6A2C6BBEA9B0867966 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/awt/dnd/annotations.xml java.awt.dnd.annotations.xml +2461DFD66282904AADF76FEADC04AC73CCD5B89E https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/awt/event/annotations.xml java.awt.event.annotations.xml +BB566AACEAA62EC4DBA2F26FCA0FD9CA8357013D https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/awt/datatransfer/annotations.xml java.awt.datatransfer.annotations.xml +649A7DC860161AA58E98948FD6FCE6F080245A77 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/awt/annotations.xml java.awt.annotations.xml +39222FA2EE85E8B6091BD305C5092D36875250B4 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/text/annotations.xml java.text.annotations.xml +85D1C7C0620A9069072F268BB21ACD433BFD1348 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/time/format/annotations.xml java.time.format.annotations.xml +2EF8F60023E40C2D75D8BB88AE19D1384789E0A1 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/time/annotations.xml java.time.annotations.xml +E1CF8C2060C3B605BFC164EE3F3C0FFD26D8C6B8 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/security/annotations.xml java.security.annotations.xml +B25262F74645A6CEFB9F08F65E44E3F347BB83CC https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/util/jar/annotations.xml java.util.jar.annotations.xml +9727BB4DF3C272C37E2CA94BE8C6059DD7618217 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/util/zip/annotations.xml java.util.zip.annotations.xml +E564CBCBB8CC9277E93943BF900F859E95EF39BD https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/util/stream/annotations.xml java.util.stream.annotations.xml +120C151D9C6ADAE198C3BD37D605FB8FDD90D6FE https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/util/regex/annotations.xml java.util.regex.annotations.xml +09AFED7FC58D2AFCDD93C1A7D16FBDC9C51DBB03 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/util/function/annotations.xml java.util.function.annotations.xml +87775D78414FA21D879D26BA09884A0A1A634066 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/util/concurrent/locks/annotations.xml java.util.concurrent.locks.annotations.xml +962EBB8010BEC7BF2CCFF2CAD30C17D9BB0EDFD6 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/util/concurrent/atomic/annotations.xml java.util.concurrent.atomic.annotations.xml +950E4F0D004A62A087831C16FA234D93513E0264 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/util/concurrent/annotations.xml java.util.concurrent.annotations.xml +54EB0B744878B80CD7DCC4F6CE031998162B9BAF https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/util/annotations.xml java.util.annotations.xml +168EACA6A54F3BAD0CB31DB46FF0A9D44943F617 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/lang/ref/annotations.xml java.lang.ref.annotations.xml +8CA596D69D74EDAB225F8133D0FCAFF2E5A82A95 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/lang/reflect/annotations.xml java.lang.reflect.annotations.xml +2C9646592355BDC106C2B72C47A2007F0948D44D https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/lang/annotations.xml java.lang.annotations.xml +D022E8015B820D5D82DEF39017AC8CBA04718219 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/lang/invoke/annotations.xml java.lang.invoke.annotations.xml +01A7D399244292E5C72A7169680CFACCDDC4D36B https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/nio/file/spi/annotations.xml java.nio.file.spi.annotations.xml +6CEF46EED432035D9BEFB9980207FA33438C1770 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/nio/file/annotations.xml java.nio.file.annotations.xml +773FBBD8A567B46A1F556988F99B74343852623F https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/nio/charset/annotations.xml java.nio.charset.annotations.xml +1F4E77EE82BA4CD7F4EEB00911E2060D17CA79AA https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/nio/channels/annotations.xml java.nio.channels.annotations.xml +A388ECCB92DB8CD385E80311F58DE0221D4DD32C https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/nio/annotations.xml java.nio.annotations.xml +08062BFF0547BE8922F2E50EED78653BB8845D04 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/math/annotations.xml java.math.annotations.xml +95CD3C8ADED6149AC36393100626B1A40906E7F8 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/sql/annotations.xml java.sql.annotations.xml +C4562D68970F19CE11E861FD6D2E13A793BD5ADC https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/io/annotations.xml java.io.annotations.xml +2063F2261A25D780B8A296FF420F8895D7A3D80C https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/java/net/annotations.xml java.net.annotations.xml +70FF29AEBD5D8095986D73F08CDFE8038CECF09A https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/annotation/processing/annotations.xml javax.annotation.processing.annotations.xml +BDE5EF583346C86B4957540D4B80349D4CA96C5C https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/naming/event/annotations.xml javax.naming.event.annotations.xml +49BA009DC66091D8664221E1C029770381E727F6 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/accessibility/annotations.xml javax.accessibility.annotations.xml +2B5729572B8C70AC0BD9F4FF3CC0BC454751BF2D https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/tools/annotations.xml javax.tools.annotations.xml +CE871E5A69C5DE18D2B91B2B162A8C2CEA9DBDBC https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/swing/text/html/annotations.xml javax.swing.text.html.annotations.xml +27DD5D91255ED0CC0235333ACF0ECE2C8A27F4A5 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/swing/tree/annotations.xml javax.swing.tree.annotations.xml +18B5426CFEF5C5D3D9A00DD30EFA7ACB20309915 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/swing/plaf/basic/annotations.xml javax.swing.plaf.basic.annotations.xml +AF1F8E758D2FFFC26429459F8F63DEFE4251CA68 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/swing/plaf/annotations.xml javax.swing.plaf.annotations.xml +D9F002E7FE7661096F65EDCE9EFFA131AC2B41B0 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/swing/event/annotations.xml javax.swing.event.annotations.xml +3D02B5AF63EA2E53E8313C32E6841C4603363E1E https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/swing/annotations.xml javax.swing.annotations.xml +022E63398E5C9C08D4B4D7E5A86114D497F22929 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/swing/table/annotations.xml javax.swing.table.annotations.xml +1E8D78C00A61B5ECF2E0199939F99578D4BB2145 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/swing/border/annotations.xml javax.swing.border.annotations.xml +7F281B4F9672DFE506751457479A7FD1EA29742B https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/javax/xml/bind/annotation/annotations.xml javax.xml.bind.annotation.annotations.xml +A65AF629112A11F96D945A6ACA85A4DB05CE3673 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/org/w3c/dom/annotations.xml org.w3c.dom.annotations.xml +0C598D203FEE043B525844A33289000AB04EE162 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/com/sun/jdi/event/annotations.xml com.sun.jdi.event.annotations.xml +8B0393127AA162DC6E7DB6D5055E631B0E96167D https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/com/sun/jdi/request/annotations.xml com.sun.jdi.request.annotations.xml +26FEB625FCCAEC1987A33BEDEF9A3739EB879541 https://raw.githubusercontent.com/JetBrains/intellij-community/73943d0839fdc7364be735ec4953f172db31130b/java/jdkAnnotations/com/sun/jdi/annotations.xml com.sun.jdi.annotations.xml diff --git a/java/libs.jdkannotations/manifest.mf b/java/libs.jdkannotations/manifest.mf new file mode 100644 index 000000000000..509dfb5f6a71 --- /dev/null +++ b/java/libs.jdkannotations/manifest.mf @@ -0,0 +1,7 @@ +Manifest-Version: 1.0 +AutoUpdate-Show-In-Client: true +OpenIDE-Module: org.netbeans.libs.jdkannotations +OpenIDE-Module-Layer: org/netbeans/libs/jdkannotations/layer.xml +OpenIDE-Module-Localizing-Bundle: org/netbeans/libs/jdkannotations/Bundle.properties +OpenIDE-Module-Specification-Version: 1.0 + diff --git a/java/libs.jdkannotations/nbproject/project.properties b/java/libs.jdkannotations/nbproject/project.properties new file mode 100644 index 000000000000..5137752915a4 --- /dev/null +++ b/java/libs.jdkannotations/nbproject/project.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +javac.source=1.8 +javac.compilerargs=-Xlint -Xlint:-serial diff --git a/java/libs.jdkannotations/nbproject/project.xml b/java/libs.jdkannotations/nbproject/project.xml new file mode 100644 index 000000000000..c591d6338a62 --- /dev/null +++ b/java/libs.jdkannotations/nbproject/project.xml @@ -0,0 +1,31 @@ + + + + org.netbeans.modules.apisupport.project + + + org.netbeans.libs.jdkannotations + + + + + diff --git a/java/libs.jdkannotations/src/org/netbeans/libs/jdkannotations/Bundle.properties b/java/libs.jdkannotations/src/org/netbeans/libs/jdkannotations/Bundle.properties new file mode 100644 index 000000000000..7c918107ae00 --- /dev/null +++ b/java/libs.jdkannotations/src/org/netbeans/libs/jdkannotations/Bundle.properties @@ -0,0 +1,18 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +OpenIDE-Module-Name=JDK Annotations diff --git a/java/libs.jdkannotations/src/org/netbeans/libs/jdkannotations/layer.xml b/java/libs.jdkannotations/src/org/netbeans/libs/jdkannotations/layer.xml new file mode 100644 index 000000000000..bc04db3476ed --- /dev/null +++ b/java/libs.jdkannotations/src/org/netbeans/libs/jdkannotations/layer.xml @@ -0,0 +1,202 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbbuild/cluster.properties b/nbbuild/cluster.properties index 177c54d53830..7326e05722c7 100644 --- a/nbbuild/cluster.properties +++ b/nbbuild/cluster.properties @@ -666,6 +666,7 @@ nb.cluster.java=\ libs.cglib,\ libs.corba.omgapi,\ libs.javacapi,\ + libs.jdkannotations,\ libs.nbjavacapi,\ libs.springframework,\ maven,\ From a33f0aaa7f4005fd8462c956361902103262b689 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 10 Oct 2025 11:34:24 +0200 Subject: [PATCH 2/2] Fixing tests. --- .../java/hints/bugs/MagicConstantHintTest.java | 15 ++++++++++++--- .../source/annotations/AugmentedAnnotations.java | 11 +++++++++-- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/MagicConstantHintTest.java b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/MagicConstantHintTest.java index 075c9f35d3e7..dc0740d85b00 100644 --- a/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/MagicConstantHintTest.java +++ b/java/java.hints/test/unit/src/org/netbeans/modules/java/hints/bugs/MagicConstantHintTest.java @@ -19,6 +19,9 @@ package org.netbeans.modules.java.hints.bugs; import java.io.IOException; +import java.lang.reflect.Modifier; +import java.util.Arrays; +import java.util.stream.Collectors; import org.junit.Test; import org.netbeans.modules.java.hints.test.api.HintTest; import org.netbeans.modules.java.source.annotations.AugmentedAnnotations; @@ -36,6 +39,12 @@ public void testFlagsFromClass() throws Exception { "\n" + "\n"); + String modifiers = + Arrays.stream(Modifier.class.getDeclaredFields()) + .filter(f -> (f.getModifiers() & Modifier.STATIC) != 0) + .map(f -> f.getName()) + .collect(Collectors.joining(", ")); + HintTest.create() .input("package test;\n" + "public class Test {\n" + @@ -44,7 +53,7 @@ public void testFlagsFromClass() throws Exception { " }\n" + "}\n") .run(MagicConstantHint.class) - .assertWarnings("3:13-3:48:verifier:" + Bundle.ERR_NotAValidValue()); + .assertWarnings("3:13-3:48:verifier:" + Bundle.ERR_NotAValidValue(modifiers)); HintTest.create() .input("package test;\n" + @@ -76,7 +85,7 @@ public void testIntValues() throws Exception { " }\n" + "}\n") .run(MagicConstantHint.class) - .assertWarnings("3:13-3:47:verifier:" + Bundle.ERR_NotAValidValue()); + .assertWarnings("3:13-3:47:verifier:" + Bundle.ERR_NotAValidValue("PUBLIC")); HintTest.create() .input("package test;\n" + @@ -112,7 +121,7 @@ public void testConstructorAndValuesFromClass() throws Exception { " public static final int V = 0;\n" + "}\n") .run(MagicConstantHint.class) - .assertWarnings("4:17-4:18:verifier:" + Bundle.ERR_NotAValidValue()); + .assertWarnings("4:17-4:18:verifier:" + Bundle.ERR_NotAValidValue("V")); HintTest.create() .input("package test;\n" + diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotations.java b/java/java.source.base/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotations.java index 0953d3af7e56..9915533d5c3e 100644 --- a/java/java.source.base/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotations.java +++ b/java/java.source.base/src/org/netbeans/modules/java/source/annotations/AugmentedAnnotations.java @@ -494,9 +494,16 @@ record RootHolder(FileObject root) {} return null; } - while (topLevel.getEnclosingElement() != null && topLevel.getEnclosingElement().getKind() == ElementKind.PACKAGE && originFO != null) { - originFO = originFO.getParent(); + originFO = originFO.getParent(); + + String name = topLevel.getQualifiedName().toString(); + + for (int i = 0; i < name.length() && originFO != null; i++) { + if (name.charAt(i) == '.') { + originFO = originFO.getParent(); + } } + return new RootHolder(originFO); } finally { if (LOG.isLoggable(Level.FINE)) {