This commit is contained in:
Lana Steuck 2015-07-16 19:31:01 -07:00
commit 5bd2057d23
55 changed files with 2885 additions and 200 deletions

View File

@ -344,6 +344,10 @@ public class DocLint implements Plugin {
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 @@ public class DocLint implements Plugin {
@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);
}

View File

@ -43,6 +43,7 @@ import javax.lang.model.util.Types;
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 @@ public class Env {
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 extends Comparable<T>> T min(T item1, T item2) {
return (item1 == null) ? item2
: (item2 == null) ? item1

View File

@ -874,8 +874,8 @@ public class JavacTrees extends DocTrees {
/**
* 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) {

View File

@ -230,9 +230,11 @@ public abstract class Attribute implements AnnotationValue {
/**
* 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
* <pre>
* {@code @com.example.foo(name1=val1, name2=val2)}
* {@code @com.example.foo(val)}
* {@code @com.example.foo}
* </pre>
* Omit parens for marker annotations, and omit "value=" when allowed.
*/
@DefinedBy(Api.LANGUAGE_MODEL)

View File

@ -461,7 +461,7 @@ public class TypeAnnotationPosition {
*
* @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 @@ public class TypeAnnotationPosition {
* 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 @@ public class TypeAnnotationPosition {
/**
* 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 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location,
@ -535,8 +535,6 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location) {
@ -564,8 +562,6 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location) {
@ -720,8 +716,6 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location) {
@ -748,8 +742,6 @@ public class TypeAnnotationPosition {
/**
* 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 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location) {
@ -792,7 +782,6 @@ public class TypeAnnotationPosition {
*
* @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 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location) {
@ -885,9 +872,7 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location,
@ -984,9 +969,7 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location,
@ -1062,7 +1045,7 @@ public class TypeAnnotationPosition {
*
* @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 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location,
@ -1097,7 +1078,7 @@ public class TypeAnnotationPosition {
*
* @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 @@ public class TypeAnnotationPosition {
* 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<TypePathEntry> location,

View File

@ -279,7 +279,7 @@ public class Attr extends JCTree.Visitor {
/** 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 @@ public class Attr extends JCTree.Visitor {
/**
* 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
*/

View File

@ -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.FileSystemNotFoundException;
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;
@ -94,11 +93,6 @@ public class JRTIndex {
*/
private final FileSystem jrtfs;
/**
* The set of module directories within the jrt: file system.
*/
private final Set<Path> jrtModules;
/**
* A lazily evaluated set of entries about the contents of the jrt: file system.
*/
@ -183,14 +177,6 @@ public class JRTIndex {
*/
private JRTIndex() throws IOException {
jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
jrtModules = new LinkedHashSet<>();
Path root = jrtfs.getPath("/");
try (DirectoryStream<Path> stream = Files.newDirectoryStream(root)) {
for (Path entry: stream) {
if (Files.isDirectory(entry))
jrtModules.add(entry);
}
}
entries = new HashMap<>();
}
@ -204,18 +190,29 @@ public class JRTIndex {
if (e == null) {
Map<String, Path> files = new LinkedHashMap<>();
Set<RelativeDirectory> subdirs = new LinkedHashSet<>();
for (Path module: jrtModules) {
Path p = rd.getFile(module);
if (!Files.exists(p))
continue;
try (DirectoryStream<Path> 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<Path> modules = Files.newDirectoryStream(dir)) {
for (Path module: modules) {
Path p = rd.getFile(module);
if (!Files.exists(p))
continue;
try (DirectoryStream<Path> 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));
}
}
}
}
}

View File

@ -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 @@ public abstract class PathFileObject implements JavaFileObject {
return new PathFileObject(fileManager, path) {
@Override
public String inferBinaryName(Iterable<? extends Path> 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()));
}
};
}

View File

@ -1047,7 +1047,6 @@ public class JavaCompiler {
/**
* 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 @@ public class JavaCompiler {
* 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<Env<AttrContext>> attribute(Queue<Env<AttrContext>> envs) {
ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
@ -1205,7 +1204,7 @@ public class JavaCompiler {
/**
* Attribute a parse tree.
* @returns the attributed parse tree
* @return the attributed parse tree
*/
public Env<AttrContext> attribute(Env<AttrContext> env) {
if (compileStates.isDone(env, CompileState.ATTR))
@ -1245,7 +1244,7 @@ public class JavaCompiler {
* 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<Env<AttrContext>> flow(Queue<Env<AttrContext>> envs) {
ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
@ -1315,7 +1314,7 @@ public class JavaCompiler {
* 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<Pair<Env<AttrContext>, JCClassDecl>> desugar(Queue<Env<AttrContext>> envs) {
ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = new ListBuffer<>();

View File

@ -409,7 +409,7 @@ public class DocCommentParser {
/**
* 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

View File

@ -1411,7 +1411,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
/**
* {@inheritdoc}
* {@inheritDoc}
*
* Command line options suitable for presenting to annotation
* processors.

View File

@ -168,7 +168,7 @@ public class JavacRoundEnvironment implements RoundEnvironment {
}
/**
* {@inheritdoc}
* {@inheritDoc}
*/
@DefinedBy(Api.ANNOTATION_PROCESSING)
public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) {

View File

@ -2368,7 +2368,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
/**
* 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 {

View File

@ -61,7 +61,7 @@ import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
* Those implementations are specifically targeting JCDiagnostic objects.
* <li> Provides basic support for i18n and a method for executing all locale-dependent conversions
* <li> Provides the formatting logic for rendering the arguments of a JCDiagnostic object.
* <ul>
* </ul>
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.

View File

@ -44,7 +44,7 @@ import java.util.*;
* instance method that is overridden in extended components. A base
* phase supporting extension would look something like this:
*
* <p><pre>{@code
* <pre>{@code
* public class Phase {
* protected static final Context.Key<Phase> phaseKey =
* new Context.Key<Phase>();
@ -70,7 +70,7 @@ import java.util.*;
* and this must be done before any reference to the phase is accessed
* using Phase.instance(). An extended phase might be declared thus:
*
* <p><pre>{@code
* <pre>{@code
* public class NewPhase extends Phase {
* protected NewPhase(Context context) {
* super(context);
@ -87,7 +87,7 @@ import java.util.*;
*
* <p>And is registered early in the extended compiler like this
*
* <p><pre>
* <pre>
* NewPhase.preRegister(context);
* </pre>
*

View File

@ -28,7 +28,7 @@ package com.sun.tools.javac.util;
/**
* 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 @@ public class IntHashTable {
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 @@ public class IntHashTable {
}
/**
* 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) {

View File

@ -187,7 +187,7 @@ public class BuildState {
/**
* 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<String,Source> srcs) {
boolean baad = false;

View File

@ -131,7 +131,7 @@ public class Util {
* 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<String> allowedSubOptions, String s) {

View File

@ -128,12 +128,6 @@ public class SjavacClient implements Sjavac {
/**
* 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() {

View File

@ -161,7 +161,7 @@ public class Options {
/**
* Get a map which maps suffixes to transformers (for example
* ".java" -> CompileJavaPackages)
* ".java" {@literal ->} CompileJavaPackages)
*/
public Map<String, Transformer> getTranslationRules() {
return trRules;

View File

@ -78,7 +78,7 @@ public class PortFile {
/**
* 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;

View File

@ -58,7 +58,6 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
*
* @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);

View File

@ -289,9 +289,11 @@ public class ConfigurationImpl extends Configuration {
} 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 @@ public class ConfigurationImpl extends Configuration {
* The options arrive as case-sensitive strings. For options that
* are not case-sensitive, use toLowerCase() on the option string
* before comparing it.
* </blockquote>
*
* @return number of arguments + 1 for a option. Zero return means
* option not known. Negative value means error occurred.
@ -349,7 +350,8 @@ public class ConfigurationImpl extends Configuration {
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 @@ public class ConfigurationImpl extends Configuration {
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;

View File

@ -247,7 +247,7 @@ public class LinkInfoImpl extends LinkInfo {
}
/**
* {@inherotDoc}
* {@inheritDoc}
*/
protected Content newContent() {
return new ContentBuilder();

View File

@ -267,7 +267,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter {
* 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))

View File

@ -231,4 +231,10 @@ doclet.X.usage=Provided by standard doclet:\n\
\ -Xdoclint Enable recommended checks for problems in javadoc comments\n\
\ -Xdoclint:(all|none|[-]<group>) \n\
\ Enable or disable specific checks for problems in javadoc comments,\n\
\ where <group> is one of accessibility, html, missing, reference, or syntax.\n
\ where <group> is one of accessibility, html, missing, reference, or syntax.\n\
\ -Xdoclint/package:([-]<packages>)\n\
\ Enable or disable checks in specific packages. <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

View File

@ -13,6 +13,7 @@ doclet.Option_conflict=Option {0} conflicts with {1}
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\

View File

@ -58,7 +58,7 @@ public abstract class TagletWriter {
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 @@ public abstract class TagletWriter {
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.

View File

@ -100,9 +100,11 @@ public class AnnotationDescImpl implements AnnotationDesc {
/**
* 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
* <pre>
* {@code @com.example.foo(name1=val1, name2=val2)}
* {@code @com.example.foo(val)}
* {@code @com.example.foo}
* </pre>
* Omit parens for marker annotations, and omit "value=" when allowed.
*/
@Override

View File

@ -1278,8 +1278,8 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
* each Serializable field defined by an <code>ObjectStreamField</code>
* array component of <code>serialPersistentField</code>.
*
* @returns an array of <code>FieldDoc</code> for the Serializable fields
* of this class.
* @return an array of {@code FieldDoc} for the Serializable fields
* of this class.
*
* @see #definesSerializableFields()
* @see SerialFieldTagImpl

View File

@ -31,6 +31,7 @@ import java.util.*;
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 @@ public class DocEnv {
void initDoclint(Collection<String> opts, Collection<String> customTagNames, String htmlVersion) {
ArrayList<String> 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 @@ public class DocEnv {
boolean showTagMessages() {
return (doclint == null);
}
Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>();
boolean shouldCheck(CompilationUnitTree unit) {
return shouldCheck.computeIfAbsent(unit, doclint :: shouldCheck);
}
}

View File

@ -129,6 +129,7 @@ public abstract class DocImpl implements Doc, Comparable<Object> {
String d = documentation();
if (env.doclint != null
&& treePath != null
&& env.shouldCheck(treePath.getCompilationUnit())
&& d.equals(getCommentText(treePath))) {
env.doclint.scan(treePath);
}

View File

@ -36,7 +36,7 @@ import static com.sun.tools.classfile.ConstantPool.*;
/**
* 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 {

View File

@ -97,23 +97,32 @@ class PlatformClassPath {
}
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);
}
}

View File

@ -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<Integer> 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<TestCase> generateTestCases();
public abstract void test(TestCase testCase, Map<String, ? extends JavaFileObject> 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<TestAnnotationInfo.Pair> 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<TestAnnotationInfo> annotations;
public TestAnnotationInfos(List<TestAnnotationInfo> 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<List<TestAnnotationInfos>> groupAnnotations(List<TestAnnotationInfos> annotations) {
List<List<TestAnnotationInfos>> groupedAnnotations = new ArrayList<>();
int size = 32;
List<TestAnnotationInfos> 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<TestAnnotationInfos> getAllCombinationsOfAnnotations() {
List<TestAnnotationInfos> combinations = new ArrayList<>();
for (Annotations annotationName1 : Annotations.values()) {
List<TestAnnotationInfo> 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<TestAnnotationInfo> 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<? extends Attribute> clazz) {
return Stream.of(attrs)
.filter(clazz::isInstance)
.count();
}
public void test() throws TestFailedException {
try {
List<TestCase> 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;
}
}
}

View File

@ -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<TestCase.TestFieldInfo> 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<? extends TestCase.TestMemberInfo> members) {
String src = members.stream()
.map(TestCase.TestMemberInfo::generateSource)
.collect(Collectors.joining("\n"));
return src.trim().isEmpty() ? "" : src + "\n\n";
}
public String collectInnerClasses(Collection<TestCase.TestClassInfo> innerClasses) {
return collectSrc(innerClasses);
}
public String collectFields(Collection<TestCase.TestFieldInfo> fields) {
return collectSrc(fields);
}
public String collectMethods(Collection<TestCase.TestMethodInfo> 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;
}
}

View File

@ -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.

View File

@ -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&lt;Integer&gt; {
* 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<TestCase> generateTestCases() {
List<TestCase> testCases = new ArrayList<>();
for (List<TestAnnotationInfos> 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<Integer>
TestCase.TestClassInfo clazz = testCase.addClassInfo("java.util.ArrayList<Integer>", 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();
}
}

View File

@ -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<TestCase> generateTestCases() {
List<TestCase> testCases = new ArrayList<>();
for (List<TestAnnotationInfos> 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();
}
}

View File

@ -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<TestCase> generateTestCases() {
List<TestCase> testCases = new ArrayList<>();
for (List<TestAnnotationInfos> 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("<init>()");
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();
}
}

View File

@ -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<TestCase> generateTestCases() {
List<TestCase> testCases = new ArrayList<>();
for (List<TestAnnotationInfos> 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();
}
}

View File

@ -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<TestCase> generateTestCases() {
List<TestCase> testCases = new ArrayList<>();
for (List<TestAnnotationInfos> 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();
}
}

View File

@ -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<TestCase> generateTestCases() {
List<TestCase> testCases = new ArrayList<>();
for (List<TestAnnotationInfos> 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("<init>()");
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();
}
}

View File

@ -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<String, ? extends JavaFileObject> classes)
throws IOException, ConstantPoolException, Descriptor.InvalidDescriptor {
for (Map.Entry<String, ? extends JavaFileObject> 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<String> foundMethods = new HashSet<>();
for (Method method : classFile.methods) {
String methodName = method.getName(classFile.constant_pool) +
method.descriptor.getParameterTypes(classFile.constant_pool);
if (methodName.startsWith("<init>")) {
String constructorName = className.replaceAll(".*\\$", "");
methodName = methodName.replace("<init>", 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<String> 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> attributes)
throws ConstantPoolException {
Map<String, Annotation> actualInvisible = collectAnnotations(
classFile,
member,
attributes.get(),
Attribute.RuntimeInvisibleAnnotations);
Map<String, Annotation> 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<String, Annotation> collectAnnotations(
ClassFile classFile,
TestCase.TestMemberInfo member,
Attributes attributes,
String attribute) throws ConstantPoolException {
RuntimeAnnotations_attribute attr = (RuntimeAnnotations_attribute) attributes.get(attribute);
Map<String, Annotation> 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;
}
}

View File

@ -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&lt;Integer&gt; {
*
* 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<TestCase> generateTestCases() {
List<TestCase> testCases = new ArrayList<>();
for (TestAnnotationInfos annotations : getAllCombinationsOfAnnotations()) {
// generate: public class Test extends java.util.ArrayList<Integer>
TestCase testCase = new TestCase();
TestCase.TestClassInfo clazz = testCase.addClassInfo("java.util.ArrayList<Integer>", 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();
}
}

View File

@ -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<TestCase> generateTestCases() {
throw new UnsupportedOperationException();
}
}

View File

@ -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<TestCase> generateTestCases() {
List<TestCase> testCases = new ArrayList<>();
for (List<TestAnnotationInfos> 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, "<init>");
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();
}
}

View File

@ -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<String, ? extends JavaFileObject> classes)
throws IOException, ConstantPoolException, Descriptor.InvalidDescriptor {
for (Map.Entry<String, ? extends JavaFileObject> entry : classes.entrySet()) {
ClassFile classFile = readClassFile(classes.get(entry.getKey()));
Set<String> 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("<init>")) {
methodName = methodName.replace("<init>", 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<Map<String, Annotation>> actualInvisible = collectAnnotations(
classFile,
testMethod,
method,
Attribute.RuntimeInvisibleParameterAnnotations);
List<Map<String, Annotation>> actualVisible = collectAnnotations(
classFile,
testMethod,
method,
Attribute.RuntimeVisibleParameterAnnotations);
List<TestCase.TestParameterInfo> 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<Map<String, Annotation>> 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<Map<String, Annotation>> 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<String, Annotation> 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;
}
}

View File

@ -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<Pair> 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<String, String> 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<TestElementValue> 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();
}
}
}

View File

@ -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<String, TestClassInfo> 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(&quot;Test$1Local&quot;)}
* 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<String, TestClassInfo> innerClasses = current.innerClasses;
Map<String, TestMethodInfo> 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<TestClassInfo> 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<String> mods;
public final String name;
public final Map<String, TestAnnotationInfo> 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<String> getRuntimeVisibleAnnotations() {
return getRuntimeAnnotations(RetentionPolicy.RUNTIME);
}
public Set<String> getRuntimeInvisibleAnnotations() {
return getRuntimeAnnotations(RetentionPolicy.CLASS);
}
private Set<String> 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<String, TestClassInfo> innerClasses;
public final Map<String, TestMethodInfo> methods;
public final Map<String, TestFieldInfo> 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("<init>");
if (isConstructor) {
methodName = methodName.replace("<init>", 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<String, TestClassInfo> localClasses;
public final List<TestParameterInfo> 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);
}
}
}

View File

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

View File

@ -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 @@ public class TestBase {
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", "."));
}

View File

@ -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<Info> testCases;
private final List<Info> testCasesInfo;
public TestResult() {
testCases = new ArrayList<>();
testCases.add(new Info("Global test info"));
testCasesInfo = new ArrayList<>();
}
/**
@ -44,21 +42,16 @@ public class TestResult extends TestBase {
* @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 class TestResult extends TestBase {
}
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 @@ public class TestResult extends TestBase {
* 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<String> asserts;
private final List<Throwable> 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 class TestResult extends TestBase {
}
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<String> list) {
return list.stream()
.map(message -> String.format("[ASSERT] : %s", message))
.collect(Collectors.joining("\n"));
}
public String getErrorMessages(List<? extends Throwable> list) {
return list.stream()
.map(throwable -> String.format("[ERROR] : %s", getStackTrace(throwable)))
.collect(Collectors.joining("\n"));
return writer.toString();
}
public String getStackTrace(Throwable throwable) {

View File

@ -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 @@ public class DocLintTest {
DocumentationTool javadoc;
StandardJavaFileManager fm;
JavaFileObject file;
Iterable<? extends JavaFileObject> files;
final String code =
/* 01 */ "/** Class comment. */\n" +
@ -77,6 +77,20 @@ public class DocLintTest {
/* 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 @@ public class DocLintTest {
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 @@ public class DocLintTest {
// 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 @@ public class DocLintTest {
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.<String>emptyList(),
Main.Result.ERROR,
@ -175,6 +188,21 @@ public class DocLintTest {
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 @@ public class DocLintTest {
System.err.println("test: " + opts);
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
List<JavaFileObject> files = Arrays.asList(file);
try {
DocumentationTask t = javadoc.getTask(pw, fm, null, null, opts, files);
boolean ok = t.call();
@ -257,4 +284,19 @@ public class DocLintTest {
}
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;
}
};
}

View File

@ -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 @@ public class ToolBox {
}
/*
* 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!/<entry> 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/<base>.
*/
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/<module>/<package>/<file>
*/
private final Pattern jrtEntry = Pattern.compile("/([^/]+)/(.*)");
private final Pattern jrtEntry = Pattern.compile("/modules/([^/]+)/(.*)");
/*
* A file: URL is of the form file:/path/to/modules/<module>/<package>/<file>
*/
private final Pattern fileEntry = Pattern.compile(".*/modules/([^/]+)/(.*)");
private String guessPath(FileObject fo) {
URI u = fo.toUri();
@ -1621,6 +1626,13 @@ public class ToolBox {
}
break;
}
case "file": {
Matcher m = fileEntry.matcher(u.getSchemeSpecificPart());
if (m.matches()) {
return m.group(2);
}
break;
}
}
throw new IllegalArgumentException(fo.getName() + "--" + fo.toUri());
}