# HG changeset patch # User lana # Date 1437100261 25200 # Node ID 02681b7c4232ba5d43ccba794492db9502211ff0 # Parent 3d40e9830cacadbfd8df2edd9eb2e561a3d2b797# Parent ad2597bdd2f5713c2936abbecc3fe49a7870d766 Merge diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java --- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/DocLint.java Thu Jul 16 19:31:01 2015 -0700 @@ -344,6 +344,10 @@ checker.scan(dc, p); } + public boolean shouldCheck(CompilationUnitTree unit) { + return env.shouldCheck(unit); + } + public void reportStats(PrintWriter out) { env.messages.reportStats(out); } @@ -406,26 +410,8 @@ @Override @DefinedBy(Api.COMPILER_TREE) public Void visitCompilationUnit(CompilationUnitTree node, Void p) { - if (env.includePackages != null) { - String packageName = node.getPackageName() != null - ? node.getPackageName().toString() - : ""; - if (!env.includePackages.isEmpty()) { - boolean included = false; - for (Pattern pack : env.includePackages) { - if (pack.matcher(packageName).matches()) { - included = true; - break; - } - } - if (!included) - return null; - } - for (Pattern pack : env.excludePackages) { - if (pack.matcher(packageName).matches()) { - return null; - } - } + if (!env.shouldCheck(node)) { + return null; } return super.visitCompilationUnit(node, p); } diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/doclint/Env.java --- a/src/jdk.compiler/share/classes/com/sun/tools/doclint/Env.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/doclint/Env.java Thu Jul 16 19:31:01 2015 -0700 @@ -43,6 +43,7 @@ import javax.tools.Diagnostic.Kind; import com.sun.source.doctree.DocCommentTree; +import com.sun.source.tree.CompilationUnitTree; import com.sun.source.util.DocTrees; import com.sun.source.util.JavacTask; import com.sun.source.util.SourcePositions; @@ -229,6 +230,35 @@ return sp.getStartPosition(p.getCompilationUnit(), p.getLeaf()); } + boolean shouldCheck(CompilationUnitTree unit) { + if (includePackages == null) + return true; + + String packageName = unit.getPackageName() != null + ? unit.getPackageName().toString() + : ""; + + if (!includePackages.isEmpty()) { + boolean included = false; + for (Pattern pack : includePackages) { + if (pack.matcher(packageName).matches()) { + included = true; + break; + } + } + if (!included) + return false; + } + + for (Pattern pack : excludePackages) { + if (pack.matcher(packageName).matches()) { + return false; + } + } + + return true; + } + private > T min(T item1, T item2) { return (item1 == null) ? item2 : (item2 == null) ? item1 diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/api/JavacTrees.java Thu Jul 16 19:31:01 2015 -0700 @@ -874,8 +874,8 @@ /** * Returns the original type from the ErrorType object. * @param errorType The errorType for which we want to get the original type. - * @returns TypeMirror corresponding to the original type, replaced by the ErrorType. - * noType (type.tag == NONE) is returned if there is no original type. + * @return TypeMirror corresponding to the original type, replaced by the ErrorType. + * noType (type.tag == NONE) is returned if there is no original type. */ @DefinedBy(Api.COMPILER_TREE) public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) { diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Attribute.java Thu Jul 16 19:31:01 2015 -0700 @@ -230,9 +230,11 @@ /** * Returns a string representation of this annotation. * String is of one of the forms: - * @com.example.foo(name1=val1, name2=val2) - * @com.example.foo(val) - * @com.example.foo + *
+         *     {@code @com.example.foo(name1=val1, name2=val2)}
+         *     {@code @com.example.foo(val)}
+         *     {@code @com.example.foo}
+         * 
* Omit parens for marker annotations, and omit "value=" when allowed. */ @DefinedBy(Api.LANGUAGE_MODEL) diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java Thu Jul 16 19:31:01 2015 -0700 @@ -461,7 +461,7 @@ * * @param location The type path. * @param onLambda The lambda for this parameter. - * @param index The index of the parameter. + * @param parameter_index The index of the parameter. * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition @@ -479,7 +479,7 @@ * Create a {@code TypeAnnotationPosition} for a method formal parameter. * * @param onLambda The lambda for this parameter. - * @param index The index of the parameter. + * @param parameter_index The index of the parameter. * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition @@ -493,7 +493,7 @@ /** * Create a {@code TypeAnnotationPosition} for a method formal parameter. * - * @param index The index of the parameter. + * @param parameter_index The index of the parameter. * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition @@ -506,7 +506,7 @@ * Create a {@code TypeAnnotationPosition} for a method formal parameter. * * @param location The type path. - * @param index The index of the parameter. + * @param parameter_index The index of the parameter. */ public static TypeAnnotationPosition methodParameter(final List location, @@ -535,8 +535,6 @@ * Create a {@code TypeAnnotationPosition} for a method reference. * * @param location The type path. - * @param onLambda The lambda for this method reference. - * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition methodRef(final List location) { @@ -564,8 +562,6 @@ * Create a {@code TypeAnnotationPosition} for a constructor reference. * * @param location The type path. - * @param onLambda The lambda for this constructor reference. - * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition constructorRef(final List location) { @@ -720,8 +716,6 @@ * Create a {@code TypeAnnotationPosition} for a resource variable. * * @param location The type path. - * @param onLambda The lambda for this variable. - * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition resourceVariable(final List location) { @@ -748,8 +742,6 @@ /** * Create a {@code TypeAnnotationPosition} for a new. * - * @param location The type path. - * @param onLambda The lambda for this variable. * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition newObj(final int pos) { @@ -760,8 +752,6 @@ * Create a {@code TypeAnnotationPosition} for a new. * * @param location The type path. - * @param onLambda The lambda for this variable. - * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition newObj(final List location) { @@ -792,7 +782,6 @@ * * @param location The type path. * @param onLambda The lambda for this variable. - * @param type_index The index of the interface. * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition @@ -854,8 +843,6 @@ * Create a {@code TypeAnnotationPosition} for an instanceof. * * @param location The type path. - * @param onLambda The lambda for this variable. - * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition instanceOf(final List location) { @@ -885,9 +872,7 @@ * Create a {@code TypeAnnotationPosition} for a type cast. * * @param location The type path. - * @param onLambda The lambda for this variable. * @param type_index The index into an intersection type. - * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition typeCast(final List location, @@ -984,9 +969,7 @@ * Create a {@code TypeAnnotationPosition} for a type parameter. * * @param location The type path. - * @param onLambda The lambda for this variable. * @param parameter_index The index of the type parameter. - * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition typeParameter(final List location, @@ -1062,7 +1045,7 @@ * * @param location The type path. * @param onLambda The lambda for this variable. - * @param parameter_index The index of the type argument. + * @param type_index The index of the type argument. * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition @@ -1081,9 +1064,7 @@ * type argument. * * @param location The type path. - * @param onLambda The lambda for this variable. - * @param parameter_index The index of the type argument. - * @param pos The position from the associated tree node. + * @param type_index The index of the type argument. */ public static TypeAnnotationPosition methodRefTypeArg(final List location, @@ -1097,7 +1078,7 @@ * * @param location The type path. * @param onLambda The lambda for this variable. - * @param parameter_index The index of the type argument. + * @param type_index The index of the type argument. * @param pos The position from the associated tree node. */ public static TypeAnnotationPosition @@ -1116,7 +1097,7 @@ * type argument. * * @param location The type path. - * @param parameter_index The index of the type argument. + * @param type_index The index of the type argument. */ public static TypeAnnotationPosition constructorRefTypeArg(final List location, diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java Thu Jul 16 19:31:01 2015 -0700 @@ -279,7 +279,7 @@ /** Check that variable can be assigned to. * @param pos The current source code position. - * @param v The assigned varaible + * @param v The assigned variable * @param base If the variable is referred to in a Select, the part * to the left of the `.', null otherwise. * @param env The current environment. @@ -759,7 +759,7 @@ /** * Attribute a "lazy constant value". * @param env The env for the const value - * @param initializer The initializer for the const value + * @param variable The initializer for the const value * @param type The expected type, or null * @see VarSymbol#setLazyConstValue */ diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JRTIndex.java Thu Jul 16 19:31:01 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.ProviderNotFoundException; -import java.nio.file.spi.FileSystemProvider; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -95,11 +94,6 @@ private final FileSystem jrtfs; /** - * The set of module directories within the jrt: file system. - */ - private final Set jrtModules; - - /** * A lazily evaluated set of entries about the contents of the jrt: file system. */ private final Map> entries; @@ -183,14 +177,6 @@ */ private JRTIndex() throws IOException { jrtfs = FileSystems.getFileSystem(URI.create("jrt:/")); - jrtModules = new LinkedHashSet<>(); - Path root = jrtfs.getPath("/"); - try (DirectoryStream stream = Files.newDirectoryStream(root)) { - for (Path entry: stream) { - if (Files.isDirectory(entry)) - jrtModules.add(entry); - } - } entries = new HashMap<>(); } @@ -204,18 +190,29 @@ if (e == null) { Map files = new LinkedHashMap<>(); Set subdirs = new LinkedHashSet<>(); - for (Path module: jrtModules) { - Path p = rd.getFile(module); - if (!Files.exists(p)) - continue; - try (DirectoryStream stream = Files.newDirectoryStream(p)) { - for (Path entry: stream) { - String name = entry.getFileName().toString(); - if (Files.isRegularFile(entry)) { - // TODO: consider issue of files with same name in different modules - files.put(name, entry); - } else if (Files.isDirectory(entry)) { - subdirs.add(new RelativeDirectory(rd, name)); + Path dir; + if (rd.path.isEmpty()) { + dir = jrtfs.getPath("/modules"); + } else { + Path pkgs = jrtfs.getPath("/packages"); + dir = pkgs.resolve(rd.getPath().replaceAll("/$", "").replace("/", ".")); + } + if (Files.exists(dir)) { + try (DirectoryStream modules = Files.newDirectoryStream(dir)) { + for (Path module: modules) { + Path p = rd.getFile(module); + if (!Files.exists(p)) + continue; + try (DirectoryStream stream = Files.newDirectoryStream(p)) { + for (Path entry: stream) { + String name = entry.getFileName().toString(); + if (Files.isRegularFile(entry)) { + // TODO: consider issue of files with same name in different modules + files.put(name, entry); + } else if (Files.isDirectory(entry)) { + subdirs.add(new RelativeDirectory(rd, name)); + } + } } } } diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/file/PathFileObject.java Thu Jul 16 19:31:01 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,8 +104,8 @@ return new PathFileObject(fileManager, path) { @Override public String inferBinaryName(Iterable paths) { - // use subpath to ignore the leading component containing the module name - return toBinaryName(path.subpath(1, path.getNameCount())); + // use subpath to ignore the leading /modules/MODULE-NAME + return toBinaryName(path.subpath(2, path.getNameCount())); } }; } diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java Thu Jul 16 19:31:01 2015 -0700 @@ -1047,7 +1047,6 @@ /** * Process any annotations found in the specified compilation units. * @param roots a list of compilation units - * @return an instance of the compiler in which to complete the compilation */ // Implementation note: when this method is called, log.deferredDiagnostics // will have been set true by initProcessAnnotations, meaning that any diagnostics @@ -1194,7 +1193,7 @@ * Note that attributing classes may cause additional files to be * parsed and entered via the SourceCompleter. * Attribution of the entries in the list does not stop if any errors occur. - * @returns a list of environments for attributd classes. + * @return a list of environments for attribute classes. */ public Queue> attribute(Queue> envs) { ListBuffer> results = new ListBuffer<>(); @@ -1205,7 +1204,7 @@ /** * Attribute a parse tree. - * @returns the attributed parse tree + * @return the attributed parse tree */ public Env attribute(Env env) { if (compileStates.isDone(env, CompileState.ATTR)) @@ -1245,7 +1244,7 @@ * Perform dataflow checks on attributed parse trees. * These include checks for definite assignment and unreachable statements. * If any errors occur, an empty list will be returned. - * @returns the list of attributed parse trees + * @return the list of attributed parse trees */ public Queue> flow(Queue> envs) { ListBuffer> results = new ListBuffer<>(); @@ -1315,7 +1314,7 @@ * Prepare attributed parse trees, in conjunction with their attribution contexts, * for source or code generation. * If any errors occur, an empty list will be returned. - * @returns a list containing the classes to be generated + * @return a list containing the classes to be generated */ public Queue, JCClassDecl>> desugar(Queue> envs) { ListBuffer, JCClassDecl>> results = new ListBuffer<>(); diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/DocCommentParser.java Thu Jul 16 19:31:01 2015 -0700 @@ -409,7 +409,7 @@ /** * Read Java class name, possibly followed by member - * Matching pairs of < > are skipped. The text is terminated by the first + * Matching pairs of {@literal < >} are skipped. The text is terminated by the first * unmatched }. It is an error if the beginning of the next tag is detected. */ // TODO: boolean allowMember should be enum FORBID, ALLOW, REQUIRE diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java Thu Jul 16 19:31:01 2015 -0700 @@ -1411,7 +1411,7 @@ } /** - * {@inheritdoc} + * {@inheritDoc} * * Command line options suitable for presenting to annotation * processors. diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacRoundEnvironment.java Thu Jul 16 19:31:01 2015 -0700 @@ -168,7 +168,7 @@ } /** - * {@inheritdoc} + * {@inheritDoc} */ @DefinedBy(Api.ANNOTATION_PROCESSING) public Set getElementsAnnotatedWith(Class a) { diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java Thu Jul 16 19:31:01 2015 -0700 @@ -2368,7 +2368,7 @@ } /** - * An intersection type, T1 & T2 & ... Tn (used in cast expressions) + * An intersection type, {@code T1 & T2 & ... Tn} (used in cast expressions) */ public static class JCTypeIntersection extends JCExpression implements IntersectionTypeTree { diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java Thu Jul 16 19:31:01 2015 -0700 @@ -61,7 +61,7 @@ * Those implementations are specifically targeting JCDiagnostic objects. *
  • Provides basic support for i18n and a method for executing all locale-dependent conversions *
  • Provides the formatting logic for rendering the arguments of a JCDiagnostic object. - *
      + *
    * *

    This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/util/Context.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Context.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Context.java Thu Jul 16 19:31:01 2015 -0700 @@ -44,7 +44,7 @@ * instance method that is overridden in extended components. A base * phase supporting extension would look something like this: * - *

    {@code
    + * 
    {@code
      * public class Phase {
      *     protected static final Context.Key phaseKey =
      *         new Context.Key();
    @@ -70,7 +70,7 @@
      * and this must be done before any reference to the phase is accessed
      * using Phase.instance().  An extended phase might be declared thus:
      *
    - * 

    {@code
    + * 
    {@code
      * public class NewPhase extends Phase {
      *     protected NewPhase(Context context) {
      *         super(context);
    @@ -87,7 +87,7 @@
      *
      * 

    And is registered early in the extended compiler like this * - *

    + * 
      *     NewPhase.preRegister(context);
      * 
    * diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/javac/util/IntHashTable.java --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/IntHashTable.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/IntHashTable.java Thu Jul 16 19:31:01 2015 -0700 @@ -28,7 +28,7 @@ /** * A hash table that maps Object to int. * - * This is a custom hash table optimised for the Object -> int + * This is a custom hash table optimised for the Object {@literal ->} int * maps. This is done to avoid unnecessary object allocation in the image set. * * @author Charles Turner @@ -43,7 +43,7 @@ private final static Object DELETED = new Object(); /** - * Construct an Object -> int hash table. + * Construct an Object {@literal ->} int hash table. * * The default size of the hash table is 64 mappings. */ @@ -54,7 +54,7 @@ } /** - * Construct an Object -> int hash table with a specified amount of mappings. + * Construct an Object {@literal ->} int hash table with a specified amount of mappings. * @param capacity The number of default mappings in this hash table. */ public IntHashTable(int capacity) { diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/BuildState.java Thu Jul 16 19:31:01 2015 -0700 @@ -187,7 +187,7 @@ /** * Verify that the setModules method above did the right thing when - * running through the module->package->source structure. + * running through the {@literal module->package->source} structure. */ public void checkInternalState(String msg, boolean linkedOnly, Map srcs) { boolean baad = false; diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java Thu Jul 16 19:31:01 2015 -0700 @@ -131,7 +131,7 @@ * do settings = cleanOptions("--server:",Util.set("-portfile"),settings); * now settings equals "--server:portfile=bar" * - * @param allowsSubOptions A set of the allowed sub options, id portfile etc. + * @param allowedSubOptions A set of the allowed sub options, id portfile etc. * @param s The option settings string. */ public static String cleanSubOptions(Set allowedSubOptions, String s) { diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java Thu Jul 16 19:31:01 2015 -0700 @@ -128,12 +128,6 @@ /** * Make a request to the server only to get the maximum possible heap size to use for compilations. - * - * @param port_file The port file used to synchronize creation of this server. - * @param id The identify of the compilation. - * @param out Standard out information. - * @param err Standard err information. - * @return The maximum heap size in bytes. */ @Override public SysInfo getSysInfo() { diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/options/Options.java Thu Jul 16 19:31:01 2015 -0700 @@ -161,7 +161,7 @@ /** * Get a map which maps suffixes to transformers (for example - * ".java" -> CompileJavaPackages) + * ".java" {@literal ->} CompileJavaPackages) */ public Map getTranslationRules() { return trRules; diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Thu Jul 16 19:31:01 2015 -0700 @@ -78,7 +78,7 @@ /** * Create a new portfile. - * @param filename is the path to the file. + * @param fn is the path to the file. */ public PortFile(String fn) throws FileNotFoundException { filename = fn; diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/AbstractExecutableMemberWriter.java Thu Jul 16 19:31:01 2015 -0700 @@ -58,7 +58,6 @@ * * @param member the member to write type parameters for. * @param htmltree the content tree to which the parameters will be added. - * @return the display length required to write this information. */ protected void addTypeParameters(ExecutableMemberDoc member, Content htmltree) { Content typeParameters = getTypeParameters(member); diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/ConfigurationImpl.java Thu Jul 16 19:31:01 2015 -0700 @@ -289,9 +289,11 @@ } else if (opt.equals("-html5")) { htmlVersion = HtmlVersion.HTML5; } else if (opt.equals("-xdoclint")) { - doclintOpts.add(null); + doclintOpts.add(DocLint.XMSGS_OPTION); } else if (opt.startsWith("-xdoclint:")) { - doclintOpts.add(opt.substring(opt.indexOf(":") + 1)); + doclintOpts.add(DocLint.XMSGS_CUSTOM_PREFIX + opt.substring(opt.indexOf(":") + 1)); + } else if (opt.startsWith("-xdoclint/package:")) { + doclintOpts.add(DocLint.XCHECK_PACKAGE + opt.substring(opt.indexOf(":") + 1)); } } if (root.specifiedClasses().length > 0) { @@ -325,7 +327,6 @@ * The options arrive as case-sensitive strings. For options that * are not case-sensitive, use toLowerCase() on the option string * before comparing it. - * * * @return number of arguments + 1 for a option. Zero return means * option not known. Negative value means error occurred. @@ -349,7 +350,8 @@ option.equals("-html4") || option.equals("-html5") || option.equals("-xdoclint") || - option.startsWith("-xdoclint:")) { + option.startsWith("-xdoclint:") || + option.startsWith("-xdoclint/package:")) { return 1; } else if (option.equals("-help")) { // Uugh: first, this should not be hidden inside optionLength, @@ -477,6 +479,12 @@ reporter.printError(getText("doclet.Option_doclint_invalid_arg")); return false; } + } else if (opt.startsWith("-xdoclint/package:")) { + if (!DocLint.isValidOption( + opt.replace("-xdoclint/package:", DocLint.XCHECK_PACKAGE))) { + reporter.printError(getText("doclet.Option_doclint_package_invalid_arg")); + return false; + } } } return true; diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/LinkInfoImpl.java Thu Jul 16 19:31:01 2015 -0700 @@ -247,7 +247,7 @@ } /** - * {@inherotDoc} + * {@inheritDoc} */ protected Content newContent() { return new ContentBuilder(); diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java Thu Jul 16 19:31:01 2015 -0700 @@ -267,7 +267,7 @@ * navigation bar, and then the title (from the"-title" * option), at the top of page. * - * @body the documentation tree to which the navigation bar header will be added + * @param body the documentation tree to which the navigation bar header will be added */ protected void addNavigationBarHeader(Content body) { Content htmlTree = (configuration.allowTag(HtmlTag.HEADER)) diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties --- a/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/resources/standard.properties Thu Jul 16 19:31:01 2015 -0700 @@ -231,4 +231,10 @@ \ -Xdoclint Enable recommended checks for problems in javadoc comments\n\ \ -Xdoclint:(all|none|[-]) \n\ \ Enable or disable specific checks for problems in javadoc comments,\n\ -\ where is one of accessibility, html, missing, reference, or syntax.\n +\ where is one of accessibility, html, missing, reference, or syntax.\n\ +\ -Xdoclint/package:([-])\n\ +\ Enable or disable checks in specific packages. is a comma separated\n\ +\ list of package specifiers. Package specifier is either a qualified name of a package\n\ +\ or a package name prefix followed by .*, which expands to all sub-packages of\n\ +\ the given package. Prefix the package specifier with - to disable checks for\n\ +\ the specified packages.\n diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties --- a/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties Thu Jul 16 19:31:01 2015 -0700 @@ -13,6 +13,7 @@ doclet.Option_reuse=Option reused: {0} doclet.Option_doclint_no_qualifiers=Access qualifiers not permitted for -Xdoclint arguments doclet.Option_doclint_invalid_arg=Invalid argument for -Xdoclint option +doclet.Option_doclint_package_invalid_arg=Invalid argument for -Xdoclint/package option doclet.exception_encountered= {0} encountered \n\ \twhile attempting to create file: {1} doclet.perform_copy_exception_encountered= {0} encountered while \n\ diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletWriter.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletWriter.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/TagletWriter.java Thu Jul 16 19:31:01 2015 -0700 @@ -58,7 +58,7 @@ public abstract Content getOutputInstance(); /** - * Return the output for a {@code...} tag. + * Return the output for a {@code {@code ...}} tag. * * @param tag the tag. * @return the output of the taglet. @@ -80,7 +80,7 @@ protected abstract Content deprecatedTagOutput(Doc doc); /** - * Return the output for a {@literal...} tag. + * Return the output for a {@code {@literal ...}} tag. * * @param tag the tag. * @return the output of the taglet. diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/AnnotationDescImpl.java Thu Jul 16 19:31:01 2015 -0700 @@ -100,9 +100,11 @@ /** * Returns a string representation of this annotation. * String is of one of the forms: - * @com.example.foo(name1=val1, name2=val2) - * @com.example.foo(val) - * @com.example.foo + *
    +     *     {@code @com.example.foo(name1=val1, name2=val2)}
    +     *     {@code @com.example.foo(val)}
    +     *     {@code @com.example.foo}
    +     * 
    * Omit parens for marker annotations, and omit "value=" when allowed. */ @Override diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Thu Jul 16 19:31:01 2015 -0700 @@ -1278,8 +1278,8 @@ * each Serializable field defined by an ObjectStreamField * array component of serialPersistentField. * - * @returns an array of FieldDoc for the Serializable fields - * of this class. + * @return an array of {@code FieldDoc} for the Serializable fields + * of this class. * * @see #definesSerializableFields() * @see SerialFieldTagImpl diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocEnv.java Thu Jul 16 19:31:01 2015 -0700 @@ -31,6 +31,7 @@ import javax.tools.JavaFileManager; import com.sun.javadoc.*; +import com.sun.source.tree.CompilationUnitTree; import com.sun.source.util.JavacTask; import com.sun.source.util.TreePath; import com.sun.tools.doclint.DocLint; @@ -816,16 +817,19 @@ void initDoclint(Collection opts, Collection customTagNames, String htmlVersion) { ArrayList doclintOpts = new ArrayList<>(); + boolean msgOptionSeen = false; - for (String opt: opts) { - doclintOpts.add(opt == null ? DocLint.XMSGS_OPTION : DocLint.XMSGS_CUSTOM_PREFIX + opt); + for (String opt : opts) { + if (opt.startsWith(DocLint.XMSGS_OPTION)) { + if (opt.equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) + return; + msgOptionSeen = true; + } + doclintOpts.add(opt); } - if (doclintOpts.isEmpty()) { + if (!msgOptionSeen) { doclintOpts.add(DocLint.XMSGS_OPTION); - } else if (doclintOpts.size() == 1 - && doclintOpts.get(0).equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) { - return; } String sep = ""; @@ -848,4 +852,10 @@ boolean showTagMessages() { return (doclint == null); } + + Map shouldCheck = new HashMap<>(); + + boolean shouldCheck(CompilationUnitTree unit) { + return shouldCheck.computeIfAbsent(unit, doclint :: shouldCheck); + } } diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocImpl.java --- a/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocImpl.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.javadoc/share/classes/com/sun/tools/javadoc/DocImpl.java Thu Jul 16 19:31:01 2015 -0700 @@ -129,6 +129,7 @@ String d = documentation(); if (env.doclint != null && treePath != null + && env.shouldCheck(treePath.getCompilationUnit()) && d.equals(getCommentText(treePath))) { env.doclint.scan(treePath); } diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java --- a/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.jdeps/share/classes/com/sun/tools/classfile/ReferenceFinder.java Thu Jul 16 19:31:01 2015 -0700 @@ -36,7 +36,7 @@ /** * A utility class to find where in a ClassFile references * a {@link CONSTANT_Methodref_info method}, - * a {@link CONSTANT_InterfaceMethodref_info interface method, + * a {@link CONSTANT_InterfaceMethodref_info interface method}, * or a {@link CONSTANT_Fieldref_info field}. */ public final class ReferenceFinder { diff -r 3d40e9830cac -r 02681b7c4232 src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java Thu Jul 16 13:51:57 2015 -0700 +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/PlatformClassPath.java Thu Jul 16 19:31:01 2015 -0700 @@ -97,23 +97,32 @@ } static class ImageHelper { + private static boolean isJrtAvailable() { + try { + FileSystems.getFileSystem(URI.create("jrt:/")); + return true; + } catch (ProviderNotFoundException | FileSystemNotFoundException e) { + return false; + } + } + static ImageHelper getInstance(Path mpath) throws IOException { if (mpath != null) { return new ImageHelper(mpath); } - Path home = Paths.get(System.getProperty("java.home")); - Path mlib = home.resolve("lib").resolve("modules"); - if (Files.isDirectory(mlib)) { - // jimage + + if (isJrtAvailable()) { + // jrt file system FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); - return new ImageHelper(fs, fs.getPath("/")); + return new ImageHelper(fs, fs.getPath("/modules")); } else { // exploded modules - mlib = home.resolve("modules"); - if (!Files.isDirectory(mlib)) { - throw new InternalError(home + " not a modular image"); + String home = System.getProperty("java.home"); + Path exploded = Paths.get(home, "modules"); + if (!Files.isDirectory(exploded)) { + throw new InternalError(home + " not a modular image"); } - return new ImageHelper(mlib); + return new ImageHelper(exploded); } } diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/AnnotationsTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/AnnotationsTestBase.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.Descriptor; + +import javax.tools.JavaFileObject; +import java.io.IOException; +import java.lang.annotation.RetentionPolicy; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.*; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +public abstract class AnnotationsTestBase extends TestResult { + + /** + * Element values which are used in generation of annotations. + */ + private static final TestAnnotationInfo.Pair[] elementValues = { + new TestAnnotationInfo.Pair("booleanValue", new TestAnnotationInfo.TestBooleanElementValue(true)), + new TestAnnotationInfo.Pair("byteValue", new TestAnnotationInfo.TestIntegerElementValue('B', 83)), + new TestAnnotationInfo.Pair("charValue", new TestAnnotationInfo.TestCharElementValue('H')), + new TestAnnotationInfo.Pair("shortValue", new TestAnnotationInfo.TestIntegerElementValue('S', 14)), + new TestAnnotationInfo.Pair("intValue", new TestAnnotationInfo.TestIntegerElementValue('I', 18)), + new TestAnnotationInfo.Pair("longValue", new TestAnnotationInfo.TestLongElementValue(14)), + new TestAnnotationInfo.Pair("floatValue", new TestAnnotationInfo.TestFloatElementValue(-1)), + new TestAnnotationInfo.Pair("doubleValue", new TestAnnotationInfo.TestDoubleElementValue(-83)), + new TestAnnotationInfo.Pair("stringValue", new TestAnnotationInfo.TestStringElementValue("///")), + new TestAnnotationInfo.Pair("arrayValue1", new TestAnnotationInfo.TestArrayElementValue( + new TestAnnotationInfo.TestIntegerElementValue('I', 1), + new TestAnnotationInfo.TestIntegerElementValue('I', 4), + new TestAnnotationInfo.TestIntegerElementValue('I', 8), + new TestAnnotationInfo.TestIntegerElementValue('I', 3))), + new TestAnnotationInfo.Pair("arrayValue2", new TestAnnotationInfo.TestArrayElementValue( + new TestAnnotationInfo.TestStringElementValue("AAA"), + new TestAnnotationInfo.TestStringElementValue("BBB"))), + new TestAnnotationInfo.Pair("enumValue", new TestAnnotationInfo.TestEnumElementValue("EnumValue", "VALUE2")), + new TestAnnotationInfo.Pair("classValue1", new TestAnnotationInfo.TestClassElementValue("void.class")), + new TestAnnotationInfo.Pair("classValue2", new TestAnnotationInfo.TestClassElementValue("Character.class")), + new TestAnnotationInfo.Pair("annoValue", new TestAnnotationInfo.TestAnnotationElementValue("AnnotationValue", + new TestAnnotationInfo("AnnotationValue", RetentionPolicy.CLASS, + new TestAnnotationInfo.Pair("stringValue", + new TestAnnotationInfo.TestStringElementValue("StringValue1"))))), + new TestAnnotationInfo.Pair("annoArrayValue", new TestAnnotationInfo.TestArrayElementValue( + new TestAnnotationInfo.TestAnnotationElementValue("AnnotationValue", + new TestAnnotationInfo("AnnotationValue", RetentionPolicy.CLASS, + new TestAnnotationInfo.Pair("stringValue", + new TestAnnotationInfo.TestStringElementValue("StringValue1")))), + new TestAnnotationInfo.TestAnnotationElementValue("AnnotationValue", + new TestAnnotationInfo("AnnotationValue", RetentionPolicy.CLASS, + new TestAnnotationInfo.Pair("stringValue", + new TestAnnotationInfo.TestStringElementValue("StringValue1")))))) + }; + + /** + * Masks which are used in generation of annotations. + * E.g. mask 0 corresponds to an annotation without element values. + */ + private static final int[] elementValuesCombinations; + + static { + List combinations = new ArrayList<>(); + combinations.add(0); + for (int i = 0; i < elementValues.length; ++i) { + combinations.add(1 << i); + } + // pairs int value and another value + for (int i = 0; i < elementValues.length; ++i) { + combinations.add((1 << 5) | (1 << i)); + } + combinations.add((1 << elementValues.length) - 1); + elementValuesCombinations = combinations.stream().mapToInt(Integer::intValue).toArray(); + } + + /** + * Method generates a list of test cases. + * Method is called in the method {@code call()}. + * + * @return a list of test cases + */ + public abstract List generateTestCases(); + + public abstract void test(TestCase testCase, Map classes) + throws IOException, ConstantPoolException, Descriptor.InvalidDescriptor; + + /** + * The method is used to create a repeatable annotation. + */ + private TestAnnotationInfo createSomeAnnotation(String annotationName) { + return new TestAnnotationInfo(annotationName, getRetentionPolicy(annotationName), + new TestAnnotationInfo.Pair("booleanValue", + new TestAnnotationInfo.TestBooleanElementValue(true)), + new TestAnnotationInfo.Pair("intValue", + new TestAnnotationInfo.TestIntegerElementValue('I', 1)), + new TestAnnotationInfo.Pair("enumValue", + new TestAnnotationInfo.TestEnumElementValue("EnumValue", "VALUE1"))); + } + + private TestAnnotationInfo getAnnotationByMask(String annotationName, int mask) { + List pairs = new ArrayList<>(); + for (int i = 0; i < elementValues.length; ++i) { + if ((mask & (1 << i)) != 0) { + pairs.add(elementValues[i]); + } + } + return new TestAnnotationInfo( + annotationName, + getRetentionPolicy(annotationName), + pairs.toArray(new TestAnnotationInfo.Pair[pairs.size()])); + } + + /** + * Class represents annotations which will be applied to one method. + */ + public static class TestAnnotationInfos { + public final List annotations; + + public TestAnnotationInfos(List a) { + this.annotations = a; + } + + public void annotate(TestCase.TestMemberInfo memberInfo) { + annotations.forEach(memberInfo::addAnnotation); + } + } + + /** + * Convenience method to group test cases. + * Increases speed of tests. + */ + public List> groupAnnotations(List annotations) { + List> groupedAnnotations = new ArrayList<>(); + int size = 32; + List current = null; + for (TestAnnotationInfos infos : annotations) { + if (current == null || current.size() == size) { + current = new ArrayList<>(); + groupedAnnotations.add(current); + } + current.add(infos); + } + return groupedAnnotations; + } + + public List getAllCombinationsOfAnnotations() { + List combinations = new ArrayList<>(); + for (Annotations annotationName1 : Annotations.values()) { + List list = IntStream.of(elementValuesCombinations) + .mapToObj(e -> getAnnotationByMask(annotationName1.getAnnotationName(), e)) + .collect(Collectors.toList()); + // add cases with a single annotation + combinations.addAll(list.stream() + .map(Collections::singletonList) + .map(TestAnnotationInfos::new) + .collect(Collectors.toList())); + + // add cases with a repeatable annotation + for (Annotations annotationName2 : Annotations.values()) { + if (annotationName1 == annotationName2 && !annotationName1.isRepeatable()) { + continue; + } + TestAnnotationInfo annotation2 = createSomeAnnotation(annotationName2.getAnnotationName()); + for (TestAnnotationInfo annotation1 : list) { + List list1 = new ArrayList<>(); + Collections.addAll(list1, annotation1, annotation2); + combinations.add(new TestAnnotationInfos(list1)); + } + } + } + return combinations; + } + + protected RetentionPolicy getRetentionPolicy(String name) { + if (name.contains("Visible")) { + return RetentionPolicy.RUNTIME; + } else if (name.contains("Invisible")) { + return RetentionPolicy.CLASS; + } + throw new IllegalArgumentException(name); + } + + protected long countNumberOfAttributes(Attribute[] attrs, + Class clazz) { + return Stream.of(attrs) + .filter(clazz::isInstance) + .count(); + } + + public void test() throws TestFailedException { + try { + List testCases = generateTestCases(); + for (int i = 0; i < testCases.size(); ++i) { + TestCase testCase = testCases.get(i); + String source = testCase.generateSource(); + Path sourceFile = Paths.get(getClass().getSimpleName() + i + ".java"); + addTestCase(sourceFile.toAbsolutePath().toString()); + writeToFile(sourceFile, source); + echo("Testing: " + sourceFile.toString()); + try { + test(testCase, compile(source).getClasses()); + } catch (Exception e) { + addFailure(e); + } + } + } catch (RuntimeException | IOException e) { + addFailure(e); + } finally { + checkStatus(); + } + } + + public enum Annotations { + RUNTIME_INVISIBLE_REPEATABLE("RuntimeInvisibleRepeatable", true), + RUNTIME_INVISIBLE_NOT_REPEATABLE("RuntimeInvisibleNotRepeatable", false), + RUNTIME_VISIBLE_REPEATABLE("RuntimeVisibleRepeatable", true), + RUNTIME_VISIBLE_NOT_REPEATABLE("RuntimeVisibleNotRepeatable", false); + + private final String annotationName; + private final boolean isRepeatable; + + Annotations(String annotationName, boolean isRepeatable) { + this.annotationName = annotationName; + this.isRepeatable = isRepeatable; + } + + public String getAnnotationName() { + return annotationName; + } + + public boolean isRepeatable() { + return isRepeatable; + } + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/ClassType.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/ClassType.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.Collection; +import java.util.stream.Collectors; + +public enum ClassType { + CLASS("class"), + INTERFACE("interface") { + @Override + public String methodToString(TestCase.TestMethodInfo method) { + String modifiers = method.mods.stream() + .collect(Collectors.joining(" ")); + boolean hasBody = modifiers.contains("static") || modifiers.contains("default"); + String parameters = method.parameters.stream() + .map(TestCase.TestMemberInfo::generateSource) + .collect(Collectors.joining(", ")); + return String.format("%s %s %s(%s) %s", + method.indention() + modifiers, + "int", + method.getName(), + parameters, + hasBody ? "{return 0;}" : ";"); + } + }, + ANNOTATION("@interface") { + @Override + public String methodToString(TestCase.TestMethodInfo method) { + String modifiers = method.mods.stream() + .collect(Collectors.joining(" ")); + return String.format("%s %s %s() %s", + method.indention() + modifiers, + "int", + method.getName(), + ";"); + } + }, + ENUM("enum") { + @Override + public String fieldToString(TestCase.TestFieldInfo field) { + return field.indention() + field.name; + } + + @Override + public String collectFields(Collection fields) { + return fields.stream() + .map(TestCase.TestMemberInfo::generateSource) + .collect(Collectors.joining(",\n")) + ";\n"; + } + }; + + private final String classType; + + ClassType(String classType) { + this.classType = classType; + } + + private String collectSrc(Collection members) { + String src = members.stream() + .map(TestCase.TestMemberInfo::generateSource) + .collect(Collectors.joining("\n")); + return src.trim().isEmpty() ? "" : src + "\n\n"; + } + + public String collectInnerClasses(Collection innerClasses) { + return collectSrc(innerClasses); + } + + public String collectFields(Collection fields) { + return collectSrc(fields); + } + + public String collectMethods(Collection methods) { + return collectSrc(methods); + } + + public String methodToString(TestCase.TestMethodInfo method) { + String modifiers = method.mods.stream() + .collect(Collectors.joining(" ")); + String parameters = method.parameters.stream() + .map(TestCase.TestMemberInfo::generateSource) + .collect(Collectors.joining(", ")); + String localClasses = collectInnerClasses(method.localClasses.values()); + String methodBody = modifiers.contains("abstract") ? ";" : + String.format("{%n%s%s%n%s}", + localClasses, + method.isConstructor + ? "" + : method.indention() + "return false;", + method.indention()); + return String.format("%s %s %s(%s) %s", + method.indention() + modifiers, + method.isConstructor ? "" : "boolean", + method.getName(), + parameters, + methodBody); + } + + public String fieldToString(TestCase.TestFieldInfo field) { + String modifiers = field.mods.stream() + .collect(Collectors.joining(" ")); + return String.format("%s int %s = 0;", + field.indention() + modifiers, + field.name); + } + + public String getDescription() { + return classType; + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/README.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/README.txt Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +== Description of tests for RuntimeVisibleAnnotations, RuntimeInVisibleAnnotations +RuntimeVisibleParameterAnnotations and RuntimeInvisibleParameterAnnotations attributes == + +* AnnotationsTestBase class is a base class for the Annotations attribute tests. +It contains some convenience methods which might be used in derived classes. + +* ClassType is a enum which is used for convenience code generation (see TestCase). + +* TestCase is a class which represent a test case. TestCase contains TestClassInfo, +which represents a class, TestMethodInfo, which represents a method, TestFieldInfo, +which represents a field, and TestParameterInfo, which represents a method's parameter. +The class is used as test case builder. For example, the following code creates +the top-level class Test with method classMethod() and local class Local. +Each program member is annotated by some annotation which is an instance of +TestAnnotationInfo (see TestAnnotationInfo): + + TestCase test = new TestCase(ClassType.CLASS, "Test", "public"); + test.clazz.addAnnotation(annotations); + TestCase.TestMethodInfo classMethod = test.clazz.addMethod("classMethod()"); + classMethod.addAnnotation(annotation); + TestCase.TestClassInfo localClassInClassMethod = classMethod.addLocalClass("Local"); + localClassInClassMethod.addAnnotation(annotations); + +Let "annotations" be a list of annotations A, B(i = 2). Thus, a test will generate the +following code: + + @A + @B(i = 2) + public class Test { + @A + @B(i = 2) + void classMethod() { + @A + @B(i = 2) + class Local { + } + } + } + +Thus, TestCase contains information about structure of classes and golden data +about annotations. Thereafter, sources can be generated from this class representation +by calling method generateSource(). Enum ClassType is used to handle "class type specific" +code generation. For example, not-abstract method in a class always has body, +while not-static and not-default method in an interface does not. \ No newline at end of file diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForGenericMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForGenericMethodTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044411 + * @summary Tests the RuntimeVisibleAnnotations/RuntimeInvisibleAnnotations attribute. + * Checks that the attribute is generated for bridge method. + * @library /tools/lib /tools/javac/lib ../lib + * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox + * @build TestCase ClassType TestAnnotationInfo + * @build RuntimeAnnotationsForGenericMethodTest AnnotationsTestBase RuntimeAnnotationsTestBase + * @run main RuntimeAnnotationsForGenericMethodTest + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * RuntimeAnnotationsGenericMethodTest is a test which check that + * RuntimeVisibleAnnotationsAttribute and RuntimeInvisibleAnnotationsAttribute + * are generated for both generic and appropriate bridge methods. + * All possible combinations of retention policies are tested. + * + * The test generates class which looks as follows: + * + * public class Test extends java.util.ArrayList<Integer> { + * here some annotations + * public boolean add(java.lang.Integer) { + * return false; + * } + * } + * + * Thereafter, various of combinations of annotations are applied + * to the add, the source is compiled and the generated byte code is checked. + * + * See README.txt for more information. + */ +public class RuntimeAnnotationsForGenericMethodTest extends RuntimeAnnotationsTestBase { + + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + for (List groupedAnnotations : groupAnnotations(getAllCombinationsOfAnnotations())) { + TestCase testCase = new TestCase(); + for (int i = 0; i < groupedAnnotations.size(); ++i) { + TestAnnotationInfos annotations = groupedAnnotations.get(i); + // generate: public class Test extends java.util.ArrayList + TestCase.TestClassInfo clazz = testCase.addClassInfo("java.util.ArrayList", ClassType.CLASS, "Test" + i); + TestCase.TestMethodInfo method = clazz.addMethodInfo("add(java.lang.Integer)", "public"); + method.addParameter("Integer", "i"); + annotations.annotate(method); + TestCase.TestMethodInfo synMethod = clazz.addMethodInfo("add(java.lang.Object)", true, "public"); + annotations.annotate(synMethod); + } + testCases.add(testCase); + } + return testCases; + } + + public static void main(String[] args) throws TestFailedException { + new RuntimeAnnotationsForGenericMethodTest().test(); + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerAnnotationTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerAnnotationTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044411 + * @summary Tests the RuntimeVisibleAnnotations/RuntimeInvisibleAnnotations attribute. + * @library /tools/lib /tools/javac/lib ../lib + * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox + * @build TestCase ClassType TestAnnotationInfo + * @build RuntimeAnnotationsForInnerAnnotationTest AnnotationsTestBase RuntimeAnnotationsTestBase + * @run main RuntimeAnnotationsForInnerAnnotationTest + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * The test checks that RuntimeVisibleAnnotationsAttribute and RuntimeInvisibleAnnotationsAttribute + * are generated properly for inner classes annotations, for methods, for fields + * + * The test checks both single and repeatable annotations. In addition, all possible combinations + * of retention policies are tested. The test generates source code, compiles it and checks the byte code. + * + * See README.txt for more information. + */ +public class RuntimeAnnotationsForInnerAnnotationTest extends RuntimeAnnotationsTestBase { + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + for (List groupedAnnotations : groupAnnotations(getAllCombinationsOfAnnotations())) { + for (ClassType outerClassType : ClassType.values()) { + TestCase test = new TestCase(); + TestCase.TestClassInfo clazz = test.addClassInfo(outerClassType, "Test"); + for (int i = 0; i < groupedAnnotations.size(); ++i) { + TestCase.TestClassInfo anno = clazz.addInnerClassInfo(ClassType.ANNOTATION, "InnerAnnotation" + i); + TestAnnotationInfos annotations = groupedAnnotations.get(i); + annotations.annotate(anno); + + TestCase.TestMethodInfo annoMethod = anno.addMethodInfo("interMethod" + i + "()"); + annotations.annotate(annoMethod); + + TestCase.TestFieldInfo annoField = anno.addFieldInfo("annoField" + i); + annotations.annotate(annoField); + } + testCases.add(test); + } + } + return testCases; + } + + public static void main(String[] args) throws TestFailedException { + new RuntimeAnnotationsForInnerAnnotationTest().test(); + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerClassTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044411 + * @summary Tests the RuntimeVisibleAnnotations/RuntimeInvisibleAnnotations attribute. + * @library /tools/lib /tools/javac/lib ../lib + * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox + * @build TestCase ClassType TestAnnotationInfo + * @build RuntimeAnnotationsForInnerClassTest AnnotationsTestBase RuntimeAnnotationsTestBase + * @run main RuntimeAnnotationsForInnerClassTest + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * The test checks that RuntimeVisibleAnnotationsAttribute and RuntimeInvisibleAnnotationsAttribute + * are generated properly for inner classes, for constructors, for methods, for fields. + * The test checks both single and repeatable annotations. In addition, all possible combinations + * of retention policies are tested. + * + * The test generates source code, compiles it and checks the byte code. + * + * See README.txt for more information. + */ +public class RuntimeAnnotationsForInnerClassTest extends RuntimeAnnotationsTestBase { + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + for (List groupedAnnotations : groupAnnotations(getAllCombinationsOfAnnotations())) { + for (ClassType outerClassType : ClassType.values()) { + TestCase test = new TestCase(); + TestCase.TestClassInfo outerClazz = test.addClassInfo(outerClassType, "Test"); + for (int i = 0; i < groupedAnnotations.size(); ++i) { + TestAnnotationInfos annotations = groupedAnnotations.get(i); + TestCase.TestClassInfo clazz = outerClazz.addInnerClassInfo(ClassType.CLASS, "InnerClass" + i, "static"); + annotations.annotate(clazz); + + TestCase.TestMethodInfo constructor = clazz.addMethodInfo("()"); + annotations.annotate(constructor); + + TestCase.TestClassInfo localClassInConstructor = constructor.addLocalClassInfo("Local1" + i); + annotations.annotate(localClassInConstructor); + + TestCase.TestMethodInfo innerClazzMethod = clazz.addMethodInfo("innerClassMethod" + i + "()"); + annotations.annotate(innerClazzMethod); + + TestCase.TestClassInfo localClassInClassMethod = innerClazzMethod.addLocalClassInfo("Local2" + i); + annotations.annotate(localClassInClassMethod); + + TestCase.TestMethodInfo innerStaticClazzMethod = clazz.addMethodInfo("innerStaticClassMethod" + i + "()", "static"); + annotations.annotate(innerStaticClazzMethod); + + TestCase.TestClassInfo localClassInStaticMethod = innerStaticClazzMethod.addLocalClassInfo("Local3" + i); + annotations.annotate(localClassInStaticMethod); + } + testCases.add(test); + } + } + return testCases; + } + + public static void main(String[] args) throws TestFailedException { + new RuntimeAnnotationsForInnerClassTest().test(); + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerEnumTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerEnumTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044411 + * @summary Tests the RuntimeVisibleAnnotations/RuntimeInvisibleAnnotations attribute. + * @library /tools/lib /tools/javac/lib ../lib + * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox + * @build TestCase ClassType TestAnnotationInfo + * @build RuntimeAnnotationsForInnerEnumTest AnnotationsTestBase RuntimeAnnotationsTestBase + * @run main RuntimeAnnotationsForInnerEnumTest + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * The test checks that RuntimeVisibleAnnotationsAttribute and RuntimeInvisibleAnnotationsAttribute + * are generated properly for inner classes enums, for constructors, for methods, + * for fields (enum, class, annotation, interface). The test checks both + * single and repeatable annotations. In addition, all possible combinations + * of retention policies are tested. + * + * The test generates source code, compiles it and checks the byte code. + * + * See README.txt for more information. + */ +public class RuntimeAnnotationsForInnerEnumTest extends RuntimeAnnotationsTestBase { + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + for (List groupedAnnotations : groupAnnotations(getAllCombinationsOfAnnotations())) { + for (ClassType outerClassType : ClassType.values()) { + TestCase test = new TestCase(); + TestCase.TestClassInfo outerClassInfo = test.addClassInfo(outerClassType, "Test"); + for (int i = 0; i < groupedAnnotations.size(); i++) { + TestAnnotationInfos annotations = groupedAnnotations.get(i); + TestCase.TestClassInfo clazz = outerClassInfo.addInnerClassInfo(ClassType.ENUM, "Enum" + i); + annotations.annotate(clazz); + + TestCase.TestMethodInfo innerClazzMethod = clazz.addMethodInfo("innerClassMethod" + i + "()"); + annotations.annotate(innerClazzMethod); + + TestCase.TestClassInfo localClassInClassMethod = innerClazzMethod.addLocalClassInfo("Local1" + i); + annotations.annotate(localClassInClassMethod); + + TestCase.TestMethodInfo innerStaticClazzMethod = clazz.addMethodInfo("innerStaticClassMethod" + i + "()", "static"); + annotations.annotate(innerStaticClazzMethod); + + TestCase.TestClassInfo localClassInStaticMethod = innerStaticClazzMethod.addLocalClassInfo("Local2" + i); + annotations.annotate(localClassInStaticMethod); + + TestCase.TestFieldInfo valueA = clazz.addFieldInfo("A" + i); + annotations.annotate(valueA); + + TestCase.TestFieldInfo valueB = clazz.addFieldInfo("B" + i); + annotations.annotate(valueB); + } + testCases.add(test); + } + } + return testCases; + } + + public static void main(String[] args) throws TestFailedException { + new RuntimeAnnotationsForInnerEnumTest().test(); + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerInterfaceTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForInnerInterfaceTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044411 + * @summary Tests the RuntimeVisibleAnnotations/RuntimeInvisibleAnnotations attribute. + * @library /tools/lib /tools/javac/lib ../lib + * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox + * @build TestCase ClassType TestAnnotationInfo + * @build RuntimeAnnotationsForInnerInterfaceTest AnnotationsTestBase RuntimeAnnotationsTestBase + * @run main RuntimeAnnotationsForInnerInterfaceTest + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * The test checks that RuntimeVisibleAnnotationsAttribute and RuntimeInvisibleAnnotationsAttribute + * are generated properly for inner interfaces, for methods, for fields. The test checks both + * single and repeatable annotations. In addition, all possible combinations + * of retention policies are tested. + * + * The test generates source code, compiles it and checks the byte code. + * + * See README.txt for more information. + */ +public class RuntimeAnnotationsForInnerInterfaceTest extends RuntimeAnnotationsTestBase { + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + for (List groupedAnnotations : groupAnnotations(getAllCombinationsOfAnnotations())) { + for (ClassType outerClassType : ClassType.values()) { + TestCase test = new TestCase(); + TestCase.TestClassInfo outerClass = test.addClassInfo(outerClassType, "Test"); + for (int i = 0; i < groupedAnnotations.size(); ++i) { + TestAnnotationInfos annotations = groupedAnnotations.get(i); + TestCase.TestClassInfo inter = outerClass.addInnerClassInfo(ClassType.INTERFACE, "InnerInterface" + i); + annotations.annotate(inter); + + TestCase.TestFieldInfo interField = inter.addFieldInfo("interField" + i); + annotations.annotate(interField); + + TestCase.TestMethodInfo interMethod = inter.addMethodInfo("interMethod" + i + "()"); + annotations.annotate(interMethod); + + TestCase.TestMethodInfo interStaticMethod = inter.addMethodInfo("interStaticMethod" + i + "()", "static"); + annotations.annotate(interStaticMethod); + + TestCase.TestClassInfo localClassInStaticMethod = interStaticMethod.addLocalClassInfo("Local1" + i); + annotations.annotate(localClassInStaticMethod); + + TestCase.TestMethodInfo interDefaultMethod = inter.addMethodInfo("interDefaultMethod" + i + "()", "default"); + annotations.annotate(interDefaultMethod); + + TestCase.TestClassInfo localClassInDefaultMethod = interDefaultMethod.addLocalClassInfo("Local2" + i); + annotations.annotate(localClassInDefaultMethod); + } + testCases.add(test); + } + } + return testCases; + } + + public static void main(String[] args) throws TestFailedException { + new RuntimeAnnotationsForInnerInterfaceTest().test(); + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForTopLevelClassTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsForTopLevelClassTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044411 + * @summary Tests the RuntimeVisibleAnnotations/RuntimeInvisibleAnnotations attribute. + * @library /tools/lib /tools/javac/lib ../lib + * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox + * @build TestCase ClassType TestAnnotationInfo + * @build RuntimeAnnotationsForTopLevelClassTest AnnotationsTestBase RuntimeAnnotationsTestBase + * @run main RuntimeAnnotationsForTopLevelClassTest + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * The test checks that RuntimeVisibleAnnotationsAttribute and RuntimeInvisibleAnnotationsAttribute + * are generated properly for top-level class (class, enum, annotation, interface), + * for constructors (in enum and in class), for methods (abstract methods, static and default methods in interface), + * for fields. The test checks both single and repeatable annotations. + * In addition, all possible combinations of retention policies are tested. + * + * The test generates source code, compiles it and checks the byte code. + * + * See README.txt for more information. + */ +public class RuntimeAnnotationsForTopLevelClassTest extends RuntimeAnnotationsTestBase { + + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + for (List groupedAnnotations : groupAnnotations(getAllCombinationsOfAnnotations())) { + for (ClassType classType : ClassType.values()) { + TestCase test = new TestCase(); + for (int i = 0; i < groupedAnnotations.size(); ++i) { + TestAnnotationInfos annotations = groupedAnnotations.get(i); + TestCase.TestClassInfo clazz = test.addClassInfo(classType, "Test" + i); + annotations.annotate(clazz); + + if (classType != ClassType.ENUM) { + TestCase.TestMethodInfo constructor = clazz.addMethodInfo("()"); + annotations.annotate(constructor); + + TestCase.TestClassInfo localClass = constructor.addLocalClassInfo("Local1" + i); + annotations.annotate(localClass); + } + if (classType != ClassType.ANNOTATION) { + TestCase.TestMethodInfo staticClassMethod = clazz.addMethodInfo("staticClassMethod" + i + "()", "static"); + annotations.annotate(staticClassMethod); + + TestCase.TestClassInfo localClassInStaticMethod = staticClassMethod.addLocalClassInfo("Local2" + i); + annotations.annotate(localClassInStaticMethod); + } + TestCase.TestMethodInfo classMethod = clazz.addMethodInfo("classMethod" + i + "()"); + annotations.annotate(classMethod); + + TestCase.TestClassInfo localClassInClassMethod = classMethod.addLocalClassInfo("Local3" + i); + annotations.annotate(localClassInClassMethod); + + TestCase.TestFieldInfo field = clazz.addFieldInfo("field" + i); + annotations.annotate(field); + + TestCase.TestFieldInfo staticField = clazz.addFieldInfo("staticField" + i, "static"); + annotations.annotate(staticField); + } + testCases.add(test); + } + } + return testCases; + } + + public static void main(String[] args) throws TestFailedException { + new RuntimeAnnotationsForTopLevelClassTest().test(); + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeAnnotationsTestBase.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.*; + +import java.io.IOException; +import java.lang.annotation.RetentionPolicy; +import java.util.*; +import java.util.function.Supplier; + +import javax.tools.JavaFileObject; + +public abstract class RuntimeAnnotationsTestBase extends AnnotationsTestBase { + + @Override + public void test(TestCase testCase, Map classes) + throws IOException, ConstantPoolException, Descriptor.InvalidDescriptor { + for (Map.Entry entry : classes.entrySet()) { + String className = entry.getKey(); + TestCase.TestClassInfo clazz = testCase.getTestClassInfo(className); + echo("Testing class : " + className); + ClassFile classFile = readClassFile(entry.getValue()); + + testAttributes(clazz, classFile, () -> classFile.attributes); + + testMethods(clazz, classFile); + + testFields(clazz, classFile); + } + } + + private void testMethods(TestCase.TestClassInfo clazz, ClassFile classFile) + throws ConstantPoolException, Descriptor.InvalidDescriptor { + String className = clazz.getName(); + Set foundMethods = new HashSet<>(); + for (Method method : classFile.methods) { + String methodName = method.getName(classFile.constant_pool) + + method.descriptor.getParameterTypes(classFile.constant_pool); + if (methodName.startsWith("")) { + String constructorName = className.replaceAll(".*\\$", ""); + methodName = methodName.replace("", constructorName); + } + echo("Testing method : " + methodName); + + TestCase.TestMethodInfo testMethod = clazz.getTestMethodInfo(methodName); + foundMethods.add(methodName); + if (testMethod == null) { + continue; + } + testAttributes(testMethod, classFile, () -> method.attributes); + } + checkContains(foundMethods, clazz.methods.keySet(), "Methods in class : " + className); + } + + private void testFields(TestCase.TestClassInfo clazz, ClassFile classFile) + throws ConstantPoolException { + Set foundFields = new HashSet<>(); + for (Field field : classFile.fields) { + String fieldName = field.getName(classFile.constant_pool); + echo("Testing field : " + fieldName); + + TestCase.TestFieldInfo testField = clazz.getTestFieldInfo(fieldName); + foundFields.add(fieldName); + if (testField == null) { + continue; + } + testAttributes(testField, classFile, () -> field.attributes); + } + checkContains(foundFields, clazz.fields.keySet(), "Fields in class : " + clazz.getName()); + } + + private void testAttributes( + TestCase.TestMemberInfo member, + ClassFile classFile, + Supplier attributes) + throws ConstantPoolException { + Map actualInvisible = collectAnnotations( + classFile, + member, + attributes.get(), + Attribute.RuntimeInvisibleAnnotations); + Map actualVisible = collectAnnotations( + classFile, + member, + attributes.get(), + Attribute.RuntimeVisibleAnnotations); + + checkEquals(actualInvisible.keySet(), + member.getRuntimeInvisibleAnnotations(), "RuntimeInvisibleAnnotations"); + checkEquals(actualVisible.keySet(), + member.getRuntimeVisibleAnnotations(), "RuntimeVisibleAnnotations"); + + for (TestAnnotationInfo expectedAnnotation : member.annotations.values()) { + RetentionPolicy policy = getRetentionPolicy(expectedAnnotation.annotationName); + if (policy == RetentionPolicy.SOURCE) { + continue; + } + printf("Testing: isVisible: %s %s%n", policy.toString(), expectedAnnotation.annotationName); + Annotation actualAnnotation = + (policy == RetentionPolicy.RUNTIME ? actualVisible : actualInvisible) + .get(expectedAnnotation.annotationName); + if (checkNotNull(actualAnnotation, "Annotation is found : " + + expectedAnnotation.annotationName)) { + expectedAnnotation.testAnnotation(this, classFile, actualAnnotation); + } + } + } + + private Map collectAnnotations( + ClassFile classFile, + TestCase.TestMemberInfo member, + Attributes attributes, + String attribute) throws ConstantPoolException { + + RuntimeAnnotations_attribute attr = (RuntimeAnnotations_attribute) attributes.get(attribute); + Map actualAnnotations = new HashMap<>(); + RetentionPolicy policy = getRetentionPolicy(attribute); + if (member.isAnnotated(policy)) { + if (!checkNotNull(attr, String.format("%s should be not null value", attribute))) { + // test case failed, stop checking + return actualAnnotations; + } + for (Annotation ann : attr.annotations) { + String name = classFile.constant_pool.getUTF8Value(ann.type_index); + actualAnnotations.put(name.substring(1, name.length() - 1), ann); + } + checkEquals(countNumberOfAttributes(attributes.attrs, + getRetentionPolicy(attribute) == RetentionPolicy.RUNTIME + ? RuntimeVisibleAnnotations_attribute.class + : RuntimeInvisibleAnnotations_attribute.class), + 1l, + String.format("Number of %s", attribute)); + } else { + checkNull(attr, String.format("%s should be null", attribute)); + } + return actualAnnotations; + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForGenericMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForGenericMethodTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044411 + * @summary Tests the RuntimeParameterVisibleAnnotations/RuntimeParameterInvisibleAnnotations attribute. + * Checks that the attribute is generated for bridge method. + * @library /tools/lib /tools/javac/lib ../lib + * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox + * @build TestCase ClassType TestAnnotationInfo + * @build RuntimeParameterAnnotationsForGenericMethodTest AnnotationsTestBase RuntimeParameterAnnotationsTestBase + * @run main RuntimeParameterAnnotationsForGenericMethodTest + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * RuntimeParameterAnnotationsGenericMethodTest is a test which check that + * RuntimeVisibleParameterAnnotationsAttribute and + * RuntimeInvisibleParameterAnnotationsAttribute are generated for both + * generic and appropriate bridge methods. + * All possible combinations of retention policies are tested. + * + * The test generates class which looks as follows: + * + * public class Test extends java.util.ArrayList<Integer> { + * + * public boolean add(here some annotations java.lang.Integer) { + * return false; + * } + * } + * + * Thereafter, various of combinations of annotations are applied + * to the add, the source is compiled and the generated byte code is checked. + * + * See README.txt for more information. + */ +public class RuntimeParameterAnnotationsForGenericMethodTest extends RuntimeParameterAnnotationsTestBase { + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + for (TestAnnotationInfos annotations : getAllCombinationsOfAnnotations()) { + // generate: public class Test extends java.util.ArrayList + TestCase testCase = new TestCase(); + TestCase.TestClassInfo clazz = testCase.addClassInfo("java.util.ArrayList", ClassType.CLASS, "Test"); + TestCase.TestParameterInfo parameter = clazz.addMethodInfo("add(java.lang.Integer)", "public").addParameter("Integer", "i"); + annotations.annotate(parameter); + TestCase.TestParameterInfo synParameter = clazz.addMethodInfo("add(java.lang.Object)", true, "public").addParameter("Object", "i"); + annotations.annotate(synParameter); + testCases.add(testCase); + } + return testCases; + } + + public static void main(String[] args) throws TestFailedException { + new RuntimeParameterAnnotationsForGenericMethodTest().test(); + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsForLambdaTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044411 8079060 + * @summary Tests the RuntimeParameterVisibleAnnotations/RuntimeParameterInvisibleAnnotations attribute. + * @library /tools/lib /tools/javac/lib ../lib + * @ignore 8079060 javac does not generate RuntimeParameterAnnotation attributes for lambda expressions + * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox + * @build TestCase ClassType TestAnnotationInfo + * @build RuntimeParameterAnnotationsForLambdaTest AnnotationsTestBase RuntimeParameterAnnotationsTestBase + * @run main RuntimeParameterAnnotationsForLambdaTest + */ + +import java.util.List; +import java.util.stream.Collectors; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Method; + +/** + * RuntimeParameterAnnotationsForLambdaTest is a test which checks that RuntimeVisibleParameterAnnotationsAttribute + * and RuntimeInvisibleParameterAnnotationsAttribute are generated properly for lambda expressions. + * The test checks both single and repeatable annotations. + * All possible combinations of retention policies are tested. + * + * The test generates source code, compiles it and checks the byte code. + * + * See README.txt for more information. + */ +public class RuntimeParameterAnnotationsForLambdaTest extends RuntimeParameterAnnotationsTestBase { + + private static final String CLASS_NAME = "Test"; + private static final String SOURCE_TEMPLATE = + "public class " + CLASS_NAME + " {\n" + + " interface I { void method(int a, double b, String c); }\n" + + " %SOURCE%\n" + + "}"; + + public static void main(String[] args) throws TestFailedException { + new RuntimeParameterAnnotationsForLambdaTest().test(); + } + + @Override + public void test() throws TestFailedException { + try { + for (TestAnnotationInfos annotations : getAllCombinationsOfAnnotations()) { + try { + TestCase.TestMethodInfo testMethodInfo = new TestCase.TestMethodInfo(0, null, "lambda", false, false); + TestCase.TestParameterInfo p1 = testMethodInfo.addParameter("int", "a"); + annotations.annotate(p1); + testMethodInfo.addParameter("double", "b"); + TestCase.TestParameterInfo p3 = testMethodInfo.addParameter("String", "c"); + annotations.annotate(p3); + String source = SOURCE_TEMPLATE.replace("%SOURCE%", generateLambdaSource(testMethodInfo)); + echo("Testing:\n" + source); + addTestCase(source); + ClassFile classFile = readClassFile(compile(source).getClasses().get(CLASS_NAME)); + boolean isFoundLambda = false; + for (Method method : classFile.methods) { + if (method.getName(classFile.constant_pool).startsWith("lambda$")) { + isFoundLambda = true; + testAttributes(testMethodInfo, classFile, method); + } + } + checkTrue(isFoundLambda, "The tested lambda method was not found."); + } catch (Exception e) { + addFailure(e); + } + } + } finally { + checkStatus(); + } + } + + public String generateLambdaSource(TestCase.TestMethodInfo method) { + return method.parameters.stream() + .map(TestCase.TestParameterInfo::generateSource) + .collect(Collectors.joining(", ", "I i = (", ") -> {};")); + } + + @Override + public List generateTestCases() { + throw new UnsupportedOperationException(); + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8044411 + * @summary Tests the RuntimeParameterVisibleAnnotations/RuntimeParameterInvisibleAnnotations attribute. + * @library /tools/lib /tools/javac/lib ../lib + * @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox + * @build TestCase ClassType TestAnnotationInfo + * @build RuntimeParameterAnnotationsTest AnnotationsTestBase RuntimeParameterAnnotationsTestBase + * @run main RuntimeParameterAnnotationsTest + */ + +import java.util.ArrayList; +import java.util.List; + +/** + * RuntimeParameterAnnotationsTest is a test which checks that RuntimeVisibleParameterAnnotationsAttribute + * and RuntimeInvisibleParameterAnnotationsAttribute are generated properly for constructors, + * for static and abstract methods of class, for abstract, default and static methods of interface. + * The test checks both single and repeatable annotations. + * All possible combinations of retention policies are tested. + * + * The test generates source code, compiles it and checks the byte code. + * + * See README.txt for more information. + */ +public class RuntimeParameterAnnotationsTest extends RuntimeParameterAnnotationsTestBase { + + @Override + public List generateTestCases() { + List testCases = new ArrayList<>(); + for (List groupedAnnotations : groupAnnotations(getAllCombinationsOfAnnotations())) { + for (ClassType classType : new ClassType[]{ClassType.CLASS, ClassType.INTERFACE}) { + TestCase test = new TestCase(); + for (int i = 0; i < groupedAnnotations.size(); i++) { + TestAnnotationInfos annotations = groupedAnnotations.get(i); + TestCase.TestClassInfo clazz = test.addClassInfo(classType, "Test" + i, "abstract"); + + initMethod(annotations, clazz, ""); + + initMethod(annotations, clazz, "method1"); + + initMethod(annotations, clazz, "method2", + classType == ClassType.CLASS ? "abstract" : "default"); + + initMethod(annotations, clazz, "staticMethod", "static"); + } + testCases.add(test); + } + } + return testCases; + } + + /** + * Adds a method to the {@code testCase} with {@code methodName}. + * + * @param annotations a list of annotations + * @param clazz a test class + * @param methodName a method name + * @param mods an array of modifiers + */ + private void initMethod(TestAnnotationInfos annotations, TestCase.TestClassInfo clazz, String methodName, String...mods) { + String methodDescriptor = methodName + "(int, double, java.lang.String)"; + TestCase.TestMethodInfo method = clazz.addMethodInfo(methodDescriptor, mods); + TestCase.TestParameterInfo p1 = method.addParameter("int", "a"); + annotations.annotate(p1); + method.addParameter("double", "b"); + TestCase.TestParameterInfo p3 = method.addParameter("String", "c"); + annotations.annotate(p3); + } + + public static void main(String[] args) throws TestFailedException { + new RuntimeParameterAnnotationsTest().test(); + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsTestBase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/RuntimeParameterAnnotationsTestBase.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.*; + +import javax.tools.JavaFileObject; +import java.io.IOException; +import java.lang.annotation.RetentionPolicy; +import java.util.*; + +public abstract class RuntimeParameterAnnotationsTestBase extends AnnotationsTestBase { + + @Override + public void test(TestCase testCase, Map classes) + throws IOException, ConstantPoolException, Descriptor.InvalidDescriptor { + for (Map.Entry entry : classes.entrySet()) { + ClassFile classFile = readClassFile(classes.get(entry.getKey())); + Set foundMethods = new HashSet<>(); + String className = classFile.getName(); + TestCase.TestClassInfo testClassInfo = testCase.classes.get(className); + for (Method method : classFile.methods) { + String methodName = method.getName(classFile.constant_pool) + + method.descriptor.getParameterTypes(classFile.constant_pool); + if (methodName.startsWith("")) { + methodName = methodName.replace("", className); + } + foundMethods.add(methodName); + echo("Testing method : " + methodName); + + TestCase.TestMethodInfo testMethod = testClassInfo.getTestMethodInfo(methodName); + if (testMethod == null) { + continue; + } + testAttributes(testMethod, classFile, method); + } + checkContains(foundMethods, testClassInfo.methods.keySet(), "Methods in " + className); + } + } + + protected void testAttributes( + TestCase.TestMethodInfo testMethod, + ClassFile classFile, + Method method) throws ConstantPoolException { + List> actualInvisible = collectAnnotations( + classFile, + testMethod, + method, + Attribute.RuntimeInvisibleParameterAnnotations); + List> actualVisible = collectAnnotations( + classFile, + testMethod, + method, + Attribute.RuntimeVisibleParameterAnnotations); + + List parameters = testMethod.parameters; + for (int i = 0; i < parameters.size(); ++i) { + TestCase.TestParameterInfo parameter = parameters.get(i); + checkEquals(actualInvisible.get(i).keySet(), parameter.getRuntimeInvisibleAnnotations(), + "RuntimeInvisibleParameterAnnotations"); + checkEquals(actualVisible.get(i).keySet(), parameter.getRuntimeVisibleAnnotations(), + "RuntimeVisibleParameterAnnotations"); + } + + for (int i = 0; i < parameters.size(); ++i) { + TestCase.TestParameterInfo parameter = parameters.get(i); + for (TestAnnotationInfo expectedAnnotation : parameter.annotations.values()) { + RetentionPolicy policy = getRetentionPolicy(expectedAnnotation.annotationName); + if (policy == RetentionPolicy.SOURCE) { + continue; + } + printf("Testing: isVisible: %s %s%n", policy.toString(), expectedAnnotation.annotationName); + Annotation actualAnnotation = + (policy == RetentionPolicy.RUNTIME + ? actualVisible + : actualInvisible) + .get(i).get(expectedAnnotation.annotationName); + if (checkNotNull(actualAnnotation, "Annotation is found : " + + expectedAnnotation.annotationName)) { + expectedAnnotation.testAnnotation(this, classFile, + actualAnnotation); + } + } + } + } + + private List> collectAnnotations( + ClassFile classFile, + TestCase.TestMethodInfo testMethod, + Method method, + String attribute) throws ConstantPoolException { + + Attributes attributes = method.attributes; + RuntimeParameterAnnotations_attribute attr = (RuntimeParameterAnnotations_attribute) attributes.get(attribute); + + List> actualAnnotations = new ArrayList<>(); + RetentionPolicy policy = getRetentionPolicy(attribute); + if (testMethod.isParameterAnnotated(policy)) { + if (!checkNotNull(attr, "Attribute " + attribute + " must not be null")) { + testMethod.parameters.forEach($ -> actualAnnotations.add(new HashMap<>())); + return actualAnnotations; + } + for (Annotation[] anns : attr.parameter_annotations) { + Map annotations = new HashMap<>(); + for (Annotation ann : anns) { + String name = classFile.constant_pool.getUTF8Value(ann.type_index); + annotations.put(name.substring(1, name.length() - 1), ann); + } + actualAnnotations.add(annotations); + } + checkEquals(countNumberOfAttributes(attributes.attrs, + getRetentionPolicy(attribute) == RetentionPolicy.RUNTIME + ? RuntimeVisibleParameterAnnotations_attribute.class + : RuntimeInvisibleParameterAnnotations_attribute.class), + 1l, + String.format("Number of %s", attribute)); + } else { + checkNull(attr, String.format("%s should be null", attribute)); + testMethod.parameters.forEach($ -> actualAnnotations.add(new HashMap<>())); + } + return actualAnnotations; + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/TestAnnotationInfo.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.Annotation; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPoolException; + +import java.lang.annotation.RetentionPolicy; +import java.util.*; +import java.util.stream.Collectors; + +public class TestAnnotationInfo { + public final String annotationName; + public final RetentionPolicy policy; + public final boolean isContainer; + public final List elementValues; + + public TestAnnotationInfo(String typeIndexName, RetentionPolicy policy, Pair... values) { + this(typeIndexName, policy, false, values); + } + + public TestAnnotationInfo(String typeIndexName, RetentionPolicy policy, boolean isRepeatable, Pair... values) { + this.annotationName = typeIndexName; + this.policy = policy; + this.isContainer = isRepeatable; + elementValues = Arrays.asList(values); + } + + public void testAnnotation(TestResult testResult, ClassFile classFile, Annotation annotation) + throws ConstantPoolException { + testResult.checkEquals(classFile.constant_pool.getUTF8Value(annotation.type_index), + String.format("L%s;", annotationName), "Testing annotation name : " + annotationName); + testResult.checkEquals(annotation.num_element_value_pairs, + elementValues.size(), "Number of element values"); + if (!testResult.checkEquals(annotation.num_element_value_pairs, elementValues.size(), + "Number of element value pairs")) { + return; + } + for (int i = 0; i < annotation.num_element_value_pairs; ++i) { + Annotation.element_value_pair pair = annotation.element_value_pairs[i]; + testResult.checkEquals(classFile.constant_pool.getUTF8Value(pair.element_name_index), + elementValues.get(i).elementName, "element_name_index : " + elementValues.get(i).elementName); + elementValues.get(i).elementValue.testElementValue(testResult, classFile, pair.value); + } + } + + @Override + public String toString() { + return String.format("@%s(%s)", annotationName, + elementValues.stream() + .map(Pair::toString) + .filter(s -> !s.isEmpty()) + .collect(Collectors.joining(", "))); + } + + public static class Pair { + public final String elementName; + public final TestElementValue elementValue; + + public Pair(String elementName, TestElementValue elementValue) { + this.elementName = elementName; + this.elementValue = elementValue; + } + + @Override + public String toString() { + return elementName + "=" + elementValue; + } + } + + public static abstract class TestElementValue { + private final int tag; + + public TestElementValue(int tag) { + this.tag = tag; + } + + public void testTag(TestResult testCase, int actualTag) { + testCase.checkEquals(actualTag, tag, "tag " + (char) tag); + } + + public abstract void testElementValue(TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException; + } + + public static class TestIntegerElementValue extends TestElementValue { + private final int value; + + public TestIntegerElementValue(int tag, int value) { + super(tag); + this.value = value; + } + + @Override + public void testElementValue(TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException { + testTag(testResult, element_value.tag); + Annotation.Primitive_element_value ev = + (Annotation.Primitive_element_value) element_value; + ConstantPool.CONSTANT_Integer_info info = + (ConstantPool.CONSTANT_Integer_info) classFile.constant_pool.get(ev.const_value_index); + testResult.checkEquals(info.value, value, "const_value_index : " + value); + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + public static class TestBooleanElementValue extends TestElementValue { + private final boolean value; + + public TestBooleanElementValue(boolean value) { + super('Z'); + this.value = value; + } + + @Override + public void testElementValue(TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException { + testTag(testResult, element_value.tag); + Annotation.Primitive_element_value ev = + (Annotation.Primitive_element_value) element_value; + ConstantPool.CONSTANT_Integer_info info = + (ConstantPool.CONSTANT_Integer_info) classFile.constant_pool.get(ev.const_value_index); + testResult.checkEquals(info.value, value ? 1 : 0, "const_value_index : " + value); + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + public static class TestCharElementValue extends TestElementValue { + private final char value; + + public TestCharElementValue(char value) { + super('C'); + this.value = value; + } + + @Override + public void testElementValue(TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException { + testTag(testResult, element_value.tag); + Annotation.Primitive_element_value ev = + (Annotation.Primitive_element_value) element_value; + ConstantPool.CONSTANT_Integer_info info = + (ConstantPool.CONSTANT_Integer_info) + classFile.constant_pool.get(ev.const_value_index); + testResult.checkEquals(info.value, (int) value, "const_value_index : " + value); + } + + @Override + public String toString() { + return String.format("\'%c\'", value); + } + } + + public static class TestLongElementValue extends TestElementValue { + private final long value; + + public TestLongElementValue(long value) { + super('J'); + this.value = value; + } + + @Override + public void testElementValue(TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPool.InvalidIndex { + testTag(testResult, element_value.tag); + Annotation.Primitive_element_value ev = + (Annotation.Primitive_element_value) element_value; + ConstantPool.CONSTANT_Long_info info = + (ConstantPool.CONSTANT_Long_info) classFile.constant_pool.get(ev.const_value_index); + testResult.checkEquals(info.value, value, "const_value_index"); + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + public static class TestFloatElementValue extends TestElementValue { + private final float value; + + public TestFloatElementValue(float value) { + super('F'); + this.value = value; + } + + @Override + public void testElementValue(TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPool.InvalidIndex { + testTag(testResult, element_value.tag); + Annotation.Primitive_element_value ev = + (Annotation.Primitive_element_value) element_value; + ConstantPool.CONSTANT_Float_info info = + (ConstantPool.CONSTANT_Float_info) classFile.constant_pool.get(ev.const_value_index); + testResult.checkEquals(info.value, value, "const_value_index"); + } + + @Override + public String toString() { + return String.valueOf(value) + "f"; + } + } + + public static class TestDoubleElementValue extends TestElementValue { + private final double value; + + public TestDoubleElementValue(double value) { + super('D'); + this.value = value; + } + + @Override + public void testElementValue(TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException { + testTag(testResult, element_value.tag); + Annotation.Primitive_element_value ev = + (Annotation.Primitive_element_value) element_value; + ConstantPool.CONSTANT_Double_info info = (ConstantPool.CONSTANT_Double_info) + classFile.constant_pool.get(ev.const_value_index); + testResult.checkEquals(info.value, value, "const_value_index"); + } + + @Override + public String toString() { + return String.valueOf(value); + } + } + + public static class TestStringElementValue extends TestElementValue { + private final String value; + + public TestStringElementValue(String value) { + super('s'); + this.value = value; + } + + @Override + public void testElementValue(TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException { + testTag(testResult, element_value.tag); + Annotation.Primitive_element_value ev = + (Annotation.Primitive_element_value) element_value; + ConstantPool.CONSTANT_Utf8_info info = + (ConstantPool.CONSTANT_Utf8_info) classFile.constant_pool.get(ev.const_value_index); + testResult.checkEquals(info.value, value, "const_value_index"); + } + + @Override + public String toString() { + return String.format("\"%s\"", value); + } + } + + public static class TestEnumElementValue extends TestElementValue { + private final String typeName; + private final String constName; + + public TestEnumElementValue(String typeName, String constName) { + super('e'); + this.typeName = typeName; + this.constName = constName; + } + + @Override + public void testElementValue( + TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException { + testTag(testResult, element_value.tag); + Annotation.Enum_element_value ev = (Annotation.Enum_element_value) element_value; + testResult.checkEquals(classFile.constant_pool.getUTF8Info(ev.type_name_index).value, + String.format("L%s;", typeName), "type_name_index"); + testResult.checkEquals(classFile.constant_pool.getUTF8Info(ev.const_name_index).value, + constName, "const_name_index"); + } + + @Override + public String toString() { + return typeName + "." + constName; + } + } + + public static class TestClassElementValue extends TestElementValue { + private final String className; + + private final static Map mappedClassName; + + static { + mappedClassName = new HashMap<>(); + mappedClassName.put("void", "V"); + mappedClassName.put("char", "C"); + mappedClassName.put("byte", "B"); + mappedClassName.put("short", "S"); + mappedClassName.put("int", "I"); + mappedClassName.put("long", "J"); + mappedClassName.put("float", "F"); + mappedClassName.put("double", "D"); + } + + public TestClassElementValue(String className) { + super('c'); + this.className = className; + } + + @Override + public void testElementValue( + TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException { + testTag(testResult, element_value.tag); + Annotation.Class_element_value ev = (Annotation.Class_element_value) element_value; + String expectedClassName = className.replace(".class", ""); + expectedClassName = mappedClassName.getOrDefault(expectedClassName, + String.format("Ljava/lang/%s;", expectedClassName)); + testResult.checkEquals( + classFile.constant_pool.getUTF8Info(ev.class_info_index).value, + expectedClassName, "class_info_index : " + expectedClassName); + } + + @Override + public String toString() { + return className; + } + } + + public static class TestArrayElementValue extends TestElementValue { + public final List values; + + public TestArrayElementValue(TestElementValue...values) { + super('['); + this.values = new ArrayList<>(Arrays.asList(values)); + } + + @Override + public void testElementValue( + TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException { + testTag(testResult, element_value.tag); + Annotation.Array_element_value ev = (Annotation.Array_element_value) element_value; + + for (int i = 0; i < values.size(); ++i) { + values.get(i).testElementValue(testResult, classFile, ev.values[i]); + } + } + + @Override + public String toString() { + return values.stream() + .map(TestElementValue::toString) + .collect(Collectors.joining(", ", "{", "}")); + } + } + + public static class TestAnnotationElementValue extends TestElementValue { + private final String annotationName; + private final TestAnnotationInfo annotation; + + public TestAnnotationElementValue(String className, TestAnnotationInfo annotation) { + super('@'); + this.annotationName = className; + this.annotation = annotation; + } + + @Override + public void testElementValue( + TestResult testResult, + ClassFile classFile, + Annotation.element_value element_value) + throws ConstantPoolException { + testTag(testResult, element_value.tag); + Annotation ev = ((Annotation.Annotation_element_value) element_value).annotation_value; + testResult.checkEquals( + classFile.constant_pool.getUTF8Info(ev.type_index).value, + String.format("L%s;", annotationName), + "type_index"); + for (int i = 0; i < ev.num_element_value_pairs; ++i) { + Annotation.element_value_pair pair = ev.element_value_pairs[i]; + Pair expectedPair = annotation.elementValues.get(i); + expectedPair.elementValue.testElementValue(testResult, classFile, pair.value); + testResult.checkEquals( + classFile.constant_pool.getUTF8Info(pair.element_name_index).value, + expectedPair.elementName, + "element_name_index"); + } + } + + @Override + public String toString() { + return annotation.toString(); + } + } +} \ No newline at end of file diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/TestCase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/TestCase.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,459 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.annotation.RetentionPolicy; +import java.util.*; +import java.util.stream.Collectors; + +public class TestCase { + + /** + * The top-level classes of the test case. + */ + public final Map classes = new LinkedHashMap<>(); + + /** + * Constructs a test class info with {@code classType} as top-level class, + * with {@code outerClassName} as name and {@code mods} as modifiers. + * + * @param classType a class type + * @param outerClassName a name + * @param mods an array of modifiers + */ + public TestClassInfo addClassInfo(ClassType classType, String outerClassName, String...mods) { + return addClassInfo(null, classType, outerClassName, mods); + } + + /** + * Constructs a test class info with {@code classType} as top-level class, + * with {@code outerClassName} as name, {@code parent} class name + * as parent class and {@code mods} as modifiers. + * + * @param classType a class type + * @param outerClassName a name + * @param mods an array of modifiers + */ + public TestClassInfo addClassInfo(String parent, ClassType classType, String outerClassName, String...mods) { + TestClassInfo clazz = new TestClassInfo(classType, outerClassName, parent, mods); + if (classes.put(outerClassName, clazz) != null) { + throw new IllegalArgumentException("Duplicate class name: " + outerClassName); + } + return clazz; + } + + public String generateSource() { + return classes.values().stream() + .map(TestMemberInfo::generateSource) + .collect(Collectors.joining("\n")); + } + + /** + * Returns {@code TestClassInfo} by class signature. + * Example, {@code getTestClassInfo("Test$1Local")} + * returns local inner class of class {@code Test}. + * + * @param classSignature a class signature + * @return {@code TestClassInfo} by class signature + */ + public TestClassInfo getTestClassInfo(String classSignature) { + String[] cs = classSignature.split("\\$"); + if (cs.length > 0 && classes.containsKey(cs[0])) { + // check signature corresponds to top level class + if (cs.length == 1) { + return classes.get(cs[0]); + } + } else { + throw new IllegalArgumentException("Cannot find class : " + classSignature); + } + TestClassInfo current = classes.get(cs[0]); + // find class info in the inner classes + for (int i = 1; i < cs.length; ++i) { + Map innerClasses = current.innerClasses; + Map methods = current.methods; + current = innerClasses.get(cs[i]); + // if current is null then class info does not exist or the class is local + if (current == null) { + if (!cs[i].isEmpty()) { + // the class is local, remove leading digit + String className = cs[i].substring(1); + Optional opt = methods.values().stream() + .flatMap(c -> c.localClasses.values().stream()) + .filter(c -> c.name.equals(className)).findAny(); + if (opt.isPresent()) { + current = opt.get(); + // continue analysis of local class + continue; + } + } + throw new IllegalArgumentException("Cannot find class : " + classSignature); + } + } + return current; + } + + /** + * Class represents a program member. + */ + public static abstract class TestMemberInfo { + // next two fields are used for formatting + protected final int indention; + protected final ClassType containerType; + public final List mods; + public final String name; + public final Map annotations; + + TestMemberInfo(int indention, ClassType containerType, String name, String... mods) { + this.indention = indention; + this.containerType = containerType; + this.mods = Arrays.asList(mods); + this.name = name; + this.annotations = new HashMap<>(); + } + + public abstract String generateSource(); + + public boolean isAnnotated(RetentionPolicy policy) { + return annotations.values().stream() + .filter(a -> a.policy == policy) + .findAny().isPresent(); + } + + public Set getRuntimeVisibleAnnotations() { + return getRuntimeAnnotations(RetentionPolicy.RUNTIME); + } + + public Set getRuntimeInvisibleAnnotations() { + return getRuntimeAnnotations(RetentionPolicy.CLASS); + } + + private Set getRuntimeAnnotations(RetentionPolicy policy) { + return annotations.values().stream() + .filter(e -> e.policy == policy) + .map(a -> a.annotationName) + .distinct() + .collect(Collectors.toSet()); + } + + /** + * Generates source for annotations. + * + * @param prefix a leading text + * @param suffix a trailing text + * @param joining a text between annotations + * @return source for annotations + */ + protected String generateSourceForAnnotations(String prefix, String suffix, String joining) { + StringBuilder sb = new StringBuilder(); + for (TestAnnotationInfo annotation : annotations.values()) { + sb.append(prefix); + if (annotation.isContainer) { + // the annotation is repeatable + // container consists of an array of annotations + TestAnnotationInfo.TestArrayElementValue containerElementValue = + (TestAnnotationInfo.TestArrayElementValue) annotation.elementValues.get(0).elementValue; + // concatenate sources of repeatable annotations + sb.append(containerElementValue.values.stream() + .map(TestAnnotationInfo.TestElementValue::toString) + .collect(Collectors.joining(joining))); + } else { + sb.append(annotation); + } + sb.append(suffix); + } + String src = sb.toString(); + return src.trim().isEmpty() ? "" : src; + + } + + /** + * Generates source for annotations. + * + * @return source for annotations + */ + public String generateSourceForAnnotations() { + return generateSourceForAnnotations(indention(), "\n", "\n" + indention()); + } + + /** + * Adds annotation info to the member. + * + * @param anno an annotation info + */ + public void addAnnotation(TestAnnotationInfo anno) { + String containerName = anno.annotationName + "Container"; + TestAnnotationInfo annotation = annotations.get(anno.annotationName); + TestAnnotationInfo containerAnnotation = annotations.get(containerName); + + if (annotation == null) { + // if annotation is null then either it is first adding of the annotation to the member + // or there is the container of the annotation. + if (containerAnnotation == null) { + // first adding to the member + annotations.put(anno.annotationName, anno); + } else { + // add annotation to container + TestAnnotationInfo.TestArrayElementValue containerElementValue = + ((TestAnnotationInfo.TestArrayElementValue) containerAnnotation.elementValues.get(0).elementValue); + containerElementValue.values.add(new TestAnnotationInfo.TestAnnotationElementValue(anno.annotationName, anno)); + } + } else { + // remove previously added annotation and add new container of repeatable annotation + // which contains previously added and new annotation + annotations.remove(anno.annotationName); + containerAnnotation = new TestAnnotationInfo( + containerName, + anno.policy, + true, + new TestAnnotationInfo.Pair("value", + new TestAnnotationInfo.TestArrayElementValue( + new TestAnnotationInfo.TestAnnotationElementValue(anno.annotationName, annotation), + new TestAnnotationInfo.TestAnnotationElementValue(anno.annotationName, anno)))); + annotations.put(containerName, containerAnnotation); + } + } + + public String indention() { + char[] a = new char[4 * indention]; + Arrays.fill(a, ' '); + return new String(a); + } + + public String getName() { + return name; + } + } + + /** + * The class represents a class. + */ + public static class TestClassInfo extends TestMemberInfo { + public final ClassType classType; + public final String parent; + public final Map innerClasses; + public final Map methods; + public final Map fields; + + TestClassInfo(int indention, ClassType classType, String className, String... mods) { + this(indention, classType, className, null, mods); + } + + TestClassInfo(ClassType classType, String className, String parent, String... mods) { + this(0, classType, className, parent, mods); + } + + TestClassInfo(int indention, ClassType classType, String className, String parent, String... mods) { + super(indention, null, className, mods); + this.classType = classType; + this.parent = parent; + innerClasses = new LinkedHashMap<>(); + methods = new LinkedHashMap<>(); + fields = new LinkedHashMap<>(); + } + + /** + * Generates source which represents the class. + * + * @return source which represents the class + */ + @Override + public String generateSource() { + String sourceForAnnotations = generateSourceForAnnotations(); + String classModifiers = mods.stream().collect(Collectors.joining(" ")); + return sourceForAnnotations + + String.format("%s%s %s %s %s {%n", + indention(), + classModifiers, + classType.getDescription(), + name, + parent == null ? "" : "extends " + parent) + + classType.collectFields(fields.values()) + + classType.collectMethods(methods.values()) + + classType.collectInnerClasses(innerClasses.values()) + + indention() + "}"; + } + + /** + * Adds a new inner class to the class. + * + * @param classType a class type + * @param className a class name + * @param mods modifiers + * @return a new added inner class to the class + */ + public TestClassInfo addInnerClassInfo(ClassType classType, String className, String... mods) { + TestClassInfo testClass = new TestClassInfo(indention + 1, classType, className, mods); + if (innerClasses.put(className, testClass) != null) { + throw new IllegalArgumentException("Duplicated class : " + className); + } + return testClass; + } + + /** + * Adds a new method to the class. + * + * @param methodName a method name + * @param mods modifiers + * @return a new inner class to the class + */ + public TestMethodInfo addMethodInfo(String methodName, String... mods) { + return addMethodInfo(methodName, false, mods); + } + + /** + * Adds a new method to the class. + * + * @param methodName a method name + * @param isSynthetic if {@code true} the method is synthetic + * @param mods modifiers + * @return a new method added to the class + */ + public TestMethodInfo addMethodInfo(String methodName, boolean isSynthetic, String... mods) { + boolean isConstructor = methodName.contains(""); + if (isConstructor) { + methodName = methodName.replace("", name); + } + TestMethodInfo testMethod = new TestMethodInfo(indention + 1, classType, methodName, isConstructor, isSynthetic, mods); + if (methods.put(methodName, testMethod) != null) { + throw new IllegalArgumentException("Duplicated method : " + methodName); + } + return testMethod; + } + + /** + * Adds a new field to the class. + * + * @param fieldName a method name + * @param mods modifiers + * @return a new field added to the class + */ + public TestFieldInfo addFieldInfo(String fieldName, String... mods) { + TestFieldInfo field = new TestFieldInfo(indention + 1, classType, fieldName, mods); + if (fields.put(fieldName, field) != null) { + throw new IllegalArgumentException("Duplicated field : " + fieldName); + } + return field; + } + + public TestMethodInfo getTestMethodInfo(String methodName) { + return methods.get(methodName); + } + + public TestFieldInfo getTestFieldInfo(String fieldName) { + return fields.get(fieldName); + } + } + + public static class TestMethodInfo extends TestMemberInfo { + public final boolean isConstructor; + public final boolean isSynthetic; + public final Map localClasses; + public final List parameters; + + TestMethodInfo(int indention, ClassType containerType, String methodName, + boolean isConstructor, boolean isSynthetic, String... mods) { + super(indention, containerType, methodName, mods); + this.isSynthetic = isSynthetic; + this.localClasses = new LinkedHashMap<>(); + this.parameters = new ArrayList<>(); + this.isConstructor = isConstructor; + } + + public boolean isParameterAnnotated(RetentionPolicy policy) { + return parameters.stream() + .filter(p -> p.isAnnotated(policy)) + .findFirst().isPresent(); + } + + public TestParameterInfo addParameter(String type, String name) { + TestParameterInfo testParameter = new TestParameterInfo(type, name); + parameters.add(testParameter); + return testParameter; + } + + /** + * Adds a local class to the method. + * + * @param className a class name + * @param mods modifiers + * @return a local class added to the method + */ + public TestClassInfo addLocalClassInfo(String className, String... mods) { + TestClassInfo testClass = new TestClassInfo(indention + 1, ClassType.CLASS, className, mods); + if (localClasses.put(className, testClass) != null) { + throw new IllegalArgumentException("Duplicated class : " + className); + } + return testClass; + } + + @Override + public String generateSource() { + if (isSynthetic) { + return ""; + } + return generateSourceForAnnotations() + + containerType.methodToString(this); + } + + @Override + public String getName() { + return name.replaceAll("\\(.*\\)", ""); + } + } + + /** + * The class represents a method parameter. + */ + public static class TestParameterInfo extends TestMemberInfo { + public final String type; + + TestParameterInfo(String type, String name) { + super(0, null, name); + this.type = type; + } + + @Override + public String generateSource() { + return generateSourceForAnnotations() + type + " " + name; + } + + public String generateSourceForAnnotations() { + return generateSourceForAnnotations("", " ", " "); + } + } + + /** + * The class represents a field. + */ + public static class TestFieldInfo extends TestMemberInfo { + + TestFieldInfo(int indention, ClassType containerType, String fieldName, String... mods) { + super(indention, containerType, fieldName, mods); + } + + @Override + public String generateSource() { + return generateSourceForAnnotations() + + containerType.fieldToString(this); + } + } +} diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/annotations/WorkAnnotations.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/classfiles/attributes/annotations/WorkAnnotations.java Thu Jul 16 19:31:01 2015 -0700 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.annotation.*; + +@Retention(RetentionPolicy.CLASS) +@Repeatable(RuntimeInvisibleRepeatableContainer.class) +@interface RuntimeInvisibleRepeatable { + boolean booleanValue() default false; + byte byteValue() default 0; + char charValue() default 0; + short shortValue() default 0; + int intValue() default 0; + long longValue() default 0; + float floatValue() default 0; + double doubleValue() default 0; + String stringValue() default ""; + int[] arrayValue1() default {}; + String[] arrayValue2() default {}; + Class classValue1() default void.class; + Class classValue2() default void.class; + EnumValue enumValue() default EnumValue.VALUE1; + AnnotationValue annoValue() default @AnnotationValue(stringValue = "StringValue"); + AnnotationValue[] annoArrayValue() default + {@AnnotationValue(stringValue = "StringValue1"), + @AnnotationValue(stringValue = "StringValue2"), + @AnnotationValue(stringValue = "StringValue3")}; +} + +@Retention(RetentionPolicy.CLASS) +@interface RuntimeInvisibleRepeatableContainer { + RuntimeInvisibleRepeatable[] value(); +} + +@interface RuntimeInvisibleNotRepeatable { + boolean booleanValue() default false; + byte byteValue() default 0; + char charValue() default 0; + short shortValue() default 0; + int intValue() default 0; + long longValue() default 0; + float floatValue() default 0; + double doubleValue() default 0; + String stringValue() default ""; + int[] arrayValue1() default {}; + String[] arrayValue2() default {}; + Class classValue1() default void.class; + Class classValue2() default void.class; + EnumValue enumValue() default EnumValue.VALUE1; + AnnotationValue annoValue() default @AnnotationValue(stringValue = "StringValue"); + AnnotationValue[] annoArrayValue() default + {@AnnotationValue(stringValue = "StringValue1"), + @AnnotationValue(stringValue = "StringValue2"), + @AnnotationValue(stringValue = "StringValue3")}; +} + +@Retention(RetentionPolicy.RUNTIME) +@Repeatable(RuntimeVisibleRepeatableContainer.class) +@interface RuntimeVisibleRepeatable { + boolean booleanValue() default false; + byte byteValue() default 0; + char charValue() default 0; + short shortValue() default 0; + int intValue() default 0; + long longValue() default 0; + float floatValue() default 0; + double doubleValue() default 0; + String stringValue() default ""; + int[] arrayValue1() default {}; + String[] arrayValue2() default {}; + Class classValue1() default void.class; + Class classValue2() default void.class; + EnumValue enumValue() default EnumValue.VALUE1; + AnnotationValue annoValue() default @AnnotationValue(stringValue = "StringValue"); + AnnotationValue[] annoArrayValue() default + {@AnnotationValue(stringValue = "StringValue1"), + @AnnotationValue(stringValue = "StringValue2"), + @AnnotationValue(stringValue = "StringValue3")}; +} + +@Retention(RetentionPolicy.RUNTIME) +@interface RuntimeVisibleRepeatableContainer { + RuntimeVisibleRepeatable[] value(); +} + +@Retention(RetentionPolicy.RUNTIME) +@interface RuntimeVisibleNotRepeatable { + boolean booleanValue() default false; + byte byteValue() default 0; + char charValue() default 0; + short shortValue() default 0; + int intValue() default 0; + long longValue() default 0; + float floatValue() default 0; + double doubleValue() default 0; + String stringValue() default ""; + int[] arrayValue1() default {}; + String[] arrayValue2() default {}; + Class classValue1() default void.class; + Class classValue2() default void.class; + EnumValue enumValue() default EnumValue.VALUE1; + AnnotationValue annoValue() default @AnnotationValue(stringValue = "StringValue"); + AnnotationValue[] annoArrayValue() default + {@AnnotationValue(stringValue = "StringValue1"), + @AnnotationValue(stringValue = "StringValue2"), + @AnnotationValue(stringValue = "StringValue3")}; +} + +enum EnumValue { + VALUE1, VALUE2, VALUE3 +} + +@interface AnnotationValue { + String stringValue() default ""; +} \ No newline at end of file diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/lib/TestBase.java --- a/test/tools/javac/classfiles/attributes/lib/TestBase.java Thu Jul 16 13:51:57 2015 -0700 +++ b/test/tools/javac/classfiles/attributes/lib/TestBase.java Thu Jul 16 19:31:01 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,10 +21,9 @@ * questions. */ -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -210,6 +209,12 @@ assertTrue(found.containsAll(expected), message + " : " + copy); } + public void writeToFile(Path path, String source) throws IOException { + try (BufferedWriter writer = Files.newBufferedWriter(path)) { + writer.write(source); + } + } + public File getSourceDir() { return new File(System.getProperty("test.src", ".")); } diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javac/classfiles/attributes/lib/TestResult.java --- a/test/tools/javac/classfiles/attributes/lib/TestResult.java Thu Jul 16 13:51:57 2015 -0700 +++ b/test/tools/javac/classfiles/attributes/lib/TestResult.java Thu Jul 16 19:31:01 2015 -0700 @@ -24,18 +24,16 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.util.*; -import java.util.stream.Collectors; /** * This class accumulates test results. Test results can be checked with method @{code checkStatus}. */ public class TestResult extends TestBase { - private final List testCases; + private final List testCasesInfo; public TestResult() { - testCases = new ArrayList<>(); - testCases.add(new Info("Global test info")); + testCasesInfo = new ArrayList<>(); } /** @@ -44,21 +42,16 @@ * @param info the information about test case */ public void addTestCase(String info) { - testCases.add(new Info(info)); - } - - private String errorMessage() { - return testCases.stream().filter(Info::isFailed) - .map(tc -> String.format("Failure in test case:\n%s\n%s", tc.info(), tc.getMessage())) - .collect(Collectors.joining("\n")); + System.err.println("Test case: " + info); + testCasesInfo.add(new Info(info)); } public boolean checkEquals(Object actual, Object expected, String message) { echo("Testing : " + message); if (!Objects.equals(actual, expected)) { getLastTestCase().addAssert(String.format("%s\n" + - "Expected: %s,\n" + - " Got: %s", message, expected, actual)); + "Expected: %s,\n" + + " Got: %s", message, expected, actual)); return false; } return true; @@ -96,14 +89,17 @@ } public void addFailure(Throwable th) { - testCases.get(testCases.size() - 1).addFailure(th); + if (testCasesInfo.isEmpty()) { + testCasesInfo.add(new Info("Dummy info")); + } + getLastTestCase().addFailure(th); } private Info getLastTestCase() { - if (testCases.size() == 1) { + if (testCasesInfo.isEmpty()) { throw new IllegalStateException("Test case should be created"); } - return testCases.get(testCases.size() - 1); + return testCasesInfo.get(testCasesInfo.size() - 1); } /** @@ -114,22 +110,41 @@ * or an exception occurs */ public void checkStatus() throws TestFailedException { - if (testCases.stream().anyMatch(Info::isFailed)) { - echo(errorMessage()); + int passed = 0; + int failed = 0; + for (Info testCaseInfo : testCasesInfo) { + if (testCaseInfo.isFailed()) { + String info = testCaseInfo.info().replace("\n", LINE_SEPARATOR); + String errorMessage = testCaseInfo.getMessage().replace("\n", LINE_SEPARATOR); + System.err.printf("Failure in test case:%n%s%n%s%n", info, errorMessage); + ++failed; + } else { + ++passed; + } + } + System.err.printf("Test cases: passed: %d, failed: %d, total: %d.%n", passed, failed, passed + failed); + if (failed > 0) { throw new TestFailedException("Test failed"); } + if (passed + failed == 0) { + throw new TestFailedException("Test cases were not found"); + } } - private class Info { + @Override + public void printf(String template, Object... args) { + getLastTestCase().printf(template, args); + } + + private static class Info { private final String info; - private final List asserts; - private final List errors; + private final StringWriter writer; + private boolean isFailed; private Info(String info) { this.info = info; - asserts = new ArrayList<>(); - errors = new ArrayList<>(); + writer = new StringWriter(); } public String info() { @@ -137,34 +152,25 @@ } public boolean isFailed() { - return !asserts.isEmpty() || !errors.isEmpty(); + return isFailed; + } + + public void printf(String template, Object... args) { + writer.write(String.format(template, args)); } public void addFailure(Throwable th) { - errors.add(th); + isFailed = true; printf("[ERROR] : %s\n", getStackTrace(th)); } public void addAssert(String e) { - asserts.add(e); + isFailed = true; printf("[ASSERT] : %s\n", e); } public String getMessage() { - return (asserts.size() > 0 ? getAssertMessages(asserts) + "\n" : "") - + getErrorMessages(errors); - } - - public String getAssertMessages(List list) { - return list.stream() - .map(message -> String.format("[ASSERT] : %s", message)) - .collect(Collectors.joining("\n")); - } - - public String getErrorMessages(List list) { - return list.stream() - .map(throwable -> String.format("[ERROR] : %s", getStackTrace(throwable))) - .collect(Collectors.joining("\n")); + return writer.toString(); } public String getStackTrace(Throwable throwable) { diff -r 3d40e9830cac -r 02681b7c4232 test/tools/javadoc/doclint/DocLintTest.java --- a/test/tools/javadoc/doclint/DocLintTest.java Thu Jul 16 13:51:57 2015 -0700 +++ b/test/tools/javadoc/doclint/DocLintTest.java Thu Jul 16 19:31:01 2015 -0700 @@ -23,7 +23,7 @@ /* * @test - * @bug 8004834 8007610 + * @bug 8004834 8007610 8129909 * @summary Add doclint support into javadoc * @modules jdk.compiler/com.sun.tools.javac.main */ @@ -59,7 +59,7 @@ DocumentationTool javadoc; StandardJavaFileManager fm; - JavaFileObject file; + Iterable files; final String code = /* 01 */ "/** Class comment. */\n" + @@ -77,6 +77,20 @@ /* 13 */ " public int emptyReturn() { return 0; }\n" + /* 14 */ "}\n"; + final String p1Code = + /* 01 */ "package p1;\n" + + /* 02 */ "public class P1Test {\n" + + /* 03 */ " /** Syntax < error. */\n" + + /* 04 */ " public void method() { }\n" + + /* 05 */ "}\n"; + + final String p2Code = + /* 01 */ "package p2;\n" + + /* 02 */ "public class P2Test {\n" + + /* 03 */ " /** Syntax < error. */\n" + + /* 04 */ " public void method() { }\n" + + /* 05 */ "}\n"; + private final String rawDiags = "-XDrawDiagnostics"; private enum Message { @@ -85,6 +99,9 @@ DL_ERR9(ERROR, "Test.java:9:14: compiler.err.proc.messager: reference not found"), DL_WRN12(WARNING, "Test.java:12:9: compiler.warn.proc.messager: no description for @return"), + DL_ERR_P1TEST(ERROR, "P1Test.java:3:16: compiler.err.proc.messager: malformed HTML"), + DL_ERR_P2TEST(ERROR, "P2Test.java:3:16: compiler.err.proc.messager: malformed HTML"), + // doclint messages when -XDrawDiagnostics is not in effect DL_ERR9A(ERROR, "Test.java:9: error: reference not found"), DL_WRN12A(WARNING, "Test.java:12: warning: no description for @return"), @@ -95,7 +112,8 @@ // javadoc messages for bad options OPT_BADARG(ERROR, "javadoc: error - Invalid argument for -Xdoclint option"), - OPT_BADQUAL(ERROR, "javadoc: error - Access qualifiers not permitted for -Xdoclint arguments"); + OPT_BADQUAL(ERROR, "javadoc: error - Access qualifiers not permitted for -Xdoclint arguments"), + OPT_BADPACKAGEARG(ERROR, "javadoc: error - Invalid argument for -Xdoclint/package option"); final Diagnostic.Kind kind; final String text; @@ -124,12 +142,7 @@ fm = javadoc.getStandardFileManager(null, null, null); try { fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File("."))); - file = new SimpleJavaFileObject(URI.create("Test.java"), JavaFileObject.Kind.SOURCE) { - @Override - public CharSequence getCharContent(boolean ignoreEncoding) { - return code; - } - }; + files = Arrays.asList(new TestJFO("Test.java", code)); test(Collections.emptyList(), Main.Result.ERROR, @@ -175,6 +188,21 @@ Main.Result.ERROR, EnumSet.of(Message.OPT_BADARG)); + files = Arrays.asList(new TestJFO("p1/P1Test.java", p1Code), + new TestJFO("p2/P2Test.java", p2Code)); + + test(Arrays.asList(rawDiags), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR_P1TEST, Message.DL_ERR_P2TEST)); + + test(Arrays.asList(rawDiags, "-Xdoclint/package:p1"), + Main.Result.ERROR, + EnumSet.of(Message.DL_ERR_P1TEST)); + + test(Arrays.asList(rawDiags, "-Xdoclint/package:*p"), + Main.Result.ERROR, + EnumSet.of(Message.OPT_BADPACKAGEARG)); + if (errors > 0) throw new Exception(errors + " errors occurred"); } finally { @@ -186,7 +214,6 @@ System.err.println("test: " + opts); StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); - List files = Arrays.asList(file); try { DocumentationTask t = javadoc.getTask(pw, fm, null, null, opts, files); boolean ok = t.call(); @@ -257,4 +284,19 @@ } int errors; + + class TestJFO extends SimpleJavaFileObject { + + private final String content; + + public TestJFO(String fileName, String content) { + super(URI.create(fileName), JavaFileObject.Kind.SOURCE); + this.content = content; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncoding) { + return content; + } + }; } diff -r 3d40e9830cac -r 02681b7c4232 test/tools/lib/ToolBox.java --- a/test/tools/lib/ToolBox.java Thu Jul 16 13:51:57 2015 -0700 +++ b/test/tools/lib/ToolBox.java Thu Jul 16 19:31:01 2015 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1594,15 +1594,20 @@ } /* - * A jar: URL is of the form jar:URL!/entry where URL is a URL for the .jar file itself. + * A jar: URL is of the form jar:URL!/ where URL is a URL for the .jar file itself. * In Symbol files (i.e. ct.sym) the underlying entry is prefixed META-INF/sym/. */ private final Pattern jarEntry = Pattern.compile(".*!/(?:META-INF/sym/[^/]+/)?(.*)"); /* - * A jrt: URL is of the form jrt:/module/package/file + * A jrt: URL is of the form jrt:/modules/// */ - private final Pattern jrtEntry = Pattern.compile("/([^/]+)/(.*)"); + private final Pattern jrtEntry = Pattern.compile("/modules/([^/]+)/(.*)"); + + /* + * A file: URL is of the form file:/path/to/modules/// + */ + private final Pattern fileEntry = Pattern.compile(".*/modules/([^/]+)/(.*)"); private String guessPath(FileObject fo) { URI u = fo.toUri(); @@ -1621,6 +1626,13 @@ } break; } + case "file": { + Matcher m = fileEntry.matcher(u.getSchemeSpecificPart()); + if (m.matches()) { + return m.group(2); + } + break; + } } throw new IllegalArgumentException(fo.getName() + "--" + fo.toUri()); }