mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 19:44:41 +02:00
Merge
This commit is contained in:
commit
5bd2057d23
55 changed files with 2885 additions and 200 deletions
|
@ -344,6 +344,10 @@ public class DocLint implements Plugin {
|
||||||
checker.scan(dc, p);
|
checker.scan(dc, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean shouldCheck(CompilationUnitTree unit) {
|
||||||
|
return env.shouldCheck(unit);
|
||||||
|
}
|
||||||
|
|
||||||
public void reportStats(PrintWriter out) {
|
public void reportStats(PrintWriter out) {
|
||||||
env.messages.reportStats(out);
|
env.messages.reportStats(out);
|
||||||
}
|
}
|
||||||
|
@ -406,27 +410,9 @@ public class DocLint implements Plugin {
|
||||||
|
|
||||||
@Override @DefinedBy(Api.COMPILER_TREE)
|
@Override @DefinedBy(Api.COMPILER_TREE)
|
||||||
public Void visitCompilationUnit(CompilationUnitTree node, Void p) {
|
public Void visitCompilationUnit(CompilationUnitTree node, Void p) {
|
||||||
if (env.includePackages != null) {
|
if (!env.shouldCheck(node)) {
|
||||||
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;
|
return null;
|
||||||
}
|
}
|
||||||
for (Pattern pack : env.excludePackages) {
|
|
||||||
if (pack.matcher(packageName).matches()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return super.visitCompilationUnit(node, p);
|
return super.visitCompilationUnit(node, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,7 @@ import javax.lang.model.util.Types;
|
||||||
import javax.tools.Diagnostic.Kind;
|
import javax.tools.Diagnostic.Kind;
|
||||||
|
|
||||||
import com.sun.source.doctree.DocCommentTree;
|
import com.sun.source.doctree.DocCommentTree;
|
||||||
|
import com.sun.source.tree.CompilationUnitTree;
|
||||||
import com.sun.source.util.DocTrees;
|
import com.sun.source.util.DocTrees;
|
||||||
import com.sun.source.util.JavacTask;
|
import com.sun.source.util.JavacTask;
|
||||||
import com.sun.source.util.SourcePositions;
|
import com.sun.source.util.SourcePositions;
|
||||||
|
@ -229,6 +230,35 @@ public class Env {
|
||||||
return sp.getStartPosition(p.getCompilationUnit(), p.getLeaf());
|
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) {
|
private <T extends Comparable<T>> T min(T item1, T item2) {
|
||||||
return (item1 == null) ? item2
|
return (item1 == null) ? item2
|
||||||
: (item2 == null) ? item1
|
: (item2 == null) ? item1
|
||||||
|
|
|
@ -874,7 +874,7 @@ public class JavacTrees extends DocTrees {
|
||||||
/**
|
/**
|
||||||
* Returns the original type from the ErrorType object.
|
* Returns the original type from the ErrorType object.
|
||||||
* @param errorType The errorType for which we want to get the original type.
|
* @param errorType The errorType for which we want to get the original type.
|
||||||
* @returns TypeMirror corresponding to the original type, replaced by the ErrorType.
|
* @return TypeMirror corresponding to the original type, replaced by the ErrorType.
|
||||||
* noType (type.tag == NONE) is returned if there is no original type.
|
* noType (type.tag == NONE) is returned if there is no original type.
|
||||||
*/
|
*/
|
||||||
@DefinedBy(Api.COMPILER_TREE)
|
@DefinedBy(Api.COMPILER_TREE)
|
||||||
|
|
|
@ -230,9 +230,11 @@ public abstract class Attribute implements AnnotationValue {
|
||||||
/**
|
/**
|
||||||
* Returns a string representation of this annotation.
|
* Returns a string representation of this annotation.
|
||||||
* String is of one of the forms:
|
* String is of one of the forms:
|
||||||
* @com.example.foo(name1=val1, name2=val2)
|
* <pre>
|
||||||
* @com.example.foo(val)
|
* {@code @com.example.foo(name1=val1, name2=val2)}
|
||||||
* @com.example.foo
|
* {@code @com.example.foo(val)}
|
||||||
|
* {@code @com.example.foo}
|
||||||
|
* </pre>
|
||||||
* Omit parens for marker annotations, and omit "value=" when allowed.
|
* Omit parens for marker annotations, and omit "value=" when allowed.
|
||||||
*/
|
*/
|
||||||
@DefinedBy(Api.LANGUAGE_MODEL)
|
@DefinedBy(Api.LANGUAGE_MODEL)
|
||||||
|
|
|
@ -461,7 +461,7 @@ public class TypeAnnotationPosition {
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this 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.
|
* @param pos The position from the associated tree node.
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
|
@ -479,7 +479,7 @@ public class TypeAnnotationPosition {
|
||||||
* Create a {@code TypeAnnotationPosition} for a method formal parameter.
|
* Create a {@code TypeAnnotationPosition} for a method formal parameter.
|
||||||
*
|
*
|
||||||
* @param onLambda The lambda for this 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.
|
* @param pos The position from the associated tree node.
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
|
@ -493,7 +493,7 @@ public class TypeAnnotationPosition {
|
||||||
/**
|
/**
|
||||||
* Create a {@code TypeAnnotationPosition} for a method formal parameter.
|
* 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.
|
* @param pos The position from the associated tree node.
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
|
@ -506,7 +506,7 @@ public class TypeAnnotationPosition {
|
||||||
* Create a {@code TypeAnnotationPosition} for a method formal parameter.
|
* Create a {@code TypeAnnotationPosition} for a method formal parameter.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param index The index of the parameter.
|
* @param parameter_index The index of the parameter.
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
methodParameter(final List<TypePathEntry> location,
|
methodParameter(final List<TypePathEntry> location,
|
||||||
|
@ -535,8 +535,6 @@ public class TypeAnnotationPosition {
|
||||||
* Create a {@code TypeAnnotationPosition} for a method reference.
|
* Create a {@code TypeAnnotationPosition} for a method reference.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @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
|
public static TypeAnnotationPosition
|
||||||
methodRef(final List<TypePathEntry> location) {
|
methodRef(final List<TypePathEntry> location) {
|
||||||
|
@ -564,8 +562,6 @@ public class TypeAnnotationPosition {
|
||||||
* Create a {@code TypeAnnotationPosition} for a constructor reference.
|
* Create a {@code TypeAnnotationPosition} for a constructor reference.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @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
|
public static TypeAnnotationPosition
|
||||||
constructorRef(final List<TypePathEntry> location) {
|
constructorRef(final List<TypePathEntry> location) {
|
||||||
|
@ -720,8 +716,6 @@ public class TypeAnnotationPosition {
|
||||||
* Create a {@code TypeAnnotationPosition} for a resource variable.
|
* Create a {@code TypeAnnotationPosition} for a resource variable.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this variable.
|
|
||||||
* @param pos The position from the associated tree node.
|
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
resourceVariable(final List<TypePathEntry> location) {
|
resourceVariable(final List<TypePathEntry> location) {
|
||||||
|
@ -748,8 +742,6 @@ public class TypeAnnotationPosition {
|
||||||
/**
|
/**
|
||||||
* Create a {@code TypeAnnotationPosition} for a new.
|
* 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.
|
* @param pos The position from the associated tree node.
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition newObj(final int pos) {
|
public static TypeAnnotationPosition newObj(final int pos) {
|
||||||
|
@ -760,8 +752,6 @@ public class TypeAnnotationPosition {
|
||||||
* Create a {@code TypeAnnotationPosition} for a new.
|
* Create a {@code TypeAnnotationPosition} for a new.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this variable.
|
|
||||||
* @param pos The position from the associated tree node.
|
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
newObj(final List<TypePathEntry> location) {
|
newObj(final List<TypePathEntry> location) {
|
||||||
|
@ -792,7 +782,6 @@ public class TypeAnnotationPosition {
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this variable.
|
* @param onLambda The lambda for this variable.
|
||||||
* @param type_index The index of the interface.
|
|
||||||
* @param pos The position from the associated tree node.
|
* @param pos The position from the associated tree node.
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
|
@ -854,8 +843,6 @@ public class TypeAnnotationPosition {
|
||||||
* Create a {@code TypeAnnotationPosition} for an instanceof.
|
* Create a {@code TypeAnnotationPosition} for an instanceof.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this variable.
|
|
||||||
* @param pos The position from the associated tree node.
|
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
instanceOf(final List<TypePathEntry> location) {
|
instanceOf(final List<TypePathEntry> location) {
|
||||||
|
@ -885,9 +872,7 @@ public class TypeAnnotationPosition {
|
||||||
* Create a {@code TypeAnnotationPosition} for a type cast.
|
* Create a {@code TypeAnnotationPosition} for a type cast.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this variable.
|
|
||||||
* @param type_index The index into an intersection type.
|
* @param type_index The index into an intersection type.
|
||||||
* @param pos The position from the associated tree node.
|
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
typeCast(final List<TypePathEntry> location,
|
typeCast(final List<TypePathEntry> location,
|
||||||
|
@ -984,9 +969,7 @@ public class TypeAnnotationPosition {
|
||||||
* Create a {@code TypeAnnotationPosition} for a type parameter.
|
* Create a {@code TypeAnnotationPosition} for a type parameter.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this variable.
|
|
||||||
* @param parameter_index The index of the type parameter.
|
* @param parameter_index The index of the type parameter.
|
||||||
* @param pos The position from the associated tree node.
|
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
typeParameter(final List<TypePathEntry> location,
|
typeParameter(final List<TypePathEntry> location,
|
||||||
|
@ -1062,7 +1045,7 @@ public class TypeAnnotationPosition {
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this variable.
|
* @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.
|
* @param pos The position from the associated tree node.
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
|
@ -1081,9 +1064,7 @@ public class TypeAnnotationPosition {
|
||||||
* type argument.
|
* type argument.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this variable.
|
* @param type_index The index of the type argument.
|
||||||
* @param parameter_index The index of the type argument.
|
|
||||||
* @param pos The position from the associated tree node.
|
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
methodRefTypeArg(final List<TypePathEntry> location,
|
methodRefTypeArg(final List<TypePathEntry> location,
|
||||||
|
@ -1097,7 +1078,7 @@ public class TypeAnnotationPosition {
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @param location The type path.
|
||||||
* @param onLambda The lambda for this variable.
|
* @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.
|
* @param pos The position from the associated tree node.
|
||||||
*/
|
*/
|
||||||
public static TypeAnnotationPosition
|
public static TypeAnnotationPosition
|
||||||
|
@ -1116,7 +1097,7 @@ public class TypeAnnotationPosition {
|
||||||
* type argument.
|
* type argument.
|
||||||
*
|
*
|
||||||
* @param location The type path.
|
* @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
|
public static TypeAnnotationPosition
|
||||||
constructorRefTypeArg(final List<TypePathEntry> location,
|
constructorRefTypeArg(final List<TypePathEntry> location,
|
||||||
|
|
|
@ -279,7 +279,7 @@ public class Attr extends JCTree.Visitor {
|
||||||
|
|
||||||
/** Check that variable can be assigned to.
|
/** Check that variable can be assigned to.
|
||||||
* @param pos The current source code position.
|
* @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
|
* @param base If the variable is referred to in a Select, the part
|
||||||
* to the left of the `.', null otherwise.
|
* to the left of the `.', null otherwise.
|
||||||
* @param env The current environment.
|
* @param env The current environment.
|
||||||
|
@ -759,7 +759,7 @@ public class Attr extends JCTree.Visitor {
|
||||||
/**
|
/**
|
||||||
* Attribute a "lazy constant value".
|
* Attribute a "lazy constant value".
|
||||||
* @param env The env for the const 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
|
* @param type The expected type, or null
|
||||||
* @see VarSymbol#setLazyConstValue
|
* @see VarSymbol#setLazyConstValue
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.ProviderNotFoundException;
|
import java.nio.file.ProviderNotFoundException;
|
||||||
import java.nio.file.spi.FileSystemProvider;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
@ -94,11 +93,6 @@ public class JRTIndex {
|
||||||
*/
|
*/
|
||||||
private final FileSystem jrtfs;
|
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.
|
* 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 {
|
private JRTIndex() throws IOException {
|
||||||
jrtfs = FileSystems.getFileSystem(URI.create("jrt:/"));
|
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<>();
|
entries = new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,7 +190,16 @@ public class JRTIndex {
|
||||||
if (e == null) {
|
if (e == null) {
|
||||||
Map<String, Path> files = new LinkedHashMap<>();
|
Map<String, Path> files = new LinkedHashMap<>();
|
||||||
Set<RelativeDirectory> subdirs = new LinkedHashSet<>();
|
Set<RelativeDirectory> subdirs = new LinkedHashSet<>();
|
||||||
for (Path module: jrtModules) {
|
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);
|
Path p = rd.getFile(module);
|
||||||
if (!Files.exists(p))
|
if (!Files.exists(p))
|
||||||
continue;
|
continue;
|
||||||
|
@ -220,6 +215,8 @@ public class JRTIndex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
e = new Entry(Collections.unmodifiableMap(files),
|
e = new Entry(Collections.unmodifiableMap(files),
|
||||||
Collections.unmodifiableSet(subdirs),
|
Collections.unmodifiableSet(subdirs),
|
||||||
getCtInfo(rd));
|
getCtInfo(rd));
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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) {
|
return new PathFileObject(fileManager, path) {
|
||||||
@Override
|
@Override
|
||||||
public String inferBinaryName(Iterable<? extends Path> paths) {
|
public String inferBinaryName(Iterable<? extends Path> paths) {
|
||||||
// use subpath to ignore the leading component containing the module name
|
// use subpath to ignore the leading /modules/MODULE-NAME
|
||||||
return toBinaryName(path.subpath(1, path.getNameCount()));
|
return toBinaryName(path.subpath(2, path.getNameCount()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1047,7 +1047,6 @@ public class JavaCompiler {
|
||||||
/**
|
/**
|
||||||
* Process any annotations found in the specified compilation units.
|
* Process any annotations found in the specified compilation units.
|
||||||
* @param roots a list of 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
|
// Implementation note: when this method is called, log.deferredDiagnostics
|
||||||
// will have been set true by initProcessAnnotations, meaning that any diagnostics
|
// 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
|
* Note that attributing classes may cause additional files to be
|
||||||
* parsed and entered via the SourceCompleter.
|
* parsed and entered via the SourceCompleter.
|
||||||
* Attribution of the entries in the list does not stop if any errors occur.
|
* 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) {
|
public Queue<Env<AttrContext>> attribute(Queue<Env<AttrContext>> envs) {
|
||||||
ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
|
ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
|
||||||
|
@ -1205,7 +1204,7 @@ public class JavaCompiler {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attribute a parse tree.
|
* Attribute a parse tree.
|
||||||
* @returns the attributed parse tree
|
* @return the attributed parse tree
|
||||||
*/
|
*/
|
||||||
public Env<AttrContext> attribute(Env<AttrContext> env) {
|
public Env<AttrContext> attribute(Env<AttrContext> env) {
|
||||||
if (compileStates.isDone(env, CompileState.ATTR))
|
if (compileStates.isDone(env, CompileState.ATTR))
|
||||||
|
@ -1245,7 +1244,7 @@ public class JavaCompiler {
|
||||||
* Perform dataflow checks on attributed parse trees.
|
* Perform dataflow checks on attributed parse trees.
|
||||||
* These include checks for definite assignment and unreachable statements.
|
* These include checks for definite assignment and unreachable statements.
|
||||||
* If any errors occur, an empty list will be returned.
|
* 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) {
|
public Queue<Env<AttrContext>> flow(Queue<Env<AttrContext>> envs) {
|
||||||
ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
|
ListBuffer<Env<AttrContext>> results = new ListBuffer<>();
|
||||||
|
@ -1315,7 +1314,7 @@ public class JavaCompiler {
|
||||||
* Prepare attributed parse trees, in conjunction with their attribution contexts,
|
* Prepare attributed parse trees, in conjunction with their attribution contexts,
|
||||||
* for source or code generation.
|
* for source or code generation.
|
||||||
* If any errors occur, an empty list will be returned.
|
* 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) {
|
public Queue<Pair<Env<AttrContext>, JCClassDecl>> desugar(Queue<Env<AttrContext>> envs) {
|
||||||
ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = new ListBuffer<>();
|
ListBuffer<Pair<Env<AttrContext>, JCClassDecl>> results = new ListBuffer<>();
|
||||||
|
|
|
@ -409,7 +409,7 @@ public class DocCommentParser {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read Java class name, possibly followed by member
|
* 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.
|
* unmatched }. It is an error if the beginning of the next tag is detected.
|
||||||
*/
|
*/
|
||||||
// TODO: boolean allowMember should be enum FORBID, ALLOW, REQUIRE
|
// TODO: boolean allowMember should be enum FORBID, ALLOW, REQUIRE
|
||||||
|
|
|
@ -1411,7 +1411,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritDoc}
|
||||||
*
|
*
|
||||||
* Command line options suitable for presenting to annotation
|
* Command line options suitable for presenting to annotation
|
||||||
* processors.
|
* processors.
|
||||||
|
|
|
@ -168,7 +168,7 @@ public class JavacRoundEnvironment implements RoundEnvironment {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritdoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@DefinedBy(Api.ANNOTATION_PROCESSING)
|
@DefinedBy(Api.ANNOTATION_PROCESSING)
|
||||||
public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) {
|
public Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> a) {
|
||||||
|
|
|
@ -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 {
|
public static class JCTypeIntersection extends JCExpression implements IntersectionTypeTree {
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,7 @@ import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticType.*;
|
||||||
* Those implementations are specifically targeting JCDiagnostic objects.
|
* Those implementations are specifically targeting JCDiagnostic objects.
|
||||||
* <li> Provides basic support for i18n and a method for executing all locale-dependent conversions
|
* <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.
|
* <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.
|
* <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.
|
* If you write code that depends on this, you do so at your own risk.
|
||||||
|
|
|
@ -44,7 +44,7 @@ import java.util.*;
|
||||||
* instance method that is overridden in extended components. A base
|
* instance method that is overridden in extended components. A base
|
||||||
* phase supporting extension would look something like this:
|
* phase supporting extension would look something like this:
|
||||||
*
|
*
|
||||||
* <p><pre>{@code
|
* <pre>{@code
|
||||||
* public class Phase {
|
* public class Phase {
|
||||||
* protected static final Context.Key<Phase> phaseKey =
|
* protected static final Context.Key<Phase> phaseKey =
|
||||||
* new Context.Key<Phase>();
|
* new Context.Key<Phase>();
|
||||||
|
@ -70,7 +70,7 @@ import java.util.*;
|
||||||
* and this must be done before any reference to the phase is accessed
|
* and this must be done before any reference to the phase is accessed
|
||||||
* using Phase.instance(). An extended phase might be declared thus:
|
* using Phase.instance(). An extended phase might be declared thus:
|
||||||
*
|
*
|
||||||
* <p><pre>{@code
|
* <pre>{@code
|
||||||
* public class NewPhase extends Phase {
|
* public class NewPhase extends Phase {
|
||||||
* protected NewPhase(Context context) {
|
* protected NewPhase(Context context) {
|
||||||
* super(context);
|
* super(context);
|
||||||
|
@ -87,7 +87,7 @@ import java.util.*;
|
||||||
*
|
*
|
||||||
* <p>And is registered early in the extended compiler like this
|
* <p>And is registered early in the extended compiler like this
|
||||||
*
|
*
|
||||||
* <p><pre>
|
* <pre>
|
||||||
* NewPhase.preRegister(context);
|
* NewPhase.preRegister(context);
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
|
|
|
@ -28,7 +28,7 @@ package com.sun.tools.javac.util;
|
||||||
/**
|
/**
|
||||||
* A hash table that maps Object to int.
|
* 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.
|
* maps. This is done to avoid unnecessary object allocation in the image set.
|
||||||
*
|
*
|
||||||
* @author Charles Turner
|
* @author Charles Turner
|
||||||
|
@ -43,7 +43,7 @@ public class IntHashTable {
|
||||||
private final static Object DELETED = new Object();
|
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.
|
* 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.
|
* @param capacity The number of default mappings in this hash table.
|
||||||
*/
|
*/
|
||||||
public IntHashTable(int capacity) {
|
public IntHashTable(int capacity) {
|
||||||
|
|
|
@ -187,7 +187,7 @@ public class BuildState {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify that the setModules method above did the right thing when
|
* 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) {
|
public void checkInternalState(String msg, boolean linkedOnly, Map<String,Source> srcs) {
|
||||||
boolean baad = false;
|
boolean baad = false;
|
||||||
|
|
|
@ -131,7 +131,7 @@ public class Util {
|
||||||
* do settings = cleanOptions("--server:",Util.set("-portfile"),settings);
|
* do settings = cleanOptions("--server:",Util.set("-portfile"),settings);
|
||||||
* now settings equals "--server:portfile=bar"
|
* 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.
|
* @param s The option settings string.
|
||||||
*/
|
*/
|
||||||
public static String cleanSubOptions(Set<String> allowedSubOptions, String s) {
|
public static String cleanSubOptions(Set<String> allowedSubOptions, String s) {
|
||||||
|
|
|
@ -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.
|
* 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
|
@Override
|
||||||
public SysInfo getSysInfo() {
|
public SysInfo getSysInfo() {
|
||||||
|
|
|
@ -161,7 +161,7 @@ public class Options {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a map which maps suffixes to transformers (for example
|
* Get a map which maps suffixes to transformers (for example
|
||||||
* ".java" -> CompileJavaPackages)
|
* ".java" {@literal ->} CompileJavaPackages)
|
||||||
*/
|
*/
|
||||||
public Map<String, Transformer> getTranslationRules() {
|
public Map<String, Transformer> getTranslationRules() {
|
||||||
return trRules;
|
return trRules;
|
||||||
|
|
|
@ -78,7 +78,7 @@ public class PortFile {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new 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 {
|
public PortFile(String fn) throws FileNotFoundException {
|
||||||
filename = fn;
|
filename = fn;
|
||||||
|
|
|
@ -58,7 +58,6 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
|
||||||
*
|
*
|
||||||
* @param member the member to write type parameters for.
|
* @param member the member to write type parameters for.
|
||||||
* @param htmltree the content tree to which the parameters will be added.
|
* @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) {
|
protected void addTypeParameters(ExecutableMemberDoc member, Content htmltree) {
|
||||||
Content typeParameters = getTypeParameters(member);
|
Content typeParameters = getTypeParameters(member);
|
||||||
|
|
|
@ -289,9 +289,11 @@ public class ConfigurationImpl extends Configuration {
|
||||||
} else if (opt.equals("-html5")) {
|
} else if (opt.equals("-html5")) {
|
||||||
htmlVersion = HtmlVersion.HTML5;
|
htmlVersion = HtmlVersion.HTML5;
|
||||||
} else if (opt.equals("-xdoclint")) {
|
} else if (opt.equals("-xdoclint")) {
|
||||||
doclintOpts.add(null);
|
doclintOpts.add(DocLint.XMSGS_OPTION);
|
||||||
} else if (opt.startsWith("-xdoclint:")) {
|
} 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) {
|
if (root.specifiedClasses().length > 0) {
|
||||||
|
@ -325,7 +327,6 @@ public class ConfigurationImpl extends Configuration {
|
||||||
* The options arrive as case-sensitive strings. For options that
|
* The options arrive as case-sensitive strings. For options that
|
||||||
* are not case-sensitive, use toLowerCase() on the option string
|
* are not case-sensitive, use toLowerCase() on the option string
|
||||||
* before comparing it.
|
* before comparing it.
|
||||||
* </blockquote>
|
|
||||||
*
|
*
|
||||||
* @return number of arguments + 1 for a option. Zero return means
|
* @return number of arguments + 1 for a option. Zero return means
|
||||||
* option not known. Negative value means error occurred.
|
* option not known. Negative value means error occurred.
|
||||||
|
@ -349,7 +350,8 @@ public class ConfigurationImpl extends Configuration {
|
||||||
option.equals("-html4") ||
|
option.equals("-html4") ||
|
||||||
option.equals("-html5") ||
|
option.equals("-html5") ||
|
||||||
option.equals("-xdoclint") ||
|
option.equals("-xdoclint") ||
|
||||||
option.startsWith("-xdoclint:")) {
|
option.startsWith("-xdoclint:") ||
|
||||||
|
option.startsWith("-xdoclint/package:")) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (option.equals("-help")) {
|
} else if (option.equals("-help")) {
|
||||||
// Uugh: first, this should not be hidden inside optionLength,
|
// 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"));
|
reporter.printError(getText("doclet.Option_doclint_invalid_arg"));
|
||||||
return false;
|
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;
|
return true;
|
||||||
|
|
|
@ -247,7 +247,7 @@ public class LinkInfoImpl extends LinkInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inherotDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
protected Content newContent() {
|
protected Content newContent() {
|
||||||
return new ContentBuilder();
|
return new ContentBuilder();
|
||||||
|
|
|
@ -267,7 +267,7 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter {
|
||||||
* navigation bar, and then the title (from the"-title"
|
* navigation bar, and then the title (from the"-title"
|
||||||
* option), at the top of page.
|
* 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) {
|
protected void addNavigationBarHeader(Content body) {
|
||||||
Content htmlTree = (configuration.allowTag(HtmlTag.HEADER))
|
Content htmlTree = (configuration.allowTag(HtmlTag.HEADER))
|
||||||
|
|
|
@ -231,4 +231,10 @@ doclet.X.usage=Provided by standard doclet:\n\
|
||||||
\ -Xdoclint Enable recommended checks for problems in javadoc comments\n\
|
\ -Xdoclint Enable recommended checks for problems in javadoc comments\n\
|
||||||
\ -Xdoclint:(all|none|[-]<group>) \n\
|
\ -Xdoclint:(all|none|[-]<group>) \n\
|
||||||
\ Enable or disable specific checks for problems in javadoc comments,\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
|
||||||
|
|
|
@ -13,6 +13,7 @@ doclet.Option_conflict=Option {0} conflicts with {1}
|
||||||
doclet.Option_reuse=Option reused: {0}
|
doclet.Option_reuse=Option reused: {0}
|
||||||
doclet.Option_doclint_no_qualifiers=Access qualifiers not permitted for -Xdoclint arguments
|
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_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\
|
doclet.exception_encountered= {0} encountered \n\
|
||||||
\twhile attempting to create file: {1}
|
\twhile attempting to create file: {1}
|
||||||
doclet.perform_copy_exception_encountered= {0} encountered while \n\
|
doclet.perform_copy_exception_encountered= {0} encountered while \n\
|
||||||
|
|
|
@ -58,7 +58,7 @@ public abstract class TagletWriter {
|
||||||
public abstract Content getOutputInstance();
|
public abstract Content getOutputInstance();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the output for a {@code...} tag.
|
* Return the output for a {@code {@code ...}} tag.
|
||||||
*
|
*
|
||||||
* @param tag the tag.
|
* @param tag the tag.
|
||||||
* @return the output of the taglet.
|
* @return the output of the taglet.
|
||||||
|
@ -80,7 +80,7 @@ public abstract class TagletWriter {
|
||||||
protected abstract Content deprecatedTagOutput(Doc doc);
|
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.
|
* @param tag the tag.
|
||||||
* @return the output of the taglet.
|
* @return the output of the taglet.
|
||||||
|
|
|
@ -100,9 +100,11 @@ public class AnnotationDescImpl implements AnnotationDesc {
|
||||||
/**
|
/**
|
||||||
* Returns a string representation of this annotation.
|
* Returns a string representation of this annotation.
|
||||||
* String is of one of the forms:
|
* String is of one of the forms:
|
||||||
* @com.example.foo(name1=val1, name2=val2)
|
* <pre>
|
||||||
* @com.example.foo(val)
|
* {@code @com.example.foo(name1=val1, name2=val2)}
|
||||||
* @com.example.foo
|
* {@code @com.example.foo(val)}
|
||||||
|
* {@code @com.example.foo}
|
||||||
|
* </pre>
|
||||||
* Omit parens for marker annotations, and omit "value=" when allowed.
|
* Omit parens for marker annotations, and omit "value=" when allowed.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1278,7 +1278,7 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
|
||||||
* each Serializable field defined by an <code>ObjectStreamField</code>
|
* each Serializable field defined by an <code>ObjectStreamField</code>
|
||||||
* array component of <code>serialPersistentField</code>.
|
* array component of <code>serialPersistentField</code>.
|
||||||
*
|
*
|
||||||
* @returns an array of <code>FieldDoc</code> for the Serializable fields
|
* @return an array of {@code FieldDoc} for the Serializable fields
|
||||||
* of this class.
|
* of this class.
|
||||||
*
|
*
|
||||||
* @see #definesSerializableFields()
|
* @see #definesSerializableFields()
|
||||||
|
|
|
@ -31,6 +31,7 @@ import java.util.*;
|
||||||
import javax.tools.JavaFileManager;
|
import javax.tools.JavaFileManager;
|
||||||
|
|
||||||
import com.sun.javadoc.*;
|
import com.sun.javadoc.*;
|
||||||
|
import com.sun.source.tree.CompilationUnitTree;
|
||||||
import com.sun.source.util.JavacTask;
|
import com.sun.source.util.JavacTask;
|
||||||
import com.sun.source.util.TreePath;
|
import com.sun.source.util.TreePath;
|
||||||
import com.sun.tools.doclint.DocLint;
|
import com.sun.tools.doclint.DocLint;
|
||||||
|
@ -816,16 +817,19 @@ public class DocEnv {
|
||||||
|
|
||||||
void initDoclint(Collection<String> opts, Collection<String> customTagNames, String htmlVersion) {
|
void initDoclint(Collection<String> opts, Collection<String> customTagNames, String htmlVersion) {
|
||||||
ArrayList<String> doclintOpts = new ArrayList<>();
|
ArrayList<String> doclintOpts = new ArrayList<>();
|
||||||
|
boolean msgOptionSeen = false;
|
||||||
|
|
||||||
for (String opt : opts) {
|
for (String opt : opts) {
|
||||||
doclintOpts.add(opt == null ? DocLint.XMSGS_OPTION : DocLint.XMSGS_CUSTOM_PREFIX + opt);
|
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);
|
doclintOpts.add(DocLint.XMSGS_OPTION);
|
||||||
} else if (doclintOpts.size() == 1
|
|
||||||
&& doclintOpts.get(0).equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String sep = "";
|
String sep = "";
|
||||||
|
@ -848,4 +852,10 @@ public class DocEnv {
|
||||||
boolean showTagMessages() {
|
boolean showTagMessages() {
|
||||||
return (doclint == null);
|
return (doclint == null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Map<CompilationUnitTree, Boolean> shouldCheck = new HashMap<>();
|
||||||
|
|
||||||
|
boolean shouldCheck(CompilationUnitTree unit) {
|
||||||
|
return shouldCheck.computeIfAbsent(unit, doclint :: shouldCheck);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,6 +129,7 @@ public abstract class DocImpl implements Doc, Comparable<Object> {
|
||||||
String d = documentation();
|
String d = documentation();
|
||||||
if (env.doclint != null
|
if (env.doclint != null
|
||||||
&& treePath != null
|
&& treePath != null
|
||||||
|
&& env.shouldCheck(treePath.getCompilationUnit())
|
||||||
&& d.equals(getCommentText(treePath))) {
|
&& d.equals(getCommentText(treePath))) {
|
||||||
env.doclint.scan(treePath);
|
env.doclint.scan(treePath);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ import static com.sun.tools.classfile.ConstantPool.*;
|
||||||
/**
|
/**
|
||||||
* A utility class to find where in a ClassFile references
|
* A utility class to find where in a ClassFile references
|
||||||
* a {@link CONSTANT_Methodref_info method},
|
* 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}.
|
* or a {@link CONSTANT_Fieldref_info field}.
|
||||||
*/
|
*/
|
||||||
public final class ReferenceFinder {
|
public final class ReferenceFinder {
|
||||||
|
|
|
@ -97,23 +97,32 @@ class PlatformClassPath {
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ImageHelper {
|
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 {
|
static ImageHelper getInstance(Path mpath) throws IOException {
|
||||||
if (mpath != null) {
|
if (mpath != null) {
|
||||||
return new ImageHelper(mpath);
|
return new ImageHelper(mpath);
|
||||||
}
|
}
|
||||||
Path home = Paths.get(System.getProperty("java.home"));
|
|
||||||
Path mlib = home.resolve("lib").resolve("modules");
|
if (isJrtAvailable()) {
|
||||||
if (Files.isDirectory(mlib)) {
|
// jrt file system
|
||||||
// jimage
|
|
||||||
FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
|
FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/"));
|
||||||
return new ImageHelper(fs, fs.getPath("/"));
|
return new ImageHelper(fs, fs.getPath("/modules"));
|
||||||
} else {
|
} else {
|
||||||
// exploded modules
|
// exploded modules
|
||||||
mlib = home.resolve("modules");
|
String home = System.getProperty("java.home");
|
||||||
if (!Files.isDirectory(mlib)) {
|
Path exploded = Paths.get(home, "modules");
|
||||||
|
if (!Files.isDirectory(exploded)) {
|
||||||
throw new InternalError(home + " not a modular image");
|
throw new InternalError(home + " not a modular image");
|
||||||
}
|
}
|
||||||
return new ImageHelper(mlib);
|
return new ImageHelper(exploded);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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.
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8044411
|
||||||
|
* @summary Tests the RuntimeVisibleAnnotations/RuntimeInvisibleAnnotations attribute.
|
||||||
|
* Checks that the attribute is generated for bridge method.
|
||||||
|
* @library /tools/lib /tools/javac/lib ../lib
|
||||||
|
* @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
|
||||||
|
* @build TestCase ClassType TestAnnotationInfo
|
||||||
|
* @build RuntimeAnnotationsForGenericMethodTest AnnotationsTestBase RuntimeAnnotationsTestBase
|
||||||
|
* @run main RuntimeAnnotationsForGenericMethodTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RuntimeAnnotationsGenericMethodTest is a test which check that
|
||||||
|
* RuntimeVisibleAnnotationsAttribute and RuntimeInvisibleAnnotationsAttribute
|
||||||
|
* are generated for both generic and appropriate bridge methods.
|
||||||
|
* All possible combinations of retention policies are tested.
|
||||||
|
*
|
||||||
|
* The test generates class which looks as follows:
|
||||||
|
*
|
||||||
|
* public class Test extends java.util.ArrayList<Integer> {
|
||||||
|
* here some annotations
|
||||||
|
* public boolean add(java.lang.Integer) {
|
||||||
|
* return false;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Thereafter, various of combinations of annotations are applied
|
||||||
|
* to the add, the source is compiled and the generated byte code is checked.
|
||||||
|
*
|
||||||
|
* See README.txt for more information.
|
||||||
|
*/
|
||||||
|
public class RuntimeAnnotationsForGenericMethodTest extends RuntimeAnnotationsTestBase {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @bug 8044411
|
||||||
|
* @summary Tests the RuntimeParameterVisibleAnnotations/RuntimeParameterInvisibleAnnotations attribute.
|
||||||
|
* Checks that the attribute is generated for bridge method.
|
||||||
|
* @library /tools/lib /tools/javac/lib ../lib
|
||||||
|
* @build WorkAnnotations TestBase TestResult InMemoryFileManager ToolBox
|
||||||
|
* @build TestCase ClassType TestAnnotationInfo
|
||||||
|
* @build RuntimeParameterAnnotationsForGenericMethodTest AnnotationsTestBase RuntimeParameterAnnotationsTestBase
|
||||||
|
* @run main RuntimeParameterAnnotationsForGenericMethodTest
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RuntimeParameterAnnotationsGenericMethodTest is a test which check that
|
||||||
|
* RuntimeVisibleParameterAnnotationsAttribute and
|
||||||
|
* RuntimeInvisibleParameterAnnotationsAttribute are generated for both
|
||||||
|
* generic and appropriate bridge methods.
|
||||||
|
* All possible combinations of retention policies are tested.
|
||||||
|
*
|
||||||
|
* The test generates class which looks as follows:
|
||||||
|
*
|
||||||
|
* public class Test extends java.util.ArrayList<Integer> {
|
||||||
|
*
|
||||||
|
* public boolean add(here some annotations java.lang.Integer) {
|
||||||
|
* return false;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Thereafter, various of combinations of annotations are applied
|
||||||
|
* to the add, the source is compiled and the generated byte code is checked.
|
||||||
|
*
|
||||||
|
* See README.txt for more information.
|
||||||
|
*/
|
||||||
|
public class RuntimeParameterAnnotationsForGenericMethodTest extends RuntimeParameterAnnotationsTestBase {
|
||||||
|
@Override
|
||||||
|
public List<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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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("Test$1Local")}
|
||||||
|
* returns local inner class of class {@code Test}.
|
||||||
|
*
|
||||||
|
* @param classSignature a class signature
|
||||||
|
* @return {@code TestClassInfo} by class signature
|
||||||
|
*/
|
||||||
|
public TestClassInfo getTestClassInfo(String classSignature) {
|
||||||
|
String[] cs = classSignature.split("\\$");
|
||||||
|
if (cs.length > 0 && classes.containsKey(cs[0])) {
|
||||||
|
// check signature corresponds to top level class
|
||||||
|
if (cs.length == 1) {
|
||||||
|
return classes.get(cs[0]);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("Cannot find class : " + classSignature);
|
||||||
|
}
|
||||||
|
TestClassInfo current = classes.get(cs[0]);
|
||||||
|
// find class info in the inner classes
|
||||||
|
for (int i = 1; i < cs.length; ++i) {
|
||||||
|
Map<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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 "";
|
||||||
|
}
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -21,10 +21,9 @@
|
||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.*;
|
||||||
import java.io.FileInputStream;
|
import java.nio.file.Files;
|
||||||
import java.io.IOException;
|
import java.nio.file.Path;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
@ -210,6 +209,12 @@ public class TestBase {
|
||||||
assertTrue(found.containsAll(expected), message + " : " + copy);
|
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() {
|
public File getSourceDir() {
|
||||||
return new File(System.getProperty("test.src", "."));
|
return new File(System.getProperty("test.src", "."));
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,18 +24,16 @@
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class accumulates test results. Test results can be checked with method @{code checkStatus}.
|
* This class accumulates test results. Test results can be checked with method @{code checkStatus}.
|
||||||
*/
|
*/
|
||||||
public class TestResult extends TestBase {
|
public class TestResult extends TestBase {
|
||||||
|
|
||||||
private final List<Info> testCases;
|
private final List<Info> testCasesInfo;
|
||||||
|
|
||||||
public TestResult() {
|
public TestResult() {
|
||||||
testCases = new ArrayList<>();
|
testCasesInfo = new ArrayList<>();
|
||||||
testCases.add(new Info("Global test info"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,13 +42,8 @@ public class TestResult extends TestBase {
|
||||||
* @param info the information about test case
|
* @param info the information about test case
|
||||||
*/
|
*/
|
||||||
public void addTestCase(String info) {
|
public void addTestCase(String info) {
|
||||||
testCases.add(new Info(info));
|
System.err.println("Test case: " + info);
|
||||||
}
|
testCasesInfo.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"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean checkEquals(Object actual, Object expected, String message) {
|
public boolean checkEquals(Object actual, Object expected, String message) {
|
||||||
|
@ -96,14 +89,17 @@ public class TestResult extends TestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addFailure(Throwable th) {
|
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() {
|
private Info getLastTestCase() {
|
||||||
if (testCases.size() == 1) {
|
if (testCasesInfo.isEmpty()) {
|
||||||
throw new IllegalStateException("Test case should be created");
|
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
|
* or an exception occurs
|
||||||
*/
|
*/
|
||||||
public void checkStatus() throws TestFailedException {
|
public void checkStatus() throws TestFailedException {
|
||||||
if (testCases.stream().anyMatch(Info::isFailed)) {
|
int passed = 0;
|
||||||
echo(errorMessage());
|
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");
|
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 String info;
|
||||||
private final List<String> asserts;
|
private final StringWriter writer;
|
||||||
private final List<Throwable> errors;
|
private boolean isFailed;
|
||||||
|
|
||||||
private Info(String info) {
|
private Info(String info) {
|
||||||
this.info = info;
|
this.info = info;
|
||||||
asserts = new ArrayList<>();
|
writer = new StringWriter();
|
||||||
errors = new ArrayList<>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String info() {
|
public String info() {
|
||||||
|
@ -137,34 +152,25 @@ public class TestResult extends TestBase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFailed() {
|
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) {
|
public void addFailure(Throwable th) {
|
||||||
errors.add(th);
|
isFailed = true;
|
||||||
printf("[ERROR] : %s\n", getStackTrace(th));
|
printf("[ERROR] : %s\n", getStackTrace(th));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAssert(String e) {
|
public void addAssert(String e) {
|
||||||
asserts.add(e);
|
isFailed = true;
|
||||||
printf("[ASSERT] : %s\n", e);
|
printf("[ASSERT] : %s\n", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getMessage() {
|
public String getMessage() {
|
||||||
return (asserts.size() > 0 ? getAssertMessages(asserts) + "\n" : "")
|
return writer.toString();
|
||||||
+ 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"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStackTrace(Throwable throwable) {
|
public String getStackTrace(Throwable throwable) {
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @test
|
||||||
* @bug 8004834 8007610
|
* @bug 8004834 8007610 8129909
|
||||||
* @summary Add doclint support into javadoc
|
* @summary Add doclint support into javadoc
|
||||||
* @modules jdk.compiler/com.sun.tools.javac.main
|
* @modules jdk.compiler/com.sun.tools.javac.main
|
||||||
*/
|
*/
|
||||||
|
@ -59,7 +59,7 @@ public class DocLintTest {
|
||||||
|
|
||||||
DocumentationTool javadoc;
|
DocumentationTool javadoc;
|
||||||
StandardJavaFileManager fm;
|
StandardJavaFileManager fm;
|
||||||
JavaFileObject file;
|
Iterable<? extends JavaFileObject> files;
|
||||||
|
|
||||||
final String code =
|
final String code =
|
||||||
/* 01 */ "/** Class comment. */\n" +
|
/* 01 */ "/** Class comment. */\n" +
|
||||||
|
@ -77,6 +77,20 @@ public class DocLintTest {
|
||||||
/* 13 */ " public int emptyReturn() { return 0; }\n" +
|
/* 13 */ " public int emptyReturn() { return 0; }\n" +
|
||||||
/* 14 */ "}\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 final String rawDiags = "-XDrawDiagnostics";
|
||||||
|
|
||||||
private enum Message {
|
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_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_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
|
// doclint messages when -XDrawDiagnostics is not in effect
|
||||||
DL_ERR9A(ERROR, "Test.java:9: error: reference not found"),
|
DL_ERR9A(ERROR, "Test.java:9: error: reference not found"),
|
||||||
DL_WRN12A(WARNING, "Test.java:12: warning: no description for @return"),
|
DL_WRN12A(WARNING, "Test.java:12: warning: no description for @return"),
|
||||||
|
@ -95,7 +112,8 @@ public class DocLintTest {
|
||||||
|
|
||||||
// javadoc messages for bad options
|
// javadoc messages for bad options
|
||||||
OPT_BADARG(ERROR, "javadoc: error - Invalid argument for -Xdoclint option"),
|
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 Diagnostic.Kind kind;
|
||||||
final String text;
|
final String text;
|
||||||
|
@ -124,12 +142,7 @@ public class DocLintTest {
|
||||||
fm = javadoc.getStandardFileManager(null, null, null);
|
fm = javadoc.getStandardFileManager(null, null, null);
|
||||||
try {
|
try {
|
||||||
fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(".")));
|
fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(new File(".")));
|
||||||
file = new SimpleJavaFileObject(URI.create("Test.java"), JavaFileObject.Kind.SOURCE) {
|
files = Arrays.asList(new TestJFO("Test.java", code));
|
||||||
@Override
|
|
||||||
public CharSequence getCharContent(boolean ignoreEncoding) {
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
test(Collections.<String>emptyList(),
|
test(Collections.<String>emptyList(),
|
||||||
Main.Result.ERROR,
|
Main.Result.ERROR,
|
||||||
|
@ -175,6 +188,21 @@ public class DocLintTest {
|
||||||
Main.Result.ERROR,
|
Main.Result.ERROR,
|
||||||
EnumSet.of(Message.OPT_BADARG));
|
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)
|
if (errors > 0)
|
||||||
throw new Exception(errors + " errors occurred");
|
throw new Exception(errors + " errors occurred");
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -186,7 +214,6 @@ public class DocLintTest {
|
||||||
System.err.println("test: " + opts);
|
System.err.println("test: " + opts);
|
||||||
StringWriter sw = new StringWriter();
|
StringWriter sw = new StringWriter();
|
||||||
PrintWriter pw = new PrintWriter(sw);
|
PrintWriter pw = new PrintWriter(sw);
|
||||||
List<JavaFileObject> files = Arrays.asList(file);
|
|
||||||
try {
|
try {
|
||||||
DocumentationTask t = javadoc.getTask(pw, fm, null, null, opts, files);
|
DocumentationTask t = javadoc.getTask(pw, fm, null, null, opts, files);
|
||||||
boolean ok = t.call();
|
boolean ok = t.call();
|
||||||
|
@ -257,4 +284,19 @@ public class DocLintTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
int errors;
|
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;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -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.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* 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>.
|
* 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/[^/]+/)?(.*)");
|
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) {
|
private String guessPath(FileObject fo) {
|
||||||
URI u = fo.toUri();
|
URI u = fo.toUri();
|
||||||
|
@ -1621,6 +1626,13 @@ public class ToolBox {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case "file": {
|
||||||
|
Matcher m = fileEntry.matcher(u.getSchemeSpecificPart());
|
||||||
|
if (m.matches()) {
|
||||||
|
return m.group(2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException(fo.getName() + "--" + fo.toUri());
|
throw new IllegalArgumentException(fo.getName() + "--" + fo.toUri());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue