8006775: JSR 308: Compiler changes in JDK8

Co-authored-by: Werner Dietl <wmdietl@cs.washington.edu>
Co-authored-by: Matt Papi <mpapi@csail.mit.edu>
Co-authored-by: Mahmood Ali <mahmood@notnoop.com>
Reviewed-by: jjg
This commit is contained in:
Michael Ernst 2013-01-23 13:27:24 -08:00 committed by Jonathan Gibbons
parent 5b1a78dc92
commit 659a96edf9
317 changed files with 17126 additions and 794 deletions

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2003, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.javadoc;
/**
* Represents an annotated type.
* For example:
* <pre>
* {@code @NonNull String}
* {@code @Positive int}
* </pre>
*
* @author Mahmood Ali
* @since 1.8
*/
public interface AnnotatedType extends Type {
AnnotationDesc[] annotations();
Type underlyingType();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2013, 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
@ -87,6 +87,15 @@ public interface ExecutableMemberDoc extends MemberDoc {
*/
Parameter[] parameters();
/**
* Get the receiver annotations of this executable element.
* Return an empty array if there are none.
*
* @return the receiver annotations of this executable element.
* @since 1.8
*/
AnnotationDesc[] receiverAnnotations();
/**
* Return the throws tags in this method.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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
@ -141,6 +141,16 @@ public interface Type {
*/
WildcardType asWildcardType();
/**
* Returns this type as a <code>AnnotatedType</code> if it represents
* an annotated type.
*
* @return a <code>AnnotatedType</code> if the type if an annotated type,
* or null if it is not
* @since 1.8
*/
AnnotatedType asAnnotatedType();
/**
* Return this type as an <code>AnnotationTypeDoc</code> if it represents
* an annotation type. Array dimensions are ignored.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -55,4 +55,11 @@ public interface TypeVariable extends Type {
* which this type variable is declared.
*/
ProgramElementDoc owner();
/**
* Get the annotations of this program element.
* Return an empty array if there are none.
*/
public AnnotationDesc[] annotations();
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (c) 2008, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.source.tree;
import java.util.List;
/**
* A tree node for an annotated type
*
* For example:
* <pre>
* {@code @}<em>annotationType String</em>
* {@code @}<em>annotationType</em> ( <em>arguments</em> ) <em>Date</em>
* </pre>
*
* @see "JSR 308: Annotations on Java Types"
*
* @author Mahmood Ali
* @since 1.8
*/
public interface AnnotatedTypeTree extends ExpressionTree {
List<? extends AnnotationTree> getAnnotations();
ExpressionTree getUnderlyingType();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -52,6 +52,7 @@ public interface MethodTree extends Tree {
Tree getReturnType();
List<? extends TypeParameterTree> getTypeParameters();
List<? extends VariableTree> getParameters();
VariableTree getReceiverParameter();
List<? extends ExpressionTree> getThrows();
BlockTree getBody();
Tree getDefaultValue(); // for annotation types

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -46,11 +46,20 @@ public interface Tree {
*/
public enum Kind {
ANNOTATED_TYPE(AnnotatedTypeTree.class),
/**
* Used for instances of {@link AnnotationTree}.
* Used for instances of {@link AnnotationTree}
* representing declaration annotations.
*/
ANNOTATION(AnnotationTree.class),
/**
* Used for instances of {@link AnnotationTree}
* representing type annotations.
*/
TYPE_ANNOTATION(AnnotationTree.class),
/**
* Used for instances of {@link ArrayAccessTree}.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -57,6 +57,7 @@ package com.sun.source.tree;
* @since 1.6
*/
public interface TreeVisitor<R,P> {
R visitAnnotatedType(AnnotatedTypeTree node, P p);
R visitAnnotation(AnnotationTree node, P p);
R visitMethodInvocation(MethodInvocationTree node, P p);
R visitAssert(AssertTree node, P p);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -47,4 +47,5 @@ import javax.lang.model.element.Name;
public interface TypeParameterTree extends Tree {
Name getName();
List<? extends Tree> getBounds();
List<? extends AnnotationTree> getAnnotations();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -260,6 +260,10 @@ public class SimpleTreeVisitor <R,P> implements TreeVisitor<R,P> {
return defaultAction(node, p);
}
public R visitAnnotatedType(AnnotatedTypeTree node, P p) {
return defaultAction(node, p);
}
public R visitErroneous(ErroneousTree node, P p) {
return defaultAction(node, p);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -60,7 +60,7 @@ public final class TaskEvent
**/
GENERATE,
/**
* For events relating to overall annotaion processing.
* For events relating to overall annotation processing.
**/
ANNOTATION_PROCESSING,
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -138,6 +138,7 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
r = scanAndReduce(node.getReturnType(), p, r);
r = scanAndReduce(node.getTypeParameters(), p, r);
r = scanAndReduce(node.getParameters(), p, r);
r = scanAndReduce(node.getReceiverParameter(), p, r);
r = scanAndReduce(node.getThrows(), p, r);
r = scanAndReduce(node.getBody(), p, r);
r = scanAndReduce(node.getDefaultValue(), p, r);
@ -376,7 +377,8 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
}
public R visitTypeParameter(TypeParameterTree node, P p) {
R r = scan(node.getBounds(), p);
R r = scan(node.getAnnotations(), p);
r = scanAndReduce(node.getBounds(), p, r);
return r;
}
@ -394,6 +396,12 @@ public class TreeScanner<R,P> implements TreeVisitor<R,P> {
return r;
}
public R visitAnnotatedType(AnnotatedTypeTree node, P p) {
R r = scan(node.getAnnotations(), p);
r = scanAndReduce(node.getUnderlyingType(), p, r);
return r;
}
public R visitOther(Tree node, P p) {
return null;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2013, 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
@ -56,6 +56,8 @@ public abstract class Attribute {
public static final String RuntimeInvisibleAnnotations = "RuntimeInvisibleAnnotations";
public static final String RuntimeVisibleParameterAnnotations = "RuntimeVisibleParameterAnnotations";
public static final String RuntimeInvisibleParameterAnnotations = "RuntimeInvisibleParameterAnnotations";
public static final String RuntimeVisibleTypeAnnotations = "RuntimeVisibleTypeAnnotations";
public static final String RuntimeInvisibleTypeAnnotations = "RuntimeInvisibleTypeAnnotations";
public static final String Signature = "Signature";
public static final String SourceDebugExtension = "SourceDebugExtension";
public static final String SourceFile = "SourceFile";
@ -120,6 +122,8 @@ public abstract class Attribute {
standardAttributes.put(RuntimeInvisibleParameterAnnotations, RuntimeInvisibleParameterAnnotations_attribute.class);
standardAttributes.put(RuntimeVisibleAnnotations, RuntimeVisibleAnnotations_attribute.class);
standardAttributes.put(RuntimeVisibleParameterAnnotations, RuntimeVisibleParameterAnnotations_attribute.class);
standardAttributes.put(RuntimeVisibleTypeAnnotations, RuntimeVisibleTypeAnnotations_attribute.class);
standardAttributes.put(RuntimeInvisibleTypeAnnotations, RuntimeInvisibleTypeAnnotations_attribute.class);
standardAttributes.put(Signature, Signature_attribute.class);
standardAttributes.put(SourceID, SourceID_attribute.class);
}
@ -178,6 +182,8 @@ public abstract class Attribute {
R visitRuntimeInvisibleAnnotations(RuntimeInvisibleAnnotations_attribute attr, P p);
R visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, P p);
R visitRuntimeInvisibleParameterAnnotations(RuntimeInvisibleParameterAnnotations_attribute attr, P p);
R visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, P p);
R visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, P p);
R visitSignature(Signature_attribute attr, P p);
R visitSourceDebugExtension(SourceDebugExtension_attribute attr, P p);
R visitSourceFile(SourceFile_attribute attr, P p);

View File

@ -1,6 +1,6 @@
/*
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2013, 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
@ -498,6 +498,16 @@ public class ClassWriter {
return null;
}
public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
annotationWriter.write(attr.annotations, out);
return null;
}
public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, ClassOutputStream out) {
annotationWriter.write(attr.annotations, out);
return null;
}
public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, ClassOutputStream out) {
out.writeByte(attr.parameter_annotations.length);
for (Annotation[] annos: attr.parameter_annotations)
@ -657,6 +667,12 @@ public class ClassWriter {
write(anno, out);
}
public void write(TypeAnnotation[] annos, ClassOutputStream out) {
out.writeShort(annos.length);
for (TypeAnnotation anno: annos)
write(anno, out);
}
public void write(Annotation anno, ClassOutputStream out) {
out.writeShort(anno.type_index);
out.writeShort(anno.element_value_pairs.length);
@ -664,6 +680,11 @@ public class ClassWriter {
write(p, out);
}
public void write(TypeAnnotation anno, ClassOutputStream out) {
write(anno.position, out);
write(anno.annotation, out);
}
public void write(element_value_pair pair, ClassOutputStream out) {
out.writeShort(pair.element_name_index);
write(pair.value, out);
@ -702,5 +723,89 @@ public class ClassWriter {
return null;
}
// TODO: Move this to TypeAnnotation to be closer with similar logic?
private void write(TypeAnnotation.Position p, ClassOutputStream out) {
out.writeByte(p.type.targetTypeValue());
switch (p.type) {
// type cast
case CAST:
// instanceof
case INSTANCEOF:
// new expression
case NEW:
out.writeShort(p.offset);
break;
// local variable
case LOCAL_VARIABLE:
// resource variable
case RESOURCE_VARIABLE:
int table_length = p.lvarOffset.length;
out.writeShort(table_length);
for (int i = 0; i < table_length; ++i) {
out.writeShort(1); // for table length
out.writeShort(p.lvarOffset[i]);
out.writeShort(p.lvarLength[i]);
out.writeShort(p.lvarIndex[i]);
}
break;
// exception parameter
case EXCEPTION_PARAMETER:
out.writeByte(p.exception_index);
break;
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameters
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
out.writeByte(p.parameter_index);
break;
// type parameters bounds
case CLASS_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND:
out.writeByte(p.parameter_index);
out.writeByte(p.bound_index);
break;
// class extends or implements clause
case CLASS_EXTENDS:
out.writeByte(p.type_index);
break;
// throws
case THROWS:
out.writeByte(p.type_index);
break;
// method parameter
case METHOD_FORMAL_PARAMETER:
out.writeByte(p.parameter_index);
break;
// method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT:
out.writeShort(p.offset);
out.writeByte(p.type_index);
break;
// We don't need to worry about these
case METHOD_RETURN:
case FIELD:
break;
// lambda formal parameter
case LAMBDA_FORMAL_PARAMETER:
out.writeByte(p.parameter_index);
break;
case UNKNOWN:
throw new AssertionError("ClassWriter: UNKNOWN target type should never occur!");
default:
throw new AssertionError("ClassWriter: Unknown target type for position: " + p);
}
{ // Append location data for generics/arrays.
// TODO: check for overrun?
out.writeByte((byte)p.location.size());
for (int i : TypeAnnotation.Position.getBinaryFromTypePath(p.location))
out.writeByte((byte)i);
}
}
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2007, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.classfile;
import java.io.IOException;
/**
* See JSR 308 specification, Section 3.
*
* <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.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class RuntimeInvisibleTypeAnnotations_attribute extends RuntimeTypeAnnotations_attribute {
RuntimeInvisibleTypeAnnotations_attribute(ClassReader cr, int name_index, int length)
throws IOException, Annotation.InvalidAnnotation {
super(cr, name_index, length);
}
public RuntimeInvisibleTypeAnnotations_attribute(ConstantPool cp, TypeAnnotation[] annotations)
throws ConstantPoolException {
this(cp.getUTF8Index(Attribute.RuntimeInvisibleTypeAnnotations), annotations);
}
public RuntimeInvisibleTypeAnnotations_attribute(int name_index, TypeAnnotation[] annotations) {
super(name_index, annotations);
}
public <R, P> R accept(Visitor<R, P> visitor, P p) {
return visitor.visitRuntimeInvisibleTypeAnnotations(this, p);
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2007, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.classfile;
import java.io.IOException;
/**
* See JSR 308 specification, Section 3.
*
* <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.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public abstract class RuntimeTypeAnnotations_attribute extends Attribute {
protected RuntimeTypeAnnotations_attribute(ClassReader cr, int name_index, int length)
throws IOException, Annotation.InvalidAnnotation {
super(name_index, length);
int num_annotations = cr.readUnsignedShort();
annotations = new TypeAnnotation[num_annotations];
for (int i = 0; i < annotations.length; i++)
annotations[i] = new TypeAnnotation(cr);
}
protected RuntimeTypeAnnotations_attribute(int name_index, TypeAnnotation[] annotations) {
super(name_index, length(annotations));
this.annotations = annotations;
}
private static int length(TypeAnnotation[] annos) {
int n = 2;
for (TypeAnnotation anno: annos)
n += anno.length();
return n;
}
public final TypeAnnotation[] annotations;
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2007, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.classfile;
import java.io.IOException;
/**
* See JSR 308 specification, Section 3.
*
* <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.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class RuntimeVisibleTypeAnnotations_attribute extends RuntimeTypeAnnotations_attribute {
RuntimeVisibleTypeAnnotations_attribute(ClassReader cr, int name_index, int length)
throws IOException, Annotation.InvalidAnnotation {
super(cr, name_index, length);
}
public RuntimeVisibleTypeAnnotations_attribute(ConstantPool cp, TypeAnnotation[] annotations)
throws ConstantPoolException {
this(cp.getUTF8Index(Attribute.RuntimeVisibleTypeAnnotations), annotations);
}
public RuntimeVisibleTypeAnnotations_attribute(int name_index, TypeAnnotation[] annotations) {
super(name_index, annotations);
}
public <R, P> R accept(Visitor<R, P> visitor, P p) {
return visitor.visitRuntimeVisibleTypeAnnotations(this, p);
}
}

View File

@ -0,0 +1,656 @@
/*
* Copyright (c) 2009, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.classfile;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.sun.tools.classfile.TypeAnnotation.Position.TypePathEntry;
/**
* See JSR 308 specification, Section 3.
*
* <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.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class TypeAnnotation {
TypeAnnotation(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
constant_pool = cr.getConstantPool();
position = read_position(cr);
annotation = new Annotation(cr);
}
public TypeAnnotation(ConstantPool constant_pool,
Annotation annotation, Position position) {
this.constant_pool = constant_pool;
this.position = position;
this.annotation = annotation;
}
public int length() {
int n = annotation.length();
n += position_length(position);
return n;
}
@Override
public String toString() {
try {
return "@" + constant_pool.getUTF8Value(annotation.type_index).toString().substring(1) +
" pos: " + position.toString();
} catch (Exception e) {
e.printStackTrace();
return e.toString();
}
}
public final ConstantPool constant_pool;
public final Position position;
public final Annotation annotation;
private static Position read_position(ClassReader cr) throws IOException, Annotation.InvalidAnnotation {
// Copied from ClassReader
int tag = cr.readUnsignedByte(); // TargetType tag is a byte
if (!TargetType.isValidTargetTypeValue(tag))
throw new Annotation.InvalidAnnotation("TypeAnnotation: Invalid type annotation target type value: " + String.format("0x%02X", tag));
TargetType type = TargetType.fromTargetTypeValue(tag);
Position position = new Position();
position.type = type;
switch (type) {
// type cast
case CAST:
// instanceof
case INSTANCEOF:
// new expression
case NEW:
position.offset = cr.readUnsignedShort();
break;
// local variable
case LOCAL_VARIABLE:
// resource variable
case RESOURCE_VARIABLE:
int table_length = cr.readUnsignedShort();
position.lvarOffset = new int[table_length];
position.lvarLength = new int[table_length];
position.lvarIndex = new int[table_length];
for (int i = 0; i < table_length; ++i) {
position.lvarOffset[i] = cr.readUnsignedShort();
position.lvarLength[i] = cr.readUnsignedShort();
position.lvarIndex[i] = cr.readUnsignedShort();
}
break;
// exception parameter
case EXCEPTION_PARAMETER:
position.exception_index = cr.readUnsignedByte();
break;
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameter
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
position.parameter_index = cr.readUnsignedByte();
break;
// type parameter bound
case CLASS_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND:
position.parameter_index = cr.readUnsignedByte();
position.bound_index = cr.readUnsignedByte();
break;
// class extends or implements clause
case CLASS_EXTENDS:
int in = cr.readUnsignedShort();
if (in == 0xFFFF)
in = -1;
position.type_index = in;
break;
// throws
case THROWS:
position.type_index = cr.readUnsignedShort();
break;
// method parameter
case METHOD_FORMAL_PARAMETER:
position.parameter_index = cr.readUnsignedByte();
break;
// method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT:
position.offset = cr.readUnsignedShort();
position.type_index = cr.readUnsignedByte();
break;
// We don't need to worry about these
case METHOD_RETURN:
case FIELD:
break;
// lambda formal parameter
case LAMBDA_FORMAL_PARAMETER:
position.parameter_index = cr.readUnsignedByte();
break;
case UNKNOWN:
throw new AssertionError("TypeAnnotation: UNKNOWN target type should never occur!");
default:
throw new AssertionError("TypeAnnotation: Unknown target type: " + type);
}
{ // Write type path
int len = cr.readUnsignedByte();
List<Integer> loc = new ArrayList<Integer>(len);
for (int i = 0; i < len * TypePathEntry.bytesPerEntry; ++i)
loc.add(cr.readUnsignedByte());
position.location = Position.getTypePathFromBinary(loc);
}
return position;
}
private static int position_length(Position pos) {
int n = 0;
n += 1; // TargetType tag is a byte
switch (pos.type) {
// type cast
case CAST:
// instanceof
case INSTANCEOF:
// new expression
case NEW:
n += 2;
break;
// local variable
case LOCAL_VARIABLE:
// resource variable
case RESOURCE_VARIABLE:
n += 2; // table_length;
int table_length = pos.lvarOffset.length;
n += 2 * table_length; // offset
n += 2 * table_length; // length;
n += 2 * table_length; // index
break;
// exception parameter
case EXCEPTION_PARAMETER:
n += 1; // exception_index
break;
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameter
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
n += 1; // parameter_index;
break;
// type parameter bound
case CLASS_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND:
n += 1; // parameter_index
n += 1; // bound_index
break;
// class extends or implements clause
case CLASS_EXTENDS:
n += 2; // type_index
break;
// throws
case THROWS:
n += 2; // type_index
break;
// method parameter
case METHOD_FORMAL_PARAMETER:
n += 1; // parameter_index
break;
// method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT:
n += 2; // offset
n += 1; // type index
break;
// We don't need to worry about these
case METHOD_RETURN:
case FIELD:
break;
// lambda formal parameter
case LAMBDA_FORMAL_PARAMETER:
n += 1; // parameter_index
break;
case UNKNOWN:
throw new AssertionError("TypeAnnotation: UNKNOWN target type should never occur!");
default:
throw new AssertionError("TypeAnnotation: Unknown target type: " + pos.type);
}
{
n += 1; // length
n += TypePathEntry.bytesPerEntry * pos.location.size(); // bytes for actual array
}
return n;
}
// Code duplicated from com.sun.tools.javac.code.TypeAnnotationPosition
public static class Position {
public enum TypePathEntryKind {
ARRAY(0),
INNER_TYPE(1),
WILDCARD(2),
TYPE_ARGUMENT(3);
public final int tag;
private TypePathEntryKind(int tag) {
this.tag = tag;
}
}
public static class TypePathEntry {
/** The fixed number of bytes per TypePathEntry. */
public static final int bytesPerEntry = 2;
public final TypePathEntryKind tag;
public final int arg;
public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY);
public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE);
public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD);
private TypePathEntry(TypePathEntryKind tag) {
if (!(tag == TypePathEntryKind.ARRAY ||
tag == TypePathEntryKind.INNER_TYPE ||
tag == TypePathEntryKind.WILDCARD)) {
throw new AssertionError("Invalid TypePathEntryKind: " + tag);
}
this.tag = tag;
this.arg = 0;
}
public TypePathEntry(TypePathEntryKind tag, int arg) {
if (tag != TypePathEntryKind.TYPE_ARGUMENT) {
throw new AssertionError("Invalid TypePathEntryKind: " + tag);
}
this.tag = tag;
this.arg = arg;
}
public static TypePathEntry fromBinary(int tag, int arg) {
if (arg != 0 && tag != TypePathEntryKind.TYPE_ARGUMENT.tag) {
throw new AssertionError("Invalid TypePathEntry tag/arg: " + tag + "/" + arg);
}
switch (tag) {
case 0:
return ARRAY;
case 1:
return INNER_TYPE;
case 2:
return WILDCARD;
case 3:
return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg);
default:
throw new AssertionError("Invalid TypePathEntryKind tag: " + tag);
}
}
@Override
public String toString() {
return tag.toString() +
(tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : "");
}
@Override
public boolean equals(Object other) {
if (! (other instanceof TypePathEntry)) {
return false;
}
TypePathEntry tpe = (TypePathEntry) other;
return this.tag == tpe.tag && this.arg == tpe.arg;
}
@Override
public int hashCode() {
return this.tag.hashCode() * 17 + this.arg;
}
}
public TargetType type = TargetType.UNKNOWN;
// For generic/array types.
// TODO: or should we use null? Noone will use this object.
public List<TypePathEntry> location = new ArrayList<TypePathEntry>(0);
// Tree position.
public int pos = -1;
// For typecasts, type tests, new (and locals, as start_pc).
public boolean isValidOffset = false;
public int offset = -1;
// For locals. arrays same length
public int[] lvarOffset = null;
public int[] lvarLength = null;
public int[] lvarIndex = null;
// For type parameter bound
public int bound_index = Integer.MIN_VALUE;
// For type parameter and method parameter
public int parameter_index = Integer.MIN_VALUE;
// For class extends, implements, and throws clauses
public int type_index = Integer.MIN_VALUE;
// For exception parameters, index into exception table
public int exception_index = Integer.MIN_VALUE;
public Position() {}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
sb.append(type);
switch (type) {
// type cast
case CAST:
// instanceof
case INSTANCEOF:
// new expression
case NEW:
sb.append(", offset = ");
sb.append(offset);
break;
// local variable
case LOCAL_VARIABLE:
// resource variable
case RESOURCE_VARIABLE:
if (lvarOffset == null) {
sb.append(", lvarOffset is null!");
break;
}
sb.append(", {");
for (int i = 0; i < lvarOffset.length; ++i) {
if (i != 0) sb.append("; ");
sb.append("start_pc = ");
sb.append(lvarOffset[i]);
sb.append(", length = ");
sb.append(lvarLength[i]);
sb.append(", index = ");
sb.append(lvarIndex[i]);
}
sb.append("}");
break;
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameter
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
sb.append(", param_index = ");
sb.append(parameter_index);
break;
// type parameter bound
case CLASS_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND:
sb.append(", param_index = ");
sb.append(parameter_index);
sb.append(", bound_index = ");
sb.append(bound_index);
break;
// class extends or implements clause
case CLASS_EXTENDS:
sb.append(", type_index = ");
sb.append(type_index);
break;
// throws
case THROWS:
sb.append(", type_index = ");
sb.append(type_index);
break;
// exception parameter
case EXCEPTION_PARAMETER:
sb.append(", exception_index = ");
sb.append(exception_index);
break;
// method parameter
case METHOD_FORMAL_PARAMETER:
sb.append(", param_index = ");
sb.append(parameter_index);
break;
// method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT:
sb.append(", offset = ");
sb.append(offset);
sb.append(", type_index = ");
sb.append(type_index);
break;
// We don't need to worry about these
case METHOD_RETURN:
case FIELD:
break;
// lambda formal parameter
case LAMBDA_FORMAL_PARAMETER:
// TODO: also needs an offset?
sb.append(", param_index = ");
sb.append(parameter_index);
break;
case UNKNOWN:
sb.append(", position UNKNOWN!");
break;
default:
throw new AssertionError("Unknown target type: " + type);
}
// Append location data for generics/arrays.
if (!location.isEmpty()) {
sb.append(", location = (");
sb.append(location);
sb.append(")");
}
sb.append(", pos = ");
sb.append(pos);
sb.append(']');
return sb.toString();
}
/**
* Indicates whether the target tree of the annotation has been optimized
* away from classfile or not.
* @return true if the target has not been optimized away
*/
public boolean emitToClassfile() {
return !type.isLocal() || isValidOffset;
}
/**
* Decode the binary representation for a type path and set
* the {@code location} field.
*
* @param list The bytecode representation of the type path.
*/
public static List<TypePathEntry> getTypePathFromBinary(List<Integer> list) {
List<TypePathEntry> loc = new ArrayList<TypePathEntry>(list.size() / TypePathEntry.bytesPerEntry);
int idx = 0;
while (idx < list.size()) {
if (idx + 1 == list.size()) {
throw new AssertionError("Could not decode type path: " + list);
}
loc.add(TypePathEntry.fromBinary(list.get(idx), list.get(idx + 1)));
idx += 2;
}
return loc;
}
public static List<Integer> getBinaryFromTypePath(List<TypePathEntry> locs) {
List<Integer> loc = new ArrayList<Integer>(locs.size() * TypePathEntry.bytesPerEntry);
for (TypePathEntry tpe : locs) {
loc.add(tpe.tag.tag);
loc.add(tpe.arg);
}
return loc;
}
}
// Code duplicated from com.sun.tools.javac.code.TargetType
// The IsLocal flag could be removed here.
public enum TargetType {
/** For annotations on a class type parameter declaration. */
CLASS_TYPE_PARAMETER(0x00),
/** For annotations on a method type parameter declaration. */
METHOD_TYPE_PARAMETER(0x01),
/** For annotations on the type of an "extends" or "implements" clause. */
CLASS_EXTENDS(0x10),
/** For annotations on a bound of a type parameter of a class. */
CLASS_TYPE_PARAMETER_BOUND(0x11),
/** For annotations on a bound of a type parameter of a method. */
METHOD_TYPE_PARAMETER_BOUND(0x12),
/** For annotations on a field. */
FIELD(0x13),
/** For annotations on a method return type. */
METHOD_RETURN(0x14),
/** For annotations on the method receiver. */
METHOD_RECEIVER(0x15),
/** For annotations on a method parameter. */
METHOD_FORMAL_PARAMETER(0x16),
/** For annotations on a throws clause in a method declaration. */
THROWS(0x17),
/** For annotations on a local variable. */
LOCAL_VARIABLE(0x40, true),
/** For annotations on a resource variable. */
RESOURCE_VARIABLE(0x41, true),
/** For annotations on an exception parameter. */
EXCEPTION_PARAMETER(0x42, true),
/** For annotations on a typecast. */
CAST(0x43, true),
/** For annotations on a type test. */
INSTANCEOF(0x44, true),
/** For annotations on an object creation expression. */
NEW(0x45, true),
/** For annotations on a type argument of an object creation expression. */
CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(0x46, true),
/** For annotations on a type argument of a method call. */
METHOD_INVOCATION_TYPE_ARGUMENT(0x47, true),
/** For annotations on a lambda parameter type. */
LAMBDA_FORMAL_PARAMETER(0x48, true),
/** For annotations on a method reference. */
METHOD_REFERENCE(0x49, true),
/** For annotations on a type argument of a method reference. */
METHOD_REFERENCE_TYPE_ARGUMENT(0x50, true),
/** For annotations with an unknown target. */
UNKNOWN(0xFF);
private static final int MAXIMUM_TARGET_TYPE_VALUE = 0x50;
private final int targetTypeValue;
private final boolean isLocal;
private TargetType(int targetTypeValue) {
this(targetTypeValue, false);
}
private TargetType(int targetTypeValue, boolean isLocal) {
if (targetTypeValue < 0
|| targetTypeValue > 255)
throw new AssertionError("Attribute type value needs to be an unsigned byte: " + String.format("0x%02X", targetTypeValue));
this.targetTypeValue = targetTypeValue;
this.isLocal = isLocal;
}
/**
* Returns whether or not this TargetType represents an annotation whose
* target is exclusively a tree in a method body
*
* Note: wildcard bound targets could target a local tree and a class
* member declaration signature tree
*/
public boolean isLocal() {
return isLocal;
}
public int targetTypeValue() {
return this.targetTypeValue;
}
private static final TargetType[] targets;
static {
targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
TargetType[] alltargets = values();
for (TargetType target : alltargets) {
if (target.targetTypeValue != UNKNOWN.targetTypeValue)
targets[target.targetTypeValue] = target;
}
for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i) {
if (targets[i] == null)
targets[i] = UNKNOWN;
}
}
public static boolean isValidTargetTypeValue(int tag) {
if (tag == UNKNOWN.targetTypeValue)
return true;
return (tag >= 0 && tag < targets.length);
}
public static TargetType fromTargetTypeValue(int tag) {
if (tag == UNKNOWN.targetTypeValue)
return UNKNOWN;
if (tag < 0 || tag >= targets.length)
throw new AssertionError("Unknown TargetType: " + tag);
return targets[tag];
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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
@ -139,6 +139,15 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite
}
}
protected void addReceiverAnnotations(ExecutableMemberDoc member,
Content tree) {
if (member.receiverAnnotations().length > 0) {
tree.addContent(writer.getSpace());
writer.addReceiverAnnotationInfo(member, tree);
}
}
/**
* Add all the parameters for the executable member.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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
@ -137,6 +137,7 @@ public class ConstructorWriterImpl extends AbstractExecutableMemberWriter
addName(constructor.name(), pre);
}
addParameters(constructor, pre);
writer.addReceiverAnnotationInfo(constructor, pre);
addExceptions(constructor, pre);
return pre;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2013, 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
@ -1729,6 +1729,17 @@ public class HtmlDocletWriter extends HtmlDocWriter {
addAnnotationInfo(packageDoc, packageDoc.annotations(), htmltree);
}
/**
* Add the annotation types of the executable receiver.
*
* @param method the executable to write the receiver annotations for.
* @param htmltree the documentation tree to which the annotation info will be
* added
*/
public void addReceiverAnnotationInfo(ExecutableMemberDoc method, Content htmltree) {
addAnnotationInfo(method, method.receiverAnnotations(), htmltree);
}
/**
* Adds the annotatation types for the given doc.
*
@ -1799,6 +1810,26 @@ public class HtmlDocletWriter extends HtmlDocWriter {
* documented.
*/
private List<String> getAnnotations(int indent, AnnotationDesc[] descList, boolean linkBreak) {
return getAnnotations(indent, descList, linkBreak, true);
}
/**
* Return the string representations of the annotation types for
* the given doc.
*
* A {@code null} {@code elementType} indicates that all the
* annotations should be returned without any filtering.
*
* @param indent the number of extra spaces to indent the annotations.
* @param descList the array of {@link AnnotationDesc}.
* @param linkBreak if true, add new line between each member value.
* @param elementType the type of targeted element (used for filtering
* type annotations from declaration annotations)
* @return an array of strings representing the annotations being
* documented.
*/
public List<String> getAnnotations(int indent, AnnotationDesc[] descList, boolean linkBreak,
boolean isJava5DeclarationLocation) {
List<String> results = new ArrayList<String>();
StringBuilder annotation;
for (int i = 0; i < descList.length; i++) {
@ -1812,6 +1843,11 @@ public class HtmlDocletWriter extends HtmlDocWriter {
(!isAnnotationDocumented && !isContainerDocumented)) {
continue;
}
/* TODO: check logic here to correctly handle declaration
* and type annotations.
if (Util.isDeclarationAnnotation(annotationDoc, isJava5DeclarationLocation)) {
continue;
}*/
annotation = new StringBuilder();
isAnnotationDocumented = false;
LinkInfoImpl linkInfo = new LinkInfoImpl(configuration,

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -25,6 +25,8 @@
package com.sun.tools.doclets.formats.html;
import java.util.List;
import com.sun.javadoc.*;
import com.sun.tools.doclets.internal.toolkit.*;
import com.sun.tools.doclets.internal.toolkit.util.*;
@ -123,11 +125,50 @@ public class LinkFactoryImpl extends LinkFactory {
typeLinkInfo.excludeTypeBounds = linkInfo.excludeTypeBounds;
typeLinkInfo.excludeTypeParameterLinks = linkInfo.excludeTypeParameterLinks;
typeLinkInfo.linkToSelf = linkInfo.linkToSelf;
typeLinkInfo.isJava5DeclarationLocation = false;
LinkOutput output = getLinkOutput(typeLinkInfo);
((LinkInfoImpl) linkInfo).displayLength += typeLinkInfo.displayLength;
return output;
}
protected LinkOutput getTypeAnnotationLink(LinkInfo linkInfo,
AnnotationDesc annotation) {
throw new RuntimeException("Not implemented yet!");
}
public LinkOutput getTypeAnnotationLinks(LinkInfo linkInfo) {
LinkOutput output = getOutputInstance();
AnnotationDesc[] annotations;
if (linkInfo.type instanceof AnnotatedType) {
annotations = linkInfo.type.asAnnotatedType().annotations();
} else if (linkInfo.type instanceof TypeVariable) {
annotations = linkInfo.type.asTypeVariable().annotations();
} else {
return output;
}
if (annotations.length == 0)
return output;
List<String> annos = m_writer.getAnnotations(0, annotations, false, linkInfo.isJava5DeclarationLocation);
boolean isFirst = true;
for (String anno : annos) {
if (!isFirst) {
linkInfo.displayLength += 1;
output.append(" ");
isFirst = false;
}
output.append(anno);
}
if (!annos.isEmpty()) {
linkInfo.displayLength += 1;
output.append(" ");
}
return output;
}
/**
* Given a class, return the appropriate tool tip.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -459,6 +459,8 @@ public class LinkInfoImpl extends LinkInfo {
case CONTEXT_RETURN_TYPE:
case CONTEXT_SUMMARY_RETURN_TYPE:
excludeTypeBounds = true;
break;
case CONTEXT_EXECUTABLE_MEMBER_PARAM:
excludeTypeBounds = true;
break;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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
@ -130,6 +130,7 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter
addName(method.name(), pre);
}
addParameters(method, pre);
addReceiverAnnotations(method, pre);
addExceptions(method, pre);
return pre;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -26,9 +26,11 @@
package com.sun.tools.doclets.internal.toolkit.util;
import java.io.*;
import java.lang.annotation.ElementType;
import java.util.*;
import com.sun.javadoc.*;
import com.sun.javadoc.AnnotationDesc.ElementValuePair;
import com.sun.tools.doclets.internal.toolkit.*;
import javax.tools.StandardLocation;
@ -304,9 +306,7 @@ public class Util {
//Try walking the tree.
addAllInterfaceTypes(results,
superType,
superType instanceof ClassDoc ?
((ClassDoc) superType).interfaceTypes() :
((ParameterizedType) superType).interfaceTypes(),
interfaceTypesOf(superType),
false, configuration);
List<Type> resultsList = new ArrayList<Type>(results.values());
if (sort) {
@ -315,6 +315,14 @@ public class Util {
return resultsList;
}
private static Type[] interfaceTypesOf(Type type) {
if (type instanceof AnnotatedType)
type = ((AnnotatedType)type).underlyingType();
return type instanceof ClassDoc ?
((ClassDoc)type).interfaceTypes() :
((ParameterizedType)type).interfaceTypes();
}
public static List<Type> getAllInterfaces(Type type, Configuration configuration) {
return getAllInterfaces(type, configuration, true);
}
@ -325,9 +333,7 @@ public class Util {
if (superType == null)
return;
addAllInterfaceTypes(results, superType,
superType instanceof ClassDoc ?
((ClassDoc) superType).interfaceTypes() :
((ParameterizedType) superType).interfaceTypes(),
interfaceTypesOf(superType),
raw, configuration);
}
@ -337,9 +343,7 @@ public class Util {
if (superType == null)
return;
addAllInterfaceTypes(results, superType,
superType instanceof ClassDoc ?
((ClassDoc) superType).interfaceTypes() :
((ParameterizedType) superType).interfaceTypes(),
interfaceTypesOf(superType),
false, configuration);
}
@ -363,6 +367,9 @@ public class Util {
results.put(superInterface.asClassDoc(), superInterface);
}
}
if (type instanceof AnnotatedType)
type = ((AnnotatedType)type).underlyingType();
if (type instanceof ParameterizedType)
findAllInterfaceTypes(results, (ParameterizedType) type, configuration);
else if (((ClassDoc) type).typeParameters().length == 0)
@ -494,6 +501,57 @@ public class Util {
return false;
}
private static boolean isDeclarationTarget(AnnotationDesc targetAnno) {
// The error recovery steps here are analogous to TypeAnnotations
ElementValuePair[] elems = targetAnno.elementValues();
if (elems == null
|| elems.length != 1
|| !"value".equals(elems[0].element().name())
|| !(elems[0].value().value() instanceof AnnotationValue[]))
return true; // error recovery
AnnotationValue[] values = (AnnotationValue[])elems[0].value().value();
for (int i = 0; i < values.length; i++) {
Object value = values[i].value();
if (!(value instanceof FieldDoc))
return true; // error recovery
FieldDoc eValue = (FieldDoc)value;
if (Util.isJava5DeclarationElementType(eValue)) {
return true;
}
}
return false;
}
/**
* Returns true if the {@code annotationDoc} is to be treated
* as a declaration annotation, when targeting the
* {@code elemType} element type.
*
* @param annotationDoc the annotationDoc to check
* @param elemType the targeted elemType
* @return true if annotationDoc is a declaration annotation
*/
public static boolean isDeclarationAnnotation(AnnotationTypeDoc annotationDoc,
boolean isJava5DeclarationLocation) {
if (!isJava5DeclarationLocation)
return false;
AnnotationDesc[] annotationDescList = annotationDoc.annotations();
// Annotations with no target are treated as declaration as well
if (annotationDescList.length==0)
return true;
for (int i = 0; i < annotationDescList.length; i++) {
if (annotationDescList[i].annotationType().qualifiedName().equals(
java.lang.annotation.Target.class.getName())) {
if (isDeclarationTarget(annotationDescList[i]))
return true;
}
}
return false;
}
/**
* Return true if this class is linkable and false if we can't link to the
* desired class.
@ -662,4 +720,25 @@ public class Util {
}
return false;
}
/**
* Test whether the given FieldDoc is one of the declaration annotation ElementTypes
* defined in Java 5.
* Instead of testing for one of the new enum constants added in Java 8, test for
* the old constants. This prevents bootstrapping problems.
*
* @param elt The FieldDoc to test
* @return true, iff the given ElementType is one of the constants defined in Java 5
* @since 1.8
*/
public static boolean isJava5DeclarationElementType(FieldDoc elt) {
return elt.name().contentEquals(ElementType.ANNOTATION_TYPE.name()) ||
elt.name().contentEquals(ElementType.CONSTRUCTOR.name()) ||
elt.name().contentEquals(ElementType.FIELD.name()) ||
elt.name().contentEquals(ElementType.LOCAL_VARIABLE.name()) ||
elt.name().contentEquals(ElementType.METHOD.name()) ||
elt.name().contentEquals(ElementType.PACKAGE.name()) ||
elt.name().contentEquals(ElementType.PARAMETER.name()) ||
elt.name().contentEquals(ElementType.TYPE.name());
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -61,6 +61,11 @@ public abstract class LinkFactory {
//Just a primitive.
linkInfo.displayLength += type.typeName().length();
linkOutput.append(type.typeName());
} else if (type.asAnnotatedType() != null) {
linkOutput.append(getTypeAnnotationLinks(linkInfo));
linkInfo.type = type.asAnnotatedType().underlyingType();
linkOutput.append(getLinkOutput(linkInfo));
return linkOutput;
} else if (type.asWildcardType() != null) {
//Wildcard type.
linkInfo.isTypeBound = true;
@ -82,6 +87,7 @@ public abstract class LinkFactory {
linkOutput.append(getLinkOutput(linkInfo));
}
} else if (type.asTypeVariable()!= null) {
linkOutput.append(getTypeAnnotationLinks(linkInfo));
linkInfo.isTypeBound = true;
//A type variable.
Doc owner = type.asTypeVariable().owner();
@ -175,6 +181,9 @@ public abstract class LinkFactory {
protected abstract LinkOutput getTypeParameterLink(LinkInfo linkInfo,
Type typeParam);
protected abstract LinkOutput getTypeAnnotationLink(LinkInfo linkInfo,
AnnotationDesc annotation);
/**
* Return the links to the type parameters.
*
@ -226,6 +235,24 @@ public abstract class LinkFactory {
return output;
}
public LinkOutput getTypeAnnotationLinks(LinkInfo linkInfo) {
LinkOutput output = getOutputInstance();
if (linkInfo.type.asAnnotatedType() == null)
return output;
AnnotationDesc[] annotations = linkInfo.type.asAnnotatedType().annotations();
for (int i = 0; i < annotations.length; i++) {
if (i > 0) {
linkInfo.displayLength += 1;
output.append(" ");
}
output.append(getTypeAnnotationLink(linkInfo, annotations[i]));
}
linkInfo.displayLength += 1;
output.append(" ");
return output;
}
/**
* Return &amp;lt;, which is used in type parameters. Override this
* if your doclet uses something different.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -68,6 +68,12 @@ public abstract class LinkInfo {
*/
public boolean isTypeBound = false;
/**
* Whether the document element is in a Java 5 declaration
* location or not.
*/
public boolean isJava5DeclarationLocation = true;
/**
* The label for the link.
*/

View File

@ -48,7 +48,7 @@ import static com.sun.tools.javac.code.Kinds.PCK;
*
* An instance of this class can be in one of three states:
*
* NOT_STARTED indicates that the Symbol this instance belongs to have not been
* NOT_STARTED indicates that the Symbol this instance belongs to has not been
* annotated (yet). Specifically if the declaration is not annotated this
* instance will never move past NOT_STARTED. You can never go back to
* NOT_STARTED.
@ -59,7 +59,7 @@ import static com.sun.tools.javac.code.Kinds.PCK;
*
* "unnamed" this Annotations contains some attributes, possibly the final set.
* While in this state you can only prepend or append to the attributes not set
* it directly. You can also move back to the IN_PROGRESS sate using reset().
* it directly. You can also move back to the IN_PROGRESS state using reset().
*
* <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. This code and its internal interfaces
@ -67,14 +67,21 @@ import static com.sun.tools.javac.code.Kinds.PCK;
*/
public class Annotations {
private static final List<Attribute.Compound> NOT_STARTED = List.of(null);
private static final List<Attribute.Compound> IN_PROGRESS = List.of(null);
private static final List<Attribute.Compound> DECL_NOT_STARTED = List.of(null);
private static final List<Attribute.Compound> DECL_IN_PROGRESS = List.of(null);
/*
* This field should never be null
*/
private List<Attribute.Compound> attributes = NOT_STARTED;
private List<Attribute.Compound> attributes = DECL_NOT_STARTED;
/*
* The Symbol this Annotations belong to
* This field should never be null
*/
private List<Attribute.TypeCompound> type_attributes = List.<Attribute.TypeCompound>nil();
/*
* The Symbol this Annotations instance belongs to
*/
private final Symbol sym;
@ -82,11 +89,15 @@ public class Annotations {
this.sym = sym;
}
public List<Attribute.Compound> getAttributes() {
return filterSentinels(attributes);
public List<Attribute.Compound> getDeclarationAttributes() {
return filterDeclSentinels(attributes);
}
public void setAttributes(List<Attribute.Compound> a) {
public List<Attribute.TypeCompound> getTypeAttributes() {
return type_attributes;
}
public void setDeclarationAttributes(List<Attribute.Compound> a) {
Assert.check(pendingCompletion() || !isStarted());
if (a == null) {
throw new NullPointerException();
@ -94,31 +105,51 @@ public class Annotations {
attributes = a;
}
public void setTypeAttributes(List<Attribute.TypeCompound> a) {
if (a == null) {
throw new NullPointerException();
}
type_attributes = a;
}
public void setAttributes(Annotations other) {
if (other == null) {
throw new NullPointerException();
}
setAttributes(other.getAttributes());
setDeclarationAttributes(other.getDeclarationAttributes());
setTypeAttributes(other.getTypeAttributes());
}
public void setAttributesWithCompletion(final Annotate.AnnotateRepeatedContext ctx) {
public void setDeclarationAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.Compound> ctx) {
Assert.check(pendingCompletion() || (!isStarted() && sym.kind == PCK));
this.setDeclarationAttributes(getAttributesForCompletion(ctx));
}
Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated = ctx.annotated;
public void appendTypeAttributesWithCompletion(final Annotate.AnnotateRepeatedContext<Attribute.TypeCompound> ctx) {
this.appendUniqueTypes(getAttributesForCompletion(ctx));
}
private <T extends Attribute.Compound> List<T> getAttributesForCompletion(
final Annotate.AnnotateRepeatedContext<T> ctx) {
Map<Symbol.TypeSymbol, ListBuffer<T>> annotated = ctx.annotated;
boolean atLeastOneRepeated = false;
List<Attribute.Compound> buf = List.<Attribute.Compound>nil();
for (ListBuffer<Attribute.Compound> lb : annotated.values()) {
List<T> buf = List.<T>nil();
for (ListBuffer<T> lb : annotated.values()) {
if (lb.size() == 1) {
buf = buf.prepend(lb.first());
} else { // repeated
buf = buf.prepend(new Placeholder(lb.toList(), sym));
// This will break when other subtypes of Attributs.Compound
// are introduced, because PlaceHolder is a subtype of TypeCompound.
T res;
@SuppressWarnings("unchecked")
T ph = (T) new Placeholder<T>(ctx, lb.toList(), sym);
res = ph;
buf = buf.prepend(res);
atLeastOneRepeated = true;
}
}
// Add non-repeating attributes
setAttributes(buf.reverse());
if (atLeastOneRepeated) {
// The Symbol s is now annotated with a combination of
// finished non-repeating annotations and placeholders for
@ -138,7 +169,6 @@ public class Annotations {
// Queue a pass that will replace Attribute.Placeholders
// with Attribute.Compound (made from synthesized containers).
ctx.annotateRepeated(new Annotate.Annotator() {
@Override
public String toString() {
return "repeated annotation pass of: " + sym + " in: " + sym.owner;
@ -150,10 +180,12 @@ public class Annotations {
}
});
}
// Add non-repeating attributes
return buf.reverse();
}
public Annotations reset() {
attributes = IN_PROGRESS;
attributes = DECL_IN_PROGRESS;
return this;
}
@ -163,12 +195,16 @@ public class Annotations {
|| attributes.isEmpty();
}
public boolean isTypesEmpty() {
return type_attributes.isEmpty();
}
public boolean pendingCompletion() {
return attributes == IN_PROGRESS;
return attributes == DECL_IN_PROGRESS;
}
public Annotations append(List<Attribute.Compound> l) {
attributes = filterSentinels(attributes);
attributes = filterDeclSentinels(attributes);
if (l.isEmpty()) {
; // no-op
@ -180,8 +216,24 @@ public class Annotations {
return this;
}
public Annotations appendUniqueTypes(List<Attribute.TypeCompound> l) {
if (l.isEmpty()) {
; // no-op
} else if (type_attributes.isEmpty()) {
type_attributes = l;
} else {
// TODO: in case we expect a large number of annotations, this
// might be inefficient.
for (Attribute.TypeCompound tc : l) {
if (!type_attributes.contains(tc))
type_attributes = type_attributes.append(tc);
}
}
return this;
}
public Annotations prepend(List<Attribute.Compound> l) {
attributes = filterSentinels(attributes);
attributes = filterDeclSentinels(attributes);
if (l.isEmpty()) {
; // no-op
@ -193,19 +245,29 @@ public class Annotations {
return this;
}
private List<Attribute.Compound> filterSentinels(List<Attribute.Compound> a) {
return (a == IN_PROGRESS || a == NOT_STARTED)
private List<Attribute.Compound> filterDeclSentinels(List<Attribute.Compound> a) {
return (a == DECL_IN_PROGRESS || a == DECL_NOT_STARTED)
? List.<Attribute.Compound>nil()
: a;
}
private boolean isStarted() {
return attributes != NOT_STARTED;
return attributes != DECL_NOT_STARTED;
}
private List<Attribute.Compound> getPlaceholders() {
List<Attribute.Compound> res = List.<Attribute.Compound>nil();
for (Attribute.Compound a : filterSentinels(attributes)) {
for (Attribute.Compound a : filterDeclSentinels(attributes)) {
if (a instanceof Placeholder) {
res = res.prepend(a);
}
}
return res.reverse();
}
private List<Attribute.TypeCompound> getTypePlaceholders() {
List<Attribute.TypeCompound> res = List.<Attribute.TypeCompound>nil();
for (Attribute.TypeCompound a : type_attributes) {
if (a instanceof Placeholder) {
res = res.prepend(a);
}
@ -216,50 +278,78 @@ public class Annotations {
/*
* Replace Placeholders for repeating annotations with their containers
*/
private void complete(Annotate.AnnotateRepeatedContext ctx) {
Assert.check(!pendingCompletion());
private <T extends Attribute.Compound> void complete(Annotate.AnnotateRepeatedContext<T> ctx) {
Log log = ctx.log;
Env<AttrContext> env = ctx.env;
JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile);
try {
// TODO: can we reduce duplication in the following branches?
if (ctx.isTypeCompound) {
Assert.check(!isTypesEmpty());
if (isEmpty()) {
return;
}
List<Attribute.Compound> result = List.nil();
for (Attribute.Compound a : getAttributes()) {
if (a instanceof Placeholder) {
Attribute.Compound replacement = replaceOne((Placeholder) a, ctx);
if (null != replacement) {
result = result.prepend(replacement);
}
} else {
result = result.prepend(a);
if (isTypesEmpty()) {
return;
}
List<Attribute.TypeCompound> result = List.nil();
for (Attribute.TypeCompound a : getTypeAttributes()) {
if (a instanceof Placeholder) {
@SuppressWarnings("unchecked")
Placeholder<Attribute.TypeCompound> ph = (Placeholder<Attribute.TypeCompound>) a;
Attribute.TypeCompound replacement = replaceOne(ph, ph.getRepeatedContext());
if (null != replacement) {
result = result.prepend(replacement);
}
} else {
result = result.prepend(a);
}
}
type_attributes = result.reverse();
Assert.check(Annotations.this.getTypePlaceholders().isEmpty());
} else {
Assert.check(!pendingCompletion());
if (isEmpty()) {
return;
}
List<Attribute.Compound> result = List.nil();
for (Attribute.Compound a : getDeclarationAttributes()) {
if (a instanceof Placeholder) {
@SuppressWarnings("unchecked")
Attribute.Compound replacement = replaceOne((Placeholder<T>) a, ctx);
if (null != replacement) {
result = result.prepend(replacement);
}
} else {
result = result.prepend(a);
}
}
attributes = result.reverse();
Assert.check(Annotations.this.getPlaceholders().isEmpty());
}
attributes = result.reverse();
Assert.check(Annotations.this.getPlaceholders().isEmpty());
} finally {
log.useSource(oldSource);
}
}
private Attribute.Compound replaceOne(Placeholder placeholder, Annotate.AnnotateRepeatedContext ctx) {
private <T extends Attribute.Compound> T replaceOne(Placeholder<T> placeholder, Annotate.AnnotateRepeatedContext<T> ctx) {
Log log = ctx.log;
// Process repeated annotations
Attribute.Compound validRepeated =
ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym);
T validRepeated = ctx.processRepeatedAnnotations(placeholder.getPlaceholderFor(), sym);
if (validRepeated != null) {
// Check that the container isn't manually
// present along with repeated instances of
// its contained annotation.
ListBuffer<Attribute.Compound> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
ListBuffer<T> manualContainer = ctx.annotated.get(validRepeated.type.tsym);
if (manualContainer != null) {
log.error(ctx.pos.get(manualContainer.first()), "invalid.repeatable.annotation.repeated.and.container.present",
manualContainer.first().type.tsym);
@ -268,16 +358,20 @@ public class Annotations {
// A null return will delete the Placeholder
return validRepeated;
}
private static class Placeholder extends Attribute.Compound {
private static class Placeholder<T extends Attribute.Compound> extends Attribute.TypeCompound {
private List<Attribute.Compound> placeholderFor;
private Symbol on;
private final Annotate.AnnotateRepeatedContext<T> ctx;
private final List<T> placeholderFor;
private final Symbol on;
public Placeholder(List<Attribute.Compound> placeholderFor, Symbol on) {
super(Type.noType, List.<Pair<Symbol.MethodSymbol, Attribute>>nil());
public Placeholder(Annotate.AnnotateRepeatedContext<T> ctx, List<T> placeholderFor, Symbol on) {
super(on.type, List.<Pair<Symbol.MethodSymbol, Attribute>>nil(),
ctx.isTypeCompound ?
((Attribute.TypeCompound)placeholderFor.head).position :
null);
this.ctx = ctx;
this.placeholderFor = placeholderFor;
this.on = on;
}
@ -287,8 +381,12 @@ public class Annotations {
return "<placeholder: " + placeholderFor + " on: " + on + ">";
}
public List<Attribute.Compound> getPlaceholderFor() {
public List<T> getPlaceholderFor() {
return placeholderFor;
}
public Annotate.AnnotateRepeatedContext<T> getRepeatedContext() {
return ctx;
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -217,6 +217,21 @@ public abstract class Attribute implements AnnotationValue {
}
}
public static class TypeCompound extends Compound {
public TypeAnnotationPosition position;
public TypeCompound(Compound compound,
TypeAnnotationPosition position) {
this(compound.type, compound.values, position);
}
public TypeCompound(Type type,
List<Pair<MethodSymbol, Attribute>> values,
TypeAnnotationPosition position) {
super(type, values);
this.position = position;
}
}
/** The value for an annotation element of an array type.
*/
public static class Array extends Attribute {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -233,23 +233,23 @@ public class Flags {
public static final long PROPRIETARY = 1L<<38;
/**
* Flag that marks a a multi-catch parameter
* Flag that marks a multi-catch parameter.
*/
public static final long UNION = 1L<<39;
/**
* Flag that marks a special kind of bridge methods (the ones that
* come from restricted supertype bounds)
* Flag that marks a special kind of bridge method (the ones that
* come from restricted supertype bounds).
*/
public static final long OVERRIDE_BRIDGE = 1L<<40;
/**
* Flag that marks an 'effectively final' local variable
* Flag that marks an 'effectively final' local variable.
*/
public static final long EFFECTIVELY_FINAL = 1L<<41;
/**
* Flag that marks non-override equivalent methods with the same signature
* Flag that marks non-override equivalent methods with the same signature.
*/
public static final long CLASH = 1L<<42;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -74,7 +74,7 @@ public class Lint
* the given annotations.
*/
public Lint augment(Annotations annots) {
return augmentor.augment(this, annots.getAttributes());
return augmentor.augment(this, annots.getDeclarationAttributes());
}
/**
@ -82,7 +82,7 @@ public class Lint
* the given annotations and flags.
*/
public Lint augment(Annotations annots, long flags) {
Lint l = augmentor.augment(this, annots.getAttributes());
Lint l = augmentor.augment(this, annots.getDeclarationAttributes());
if ((flags & DEPRECATED) != 0) {
if (l == this)
l = new Lint(this);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2013, 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
@ -27,7 +27,10 @@ package com.sun.tools.javac.code;
import java.util.Locale;
import javax.lang.model.type.TypeKind;
import com.sun.tools.javac.api.Messages;
import com.sun.tools.javac.code.Type.AnnotatedType;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.util.List;
@ -35,7 +38,6 @@ import com.sun.tools.javac.util.ListBuffer;
import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.TypeTag.ARRAY;
import static com.sun.tools.javac.code.TypeTag.CLASS;
import static com.sun.tools.javac.code.TypeTag.FORALL;
@ -188,7 +190,7 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
StringBuilder buf = new StringBuilder();
if (t.getEnclosingType().tag == CLASS && t.tsym.owner.kind == Kinds.TYP) {
buf.append(visit(t.getEnclosingType(), locale));
buf.append(".");
buf.append('.');
buf.append(className(t, false, locale));
} else {
buf.append(className(t, true, locale));
@ -196,7 +198,7 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
if (t.getTypeArguments().nonEmpty()) {
buf.append('<');
buf.append(visitTypes(t.getTypeArguments(), locale));
buf.append(">");
buf.append('>');
}
return buf.toString();
}
@ -231,6 +233,17 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
return visitType(t, locale);
}
@Override
public String visitAnnotatedType(AnnotatedType t, Locale locale) {
if (t.typeAnnotations != null &&
t.typeAnnotations.nonEmpty()) {
// TODO: better logic for arrays, ...
return "(" + t.typeAnnotations + " :: " + visit(t.underlyingType, locale) + ")";
} else {
return "({} :: " + visit(t.underlyingType, locale) + ")";
}
}
public String visitType(Type t, Locale locale) {
String s = (t.tsym == null || t.tsym.name == null)
? localize(locale, "compiler.misc.type.none")
@ -296,8 +309,13 @@ public abstract class Printer implements Type.Visitor<String, Locale>, Symbol.Vi
args = args.tail;
buf.append(',');
}
if (args.head.tag == ARRAY) {
buf.append(visit(((ArrayType) args.head).elemtype, locale));
if (args.head.unannotatedType().getKind() == TypeKind.ARRAY) {
buf.append(visit(((ArrayType) args.head.unannotatedType()).elemtype, locale));
if (args.head.getAnnotations().nonEmpty()) {
buf.append(' ');
buf.append(args.head.getAnnotations());
buf.append(' ');
}
buf.append("...");
} else {
buf.append(visit(args.head, locale));

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2002, 2013, 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
@ -176,9 +176,6 @@ public enum Source {
public boolean allowTryWithResources() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowTypeAnnotations() {
return compareTo(JDK1_7) >= 0;
}
public boolean allowBinaryLiterals() {
return compareTo(JDK1_7) >= 0;
}
@ -215,6 +212,9 @@ public enum Source {
public boolean allowEffectivelyFinalInInnerClasses() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowTypeAnnotations() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowRepeatedAnnotations() {
return compareTo(JDK1_8) >= 0;
}

View File

@ -84,7 +84,15 @@ public abstract class Symbol implements Element {
* method to make sure that the class symbol is loaded.
*/
public List<Attribute.Compound> getRawAttributes() {
return annotations.getAttributes();
return annotations.getDeclarationAttributes();
}
/** An accessor method for the type attributes of this symbol.
* Attributes of class symbols should be accessed through the accessor
* method to make sure that the class symbol is loaded.
*/
public List<Attribute.TypeCompound> getRawTypeAttributes() {
return annotations.getTypeAttributes();
}
/** Fetch a particular annotation from a symbol. */
@ -454,6 +462,14 @@ public abstract class Symbol implements Element {
return getRawAttributes();
}
/**
* TODO: Should there be a {@code
* javax.lang.model.element.Element.getTypeAnnotationMirrors()}.
*/
public final List<Attribute.TypeCompound> getTypeAnnotationMirrors() {
return getRawTypeAttributes();
}
/**
* @deprecated this method should never be used by javac internally.
*/
@ -795,6 +811,12 @@ public abstract class Symbol implements Element {
return super.getRawAttributes();
}
@Override
public List<Attribute.TypeCompound> getRawTypeAttributes() {
if (completer != null) complete();
return super.getRawTypeAttributes();
}
public Type erasure(Types types) {
if (erasure_field == null)
erasure_field = new ClassType(types.erasure(type.getEnclosingType()),
@ -1387,7 +1409,7 @@ public abstract class Symbol implements Element {
return defaultValue;
}
public List<VarSymbol> getParameters() {
public List<VarSymbol> getParameters() {
return params();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2008, 2013, 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
@ -25,10 +25,7 @@
package com.sun.tools.javac.code;
import java.util.EnumSet;
import java.util.Set;
import static com.sun.tools.javac.code.TargetType.TargetAttribute.*;
import com.sun.tools.javac.util.Assert;
/**
* Describes the type of program element an extended annotation (or extended
@ -44,178 +41,89 @@ import static com.sun.tools.javac.code.TargetType.TargetAttribute.*;
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
// Code duplicated in com.sun.tools.classfile.TypeAnnotation.TargetType
public enum TargetType {
/** For annotations on a class type parameter declaration. */
CLASS_TYPE_PARAMETER(0x00),
//
// Some target types are commented out, because Java doesn't permit such
// targets. They are included here to confirm that their omission is
// intentional omission not an accidental omission.
//
/** For annotations on typecasts. */
TYPECAST(0x00, IsLocal),
/** For annotations on a type argument or nested array of a typecast. */
TYPECAST_GENERIC_OR_ARRAY(0x01, HasLocation, IsLocal),
/** For annotations on type tests. */
INSTANCEOF(0x02, IsLocal),
/** For annotations on a type argument or nested array of a type test. */
INSTANCEOF_GENERIC_OR_ARRAY(0x03, HasLocation, IsLocal),
/** For annotations on object creation expressions. */
NEW(0x04, IsLocal),
/**
* For annotations on a type argument or nested array of an object creation
* expression.
*/
NEW_GENERIC_OR_ARRAY(0x05, HasLocation, IsLocal),
/** For annotations on the method receiver. */
METHOD_RECEIVER(0x06),
// invalid location
//@Deprecated METHOD_RECEIVER_GENERIC_OR_ARRAY(0x07, HasLocation),
/** For annotations on local variables. */
LOCAL_VARIABLE(0x08, IsLocal),
/** For annotations on a type argument or nested array of a local. */
LOCAL_VARIABLE_GENERIC_OR_ARRAY(0x09, HasLocation, IsLocal),
// handled by regular annotations
//@Deprecated METHOD_RETURN(0x0A),
/**
* For annotations on a type argument or nested array of a method return
* type.
*/
METHOD_RETURN_GENERIC_OR_ARRAY(0x0B, HasLocation),
// handled by regular annotations
//@Deprecated METHOD_PARAMETER(0x0C),
/** For annotations on a type argument or nested array of a method parameter. */
METHOD_PARAMETER_GENERIC_OR_ARRAY(0x0D, HasLocation),
// handled by regular annotations
//@Deprecated FIELD(0x0E),
/** For annotations on a type argument or nested array of a field. */
FIELD_GENERIC_OR_ARRAY(0x0F, HasLocation),
/** For annotations on a bound of a type parameter of a class. */
CLASS_TYPE_PARAMETER_BOUND(0x10, HasBound, HasParameter),
/**
* For annotations on a type argument or nested array of a bound of a type
* parameter of a class.
*/
CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x11, HasBound, HasLocation, HasParameter),
/** For annotations on a bound of a type parameter of a method. */
METHOD_TYPE_PARAMETER_BOUND(0x12, HasBound, HasParameter),
/**
* For annotations on a type argument or nested array of a bound of a type
* parameter of a method.
*/
METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY(0x13, HasBound, HasLocation, HasParameter),
/** For annotations on a method type parameter declaration. */
METHOD_TYPE_PARAMETER(0x01),
/** For annotations on the type of an "extends" or "implements" clause. */
CLASS_EXTENDS(0x14),
CLASS_EXTENDS(0x10),
/** For annotations on the inner type of an "extends" or "implements" clause. */
CLASS_EXTENDS_GENERIC_OR_ARRAY(0x15, HasLocation),
/** For annotations on a bound of a type parameter of a class. */
CLASS_TYPE_PARAMETER_BOUND(0x11),
/** For annotations on a bound of a type parameter of a method. */
METHOD_TYPE_PARAMETER_BOUND(0x12),
/** For annotations on a field. */
FIELD(0x13),
/** For annotations on a method return type. */
METHOD_RETURN(0x14),
/** For annotations on the method receiver. */
METHOD_RECEIVER(0x15),
/** For annotations on a method parameter. */
METHOD_FORMAL_PARAMETER(0x16),
/** For annotations on a throws clause in a method declaration. */
THROWS(0x16),
THROWS(0x17),
// invalid location
//@Deprecated THROWS_GENERIC_OR_ARRAY(0x17, HasLocation),
/** For annotations on a local variable. */
LOCAL_VARIABLE(0x40, true),
/** For annotations in type arguments of object creation expressions. */
NEW_TYPE_ARGUMENT(0x18, IsLocal),
NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x19, HasLocation, IsLocal),
/** For annotations on a resource variable. */
RESOURCE_VARIABLE(0x41, true),
METHOD_TYPE_ARGUMENT(0x1A, IsLocal),
METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY(0x1B, HasLocation, IsLocal),
/** For annotations on an exception parameter. */
EXCEPTION_PARAMETER(0x42, true),
WILDCARD_BOUND(0x1C, HasBound),
WILDCARD_BOUND_GENERIC_OR_ARRAY(0x1D, HasBound, HasLocation),
/** For annotations on a typecast. */
CAST(0x43, true),
CLASS_LITERAL(0x1E, IsLocal),
CLASS_LITERAL_GENERIC_OR_ARRAY(0x1F, HasLocation, IsLocal),
/** For annotations on a type test. */
INSTANCEOF(0x44, true),
METHOD_TYPE_PARAMETER(0x20, HasParameter),
/** For annotations on an object creation expression. */
NEW(0x45, true),
// invalid location
//@Deprecated METHOD_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x21, HasLocation, HasParameter),
/** For annotations on a type argument of an object creation expression. */
CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT(0x46, true),
CLASS_TYPE_PARAMETER(0x22, HasParameter),
/** For annotations on a type argument of a method call. */
METHOD_INVOCATION_TYPE_ARGUMENT(0x47, true),
// invalid location
//@Deprecated CLASS_TYPE_PARAMETER_GENERIC_OR_ARRAY(0x23, HasLocation, HasParameter),
/** For annotations on a lambda parameter type. */
LAMBDA_FORMAL_PARAMETER(0x48, true),
/** For annotations on a method reference. */
METHOD_REFERENCE(0x49, true),
/** For annotations on a type argument of a method reference. */
METHOD_REFERENCE_TYPE_ARGUMENT(0x50, true),
/** For annotations with an unknown target. */
UNKNOWN(-1);
UNKNOWN(0xFF);
static final int MAXIMUM_TARGET_TYPE_VALUE = 0x22;
private static final int MAXIMUM_TARGET_TYPE_VALUE = 0x92;
private final int targetTypeValue;
private final Set<TargetAttribute> flags;
private final boolean isLocal;
TargetType(int targetTypeValue, TargetAttribute... attributes) {
if (targetTypeValue < Byte.MIN_VALUE
|| targetTypeValue > Byte.MAX_VALUE)
throw new AssertionError("attribute type value needs to be a byte: " + targetTypeValue);
this.targetTypeValue = (byte)targetTypeValue;
flags = EnumSet.noneOf(TargetAttribute.class);
for (TargetAttribute attr : attributes)
flags.add(attr);
private TargetType(int targetTypeValue) {
this(targetTypeValue, false);
}
/**
* Returns whether or not this TargetType represents an annotation whose
* target is an inner type of a generic or array type.
*
* @return true if this TargetType represents an annotation on an inner
* type, false otherwise
*/
public boolean hasLocation() {
return flags.contains(HasLocation);
}
public TargetType getGenericComplement() {
if (hasLocation())
return this;
else
return fromTargetTypeValue(targetTypeValue() + 1);
}
/**
* Returns whether or not this TargetType represents an annotation whose
* target has a parameter index.
*
* @return true if this TargetType has a parameter index,
* false otherwise
*/
public boolean hasParameter() {
return flags.contains(HasParameter);
}
/**
* Returns whether or not this TargetType represents an annotation whose
* target is a type parameter bound.
*
* @return true if this TargetType represents an type parameter bound
* annotation, false otherwise
*/
public boolean hasBound() {
return flags.contains(HasBound);
private TargetType(int targetTypeValue, boolean isLocal) {
if (targetTypeValue < 0
|| targetTypeValue > 255)
Assert.error("Attribute type value needs to be an unsigned byte: " + String.format("0x%02X", targetTypeValue));
this.targetTypeValue = targetTypeValue;
this.isLocal = isLocal;
}
/**
@ -226,7 +134,7 @@ public enum TargetType {
* member declaration signature tree
*/
public boolean isLocal() {
return flags.contains(IsLocal);
return isLocal;
}
public int targetTypeValue() {
@ -239,7 +147,7 @@ public enum TargetType {
targets = new TargetType[MAXIMUM_TARGET_TYPE_VALUE + 1];
TargetType[] alltargets = values();
for (TargetType target : alltargets) {
if (target.targetTypeValue >= 0)
if (target.targetTypeValue != UNKNOWN.targetTypeValue)
targets[target.targetTypeValue] = target;
}
for (int i = 0; i <= MAXIMUM_TARGET_TYPE_VALUE; ++i) {
@ -249,22 +157,18 @@ public enum TargetType {
}
public static boolean isValidTargetTypeValue(int tag) {
if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
if (tag == UNKNOWN.targetTypeValue)
return true;
return (tag >= 0 && tag < targets.length);
}
public static TargetType fromTargetTypeValue(int tag) {
if (((byte)tag) == ((byte)UNKNOWN.targetTypeValue))
if (tag == UNKNOWN.targetTypeValue)
return UNKNOWN;
if (tag < 0 || tag >= targets.length)
throw new IllegalArgumentException("Unknown TargetType: " + tag);
Assert.error("Unknown TargetType: " + tag);
return targets[tag];
}
static enum TargetAttribute {
HasLocation, HasParameter, HasBound, IsLocal;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -31,6 +31,7 @@ import java.util.EnumSet;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.type.*;
import com.sun.tools.javac.code.Symbol.*;
@ -87,7 +88,7 @@ public class Type implements PrimitiveType {
*/
protected TypeTag tag;
/** The defining class / interface / package / type variable
/** The defining class / interface / package / type variable.
*/
public TypeSymbol tsym;
@ -166,7 +167,7 @@ public class Type implements PrimitiveType {
/**
* Get the representation of this type used for modelling purposes.
* By default, this is itself. For ErrorType, a different value
* may be provided,
* may be provided.
*/
public Type getModelType() {
return this;
@ -245,6 +246,14 @@ public class Type implements PrimitiveType {
return this;
}
/**
* If this is an annotated type, return the underlying type.
* Otherwise, return the type itself.
*/
public Type unannotatedType() {
return this;
}
/** Return the base types of a list of types.
*/
public static List<Type> baseTypes(List<Type> ts) {
@ -339,8 +348,11 @@ public class Type implements PrimitiveType {
args = args.tail;
buf.append(',');
}
if (args.head.tag == ARRAY) {
buf.append(((ArrayType)args.head).elemtype);
if (args.head.unannotatedType().tag == ARRAY) {
buf.append(((ArrayType)args.head.unannotatedType()).elemtype);
if (args.head.getAnnotations().nonEmpty()) {
buf.append(args.head.getAnnotations());
}
buf.append("...");
} else {
buf.append(args.head);
@ -350,10 +362,12 @@ public class Type implements PrimitiveType {
/** Access methods.
*/
public List<? extends AnnotationMirror> getAnnotations() { return List.nil(); }
public List<Type> getTypeArguments() { return List.nil(); }
public Type getEnclosingType() { return null; }
public Type getEnclosingType() { return null; }
public List<Type> getParameterTypes() { return List.nil(); }
public Type getReturnType() { return null; }
public Type getReceiverType() { return null; }
public List<Type> getThrownTypes() { return List.nil(); }
public Type getUpperBound() { return null; }
public Type getLowerBound() { return null; }
@ -600,7 +614,7 @@ public class Type implements PrimitiveType {
/** The enclosing type of this type. If this is the type of an inner
* class, outer_field refers to the type of its enclosing
* instance class, in all other cases it referes to noType.
* instance class, in all other cases it refers to noType.
*/
private Type outer_field;
@ -974,6 +988,10 @@ public class Type implements PrimitiveType {
public Type restype;
public List<Type> thrown;
/** The type annotations on the method receiver.
*/
public Type recvtype;
public MethodType(List<Type> argtypes,
Type restype,
List<Type> thrown,
@ -1000,6 +1018,7 @@ public class Type implements PrimitiveType {
public List<Type> getParameterTypes() { return argtypes; }
public Type getReturnType() { return restype; }
public Type getReceiverType() { return recvtype; }
public List<Type> getThrownTypes() { return thrown; }
public boolean isErroneous() {
@ -1028,6 +1047,7 @@ public class Type implements PrimitiveType {
for (List<Type> l = argtypes; l.nonEmpty(); l = l.tail)
l.head.complete();
restype.complete();
recvtype.complete();
for (List<Type> l = thrown; l.nonEmpty(); l = l.tail)
l.head.complete();
}
@ -1112,7 +1132,11 @@ public class Type implements PrimitiveType {
}
@Override
public Type getUpperBound() { return bound; }
public Type getUpperBound() {
if ((bound == null || bound.tag == NONE) && this != tsym.type)
bound = tsym.type.getUpperBound();
return bound;
}
int rank_field = -1;
@ -1183,6 +1207,7 @@ public class Type implements PrimitiveType {
public Type getEnclosingType() { return qtype.getEnclosingType(); }
public List<Type> getParameterTypes() { return qtype.getParameterTypes(); }
public Type getReturnType() { return qtype.getReturnType(); }
public Type getReceiverType() { return qtype.getReceiverType(); }
public List<Type> getThrownTypes() { return qtype.getThrownTypes(); }
public List<Type> allparams() { return qtype.allparams(); }
public Type getUpperBound() { return qtype.getUpperBound(); }
@ -1435,7 +1460,7 @@ public class Type implements PrimitiveType {
}
public Type constType(Object constValue) { return this; }
public Type getEnclosingType() { return this; }
public Type getEnclosingType() { return this; }
public Type getReturnType() { return this; }
public Type asSub(Symbol sym) { return this; }
public Type map(Mapping f) { return this; }
@ -1461,11 +1486,165 @@ public class Type implements PrimitiveType {
}
}
public static class AnnotatedType extends Type
implements javax.lang.model.type.AnnotatedType {
/** The type annotations on this type.
*/
public List<Attribute.TypeCompound> typeAnnotations;
/** The underlying type that is annotated.
*/
public Type underlyingType;
public AnnotatedType(Type underlyingType) {
super(underlyingType.tag, underlyingType.tsym);
this.typeAnnotations = List.nil();
this.underlyingType = underlyingType;
Assert.check(underlyingType.getKind() != TypeKind.ANNOTATED,
"Can't annotate already annotated type: " + underlyingType);
}
public AnnotatedType(List<Attribute.TypeCompound> typeAnnotations,
Type underlyingType) {
super(underlyingType.tag, underlyingType.tsym);
this.typeAnnotations = typeAnnotations;
this.underlyingType = underlyingType;
Assert.check(underlyingType.getKind() != TypeKind.ANNOTATED,
"Can't annotate already annotated type: " + underlyingType +
"; adding: " + typeAnnotations);
}
@Override
public TypeKind getKind() {
return TypeKind.ANNOTATED;
}
@Override
public List<? extends AnnotationMirror> getAnnotations() {
return typeAnnotations;
}
@Override
public TypeMirror getUnderlyingType() {
return underlyingType;
}
@Override
public Type unannotatedType() {
return underlyingType;
}
@Override
public <R,S> R accept(Type.Visitor<R,S> v, S s) {
return v.visitAnnotatedType(this, s);
}
@Override
public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return v.visitAnnotated(this, p);
}
@Override
public Type map(Mapping f) {
underlyingType.map(f);
return this;
}
@Override
public Type constType(Object constValue) { return underlyingType.constType(constValue); }
@Override
public Type getEnclosingType() { return underlyingType.getEnclosingType(); }
@Override
public Type getReturnType() { return underlyingType.getReturnType(); }
@Override
public List<Type> getTypeArguments() { return underlyingType.getTypeArguments(); }
@Override
public List<Type> getParameterTypes() { return underlyingType.getParameterTypes(); }
@Override
public Type getReceiverType() { return underlyingType.getReceiverType(); }
@Override
public List<Type> getThrownTypes() { return underlyingType.getThrownTypes(); }
@Override
public Type getUpperBound() { return underlyingType.getUpperBound(); }
@Override
public Type getLowerBound() { return underlyingType.getLowerBound(); }
@Override
public boolean isErroneous() { return underlyingType.isErroneous(); }
@Override
public boolean isCompound() { return underlyingType.isCompound(); }
@Override
public boolean isInterface() { return underlyingType.isInterface(); }
@Override
public List<Type> allparams() { return underlyingType.allparams(); }
@Override
public boolean isNumeric() { return underlyingType.isNumeric(); }
@Override
public boolean isReference() { return underlyingType.isReference(); }
@Override
public boolean isParameterized() { return underlyingType.isParameterized(); }
@Override
public boolean isRaw() { return underlyingType.isRaw(); }
@Override
public boolean isFinal() { return underlyingType.isFinal(); }
@Override
public boolean isSuperBound() { return underlyingType.isSuperBound(); }
@Override
public boolean isExtendsBound() { return underlyingType.isExtendsBound(); }
@Override
public boolean isUnbound() { return underlyingType.isUnbound(); }
@Override
public String toString() {
// TODO more logic for arrays, etc.
if (typeAnnotations != null &&
!typeAnnotations.isEmpty()) {
return "(" + typeAnnotations.toString() + " :: " + underlyingType.toString() + ")";
} else {
return "({} :: " + underlyingType.toString() +")";
}
}
@Override
public boolean contains(Type t) { return underlyingType.contains(t); }
// TODO: attach annotations?
@Override
public Type withTypeVar(Type t) { return underlyingType.withTypeVar(t); }
// TODO: attach annotations?
@Override
public TypeSymbol asElement() { return underlyingType.asElement(); }
// TODO: attach annotations?
@Override
public MethodType asMethodType() { return underlyingType.asMethodType(); }
@Override
public void complete() { underlyingType.complete(); }
@Override
public TypeMirror getComponentType() { return ((ArrayType)underlyingType).getComponentType(); }
// The result is an ArrayType, but only in the model sense, not the Type sense.
public AnnotatedType makeVarargs() {
AnnotatedType atype = new AnnotatedType(((ArrayType)underlyingType).makeVarargs());
atype.typeAnnotations = this.typeAnnotations;
return atype;
}
@Override
public TypeMirror getExtendsBound() { return ((WildcardType)underlyingType).getExtendsBound(); }
@Override
public TypeMirror getSuperBound() { return ((WildcardType)underlyingType).getSuperBound(); }
}
/**
* A visitor for types. A visitor is used to implement operations
* (or relations) on types. Most common operations on types are
* binary relations and this interface is designed for binary
* relations, that is, operations on the form
* relations, that is, operations of the form
* Type&nbsp;&times;&nbsp;S&nbsp;&rarr;&nbsp;R.
* <!-- In plain text: Type x S -> R -->
*
@ -1486,6 +1665,7 @@ public class Type implements PrimitiveType {
R visitForAll(ForAll t, S s);
R visitUndetVar(UndetVar t, S s);
R visitErrorType(ErrorType t, S s);
R visitAnnotatedType(AnnotatedType t, S s);
R visitType(Type t, S s);
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -25,6 +25,8 @@
package com.sun.tools.javac.code;
import java.util.Iterator;
import com.sun.tools.javac.util.*;
/** A type annotation position.
@ -34,12 +36,92 @@ import com.sun.tools.javac.util.*;
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
// Code duplicated in com.sun.tools.classfile.TypeAnnotation.Position
public class TypeAnnotationPosition {
public enum TypePathEntryKind {
ARRAY(0),
INNER_TYPE(1),
WILDCARD(2),
TYPE_ARGUMENT(3);
public final int tag;
private TypePathEntryKind(int tag) {
this.tag = tag;
}
}
public static class TypePathEntry {
/** The fixed number of bytes per TypePathEntry. */
public static final int bytesPerEntry = 2;
public final TypePathEntryKind tag;
public final int arg;
public static final TypePathEntry ARRAY = new TypePathEntry(TypePathEntryKind.ARRAY);
public static final TypePathEntry INNER_TYPE = new TypePathEntry(TypePathEntryKind.INNER_TYPE);
public static final TypePathEntry WILDCARD = new TypePathEntry(TypePathEntryKind.WILDCARD);
private TypePathEntry(TypePathEntryKind tag) {
Assert.check(tag == TypePathEntryKind.ARRAY ||
tag == TypePathEntryKind.INNER_TYPE ||
tag == TypePathEntryKind.WILDCARD,
"Invalid TypePathEntryKind: " + tag);
this.tag = tag;
this.arg = 0;
}
public TypePathEntry(TypePathEntryKind tag, int arg) {
Assert.check(tag == TypePathEntryKind.TYPE_ARGUMENT,
"Invalid TypePathEntryKind: " + tag);
this.tag = tag;
this.arg = arg;
}
public static TypePathEntry fromBinary(int tag, int arg) {
Assert.check(arg == 0 || tag == TypePathEntryKind.TYPE_ARGUMENT.tag,
"Invalid TypePathEntry tag/arg: " + tag + "/" + arg);
switch (tag) {
case 0:
return ARRAY;
case 1:
return INNER_TYPE;
case 2:
return WILDCARD;
case 3:
return new TypePathEntry(TypePathEntryKind.TYPE_ARGUMENT, arg);
default:
Assert.error("Invalid TypePathEntryKind tag: " + tag);
return null;
}
}
@Override
public String toString() {
return tag.toString() +
(tag == TypePathEntryKind.TYPE_ARGUMENT ? ("(" + arg + ")") : "");
}
@Override
public boolean equals(Object other) {
if (! (other instanceof TypePathEntry)) {
return false;
}
TypePathEntry tpe = (TypePathEntry) other;
return this.tag == tpe.tag && this.arg == tpe.arg;
}
@Override
public int hashCode() {
return this.tag.hashCode() * 17 + this.arg;
}
}
public TargetType type = TargetType.UNKNOWN;
// For generic/array types.
public List<Integer> location = List.nil();
public List<TypePathEntry> location = List.nil();
// Tree position.
public int pos = -1;
@ -59,11 +141,13 @@ public class TypeAnnotationPosition {
// For type parameter and method parameter
public int parameter_index = Integer.MIN_VALUE;
// For class extends, implements, and throws classes
// For class extends, implements, and throws clauses
public int type_index = Integer.MIN_VALUE;
// For wildcards
public TypeAnnotationPosition wildcard_position = null;
// For exception parameters, index into exception table
public int exception_index = Integer.MIN_VALUE;
public TypeAnnotationPosition() {}
@Override
public String toString() {
@ -72,27 +156,27 @@ public class TypeAnnotationPosition {
sb.append(type);
switch (type) {
// type case
case TYPECAST:
case TYPECAST_GENERIC_OR_ARRAY:
// object creation
// type cast
case CAST:
// instanceof
case INSTANCEOF:
case INSTANCEOF_GENERIC_OR_ARRAY:
// new expression
// new expression
case NEW:
case NEW_GENERIC_OR_ARRAY:
case NEW_TYPE_ARGUMENT:
case NEW_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
sb.append(", offset = ");
sb.append(offset);
break;
// local variable
// local variable
case LOCAL_VARIABLE:
case LOCAL_VARIABLE_GENERIC_OR_ARRAY:
// resource variable
case RESOURCE_VARIABLE:
if (lvarOffset == null) {
sb.append(", lvarOffset is null!");
break;
}
sb.append(", {");
for (int i = 0; i < lvarOffset.length; ++i) {
if (i != 0) sb.append("; ");
sb.append(", start_pc = ");
sb.append("start_pc = ");
sb.append(lvarOffset[i]);
sb.append(", length = ");
sb.append(lvarLength[i]);
@ -101,73 +185,72 @@ public class TypeAnnotationPosition {
}
sb.append("}");
break;
// method receiver
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameters
// type parameter
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
sb.append(", param_index = ");
sb.append(parameter_index);
break;
// type parameters bound
// type parameter bound
case CLASS_TYPE_PARAMETER_BOUND:
case CLASS_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
case METHOD_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND_GENERIC_OR_ARRAY:
sb.append(", param_index = ");
sb.append(parameter_index);
sb.append(", bound_index = ");
sb.append(bound_index);
break;
// wildcard
case WILDCARD_BOUND:
case WILDCARD_BOUND_GENERIC_OR_ARRAY:
sb.append(", wild_card = ");
sb.append(wildcard_position);
break;
// Class extends and implements clauses
// class extends or implements clause
case CLASS_EXTENDS:
case CLASS_EXTENDS_GENERIC_OR_ARRAY:
sb.append(", type_index = ");
sb.append(type_index);
break;
// throws
// throws
case THROWS:
sb.append(", type_index = ");
sb.append(type_index);
break;
case CLASS_LITERAL:
case CLASS_LITERAL_GENERIC_OR_ARRAY:
sb.append(", offset = ");
sb.append(offset);
// exception parameter
case EXCEPTION_PARAMETER:
sb.append(", exception_index = ");
sb.append(exception_index);
break;
// method parameter: not specified
case METHOD_PARAMETER_GENERIC_OR_ARRAY:
// method parameter
case METHOD_FORMAL_PARAMETER:
sb.append(", param_index = ");
sb.append(parameter_index);
break;
// method type argument: wasn't specified
case METHOD_TYPE_ARGUMENT:
case METHOD_TYPE_ARGUMENT_GENERIC_OR_ARRAY:
// method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT:
sb.append(", offset = ");
sb.append(offset);
sb.append(", type_index = ");
sb.append(type_index);
break;
// We don't need to worry abut these
case METHOD_RETURN_GENERIC_OR_ARRAY:
case FIELD_GENERIC_OR_ARRAY:
// We don't need to worry about these
case METHOD_RETURN:
case FIELD:
break;
// lambda formal parameter
case LAMBDA_FORMAL_PARAMETER:
// TODO: also needs an offset?
sb.append(", param_index = ");
sb.append(parameter_index);
break;
case UNKNOWN:
sb.append(", position UNKNOWN!");
break;
default:
// throw new AssertionError("unknown type: " + type);
Assert.error("Unknown target type: " + type);
}
// Append location data for generics/arrays.
if (type.hasLocation()) {
if (!location.isEmpty()) {
sb.append(", location = (");
sb.append(location);
sb.append(")");
@ -186,10 +269,33 @@ public class TypeAnnotationPosition {
* @return true if the target has not been optimized away
*/
public boolean emitToClassfile() {
if (type == TargetType.WILDCARD_BOUND
|| type == TargetType.WILDCARD_BOUND_GENERIC_OR_ARRAY)
return wildcard_position.isValidOffset;
else
return !type.isLocal() || isValidOffset;
return !type.isLocal() || isValidOffset;
}
/**
* Decode the binary representation for a type path and set
* the {@code location} field.
*
* @param list The bytecode representation of the type path.
*/
public static List<TypePathEntry> getTypePathFromBinary(java.util.List<Integer> list) {
ListBuffer<TypePathEntry> loc = ListBuffer.lb();
Iterator<Integer> iter = list.iterator();
while (iter.hasNext()) {
Integer fst = iter.next();
Assert.check(iter.hasNext(), "Could not decode type path: " + list);
Integer snd = iter.next();
loc = loc.append(TypePathEntry.fromBinary(fst, snd));
}
return loc.toList();
}
public static List<Integer> getBinaryFromTypePath(java.util.List<TypePathEntry> locs) {
ListBuffer<Integer> loc = ListBuffer.lb();
for (TypePathEntry tpe : locs) {
loc = loc.append(tpe.tag.tag);
loc = loc.append(tpe.arg);
}
return loc.toList();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -34,13 +34,14 @@ import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import javax.lang.model.type.TypeKind;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Type.UndetVar.InferenceBound;
import com.sun.tools.javac.comp.Check;
import com.sun.tools.javac.jvm.ClassReader;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Scope.*;
@ -684,6 +685,8 @@ public class Types {
//where
private boolean isSubtypeUncheckedInternal(Type t, Type s, Warner warn) {
if (t.hasTag(ARRAY) && s.hasTag(ARRAY)) {
t = t.unannotatedType();
s = s.unannotatedType();
if (((ArrayType)t).elemtype.isPrimitive()) {
return isSameType(elemtype(t), elemtype(s));
} else {
@ -709,7 +712,10 @@ public class Types {
}
private void checkUnsafeVarargsConversion(Type t, Type s, Warner warn) {
if (t.tag != ARRAY || isReifiable(t)) return;
if (t.tag != ARRAY || isReifiable(t))
return;
t = t.unannotatedType();
s = s.unannotatedType();
ArrayType from = (ArrayType)t;
boolean shouldWarn = false;
switch (s.tag) {
@ -739,6 +745,12 @@ public class Types {
return isSubtype(t, s, false);
}
public boolean isSubtype(Type t, Type s, boolean capture) {
if (t == s)
return true;
t = t.unannotatedType();
s = s.unannotatedType();
if (t == s)
return true;
@ -1683,6 +1695,7 @@ public class Types {
case WILDCARD:
return elemtype(upperBound(t));
case ARRAY:
t = t.unannotatedType();
return ((ArrayType)t).elemtype;
case FORALL:
return elemtype(((ForAll)t).qtype);
@ -2011,6 +2024,11 @@ public class Types {
public Type visitErrorType(ErrorType t, Boolean recurse) {
return t;
}
@Override
public Type visitAnnotatedType(AnnotatedType t, Boolean recurse) {
return new AnnotatedType(t.typeAnnotations, erasure(t.underlyingType, recurse));
}
};
private Mapping erasureFun = new Mapping ("erasure") {
@ -2953,6 +2971,7 @@ public class Types {
* graph. Undefined for all but reference types.
*/
public int rank(Type t) {
t = t.unannotatedType();
switch(t.tag) {
case CLASS: {
ClassType cls = (ClassType)t;
@ -3654,6 +3673,7 @@ public class Types {
t = subst(type1, t.tsym.type.getTypeArguments(), t.getTypeArguments());
}
}
t = t.unannotatedType();
ClassType cls = (ClassType)t;
if (cls.isRaw() || !cls.isParameterized())
return cls;
@ -4172,6 +4192,8 @@ public class Types {
public R visitForAll(ForAll t, S s) { return visitType(t, s); }
public R visitUndetVar(UndetVar t, S s) { return visitType(t, s); }
public R visitErrorType(ErrorType t, S s) { return visitType(t, s); }
// Pretend annotations don't exist
public R visitAnnotatedType(AnnotatedType t, S s) { return visit(t.underlyingType, s); }
}
/**

View File

@ -26,6 +26,7 @@
package com.sun.tools.javac.comp;
import java.util.Map;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.code.*;
@ -87,20 +88,30 @@ public class Annotate {
private int enterCount = 0;
ListBuffer<Annotator> q = new ListBuffer<Annotator>();
ListBuffer<Annotator> typesQ = new ListBuffer<Annotator>();
ListBuffer<Annotator> repeatedQ = new ListBuffer<Annotator>();
public void normal(Annotator a) {
q.append(a);
}
ListBuffer<Annotator> afterRepeatedQ = new ListBuffer<Annotator>();
public void earlier(Annotator a) {
q.prepend(a);
}
public void normal(Annotator a) {
q.append(a);
}
public void typeAnnotation(Annotator a) {
typesQ.append(a);
}
public void repeated(Annotator a) {
repeatedQ.append(a);
}
public void afterRepeated(Annotator a) {
afterRepeatedQ.append(a);
}
/** Called when the Enter phase starts. */
public void enterStart() {
enterCount++;
@ -116,12 +127,18 @@ public class Annotate {
if (enterCount != 0) return;
enterCount++;
try {
while (q.nonEmpty())
while (q.nonEmpty()) {
q.next().enterAnnotation();
}
while (typesQ.nonEmpty()) {
typesQ.next().enterAnnotation();
}
while (repeatedQ.nonEmpty()) {
repeatedQ.next().enterAnnotation();
}
while (afterRepeatedQ.nonEmpty()) {
afterRepeatedQ.next().enterAnnotation();
}
} finally {
enterCount--;
}
@ -141,16 +158,18 @@ public class Annotate {
* This context contains all the information needed to synthesize new
* annotations trees by the completer for repeating annotations.
*/
public class AnnotateRepeatedContext {
public class AnnotateRepeatedContext<T extends Attribute.Compound> {
public final Env<AttrContext> env;
public final Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated;
public final Map<Attribute.Compound, JCDiagnostic.DiagnosticPosition> pos;
public final Map<Symbol.TypeSymbol, ListBuffer<T>> annotated;
public final Map<T, JCDiagnostic.DiagnosticPosition> pos;
public final Log log;
public final boolean isTypeCompound;
public AnnotateRepeatedContext(Env<AttrContext> env,
Map<Symbol.TypeSymbol, ListBuffer<Attribute.Compound>> annotated,
Map<Attribute.Compound, JCDiagnostic.DiagnosticPosition> pos,
Log log) {
Map<Symbol.TypeSymbol, ListBuffer<T>> annotated,
Map<T, JCDiagnostic.DiagnosticPosition> pos,
Log log,
boolean isTypeCompound) {
Assert.checkNonNull(env);
Assert.checkNonNull(annotated);
Assert.checkNonNull(pos);
@ -160,6 +179,7 @@ public class Annotate {
this.annotated = annotated;
this.pos = pos;
this.log = log;
this.isTypeCompound = isTypeCompound;
}
/**
@ -170,7 +190,7 @@ public class Annotate {
* @param repeatingAnnotations a List of repeating annotations
* @return a new Attribute.Compound that is the container for the repeatingAnnotations
*/
public Attribute.Compound processRepeatedAnnotations(List<Attribute.Compound> repeatingAnnotations, Symbol sym) {
public T processRepeatedAnnotations(List<T> repeatingAnnotations, Symbol sym) {
return Annotate.this.processRepeatedAnnotations(repeatingAnnotations, this, sym);
}
@ -246,7 +266,12 @@ public class Annotate {
((MethodSymbol)method, value));
t.type = result;
}
return new Attribute.Compound(a.type, buf.toList());
// TODO: this should be a TypeCompound if "a" is a JCTypeAnnotation.
// However, how do we find the correct position?
Attribute.Compound ac = new Attribute.Compound(a.type, buf.toList());
// TODO: is this something we want? Who would use it?
// a.attribute = ac;
return ac;
}
Attribute enterAttributeValue(Type expected,
@ -329,6 +354,15 @@ public class Annotate {
return new Attribute.Error(attr.attribExpr(tree, env, expected));
}
Attribute.TypeCompound enterTypeAnnotation(JCAnnotation a,
Type expected,
Env<AttrContext> env) {
Attribute.Compound c = enterAnnotation(a, expected, env);
Attribute.TypeCompound tc = new Attribute.TypeCompound(c.type, c.values, new TypeAnnotationPosition());
a.attribute = tc;
return tc;
}
/* *********************************
* Support for repeating annotations
***********************************/
@ -337,10 +371,10 @@ public class Annotate {
* synthesized container annotation or null IFF all repeating
* annotation are invalid. This method reports errors/warnings.
*/
private Attribute.Compound processRepeatedAnnotations(List<Attribute.Compound> annotations,
AnnotateRepeatedContext ctx,
Symbol on) {
Attribute.Compound firstOccurrence = annotations.head;
private <T extends Attribute.Compound> T processRepeatedAnnotations(List<T> annotations,
AnnotateRepeatedContext<T> ctx,
Symbol on) {
T firstOccurrence = annotations.head;
List<Attribute> repeated = List.nil();
Type origAnnoType = null;
Type arrayOfOrigAnnoType = null;
@ -350,16 +384,16 @@ public class Annotate {
Assert.check(!annotations.isEmpty() &&
!annotations.tail.isEmpty()); // i.e. size() > 1
for (List<Attribute.Compound> al = annotations;
for (List<T> al = annotations;
!al.isEmpty();
al = al.tail)
{
Attribute.Compound currentAnno = al.head;
T currentAnno = al.head;
origAnnoType = currentAnno.type;
if (arrayOfOrigAnnoType == null) {
arrayOfOrigAnnoType = types.makeArrayType(origAnnoType);
}
}
Type currentContainerType = getContainingType(currentAnno, ctx.pos.get(currentAnno));
if (currentContainerType == null) {
@ -383,25 +417,46 @@ public class Annotate {
if (!repeated.isEmpty()) {
repeated = repeated.reverse();
JCAnnotation annoTree;
TreeMaker m = make.at(ctx.pos.get(firstOccurrence));
Pair<MethodSymbol, Attribute> p =
new Pair<MethodSymbol, Attribute>(containerValueSymbol,
new Attribute.Array(arrayOfOrigAnnoType, repeated));
annoTree = m.Annotation(new Attribute.Compound(targetContainerType,
List.of(p)));
if (ctx.isTypeCompound) {
/* TODO: the following code would be cleaner:
Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
((Attribute.TypeCompound)annotations.head).position);
JCTypeAnnotation annoTree = m.TypeAnnotation(at);
at = enterTypeAnnotation(annoTree, targetContainerType, ctx.env);
*/
// However, we directly construct the TypeCompound to keep the
// direct relation to the contained TypeCompounds.
Attribute.TypeCompound at = new Attribute.TypeCompound(targetContainerType, List.of(p),
((Attribute.TypeCompound)annotations.head).position);
if (!chk.annotationApplicable(annoTree, on))
log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType);
// TODO: annotation applicability checks from below?
if (!chk.validateAnnotationDeferErrors(annoTree))
log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType);
at.setSynthesized(true);
Attribute.Compound c = enterAnnotation(annoTree,
targetContainerType,
ctx.env);
c.setSynthesized(true);
return c;
@SuppressWarnings("unchecked")
T x = (T) at;
return x;
} else {
Attribute.Compound c = new Attribute.Compound(targetContainerType, List.of(p));
JCAnnotation annoTree = m.Annotation(c);
if (!chk.annotationApplicable(annoTree, on))
log.error(annoTree.pos(), "invalid.repeatable.annotation.incompatible.target", targetContainerType, origAnnoType);
if (!chk.validateAnnotationDeferErrors(annoTree))
log.error(annoTree.pos(), "duplicate.annotation.invalid.repeated", origAnnoType);
c = enterAnnotation(annoTree, targetContainerType, ctx.env);
c.setSynthesized(true);
@SuppressWarnings("unchecked")
T x = (T) c;
return x;
}
} else {
return null; // errors should have been reported elsewhere
}

View File

@ -26,9 +26,9 @@
package com.sun.tools.javac.comp;
import java.util.*;
import java.util.Set;
import javax.lang.model.element.ElementKind;
import javax.lang.model.type.TypeKind;
import javax.tools.JavaFileObject;
import com.sun.source.tree.IdentifierTree;
@ -45,7 +45,6 @@ import com.sun.tools.javac.comp.DeferredAttr.AttrMode;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.jvm.Target;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
@ -880,6 +879,7 @@ public class Attr extends JCTree.Visitor {
deferredLintHandler.flush(tree.pos());
chk.checkDeprecatedAnnotation(tree.pos(), m);
// Create a new environment with local scope
// for attributing the method.
Env<AttrContext> localEnv = memberEnter.methodEnv(tree, env);
@ -923,6 +923,21 @@ public class Attr extends JCTree.Visitor {
// Check that result type is well-formed.
chk.validate(tree.restype, localEnv);
// Check that receiver type is well-formed.
if (tree.recvparam != null) {
// Use a new environment to check the receiver parameter.
// Otherwise I get "might not have been initialized" errors.
// Is there a better way?
Env<AttrContext> newEnv = memberEnter.methodEnv(tree, env);
attribType(tree.recvparam, newEnv);
chk.validate(tree.recvparam, newEnv);
if (!(tree.recvparam.type == m.owner.type || types.isSameType(tree.recvparam.type, m.owner.type))) {
// The == covers the common non-generic case, but for generic classes we need isSameType;
// note that equals didn't work.
log.error(tree.recvparam.pos(), "incorrect.receiver.type");
}
}
// annotation method checks
if ((owner.flags() & ANNOTATION) != 0) {
// annotation method cannot have throws clause
@ -996,9 +1011,14 @@ public class Attr extends JCTree.Visitor {
}
}
// Attribute all type annotations in the body
memberEnter.typeAnnotate(tree.body, localEnv, m);
annotate.flush();
// Attribute method body.
attribStat(tree.body, localEnv);
}
localEnv.info.scope.leave();
result = tree.type = m.type;
chk.validateAnnotations(tree.mods.annotations, m);
@ -1019,6 +1039,12 @@ public class Attr extends JCTree.Visitor {
memberEnter.memberEnter(tree, env);
annotate.flush();
}
} else {
if (tree.init != null) {
// Field initializer expression need to be entered.
memberEnter.typeAnnotate(tree.init, env, tree.sym);
annotate.flush();
}
}
VarSymbol v = tree.sym;
@ -1076,6 +1102,11 @@ public class Attr extends JCTree.Visitor {
new MethodSymbol(tree.flags | BLOCK, names.empty, null,
env.info.scope.owner);
if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++;
// Attribute all type annotations in the block
memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner);
annotate.flush();
attribStats(tree.stats, localEnv);
} else {
// Create a new local environment with a local scope.
@ -1847,10 +1878,24 @@ public class Attr extends JCTree.Visitor {
// If enclosing class is given, attribute it, and
// complete class name to be fully qualified
JCExpression clazz = tree.clazz; // Class field following new
JCExpression clazzid = // Identifier in class field
(clazz.hasTag(TYPEAPPLY))
? ((JCTypeApply) clazz).clazz
: clazz;
JCExpression clazzid; // Identifier in class field
JCAnnotatedType annoclazzid; // Annotated type enclosing clazzid
annoclazzid = null;
if (clazz.hasTag(TYPEAPPLY)) {
clazzid = ((JCTypeApply) clazz).clazz;
if (clazzid.hasTag(ANNOTATED_TYPE)) {
annoclazzid = (JCAnnotatedType) clazzid;
clazzid = annoclazzid.underlyingType;
}
} else {
if (clazz.hasTag(ANNOTATED_TYPE)) {
annoclazzid = (JCAnnotatedType) clazz;
clazzid = annoclazzid.underlyingType;
} else {
clazzid = clazz;
}
}
JCExpression clazzid1 = clazzid; // The same in fully qualified form
@ -1865,14 +1910,30 @@ public class Attr extends JCTree.Visitor {
// yields a clazz T.C.
Type encltype = chk.checkRefType(tree.encl.pos(),
attribExpr(tree.encl, env));
// TODO 308: in <expr>.new C, do we also want to add the type annotations
// from expr to the combined type, or not? Yes, do this.
clazzid1 = make.at(clazz.pos).Select(make.Type(encltype),
((JCIdent) clazzid).name);
if (clazz.hasTag(TYPEAPPLY))
clazz = make.at(tree.pos).
if (clazz.hasTag(ANNOTATED_TYPE)) {
JCAnnotatedType annoType = (JCAnnotatedType) clazz;
List<JCAnnotation> annos = annoType.annotations;
if (annoType.underlyingType.hasTag(TYPEAPPLY)) {
clazzid1 = make.at(tree.pos).
TypeApply(clazzid1,
((JCTypeApply) clazz).arguments);
}
clazzid1 = make.at(tree.pos).
AnnotatedType(annos, clazzid1);
} else if (clazz.hasTag(TYPEAPPLY)) {
clazzid1 = make.at(tree.pos).
TypeApply(clazzid1,
((JCTypeApply) clazz).arguments);
else
clazz = clazzid1;
}
clazz = clazzid1;
}
// Attribute clazz expression and store
@ -1889,6 +1950,9 @@ public class Attr extends JCTree.Visitor {
tree.clazz.type = clazztype;
TreeInfo.setSymbol(clazzid, TreeInfo.symbol(clazzid1));
clazzid.type = ((JCIdent) clazzid).sym.type;
if (annoclazzid != null) {
annoclazzid.type = clazzid.type;
}
if (!clazztype.isErroneous()) {
if (cdef != null && clazztype.tsym.isInterface()) {
log.error(tree.encl.pos(), "anon.class.impl.intf.no.qual.for.new");
@ -3255,8 +3319,18 @@ public class Attr extends JCTree.Visitor {
// Tree<Point>.Visitor.
else if (ownOuter.hasTag(CLASS) && site != ownOuter) {
Type normOuter = site;
if (normOuter.hasTag(CLASS))
if (normOuter.hasTag(CLASS)) {
normOuter = types.asEnclosingSuper(site, ownOuter.tsym);
if (site.getKind() == TypeKind.ANNOTATED) {
// Propagate any type annotations.
// TODO: should asEnclosingSuper do this?
// Note that the type annotations in site will be updated
// by annotateType. Therefore, modify site instead
// of creating a new AnnotatedType.
((AnnotatedType)site).underlyingType = normOuter;
normOuter = site;
}
}
if (normOuter == null) // perhaps from an import
normOuter = types.erasure(ownOuter);
if (normOuter != ownOuter)
@ -3644,8 +3718,15 @@ public class Attr extends JCTree.Visitor {
tree.type = result = checkIntersection(tree, tree.bounds);
}
public void visitTypeParameter(JCTypeParameter tree) {
TypeVar typeVar = (TypeVar)tree.type;
public void visitTypeParameter(JCTypeParameter tree) {
TypeVar typeVar = (TypeVar) tree.type;
if (tree.annotations != null && tree.annotations.nonEmpty()) {
AnnotatedType antype = new AnnotatedType(typeVar);
annotateType(antype, tree.annotations);
tree.type = antype;
}
if (!typeVar.bound.isErroneous()) {
//fixup type-parameter bound computed in 'attribTypeVariables'
typeVar.bound = checkIntersection(tree, tree.bounds);
@ -3741,6 +3822,44 @@ public class Attr extends JCTree.Visitor {
result = tree.type = syms.errType;
}
public void visitAnnotatedType(JCAnnotatedType tree) {
Type underlyingType = attribType(tree.getUnderlyingType(), env);
this.attribAnnotationTypes(tree.annotations, env);
AnnotatedType antype = new AnnotatedType(underlyingType);
annotateType(antype, tree.annotations);
result = tree.type = antype;
}
/**
* Apply the annotations to the particular type.
*/
public void annotateType(final AnnotatedType type, final List<JCAnnotation> annotations) {
if (annotations.isEmpty())
return;
annotate.typeAnnotation(new Annotate.Annotator() {
@Override
public String toString() {
return "annotate " + annotations + " onto " + type;
}
@Override
public void enterAnnotation() {
List<Attribute.TypeCompound> compounds = fromAnnotations(annotations);
type.typeAnnotations = compounds;
}
});
}
private static List<Attribute.TypeCompound> fromAnnotations(List<JCAnnotation> annotations) {
if (annotations.isEmpty())
return List.nil();
ListBuffer<Attribute.TypeCompound> buf = ListBuffer.lb();
for (JCAnnotation anno : annotations) {
buf.append((Attribute.TypeCompound) anno.attribute);
}
return buf.toList();
}
public void visitErroneous(JCErroneous tree) {
if (tree.errs != null)
for (JCTree err : tree.errs)
@ -3972,6 +4091,12 @@ public class Attr extends JCTree.Visitor {
(c.flags() & ABSTRACT) == 0) {
checkSerialVersionUID(tree, c);
}
// Correctly organize the postions of the type annotations
TypeAnnotations.organizeTypeAnnotationsBodies(this.syms, this.names, this.log, tree);
// Check type annotations applicability rules
validateTypeAnnotations(tree);
}
// where
/** get a diagnostic position for an attribute of Type t, or null if attribute missing */
@ -4029,6 +4154,94 @@ public class Attr extends JCTree.Visitor {
return types.capture(type);
}
private void validateTypeAnnotations(JCTree tree) {
tree.accept(typeAnnotationsValidator);
}
//where
private final JCTree.Visitor typeAnnotationsValidator =
new TreeScanner() {
public void visitAnnotation(JCAnnotation tree) {
if (tree.hasTag(TYPE_ANNOTATION)) {
// TODO: It seems to WMD as if the annotation in
// parameters, in particular also the recvparam, are never
// of type JCTypeAnnotation and therefore never checked!
// Luckily this check doesn't really do anything that isn't
// also done elsewhere.
chk.validateTypeAnnotation(tree, false);
}
super.visitAnnotation(tree);
}
public void visitTypeParameter(JCTypeParameter tree) {
chk.validateTypeAnnotations(tree.annotations, true);
scan(tree.bounds);
// Don't call super.
// This is needed because above we call validateTypeAnnotation with
// false, which would forbid annotations on type parameters.
// super.visitTypeParameter(tree);
}
public void visitMethodDef(JCMethodDecl tree) {
// Static methods cannot have receiver type annotations.
// In test case FailOver15.java, the nested method getString has
// a null sym, because an unknown class is instantiated.
// I would say it's safe to skip.
if (tree.sym != null && (tree.sym.flags() & Flags.STATIC) != 0) {
if (tree.recvparam != null) {
// TODO: better error message. Is the pos good?
log.error(tree.recvparam.pos(), "annotation.type.not.applicable");
}
}
if (tree.restype != null && tree.restype.type != null) {
validateAnnotatedType(tree.restype, tree.restype.type);
}
super.visitMethodDef(tree);
}
public void visitVarDef(final JCVariableDecl tree) {
if (tree.sym != null && tree.sym.type != null)
validateAnnotatedType(tree, tree.sym.type);
super.visitVarDef(tree);
}
public void visitTypeCast(JCTypeCast tree) {
if (tree.clazz != null && tree.clazz.type != null)
validateAnnotatedType(tree.clazz, tree.clazz.type);
super.visitTypeCast(tree);
}
public void visitTypeTest(JCInstanceOf tree) {
if (tree.clazz != null && tree.clazz.type != null)
validateAnnotatedType(tree.clazz, tree.clazz.type);
super.visitTypeTest(tree);
}
// TODO: what else do we need?
// public void visitNewClass(JCNewClass tree) {
// public void visitNewArray(JCNewArray tree) {
/* I would want to model this after
* com.sun.tools.javac.comp.Check.Validator.visitSelectInternal(JCFieldAccess)
* and override visitSelect and visitTypeApply.
* However, we only set the annotated type in the top-level type
* of the symbol.
* Therefore, we need to override each individual location where a type
* can occur.
*/
private void validateAnnotatedType(final JCTree errtree, final Type type) {
if (type.getEnclosingType() != null &&
type != type.getEnclosingType()) {
validateEnclosingAnnotatedType(errtree, type.getEnclosingType());
}
for (Type targ : type.getTypeArguments()) {
validateAnnotatedType(errtree, targ);
}
}
private void validateEnclosingAnnotatedType(final JCTree errtree, final Type type) {
validateAnnotatedType(errtree, type);
if (type.tsym != null &&
type.tsym.isStatic() &&
type.getAnnotations().nonEmpty()) {
// Enclosing static classes cannot have type annotations.
log.error(errtree.pos(), "cant.annotate.static.class");
}
}
};
// <editor-fold desc="post-attribution visitor">
/**

View File

@ -26,7 +26,7 @@
package com.sun.tools.javac.comp;
import java.util.*;
import java.util.Set;
import javax.tools.JavaFileManager;
import com.sun.tools.javac.code.*;
@ -101,6 +101,9 @@ public class Check {
context.put(checkKey, this);
names = Names.instance(context);
dfltTargetMeta = new Name[] { names.PACKAGE, names.TYPE,
names.FIELD, names.METHOD, names.CONSTRUCTOR,
names.ANNOTATION_TYPE, names.LOCAL_VARIABLE, names.PARAMETER};
log = Log.instance(context);
rs = Resolve.instance(context);
syms = Symtab.instance(context);
@ -572,35 +575,28 @@ public class Check {
if (!tree.type.isErroneous() &&
(env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
&& types.isSameType(tree.expr.type, tree.clazz.type)
&& !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz))
&& !is292targetTypeCast(tree)) {
log.warning(Lint.LintCategory.CAST,
tree.pos(), "redundant.cast", tree.expr.type);
}
}
//where
private boolean is292targetTypeCast(JCTypeCast tree) {
boolean is292targetTypeCast = false;
JCExpression expr = TreeInfo.skipParens(tree.expr);
if (expr.hasTag(APPLY)) {
JCMethodInvocation apply = (JCMethodInvocation)expr;
Symbol sym = TreeInfo.symbol(apply.meth);
is292targetTypeCast = sym != null &&
sym.kind == MTH &&
(sym.flags() & HYPOTHETICAL) != 0;
}
return is292targetTypeCast;
private boolean is292targetTypeCast(JCTypeCast tree) {
boolean is292targetTypeCast = false;
JCExpression expr = TreeInfo.skipParens(tree.expr);
if (expr.hasTag(APPLY)) {
JCMethodInvocation apply = (JCMethodInvocation)expr;
Symbol sym = TreeInfo.symbol(apply.meth);
is292targetTypeCast = sym != null &&
sym.kind == MTH &&
(sym.flags() & HYPOTHETICAL) != 0;
}
//where
/** Is type a type variable, or a (possibly multi-dimensional) array of
* type variables?
*/
boolean isTypeVar(Type t) {
return t.hasTag(TYPEVAR) || t.hasTag(ARRAY) && isTypeVar(types.elemtype(t));
return is292targetTypeCast;
}
private static final boolean ignoreAnnotatedCasts = true;
/** Check that a type is within some bounds.
*
* Used in TypeApply to verify that, e.g., X in {@code V<X>} is a valid
@ -853,7 +849,7 @@ public class Check {
// System.out.println("actuals: " + argtypes);
List<Type> formals = owntype.getParameterTypes();
Type last = useVarargs ? formals.last() : null;
if (sym.name==names.init &&
if (sym.name == names.init &&
sym.owner == syms.enumSym)
formals = formals.tail.tail;
List<JCExpression> args = argtrees;
@ -1326,6 +1322,11 @@ public class Check {
}
}
@Override
public void visitAnnotatedType(JCAnnotatedType tree) {
tree.underlyingType.accept(this);
}
/** Default visitor method: do nothing.
*/
@Override
@ -2246,7 +2247,7 @@ public class Check {
void checkImplementations(JCClassDecl tree) {
checkImplementations(tree, tree.sym, tree.sym);
}
//where
//where
/** Check that all methods which implement some
* method in `ic' conform to the method they implement.
*/
@ -2587,6 +2588,13 @@ public class Check {
validateAnnotation(a, s);
}
/** Check the type annotations.
*/
public void validateTypeAnnotations(List<JCAnnotation> annotations, boolean isTypeParameter) {
for (JCAnnotation a : annotations)
validateTypeAnnotation(a, isTypeParameter);
}
/** Check an annotation of a symbol.
*/
private void validateAnnotation(JCAnnotation a, Symbol s) {
@ -2613,6 +2621,14 @@ public class Check {
}
}
public void validateTypeAnnotation(JCAnnotation a, boolean isTypeParameter) {
Assert.checkNonNull(a.type, "annotation tree hasn't been attributed yet: " + a);
validateAnnotationTree(a);
if (!isTypeAnnotation(a, isTypeParameter))
log.error(a.pos(), "annotation.type.not.applicable");
}
/**
* Validate the proposed container 'repeatable' on the
* annotation type symbol 's'. Report errors at position
@ -2795,45 +2811,90 @@ public class Check {
return false;
}
/** Is the annotation applicable to type annotations? */
protected boolean isTypeAnnotation(JCAnnotation a, boolean isTypeParameter) {
Attribute.Compound atTarget =
a.annotationType.type.tsym.attribute(syms.annotationTargetType.tsym);
if (atTarget == null) {
// An annotation without @Target is not a type annotation.
return false;
}
Attribute atValue = atTarget.member(names.value);
if (!(atValue instanceof Attribute.Array)) {
return false; // error recovery
}
Attribute.Array arr = (Attribute.Array) atValue;
for (Attribute app : arr.values) {
if (!(app instanceof Attribute.Enum)) {
return false; // recovery
}
Attribute.Enum e = (Attribute.Enum) app;
if (e.value.name == names.TYPE_USE)
return true;
else if (isTypeParameter && e.value.name == names.TYPE_PARAMETER)
return true;
}
return false;
}
/** Is the annotation applicable to the symbol? */
boolean annotationApplicable(JCAnnotation a, Symbol s) {
Attribute.Array arr = getAttributeTargetAttribute(a.annotationType.type.tsym);
Name[] targets;
if (arr == null) {
return true;
targets = defaultTargetMetaInfo(a, s);
} else {
// TODO: can we optimize this?
targets = new Name[arr.values.length];
for (int i=0; i<arr.values.length; ++i) {
Attribute app = arr.values[i];
if (!(app instanceof Attribute.Enum)) {
return true; // recovery
}
Attribute.Enum e = (Attribute.Enum) app;
targets[i] = e.value.name;
}
}
for (Attribute app : arr.values) {
if (!(app instanceof Attribute.Enum)) return true; // recovery
Attribute.Enum e = (Attribute.Enum) app;
if (e.value.name == names.TYPE)
for (Name target : targets) {
if (target == names.TYPE)
{ if (s.kind == TYP) return true; }
else if (e.value.name == names.FIELD)
else if (target == names.FIELD)
{ if (s.kind == VAR && s.owner.kind != MTH) return true; }
else if (e.value.name == names.METHOD)
else if (target == names.METHOD)
{ if (s.kind == MTH && !s.isConstructor()) return true; }
else if (e.value.name == names.PARAMETER)
else if (target == names.PARAMETER)
{ if (s.kind == VAR &&
s.owner.kind == MTH &&
(s.flags() & PARAMETER) != 0)
return true;
}
else if (e.value.name == names.CONSTRUCTOR)
else if (target == names.CONSTRUCTOR)
{ if (s.kind == MTH && s.isConstructor()) return true; }
else if (e.value.name == names.LOCAL_VARIABLE)
else if (target == names.LOCAL_VARIABLE)
{ if (s.kind == VAR && s.owner.kind == MTH &&
(s.flags() & PARAMETER) == 0)
return true;
}
else if (e.value.name == names.ANNOTATION_TYPE)
else if (target == names.ANNOTATION_TYPE)
{ if (s.kind == TYP && (s.flags() & ANNOTATION) != 0)
return true;
}
else if (e.value.name == names.PACKAGE)
else if (target == names.PACKAGE)
{ if (s.kind == PCK) return true; }
else if (e.value.name == names.TYPE_USE)
else if (target == names.TYPE_USE)
{ if (s.kind == TYP ||
s.kind == VAR ||
(s.kind == MTH && !s.isConstructor() &&
!s.type.getReturnType().hasTag(VOID)))
!s.type.getReturnType().hasTag(VOID)) ||
(s.kind == MTH && s.isConstructor()))
return true;
}
else if (target == names.TYPE_PARAMETER)
{ if (s.kind == TYP && s.type.hasTag(TYPEVAR))
return true;
}
else
@ -2852,6 +2913,11 @@ public class Check {
return (Attribute.Array) atValue;
}
private final Name[] dfltTargetMeta;
private Name[] defaultTargetMetaInfo(JCAnnotation a, Symbol s) {
return dfltTargetMeta;
}
/** Check an annotation value.
*
* @param a The annotation tree to check

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -29,8 +29,6 @@ import com.sun.tools.javac.code.*;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.code.Type.*;
import static com.sun.tools.javac.code.TypeTag.BOOLEAN;
import static com.sun.tools.javac.jvm.ByteCodes.*;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,6 +35,7 @@ import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.Resolve;
import com.sun.tools.javac.tree.JCTree.*;
import static com.sun.tools.javac.code.Flags.*;
@ -2175,6 +2176,11 @@ public class Flow {
unrefdResources.remove(sym);
}
public void visitAnnotatedType(JCAnnotatedType tree) {
// annotations don't get scanned
tree.underlyingType.accept(this);
}
public void visitTopLevel(JCCompilationUnit tree) {
// Do nothing for TopLevel since each class is visited individually
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -2288,7 +2288,7 @@ public class Lower extends TreeTranslator {
return tree.packageAnnotations.nonEmpty();
case NONEMPTY:
for (Attribute.Compound a :
tree.packge.annotations.getAttributes()) {
tree.packge.annotations.getDeclarationAttributes()) {
Attribute.RetentionPolicy p = types.getRetention(a);
if (p != Attribute.RetentionPolicy.SOURCE)
return true;
@ -2685,6 +2685,13 @@ public class Lower extends TreeTranslator {
result = tree;
}
public void visitAnnotatedType(JCAnnotatedType tree) {
// No need to retain type annotations any longer.
// tree.annotations = translate(tree.annotations);
tree.underlyingType = translate(tree.underlyingType);
result = tree.underlyingType;
}
public void visitTypeCast(JCTypeCast tree) {
tree.clazz = translate(tree.clazz);
if (tree.type.isPrimitive() != tree.expr.type.isPrimitive())

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -25,15 +25,19 @@
package com.sun.tools.javac.comp;
import java.util.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import javax.lang.model.type.TypeKind;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Symbol.*;
@ -345,12 +349,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
* @param params The method's value parameters.
* @param res The method's result type,
* null if it is a constructor.
* @param recvparam The method's receiver parameter,
* null if none given; TODO: or already set here?
* @param thrown The method's thrown exceptions.
* @param env The method's (local) environment.
*/
Type signature(List<JCTypeParameter> typarams,
List<JCVariableDecl> params,
JCTree res,
JCVariableDecl recvparam,
List<JCExpression> thrown,
Env<AttrContext> env) {
@ -368,6 +375,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
// Attribute result type, if one is given.
Type restype = res == null ? syms.voidType : attr.attribType(res, env);
// Attribute receiver type, if one is given.
Type recvtype;
if (recvparam!=null) {
memberEnter(recvparam, env);
recvtype = recvparam.vartype.type;
} else {
recvtype = null;
}
// Attribute thrown exceptions.
ListBuffer<Type> thrownbuf = new ListBuffer<Type>();
for (List<JCExpression> l = thrown; l.nonEmpty(); l = l.tail) {
@ -376,10 +392,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
exc = chk.checkClassType(l.head.pos(), exc);
thrownbuf.append(exc);
}
Type mtype = new MethodType(argbuf.toList(),
MethodType mtype = new MethodType(argbuf.toList(),
restype,
thrownbuf.toList(),
syms.methodClass);
mtype.recvtype = recvtype;
return tvars.isEmpty() ? mtype : new ForAll(tvars, mtype);
}
@ -573,7 +591,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
try {
// Compute the method type
m.type = signature(tree.typarams, tree.params,
tree.restype, tree.thrown,
tree.restype, tree.recvparam,
tree.thrown,
localEnv);
} finally {
chk.setDeferredLintHandler(prevLintHandler);
@ -597,6 +616,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
enclScope.enter(m);
}
annotateLater(tree.mods.annotations, localEnv, m);
// Visit the signature of the method. Note that
// TypeAnnotate doesn't descend into the body.
typeAnnotate(tree, localEnv, m);
if (tree.defaultValue != null)
annotateDefaultValueLater(tree.defaultValue, localEnv, m);
}
@ -642,7 +665,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
//(a plain array type) with the more precise VarargsType --- we need
//to do it this way because varargs is represented in the tree as a modifier
//on the parameter declaration, and not as a distinct type of array node.
ArrayType atype = (ArrayType)tree.vartype.type;
ArrayType atype = (ArrayType)tree.vartype.type.unannotatedType();
tree.vartype.type = atype.makeVarargs();
}
Scope enclScope = enter.enterScope(env);
@ -665,6 +688,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
enclScope.enter(v);
}
annotateLater(tree.mods.annotations, localEnv, v);
typeAnnotate(tree.vartype, env, tree.sym);
annotate.flush();
v.pos = tree.pos;
}
@ -759,7 +784,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
log.error(annotations.head.pos,
"already.annotated",
kindName(s), s);
enterAnnotations(annotations, localEnv, s);
actualEnterAnnotations(annotations, localEnv, s);
} finally {
log.useSource(prev);
}
@ -781,7 +806,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
}
/** Enter a set of annotations. */
private void enterAnnotations(List<JCAnnotation> annotations,
private void actualEnterAnnotations(List<JCAnnotation> annotations,
Env<AttrContext> env,
Symbol s) {
Map<TypeSymbol, ListBuffer<Attribute.Compound>> annotated =
@ -817,11 +842,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
&& s.owner.kind != MTH
&& types.isSameType(c.type, syms.deprecatedType)) {
s.flags_field |= Flags.DEPRECATED;
}
}
}
s.annotations.setAttributesWithCompletion(
annotate.new AnnotateRepeatedContext(env, annotated, pos, log));
s.annotations.setDeclarationAttributesWithCompletion(
annotate.new AnnotateRepeatedContext<Attribute.Compound>(env, annotated, pos, log, false));
}
/** Queue processing of an attribute default value. */
@ -900,6 +925,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
// create an environment for evaluating the base clauses
Env<AttrContext> baseEnv = baseEnv(tree, env);
if (tree.extending != null)
typeAnnotate(tree.extending, baseEnv, sym);
for (JCExpression impl : tree.implementing)
typeAnnotate(impl, baseEnv, sym);
annotate.flush();
// Determine supertype.
Type supertype =
(tree.extending != null)
@ -969,10 +1000,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
if (hasDeprecatedAnnotation(tree.mods.annotations))
c.flags_field |= DEPRECATED;
annotateLater(tree.mods.annotations, baseEnv, c);
// class type parameters use baseEnv but everything uses env
chk.checkNonCyclicDecl(tree);
attr.attribTypeVariables(tree.typarams, baseEnv);
// Do this here, where we have the symbol.
for (JCTypeParameter tp : tree.typarams)
typeAnnotate(tp, baseEnv, sym);
annotate.flush();
// Add default constructor if needed.
if ((c.flags() & INTERFACE) == 0 &&
@ -1050,12 +1086,120 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
} finally {
isFirst = true;
}
}
annotate.afterRepeated(TypeAnnotations.organizeTypeAnnotationsSignatures(syms, names, log, tree));
}
// commit pending annotations
annotate.flush();
private void actualEnterTypeAnnotations(final List<JCAnnotation> annotations,
final Env<AttrContext> env,
final Symbol s) {
Map<TypeSymbol, ListBuffer<Attribute.TypeCompound>> annotated =
new LinkedHashMap<TypeSymbol, ListBuffer<Attribute.TypeCompound>>();
Map<Attribute.TypeCompound, DiagnosticPosition> pos =
new HashMap<Attribute.TypeCompound, DiagnosticPosition>();
for (List<JCAnnotation> al = annotations; !al.isEmpty(); al = al.tail) {
JCAnnotation a = al.head;
Attribute.TypeCompound tc = annotate.enterTypeAnnotation(a,
syms.annotationType,
env);
if (tc == null) {
continue;
}
if (annotated.containsKey(a.type.tsym)) {
if (source.allowRepeatedAnnotations()) {
ListBuffer<Attribute.TypeCompound> l = annotated.get(a.type.tsym);
l = l.append(tc);
annotated.put(a.type.tsym, l);
pos.put(tc, a.pos());
} else {
log.error(a.pos(), "duplicate.annotation");
}
} else {
annotated.put(a.type.tsym, ListBuffer.of(tc));
pos.put(tc, a.pos());
}
}
s.annotations.appendTypeAttributesWithCompletion(
annotate.new AnnotateRepeatedContext<Attribute.TypeCompound>(env, annotated, pos, log, true));
}
public void typeAnnotate(final JCTree tree, final Env<AttrContext> env, final Symbol sym) {
tree.accept(new TypeAnnotate(env, sym));
}
/**
* We need to use a TreeScanner, because it is not enough to visit the top-level
* annotations. We also need to visit type arguments, etc.
*/
private class TypeAnnotate extends TreeScanner {
private Env<AttrContext> env;
private Symbol sym;
public TypeAnnotate(final Env<AttrContext> env, final Symbol sym) {
this.env = env;
this.sym = sym;
}
void annotateTypeLater(final List<JCAnnotation> annotations) {
if (annotations.isEmpty()) {
return;
}
annotate.normal(new Annotate.Annotator() {
@Override
public String toString() {
return "type annotate " + annotations + " onto " + sym + " in " + sym.owner;
}
@Override
public void enterAnnotation() {
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
try {
actualEnterTypeAnnotations(annotations, env, sym);
} finally {
log.useSource(prev);
}
}
});
}
@Override
public void visitAnnotatedType(final JCAnnotatedType tree) {
annotateTypeLater(tree.annotations);
super.visitAnnotatedType(tree);
}
@Override
public void visitTypeParameter(final JCTypeParameter tree) {
annotateTypeLater(tree.annotations);
super.visitTypeParameter(tree);
}
@Override
public void visitNewArray(final JCNewArray tree) {
annotateTypeLater(tree.annotations);
for (List<JCAnnotation> dimAnnos : tree.dimAnnotations)
annotateTypeLater(dimAnnos);
super.visitNewArray(tree);
}
@Override
public void visitMethodDef(final JCMethodDecl tree) {
scan(tree.mods);
scan(tree.restype);
scan(tree.typarams);
scan(tree.recvparam);
scan(tree.params);
scan(tree.thrown);
scan(tree.defaultValue);
// Do not annotate the body, just the signature.
// scan(tree.body);
}
}
private Env<AttrContext> baseEnv(JCClassDecl tree, Env<AttrContext> env) {
Scope baseScope = new Scope(tree.sym);
//import already entered local classes into base scope

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -55,7 +55,6 @@ import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import javax.lang.model.element.ElementVisitor;
@ -696,7 +695,7 @@ public class Resolve {
if (varargsFormal == null &&
argtypes.size() != formals.size()) {
report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
}
while (argtypes.nonEmpty() && formals.head != varargsFormal) {
@ -707,7 +706,7 @@ public class Resolve {
}
if (formals.head != varargsFormal) {
report(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
reportMC(MethodCheckDiag.ARITY_MISMATCH, inferenceContext); // not enough args
}
if (useVarargs) {
@ -724,7 +723,7 @@ public class Resolve {
}
}
private void report(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
private void reportMC(MethodCheckDiag diag, InferenceContext inferenceContext, Object... args) {
boolean inferDiag = inferenceContext != infer.emptyContext;
InapplicableMethodException ex = inferDiag ?
infer.inferenceException : inapplicableMethodException;
@ -748,7 +747,7 @@ public class Resolve {
} else {
if (!isAccessible(env, t)) {
Symbol location = env.enclClass.sym;
report(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
reportMC(MethodCheckDiag.INACCESSIBLE_VARARGS, inferenceContext, t, Kinds.kindName(location), location);
}
}
}
@ -761,7 +760,7 @@ public class Resolve {
@Override
public void report(DiagnosticPosition pos, JCDiagnostic details) {
report(methodDiag, deferredAttrContext.inferenceContext, details);
reportMC(methodDiag, deferredAttrContext.inferenceContext, details);
}
};
return new MethodResultInfo(to, checkContext);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -483,6 +483,7 @@ public class TransTypes extends TreeTranslator {
tree.restype = translate(tree.restype, null);
tree.typarams = List.nil();
tree.params = translateVarDefs(tree.params);
tree.recvparam = translate(tree.recvparam, null);
tree.thrown = translate(tree.thrown, null);
tree.body = translate(tree.body, tree.sym.erasure(types).getReturnType());
tree.type = erasure(tree.type);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -351,8 +351,8 @@ public class ClassReader implements Completer {
/** Read a byte.
*/
byte nextByte() {
return buf[bp++];
int nextByte() {
return buf[bp++] & 0xFF;
}
/** Read an integer.
@ -1172,6 +1172,19 @@ public class ClassReader implements Completer {
}
},
new AttributeReader(names.RuntimeVisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
protected void read(Symbol sym, int attrLen) {
attachTypeAnnotations(sym);
}
},
new AttributeReader(names.RuntimeInvisibleTypeAnnotations, V52, CLASS_OR_MEMBER_ATTRIBUTE) {
protected void read(Symbol sym, int attrLen) {
attachTypeAnnotations(sym);
}
},
// The following attributes for a Code attribute are not currently handled
// StackMapTable
// SourceDebugExtension
@ -1381,6 +1394,17 @@ public class ClassReader implements Completer {
}
}
void attachTypeAnnotations(final Symbol sym) {
int numAttributes = nextChar();
if (numAttributes != 0) {
ListBuffer<TypeAnnotationProxy> proxies =
ListBuffer.lb();
for (int i = 0; i < numAttributes; i++)
proxies.append(readTypeAnnotation());
annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList()));
}
}
/** Attach the default value for an annotation element.
*/
void attachAnnotationDefault(final Symbol sym) {
@ -1427,6 +1451,111 @@ public class ClassReader implements Completer {
return new CompoundAnnotationProxy(t, pairs.toList());
}
TypeAnnotationProxy readTypeAnnotation() {
TypeAnnotationPosition position = readPosition();
CompoundAnnotationProxy proxy = readCompoundAnnotation();
return new TypeAnnotationProxy(proxy, position);
}
TypeAnnotationPosition readPosition() {
int tag = nextByte(); // TargetType tag is a byte
if (!TargetType.isValidTargetTypeValue(tag))
throw this.badClassFile("bad.type.annotation.value", String.format("0x%02X", tag));
TypeAnnotationPosition position = new TypeAnnotationPosition();
TargetType type = TargetType.fromTargetTypeValue(tag);
position.type = type;
switch (type) {
// type cast
case CAST:
// instanceof
case INSTANCEOF:
// new expression
case NEW:
position.offset = nextChar();
break;
// local variable
case LOCAL_VARIABLE:
// resource variable
case RESOURCE_VARIABLE:
int table_length = nextChar();
position.lvarOffset = new int[table_length];
position.lvarLength = new int[table_length];
position.lvarIndex = new int[table_length];
for (int i = 0; i < table_length; ++i) {
position.lvarOffset[i] = nextChar();
position.lvarLength[i] = nextChar();
position.lvarIndex[i] = nextChar();
}
break;
// exception parameter
case EXCEPTION_PARAMETER:
position.exception_index = nextByte();
break;
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameter
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
position.parameter_index = nextByte();
break;
// type parameter bound
case CLASS_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND:
position.parameter_index = nextByte();
position.bound_index = nextByte();
break;
// class extends or implements clause
case CLASS_EXTENDS:
position.type_index = nextChar();
break;
// throws
case THROWS:
position.type_index = nextChar();
break;
// method parameter
case METHOD_FORMAL_PARAMETER:
position.parameter_index = nextByte();
break;
// method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT:
position.offset = nextChar();
position.type_index = nextByte();
break;
// We don't need to worry about these
case METHOD_RETURN:
case FIELD:
break;
// lambda formal parameter
case LAMBDA_FORMAL_PARAMETER:
position.parameter_index = nextByte();
break;
case UNKNOWN:
throw new AssertionError("jvm.ClassReader: UNKNOWN target type should never occur!");
default:
throw new AssertionError("jvm.ClassReader: Unknown target type for position: " + position);
}
{ // See whether there is location info and read it
int len = nextByte();
ListBuffer<Integer> loc = ListBuffer.lb();
for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i)
loc = loc.append(nextByte());
position.location = TypeAnnotationPosition.getTypePathFromBinary(loc.toList());
}
return position;
}
Attribute readAttributeValue() {
char c = (char) buf[bp++];
switch (c) {
@ -1748,7 +1877,7 @@ public class ClassReader implements Completer {
Annotations annotations = sym.annotations;
List<Attribute.Compound> newList = deproxyCompoundList(l);
if (annotations.pendingCompletion()) {
annotations.setAttributes(newList);
annotations.setDeclarationAttributes(newList);
} else {
annotations.append(newList);
}
@ -1758,6 +1887,39 @@ public class ClassReader implements Completer {
}
}
class TypeAnnotationCompleter extends AnnotationCompleter {
List<TypeAnnotationProxy> proxies;
TypeAnnotationCompleter(Symbol sym,
List<TypeAnnotationProxy> proxies) {
super(sym, List.<CompoundAnnotationProxy>nil());
this.proxies = proxies;
}
List<Attribute.TypeCompound> deproxyTypeCompoundList(List<TypeAnnotationProxy> proxies) {
ListBuffer<Attribute.TypeCompound> buf = ListBuffer.lb();
for (TypeAnnotationProxy proxy: proxies) {
Attribute.Compound compound = deproxyCompound(proxy.compound);
Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position);
buf.add(typeCompound);
}
return buf.toList();
}
@Override
public void enterAnnotation() {
JavaFileObject previousClassFile = currentClassFile;
try {
currentClassFile = classFile;
List<Attribute.TypeCompound> newList = deproxyTypeCompoundList(proxies);
sym.annotations.setTypeAttributes(newList.prependList(sym.getRawTypeAttributes()));
} finally {
currentClassFile = previousClassFile;
}
}
}
/************************************************************************
* Reading Symbols

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -31,12 +31,14 @@ import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import javax.lang.model.type.TypeKind;
import javax.tools.JavaFileManager;
import javax.tools.FileObject;
import javax.tools.JavaFileObject;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
import com.sun.tools.javac.code.Attribute.TypeCompound;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.*;
import com.sun.tools.javac.code.Types.UniqueType;
@ -47,7 +49,6 @@ import com.sun.tools.javac.jvm.Pool.MethodHandle;
import com.sun.tools.javac.jvm.Pool.Variable;
import com.sun.tools.javac.util.*;
import static com.sun.tools.javac.code.BoundKind.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Kinds.*;
import static com.sun.tools.javac.code.TypeTag.*;
@ -68,19 +69,17 @@ public class ClassWriter extends ClassFile {
protected static final Context.Key<ClassWriter> classWriterKey =
new Context.Key<ClassWriter>();
private final Symtab syms;
private final Options options;
/** Switch: verbose output.
*/
private boolean verbose;
/** Switch: scramble private names.
/** Switch: scramble private field names.
*/
private boolean scramble;
/** Switch: scramble private names.
/** Switch: scramble all field names.
*/
private boolean scrambleAll;
@ -96,7 +95,7 @@ public class ClassWriter extends ClassFile {
*/
private boolean genCrt;
/** Switch: describe the generated stackmap
/** Switch: describe the generated stackmap.
*/
boolean debugstackmap;
@ -114,7 +113,7 @@ public class ClassWriter extends ClassFile {
private Types types;
/** The initial sizes of the data and constant pool buffers.
* sizes are increased when buffers get full.
* Sizes are increased when buffers get full.
*/
static final int DATA_BUF_SIZE = 0x0fff0;
static final int POOL_BUF_SIZE = 0x1fff0;
@ -181,7 +180,6 @@ public class ClassWriter extends ClassFile {
log = Log.instance(context);
names = Names.instance(context);
syms = Symtab.instance(context);
options = Options.instance(context);
target = Target.instance(context);
source = Source.instance(context);
@ -279,6 +277,7 @@ public class ClassWriter extends ClassFile {
/** Assemble signature of given type in string buffer.
*/
void assembleSig(Type type) {
type = type.unannotatedType();
switch (type.getTag()) {
case BYTE:
sigbuf.appendByte('B');
@ -379,6 +378,7 @@ public class ClassWriter extends ClassFile {
}
void assembleClassSig(Type type) {
type = type.unannotatedType();
ClassType ct = (ClassType)type;
ClassSymbol c = (ClassSymbol)ct.tsym;
enterInner(c);
@ -722,6 +722,7 @@ public class ClassWriter extends ClassFile {
acount++;
}
acount += writeJavaAnnotations(sym.getRawAttributes());
acount += writeTypeAnnotations(sym.getRawTypeAttributes());
return acount;
}
@ -838,6 +839,76 @@ public class ClassWriter extends ClassFile {
return attrCount;
}
int writeTypeAnnotations(List<Attribute.TypeCompound> typeAnnos) {
if (typeAnnos.isEmpty()) return 0;
ListBuffer<Attribute.TypeCompound> visibles = ListBuffer.lb();
ListBuffer<Attribute.TypeCompound> invisibles = ListBuffer.lb();
for (Attribute.TypeCompound tc : typeAnnos) {
if (tc.position == null || tc.position.type == TargetType.UNKNOWN) {
boolean found = false;
// TODO: the position for the container annotation of a
// repeating type annotation has to be set.
// This cannot be done when the container is created, because
// then the position is not determined yet.
// How can we link these pieces better together?
if (tc.values.size() == 1) {
Pair<MethodSymbol, Attribute> val = tc.values.get(0);
if (val.fst.getSimpleName().contentEquals("value") &&
val.snd instanceof Attribute.Array) {
Attribute.Array arr = (Attribute.Array) val.snd;
if (arr.values.length != 0 &&
arr.values[0] instanceof Attribute.TypeCompound) {
TypeCompound atycomp = (Attribute.TypeCompound) arr.values[0];
if (atycomp.position.type != TargetType.UNKNOWN) {
tc.position = atycomp.position;
found = true;
}
}
}
}
if (!found) {
// This happens for nested types like @A Outer. @B Inner.
// For method parameters we get the annotation twice! Once with
// a valid position, once unknown.
// TODO: find a cleaner solution.
// System.err.println("ClassWriter: Position UNKNOWN in type annotation: " + tc);
continue;
}
}
if (!tc.position.emitToClassfile())
continue;
switch (types.getRetention(tc)) {
case SOURCE: break;
case CLASS: invisibles.append(tc); break;
case RUNTIME: visibles.append(tc); break;
default: ;// /* fail soft */ throw new AssertionError(vis);
}
}
int attrCount = 0;
if (visibles.length() != 0) {
int attrIndex = writeAttr(names.RuntimeVisibleTypeAnnotations);
databuf.appendChar(visibles.length());
for (Attribute.TypeCompound p : visibles)
writeTypeAnnotation(p);
endAttr(attrIndex);
attrCount++;
}
if (invisibles.length() != 0) {
int attrIndex = writeAttr(names.RuntimeInvisibleTypeAnnotations);
databuf.appendChar(invisibles.length());
for (Attribute.TypeCompound p : invisibles)
writeTypeAnnotation(p);
endAttr(attrIndex);
attrCount++;
}
return attrCount;
}
/** A visitor to write an attribute including its leading
* single-character marker.
*/
@ -914,6 +985,94 @@ public class ClassWriter extends ClassFile {
p.snd.accept(awriter);
}
}
void writeTypeAnnotation(Attribute.TypeCompound c) {
writePosition(c.position);
writeCompoundAttribute(c);
}
void writePosition(TypeAnnotationPosition p) {
databuf.appendByte(p.type.targetTypeValue()); // TargetType tag is a byte
switch (p.type) {
// type cast
case CAST:
// instanceof
case INSTANCEOF:
// new expression
case NEW:
databuf.appendChar(p.offset);
break;
// local variable
case LOCAL_VARIABLE:
// resource variable
case RESOURCE_VARIABLE:
databuf.appendChar(p.lvarOffset.length); // for table length
for (int i = 0; i < p.lvarOffset.length; ++i) {
databuf.appendChar(p.lvarOffset[i]);
databuf.appendChar(p.lvarLength[i]);
databuf.appendChar(p.lvarIndex[i]);
}
break;
// exception parameter
case EXCEPTION_PARAMETER:
databuf.appendByte(p.exception_index);
break;
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameter
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
databuf.appendByte(p.parameter_index);
break;
// type parameter bound
case CLASS_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND:
databuf.appendByte(p.parameter_index);
databuf.appendByte(p.bound_index);
break;
// class extends or implements clause
case CLASS_EXTENDS:
databuf.appendChar(p.type_index);
break;
// throws
case THROWS:
databuf.appendChar(p.type_index);
break;
// method parameter
case METHOD_FORMAL_PARAMETER:
databuf.appendByte(p.parameter_index);
break;
// method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT:
databuf.appendChar(p.offset);
databuf.appendByte(p.type_index);
break;
// We don't need to worry about these
case METHOD_RETURN:
case FIELD:
break;
// lambda formal parameter
case LAMBDA_FORMAL_PARAMETER:
databuf.appendByte(p.parameter_index);
break;
case UNKNOWN:
throw new AssertionError("jvm.ClassWriter: UNKNOWN target type should never occur!");
default:
throw new AssertionError("jvm.ClassWriter: Unknown target type for position: " + p);
}
{ // Append location data for generics/arrays.
databuf.appendByte(p.location.size());
java.util.List<Integer> loc = TypeAnnotationPosition.getBinaryFromTypePath(p.location);
for (int i : loc)
databuf.appendByte((byte)i);
}
}
/**********************************************************************
* Writing Objects
**********************************************************************/
@ -1661,6 +1820,7 @@ public class ClassWriter extends ClassFile {
acount += writeFlagAttrs(c.flags());
acount += writeJavaAnnotations(c.getRawAttributes());
acount += writeTypeAnnotations(c.getRawTypeAttributes());
acount += writeEnclosingMethodAttribute(c);
acount += writeExtraClassAttributes(c);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -1924,17 +1924,70 @@ public class Code {
if (length < Character.MAX_VALUE) {
v.length = length;
putVar(v);
fillLocalVarPosition(v);
}
}
}
state.defined.excl(adr);
}
private void fillLocalVarPosition(LocalVar lv) {
if (lv == null || lv.sym == null
|| lv.sym.annotations.isTypesEmpty())
return;
for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
TypeAnnotationPosition p = ta.position;
p.lvarOffset = new int[] { (int)lv.start_pc };
p.lvarLength = new int[] { (int)lv.length };
p.lvarIndex = new int[] { (int)lv.reg };
p.isValidOffset = true;
}
}
// Method to be called after compressCatchTable to
// fill in the exception table index for type
// annotations on exception parameters.
public void fillExceptionParameterPositions() {
for (int i = 0; i < varBufferSize; ++i) {
LocalVar lv = varBuffer[i];
if (lv == null || lv.sym == null
|| lv.sym.annotations.isTypesEmpty()
|| !lv.sym.isExceptionParameter())
return;
int exidx = findExceptionIndex(lv);
for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
TypeAnnotationPosition p = ta.position;
p.exception_index = exidx;
}
}
}
private int findExceptionIndex(LocalVar lv) {
List<char[]> iter = catchInfo.toList();
int len = catchInfo.length();
for (int i = 0; i < len; ++i) {
char[] catchEntry = iter.head;
iter = iter.tail;
char handlerpc = catchEntry[2];
if (lv.start_pc == handlerpc + 1) {
return i;
}
}
return -1;
}
/** Put a live variable range into the buffer to be output to the
* class file.
*/
void putVar(LocalVar var) {
if (!varDebugInfo) return;
// Keep local variables if
// 1) we need them for debug information
// 2) it is an exception type and it contains type annotations
if (!varDebugInfo &&
(!var.sym.isExceptionParameter() ||
var.sym.annotations.isTypesEmpty())) return;
if ((var.sym.flags() & Flags.SYNTHETIC) != 0) return;
if (varBuffer == null)
varBuffer = new LocalVar[20];

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -1016,8 +1016,11 @@ public class Gen extends JCTree.Visitor {
code.frameBeforeLast = null;
}
//compress exception table
// Compress exception table
code.compressCatchTable();
// Fill in type annotation positions for exception parameters
code.fillExceptionParameterPositions();
}
}
@ -1738,6 +1741,7 @@ public class Gen extends JCTree.Visitor {
*************************************************************************/
public void visitApply(JCMethodInvocation tree) {
setTypeAnnotationPositions(tree.pos);
// Generate code for method.
Item m = genExpr(tree.meth, methodType);
// Generate code for all arguments, where the expected types are
@ -1775,10 +1779,48 @@ public class Gen extends JCTree.Visitor {
result = items.makeStackItem(pt);
}
private void setTypeAnnotationPositions(int treePos) {
MethodSymbol meth = code.meth;
for (Attribute.TypeCompound ta : meth.getRawTypeAttributes()) {
if (ta.position.pos == treePos) {
ta.position.offset = code.cp;
ta.position.lvarOffset = new int[] { code.cp };
ta.position.isValidOffset = true;
}
}
if (code.meth.getKind() != javax.lang.model.element.ElementKind.CONSTRUCTOR
&& code.meth.getKind() != javax.lang.model.element.ElementKind.STATIC_INIT)
return;
for (Attribute.TypeCompound ta : meth.owner.getRawTypeAttributes()) {
if (ta.position.pos == treePos) {
ta.position.offset = code.cp;
ta.position.lvarOffset = new int[] { code.cp };
ta.position.isValidOffset = true;
}
}
ClassSymbol clazz = meth.enclClass();
for (Symbol s : new com.sun.tools.javac.model.FilteredMemberList(clazz.members())) {
if (!s.getKind().isField())
continue;
for (Attribute.TypeCompound ta : s.getRawTypeAttributes()) {
if (ta.position.pos == treePos) {
ta.position.offset = code.cp;
ta.position.lvarOffset = new int[] { code.cp };
ta.position.isValidOffset = true;
}
}
}
}
public void visitNewClass(JCNewClass tree) {
// Enclosing instances or anonymous classes should have been eliminated
// by now.
Assert.check(tree.encl == null && tree.def == null);
setTypeAnnotationPositions(tree.pos);
code.emitop2(new_, makeRef(tree.pos(), tree.type));
code.emitop0(dup);
@ -1793,6 +1835,7 @@ public class Gen extends JCTree.Visitor {
}
public void visitNewArray(JCNewArray tree) {
setTypeAnnotationPositions(tree.pos);
if (tree.elems != null) {
Type elemtype = types.elemtype(tree.type);
@ -2122,6 +2165,7 @@ public class Gen extends JCTree.Visitor {
}
public void visitTypeCast(JCTypeCast tree) {
setTypeAnnotationPositions(tree.pos);
result = genExpr(tree.expr, tree.clazz.type).load();
// Additional code is only needed if we cast to a reference type
// which is not statically a supertype of the expression's type.
@ -2138,6 +2182,7 @@ public class Gen extends JCTree.Visitor {
}
public void visitTypeTest(JCInstanceOf tree) {
setTypeAnnotationPositions(tree.pos);
genExpr(tree.expr, tree.expr.type).load();
code.emitop2(instanceof_, makeRef(tree.pos(), tree.clazz.type));
result = items.makeStackItem(syms.booleanType);
@ -2184,7 +2229,7 @@ public class Gen extends JCTree.Visitor {
code.emitop2(ldc2, makeRef(tree.pos(), tree.selected.type));
result = items.makeStackItem(pt);
return;
}
}
Symbol ssym = TreeInfo.symbol(tree.selected);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -158,7 +158,7 @@ public class JNIWriter {
return false;
/* temporary code for backwards compatibility */
for (Attribute.Compound a: c.annotations.getAttributes()) {
for (Attribute.Compound a: c.annotations.getDeclarationAttributes()) {
if (a.type.tsym == syms.nativeHeaderType_old.tsym)
return true;
}
@ -167,7 +167,7 @@ public class JNIWriter {
for (Scope.Entry i = c.members_field.elems; i != null; i = i.sibling) {
if (i.sym.kind == Kinds.MTH && (i.sym.flags() & Flags.NATIVE) != 0)
return true;
for (Attribute.Compound a: i.sym.annotations.getAttributes()) {
for (Attribute.Compound a: i.sym.annotations.getDeclarationAttributes()) {
if (a.type.tsym == syms.nativeHeaderType.tsym)
return true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -513,7 +513,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
*/
public CompileState shouldStopPolicyIfNoError;
/** A queue of all as yet unattributed classes.oLo
/** A queue of all as yet unattributed classes.
*/
public Todo todo;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -25,9 +25,9 @@
package com.sun.tools.javac.model;
import java.lang.annotation.Annotation;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
@ -333,4 +333,28 @@ public class JavacTypes implements javax.lang.model.util.Types {
return results;
}
public List<? extends AnnotationMirror> typeAnnotationsOf(TypeMirror type) {
// TODO: these methods can be removed.
return null; // ((Type)type).typeAnnotations;
}
public <A extends Annotation> A typeAnnotationOf(TypeMirror type,
Class<A> annotationType) {
// TODO: these methods can be removed.
return null; // JavacElements.getAnnotation(((Type)type).typeAnnotations, annotationType);
}
public TypeMirror receiverTypeOf(ExecutableType type) {
return ((Type)type).asMethodType().recvtype;
}
/*
public <A extends Annotation> A receiverTypeAnnotationOf(
ExecutableType type, Class<A> annotationType) {
return JavacElements.getAnnotation(
((Type)type).asMethodType().receiverTypeAnnotations,
annotationType);
}*/
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -59,6 +59,7 @@ public class Scanner implements Lexer {
private List<Token> savedTokens = new ArrayList<Token>();
private JavaTokenizer tokenizer;
/**
* Create a scanner from the input array. This method might
* modify the array. To avoid copying the input array, ensure

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011, 2013, 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
@ -38,7 +38,7 @@ import static com.sun.tools.javac.util.LayoutCharacters.*;
/** The char reader used by the javac lexer/tokenizer. Returns the sequence of
* characters contained in the input stream, handling unicode escape accordingly.
* Additionally, it provide features for saving chars into a buffer and to retrieve
* Additionally, it provides features for saving chars into a buffer and to retrieve
* them at a later stage.
*
* <p><b>This is NOT part of any supported API.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -817,9 +817,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
/** The set of package-info files to be processed this round. */
List<PackageSymbol> packageInfoFiles;
/** The number of Messager errors generated in this round. */
int nMessagerErrors;
/** Create a round (common code). */
private Round(Context context, int number, int priorErrors, int priorWarnings,
Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
@ -829,7 +826,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
compiler = JavaCompiler.instance(context);
log = Log.instance(context);
log.nerrors = priorErrors;
log.nwarnings += priorWarnings;
log.nwarnings = priorWarnings;
if (number == 1) {
Assert.checkNonNull(deferredDiagnosticHandler);
this.deferredDiagnosticHandler = deferredDiagnosticHandler;
@ -870,7 +867,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
Set<JavaFileObject> newSourceFiles, Map<String,JavaFileObject> newClassFiles) {
this(prev.nextContext(),
prev.number+1,
prev.nMessagerErrors,
prev.compiler.log.nerrors,
prev.compiler.log.nwarnings,
null);
this.genClassFiles = prev.genClassFiles;
@ -911,15 +908,12 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
}
/** Create the compiler to be used for the final compilation. */
JavaCompiler finalCompiler(boolean errorStatus) {
JavaCompiler finalCompiler() {
try {
Context nextCtx = nextContext();
JavacProcessingEnvironment.this.context = nextCtx;
JavaCompiler c = JavaCompiler.instance(nextCtx);
c.log.nwarnings += compiler.log.nwarnings;
if (errorStatus) {
c.log.nerrors += compiler.log.nerrors;
}
c.log.initRound(compiler.log);
return c;
} finally {
compiler.close(false);
@ -1027,8 +1021,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
if (!taskListener.isEmpty())
taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND));
}
nMessagerErrors = messager.errorCount();
}
void showDiagnostics(boolean showAll) {
@ -1107,9 +1099,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
next.put(Tokens.tokensKey, tokens);
Log nextLog = Log.instance(next);
// propogate the log's writers directly, instead of going through context
nextLog.setWriters(log);
nextLog.setSourceMap(log);
nextLog.initRound(log);
JavaCompiler oldCompiler = JavaCompiler.instance(context);
JavaCompiler nextCompiler = JavaCompiler.instance(next);
@ -1206,7 +1196,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
new LinkedHashSet<JavaFileObject>(filer.getGeneratedSourceFileObjects());
roots = cleanTrees(round.roots);
JavaCompiler compiler = round.finalCompiler(errorStatus);
JavaCompiler compiler = round.finalCompiler();
if (newSourceFiles.size() > 0)
roots = roots.appendList(compiler.parseFiles(newSourceFiles));
@ -1311,7 +1301,6 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
if (procNames != null)
return true;
String procPath;
URL[] urls = new URL[1];
for(File pathElement : workingpath) {
try {
@ -1382,6 +1371,10 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea
node.sym = null;
super.visitIdent(node);
}
public void visitAnnotation(JCAnnotation node) {
node.attribute = null;
super.visitAnnotation(node);
}
};

View File

@ -1666,6 +1666,9 @@ compiler.misc.bad.const.pool.tag.at=\
compiler.misc.bad.signature=\
bad signature: {0}
compiler.misc.bad.type.annotation.value=\
bad type annotation target type value: {0}
compiler.misc.class.file.wrong.class=\
class file contains wrong class: {0}
@ -2149,6 +2152,23 @@ compiler.err.assert.as.identifier=\
as of release 1.4, ''assert'' is a keyword, and may not be used as an identifier\n\
(use -source 1.3 or lower to use ''assert'' as an identifier)
# TODO 308: make a better error message
compiler.err.this.as.identifier=\
as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter
# TODO 308: make a better error message
compiler.err.cant.annotate.static.class=\
enclosing static nested class cannot be annotated
# TODO 308: make a better error message
compiler.err.cant.annotate.nested.type=\
nested type cannot be annotated
compiler.err.incorrect.receiver.type=\
the receiver type does not match the enclosing class type
compiler.err.no.annotations.on.dot.class=\
no annotations are allowed in the type of a class literal
# 0: string
compiler.err.generics.not.supported.in.source=\
generics are not supported in -source {0}\n\
@ -2164,9 +2184,10 @@ compiler.err.annotations.not.supported.in.source=\
annotations are not supported in -source {0}\n\
(use -source 5 or higher to enable annotations)
#308 compiler.err.type.annotations.not.supported.in.source=\
#308 type annotations are not supported in -source {0}\n\
#308 (use -source 7 or higher to enable type annotations)
# 0: string
compiler.err.type.annotations.not.supported.in.source=\
type annotations are not supported in -source {0}\n\
(use -source 8 or higher to enable type annotations)
# 0: string
compiler.err.foreach.not.supported.in.source=\

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1999, 2013, 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
@ -1340,6 +1340,10 @@ compiler.err.enum.as.identifier=\u30EA\u30EA\u30FC\u30B95\u304B\u3089''enum''\u3
compiler.err.assert.as.identifier=\u30EA\u30EA\u30FC\u30B91.4\u304B\u3089''assert''\u306F\u30AD\u30FC\u30EF\u30FC\u30C9\u306A\u306E\u3067\u3001\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\n(''assert''\u3092\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u306B\u306F\u3001-source 1.3\u4EE5\u524D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044)
# TODO 308: make a better error message
# compiler.err.this.as.identifier=\
# as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter
# 0: string
compiler.err.generics.not.supported.in.source=\u7DCF\u79F0\u578B\u306F-source {0}\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\n(\u7DCF\u79F0\u578B\u3092\u4F7F\u7528\u53EF\u80FD\u306B\u3059\u308B\u306B\u306F\u3001-source 5\u4EE5\u964D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044)
@ -1351,7 +1355,7 @@ compiler.err.annotations.not.supported.in.source=\u6CE8\u91C8\u306F-source {0}\u
#308 compiler.err.type.annotations.not.supported.in.source=\
#308 type annotations are not supported in -source {0}\n\
#308 (use -source 7 or higher to enable type annotations)
#308 (use -source 8 or higher to enable type annotations)
# 0: string
compiler.err.foreach.not.supported.in.source=for-each\u30EB\u30FC\u30D7\u306F-source {0}\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\n(for-each\u30EB\u30FC\u30D7\u3092\u4F7F\u7528\u53EF\u80FD\u306B\u3059\u308B\u306B\u306F\u3001-source 5\u4EE5\u964D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044)

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1999, 2013, 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
@ -1340,6 +1340,10 @@ compiler.err.enum.as.identifier=\u4ECE\u53D1\u884C\u7248 5 \u5F00\u59CB, ''enum'
compiler.err.assert.as.identifier=\u4ECE\u53D1\u884C\u7248 1.4 \u5F00\u59CB, ''assert'' \u662F\u4E00\u4E2A\u5173\u952E\u5B57, \u4F46\u4E0D\u80FD\u7528\u4F5C\u6807\u8BC6\u7B26\n(\u8BF7\u4F7F\u7528 -source 1.3 \u6216\u66F4\u4F4E\u7248\u672C\u4EE5\u5C06 ''assert'' \u7528\u4F5C\u6807\u8BC6\u7B26)
# TODO 308: make a better error message
# compiler.err.this.as.identifier=\
# as of release 8, ''this'' is allowed as the parameter name for the receiver type only, which has to be the first parameter
# 0: string
compiler.err.generics.not.supported.in.source=-source {0} \u4E2D\u4E0D\u652F\u6301\u6CDB\u578B\n(\u8BF7\u4F7F\u7528 -source 5 \u6216\u66F4\u9AD8\u7248\u672C\u4EE5\u542F\u7528\u6CDB\u578B)
@ -1351,7 +1355,7 @@ compiler.err.annotations.not.supported.in.source=-source {0} \u4E2D\u4E0D\u652F\
#308 compiler.err.type.annotations.not.supported.in.source=\
#308 type annotations are not supported in -source {0}\n\
#308 (use -source 7 or higher to enable type annotations)
#308 (use -source 8 or higher to enable type annotations)
# 0: string
compiler.err.foreach.not.supported.in.source=-source {0} \u4E2D\u4E0D\u652F\u6301 for-each \u5FAA\u73AF\n(\u8BF7\u4F7F\u7528 -source 5 \u6216\u66F4\u9AD8\u7248\u672C\u4EE5\u542F\u7528 for-each \u5FAA\u73AF)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -250,11 +250,11 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/
TYPEAPPLY,
/** Union types, of type TypeUnion
/** Union types, of type TypeUnion.
*/
TYPEUNION,
/** Intersection types, of type TypeIntersection
/** Intersection types, of type TypeIntersection.
*/
TYPEINTERSECTION,
@ -274,10 +274,16 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
*/
ANNOTATION,
/** metadata: Type annotation.
*/
TYPE_ANNOTATION,
/** metadata: Modifiers
*/
MODIFIERS,
/** An annotated type tree.
*/
ANNOTATED_TYPE,
/** Error trees, of type Erroneous.
@ -725,6 +731,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public JCExpression restype;
/** type parameters */
public List<JCTypeParameter> typarams;
/** receiver parameter */
public JCVariableDecl recvparam;
/** value parameters */
public List<JCVariableDecl> params;
/** exceptions thrown by this method */
@ -739,6 +747,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
Name name,
JCExpression restype,
List<JCTypeParameter> typarams,
JCVariableDecl recvparam,
List<JCVariableDecl> params,
List<JCExpression> thrown,
JCBlock body,
@ -750,6 +759,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
this.restype = restype;
this.typarams = typarams;
this.params = params;
this.recvparam = recvparam;
// TODO: do something special if the given type is null?
// receiver != null ? receiver : List.<JCTypeAnnotation>nil());
this.thrown = thrown;
this.body = body;
this.defaultValue = defaultValue;
@ -768,6 +780,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public List<JCVariableDecl> getParameters() {
return params;
}
public JCVariableDecl getReceiverParameter() { return recvparam; }
public List<JCExpression> getThrows() {
return thrown;
}
@ -1505,6 +1518,10 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public static class JCNewArray extends JCExpression implements NewArrayTree {
public JCExpression elemtype;
public List<JCExpression> dims;
// type annotations on inner-most component
public List<JCAnnotation> annotations;
// type annotations on dimensions
public List<List<JCAnnotation>> dimAnnotations;
public List<JCExpression> elems;
protected JCNewArray(JCExpression elemtype,
List<JCExpression> dims,
@ -1512,6 +1529,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
{
this.elemtype = elemtype;
this.dims = dims;
this.annotations = List.nil();
this.dimAnnotations = List.nil();
this.elems = elems;
}
@Override
@ -2152,9 +2171,12 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public Name name;
/** bounds */
public List<JCExpression> bounds;
protected JCTypeParameter(Name name, List<JCExpression> bounds) {
/** type annotations on type parameter */
public List<JCAnnotation> annotations;
protected JCTypeParameter(Name name, List<JCExpression> bounds, List<JCAnnotation> annotations) {
this.name = name;
this.bounds = bounds;
this.annotations = annotations;
}
@Override
public void accept(Visitor v) { v.visitTypeParameter(this); }
@ -2164,6 +2186,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public List<JCExpression> getBounds() {
return bounds;
}
public List<JCAnnotation> getAnnotations() {
return annotations;
}
@Override
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitTypeParameter(this, d);
@ -2230,16 +2255,27 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
public static class JCAnnotation extends JCExpression implements AnnotationTree {
// Either Tag.ANNOTATION or Tag.TYPE_ANNOTATION
private Tag tag;
public JCTree annotationType;
public List<JCExpression> args;
protected JCAnnotation(JCTree annotationType, List<JCExpression> args) {
// Attribute.Compound if tag is ANNOTATION
// Attribute.TypeCompound if tag is TYPE_ANNOTATION
public Attribute.Compound attribute;
protected JCAnnotation(Tag tag, JCTree annotationType, List<JCExpression> args) {
this.tag = tag;
this.annotationType = annotationType;
this.args = args;
}
@Override
public void accept(Visitor v) { v.visitAnnotation(this); }
public Kind getKind() { return Kind.ANNOTATION; }
public Kind getKind() { return TreeInfo.tagToKind(getTag()); }
public JCTree getAnnotationType() { return annotationType; }
public List<JCExpression> getArguments() {
return args;
@ -2250,7 +2286,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
@Override
public Tag getTag() {
return ANNOTATION;
return tag;
}
}
@ -2281,6 +2317,35 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
}
public static class JCAnnotatedType extends JCExpression implements com.sun.source.tree.AnnotatedTypeTree {
// type annotations
public List<JCAnnotation> annotations;
public JCExpression underlyingType;
protected JCAnnotatedType(List<JCAnnotation> annotations, JCExpression underlyingType) {
this.annotations = annotations;
this.underlyingType = underlyingType;
}
@Override
public void accept(Visitor v) { v.visitAnnotatedType(this); }
public Kind getKind() { return Kind.ANNOTATED_TYPE; }
public List<JCAnnotation> getAnnotations() {
return annotations;
}
public JCExpression getUnderlyingType() {
return underlyingType;
}
@Override
public <R,D> R accept(TreeVisitor<R,D> v, D d) {
return v.visitAnnotatedType(this, d);
}
@Override
public Tag getTag() {
return ANNOTATED_TYPE;
}
}
public static class JCErroneous extends JCExpression
implements com.sun.source.tree.ErroneousTree {
public List<? extends JCTree> errs;
@ -2347,6 +2412,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
Name name,
JCExpression restype,
List<JCTypeParameter> typarams,
JCVariableDecl recvparam,
List<JCVariableDecl> params,
List<JCExpression> thrown,
JCBlock body,
@ -2472,6 +2538,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
public void visitTypeBoundKind(TypeBoundKind that) { visitTree(that); }
public void visitAnnotation(JCAnnotation that) { visitTree(that); }
public void visitModifiers(JCModifiers that) { visitTree(that); }
public void visitAnnotatedType(JCAnnotatedType that) { visitTree(that); }
public void visitErroneous(JCErroneous that) { visitTree(that); }
public void visitLetExpr(LetExpr that) { visitTree(that); }

View File

@ -29,7 +29,6 @@ import java.io.*;
import com.sun.source.tree.MemberReferenceTree.ReferenceMode;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.List;
@ -261,6 +260,15 @@ public class Pretty extends JCTree.Visitor {
}
}
public void printTypeAnnotations(List<JCAnnotation> trees) throws IOException {
if (trees.nonEmpty())
print(" ");
for (List<JCAnnotation> l = trees; l.nonEmpty(); l = l.tail) {
printExpr(l.head);
print(" ");
}
}
/** Print documentation comment, if it exists
* @param tree The tree for which a documentation comment should be printed.
*/
@ -491,6 +499,12 @@ public class Pretty extends JCTree.Visitor {
print(" " + tree.name);
}
print("(");
if (tree.recvparam!=null) {
printExpr(tree.recvparam);
if (tree.params.size() > 0) {
print(", ");
}
}
printExprs(tree.params);
print(")");
if (tree.thrown.nonEmpty()) {
@ -543,7 +557,15 @@ public class Pretty extends JCTree.Visitor {
} else {
printExpr(tree.mods);
if ((tree.mods.flags & VARARGS) != 0) {
printExpr(((JCArrayTypeTree) tree.vartype).elemtype);
JCTree vartype = tree.vartype;
List<JCAnnotation> tas = null;
if (vartype instanceof JCAnnotatedType) {
tas = ((JCAnnotatedType)vartype).annotations;
vartype = ((JCAnnotatedType)vartype).underlyingType;
}
printExpr(((JCArrayTypeTree) vartype).elemtype);
if (tas != null)
printTypeAnnotations(tas);
print("... " + tree.name);
} else {
printExpr(tree.vartype);
@ -919,16 +941,29 @@ public class Pretty extends JCTree.Visitor {
try {
if (tree.elemtype != null) {
print("new ");
printTypeAnnotations(tree.annotations);
JCTree elem = tree.elemtype;
if (elem.hasTag(TYPEARRAY))
printBaseElementType((JCArrayTypeTree) elem);
else
printExpr(elem);
printBaseElementType(elem);
boolean isElemAnnoType = elem instanceof JCAnnotatedType;
int i = 0;
List<List<JCAnnotation>> da = tree.dimAnnotations;
for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
if (da.size() > i) {
printTypeAnnotations(da.get(i));
}
print("[");
i++;
printExpr(l.head);
print("]");
}
if (tree.elems != null) {
if (isElemAnnoType) {
printTypeAnnotations(((JCAnnotatedType)tree.elemtype).annotations);
}
print("[]");
}
if (isElemAnnoType)
elem = ((JCAnnotatedType)elem).underlyingType;
if (elem instanceof JCArrayTypeTree)
printBrackets((JCArrayTypeTree) elem);
}
@ -1225,6 +1260,12 @@ public class Pretty extends JCTree.Visitor {
JCTree elem;
while (true) {
elem = tree.elemtype;
if (elem.hasTag(ANNOTATED_TYPE)) {
JCAnnotatedType atype = (JCAnnotatedType) elem;
elem = atype.underlyingType;
if (!elem.hasTag(TYPEARRAY)) break;
printTypeAnnotations(atype.annotations);
}
print("[]");
if (!elem.hasTag(TYPEARRAY)) break;
tree = (JCArrayTypeTree) elem;
@ -1327,6 +1368,32 @@ public class Pretty extends JCTree.Visitor {
}
}
public void visitAnnotatedType(JCAnnotatedType tree) {
try {
if (tree.underlyingType.getKind() == JCTree.Kind.MEMBER_SELECT) {
JCFieldAccess access = (JCFieldAccess) tree.underlyingType;
printExpr(access.selected, TreeInfo.postfixPrec);
print(".");
printTypeAnnotations(tree.annotations);
print(access.name);
} else if (tree.underlyingType.getKind() == JCTree.Kind.ARRAY_TYPE) {
JCArrayTypeTree array = (JCArrayTypeTree) tree.underlyingType;
printBaseElementType(tree);
printTypeAnnotations(tree.annotations);
print("[]");
JCExpression elem = array.elemtype;
if (elem.hasTag(TYPEARRAY)) {
printBrackets((JCArrayTypeTree) elem);
}
} else {
printTypeAnnotations(tree.annotations);
printExpr(tree.underlyingType);
}
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
public void visitTree(JCTree tree) {
try {
print("(UNKNOWN: " + tree + ")");

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2013, 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
@ -71,11 +71,26 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
return lb.toList();
}
public JCTree visitAnnotatedType(AnnotatedTypeTree node, P p) {
JCAnnotatedType t = (JCAnnotatedType) node;
List<JCAnnotation> annotations = copy(t.annotations, p);
JCExpression underlyingType = copy(t.underlyingType, p);
return M.at(t.pos).AnnotatedType(annotations, underlyingType);
}
public JCTree visitAnnotation(AnnotationTree node, P p) {
JCAnnotation t = (JCAnnotation) node;
JCTree annotationType = copy(t.annotationType, p);
List<JCExpression> args = copy(t.args, p);
return M.at(t.pos).Annotation(annotationType, args);
if (t.getKind() == Tree.Kind.TYPE_ANNOTATION) {
JCAnnotation newTA = M.at(t.pos).TypeAnnotation(annotationType, args);
newTA.attribute = t.attribute;
return newTA;
} else {
JCAnnotation newT = M.at(t.pos).Annotation(annotationType, args);
newT.attribute = t.attribute;
return newT;
}
}
public JCTree visitAssert(AssertTree node, P p) {
@ -233,10 +248,11 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
JCExpression restype = copy(t.restype, p);
List<JCTypeParameter> typarams = copy(t.typarams, p);
List<JCVariableDecl> params = copy(t.params, p);
JCVariableDecl recvparam = copy(t.recvparam, p);
List<JCExpression> thrown = copy(t.thrown, p);
JCBlock body = copy(t.body, p);
JCExpression defaultValue = copy(t.defaultValue, p);
return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, params, thrown, body, defaultValue);
return M.at(t.pos).MethodDef(mods, t.name, restype, typarams, recvparam, params, thrown, body, defaultValue);
}
public JCTree visitMethodInvocation(MethodInvocationTree node, P p) {
@ -384,8 +400,9 @@ public class TreeCopier<P> implements TreeVisitor<JCTree,P> {
public JCTree visitTypeParameter(TypeParameterTree node, P p) {
JCTypeParameter t = (JCTypeParameter) node;
List<JCAnnotation> annos = copy(t.annotations, p);
List<JCExpression> bounds = copy(t.bounds, p);
return M.at(t.pos).TypeParameter(t.name, bounds);
return M.at(t.pos).TypeParameter(t.name, bounds, annos);
}
public JCTree visitInstanceOf(InstanceOfTree node, P p) {

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -453,6 +453,19 @@ public class TreeInfo {
case POSTINC:
case POSTDEC:
return getStartPos(((JCUnary) tree).arg);
case ANNOTATED_TYPE: {
JCAnnotatedType node = (JCAnnotatedType) tree;
if (node.annotations.nonEmpty()) {
if (node.underlyingType.hasTag(TYPEARRAY) ||
node.underlyingType.hasTag(SELECT)) {
return getStartPos(node.underlyingType);
} else {
return getStartPos(node.annotations.head);
}
} else {
return getStartPos(node.underlyingType);
}
}
case NEWCLASS: {
JCNewClass node = (JCNewClass)tree;
if (node.encl != null)
@ -560,6 +573,8 @@ public class TreeInfo {
return getEndPos(((JCUnary) tree).arg, endPosTable);
case WHILELOOP:
return getEndPos(((JCWhileLoop) tree).body, endPosTable);
case ANNOTATED_TYPE:
return getEndPos(((JCAnnotatedType) tree).underlyingType, endPosTable);
case ERRONEOUS: {
JCErroneous node = (JCErroneous)tree;
if (node.errs != null && node.errs.nonEmpty())
@ -799,6 +814,8 @@ public class TreeInfo {
return ((JCFieldAccess) tree).sym;
case TYPEAPPLY:
return symbol(((JCTypeApply) tree).clazz);
case ANNOTATED_TYPE:
return symbol(((JCAnnotatedType) tree).underlyingType);
default:
return null;
}
@ -1036,17 +1053,24 @@ public class TreeInfo {
case NULLCHK:
return Tree.Kind.OTHER;
case ANNOTATION:
return Tree.Kind.ANNOTATION;
case TYPE_ANNOTATION:
return Tree.Kind.TYPE_ANNOTATION;
default:
return null;
}
}
/**
* Returns the underlying type of the tree if it is annotated type,
* or the tree itself otherwise
* Returns the underlying type of the tree if it is an annotated type,
* or the tree itself otherwise.
*/
public static JCExpression typeIn(JCExpression tree) {
switch (tree.getTag()) {
case ANNOTATED_TYPE:
return ((JCAnnotatedType)tree).underlyingType;
case IDENT: /* simple names */
case TYPEIDENT: /* primitive name */
case SELECT: /* qualified name */
@ -1054,20 +1078,55 @@ public class TreeInfo {
case WILDCARD: /* wild cards */
case TYPEPARAMETER: /* type parameters */
case TYPEAPPLY: /* parameterized types */
case ERRONEOUS: /* error tree TODO: needed for BadCast JSR308 test case. Better way? */
return tree;
default:
throw new AssertionError("Unexpected type tree: " + tree);
}
}
/* Return the inner-most type of a type tree.
* For an array that contains an annotated type, return that annotated type.
* TODO: currently only used by Pretty. Describe behavior better.
*/
public static JCTree innermostType(JCTree type) {
switch (type.getTag()) {
case TYPEARRAY:
return innermostType(((JCArrayTypeTree)type).elemtype);
case WILDCARD:
return innermostType(((JCWildcard)type).inner);
default:
return type;
JCTree lastAnnotatedType = null;
JCTree cur = type;
loop: while (true) {
switch (cur.getTag()) {
case TYPEARRAY:
lastAnnotatedType = null;
cur = ((JCArrayTypeTree)cur).elemtype;
break;
case WILDCARD:
lastAnnotatedType = null;
cur = ((JCWildcard)cur).inner;
break;
case ANNOTATED_TYPE:
lastAnnotatedType = cur;
cur = ((JCAnnotatedType)cur).underlyingType;
break;
default:
break loop;
}
}
if (lastAnnotatedType!=null) {
return lastAnnotatedType;
} else {
return cur;
}
}
private static class TypeAnnotationFinder extends TreeScanner {
public boolean foundTypeAnno = false;
public void visitAnnotation(JCAnnotation tree) {
foundTypeAnno = foundTypeAnno || tree.hasTag(TYPE_ANNOTATION);
}
}
public static boolean containsTypeAnnotation(JCTree e) {
TypeAnnotationFinder finder = new TypeAnnotationFinder();
finder.scan(e);
return finder.foundTypeAnno;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -169,10 +169,26 @@ public class TreeMaker implements JCTree.Factory {
List<JCExpression> thrown,
JCBlock body,
JCExpression defaultValue) {
return MethodDef(
mods, name, restype, typarams, null, params,
thrown, body, defaultValue);
}
public JCMethodDecl MethodDef(JCModifiers mods,
Name name,
JCExpression restype,
List<JCTypeParameter> typarams,
JCVariableDecl recvparam,
List<JCVariableDecl> params,
List<JCExpression> thrown,
JCBlock body,
JCExpression defaultValue)
{
JCMethodDecl tree = new JCMethodDecl(mods,
name,
restype,
typarams,
recvparam,
params,
thrown,
body,
@ -463,7 +479,11 @@ public class TreeMaker implements JCTree.Factory {
}
public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds) {
JCTypeParameter tree = new JCTypeParameter(name, bounds);
return TypeParameter(name, bounds, List.<JCAnnotation>nil());
}
public JCTypeParameter TypeParameter(Name name, List<JCExpression> bounds, List<JCAnnotation> annos) {
JCTypeParameter tree = new JCTypeParameter(name, bounds, annos);
tree.pos = pos;
return tree;
}
@ -481,7 +501,13 @@ public class TreeMaker implements JCTree.Factory {
}
public JCAnnotation Annotation(JCTree annotationType, List<JCExpression> args) {
JCAnnotation tree = new JCAnnotation(annotationType, args);
JCAnnotation tree = new JCAnnotation(Tag.ANNOTATION, annotationType, args);
tree.pos = pos;
return tree;
}
public JCAnnotation TypeAnnotation(JCTree annotationType, List<JCExpression> args) {
JCAnnotation tree = new JCAnnotation(Tag.TYPE_ANNOTATION, annotationType, args);
tree.pos = pos;
return tree;
}
@ -497,6 +523,12 @@ public class TreeMaker implements JCTree.Factory {
return Modifiers(flags, List.<JCAnnotation>nil());
}
public JCAnnotatedType AnnotatedType(List<JCAnnotation> annotations, JCExpression underlyingType) {
JCAnnotatedType tree = new JCAnnotatedType(annotations, underlyingType);
tree.pos = pos;
return tree;
}
public JCErroneous Erroneous() {
return Erroneous(List.<JCTree>nil());
}
@ -755,7 +787,11 @@ public class TreeMaker implements JCTree.Factory {
result = Erroneous();
}
public void visitCompound(Attribute.Compound compound) {
result = visitCompoundInternal(compound);
if (compound instanceof Attribute.TypeCompound) {
result = visitTypeCompoundInternal((Attribute.TypeCompound) compound);
} else {
result = visitCompoundInternal(compound);
}
}
public JCAnnotation visitCompoundInternal(Attribute.Compound compound) {
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
@ -766,6 +802,15 @@ public class TreeMaker implements JCTree.Factory {
}
return Annotation(Type(compound.type), args.toList());
}
public JCAnnotation visitTypeCompoundInternal(Attribute.TypeCompound compound) {
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
for (List<Pair<Symbol.MethodSymbol,Attribute>> values = compound.values; values.nonEmpty(); values=values.tail) {
Pair<MethodSymbol,Attribute> pair = values.head;
JCExpression valueTree = translate(pair.snd);
args.append(Assign(Ident(pair.fst), valueTree).setType(valueTree.type));
}
return TypeAnnotation(Type(compound.type), args.toList());
}
public void visitArray(Attribute.Array array) {
ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
for (int i = 0; i < array.values.length; i++)
@ -779,7 +824,11 @@ public class TreeMaker implements JCTree.Factory {
JCAnnotation translate(Attribute.Compound a) {
return visitCompoundInternal(a);
}
JCAnnotation translate(Attribute.TypeCompound a) {
return visitTypeCompoundInternal(a);
}
}
AnnotationBuilder annotationBuilder = new AnnotationBuilder();
/** Create an annotation tree from an attribute.
@ -788,6 +837,10 @@ public class TreeMaker implements JCTree.Factory {
return annotationBuilder.translate((Attribute.Compound)a);
}
public JCAnnotation TypeAnnotation(Attribute a) {
return annotationBuilder.translate((Attribute.TypeCompound) a);
}
/** Create a method definition from a method symbol and a method body.
*/
public JCMethodDecl MethodDef(MethodSymbol m, JCBlock body) {
@ -804,6 +857,7 @@ public class TreeMaker implements JCTree.Factory {
m.name,
Type(mtype.getReturnType()),
TypeParams(mtype.getTypeArguments()),
null, // receiver type
Params(mtype.getParameterTypes(), m),
Types(mtype.getThrownTypes()),
body,
@ -822,7 +876,6 @@ public class TreeMaker implements JCTree.Factory {
*/
public List<JCTypeParameter> TypeParams(List<Type> typarams) {
ListBuffer<JCTypeParameter> tparams = new ListBuffer<JCTypeParameter>();
int i = 0;
for (List<Type> l = typarams; l.nonEmpty(); l = l.tail)
tparams.append(TypeParam(l.head.tsym.name, (TypeVar)l.head));
return tparams.toList();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2013, 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
@ -84,6 +84,7 @@ public class TreeScanner extends Visitor {
scan(tree.mods);
scan(tree.restype);
scan(tree.typarams);
scan(tree.recvparam);
scan(tree.params);
scan(tree.thrown);
scan(tree.defaultValue);
@ -200,15 +201,18 @@ public class TreeScanner extends Visitor {
public void visitNewClass(JCNewClass tree) {
scan(tree.encl);
scan(tree.clazz);
scan(tree.typeargs);
scan(tree.clazz);
scan(tree.args);
scan(tree.def);
}
public void visitNewArray(JCNewArray tree) {
scan(tree.annotations);
scan(tree.elemtype);
scan(tree.dims);
for (List<JCAnnotation> annos : tree.dimAnnotations)
scan(annos);
scan(tree.elems);
}
@ -291,6 +295,7 @@ public class TreeScanner extends Visitor {
}
public void visitTypeParameter(JCTypeParameter tree) {
scan(tree.annotations);
scan(tree.bounds);
}
@ -314,6 +319,11 @@ public class TreeScanner extends Visitor {
scan(tree.args);
}
public void visitAnnotatedType(JCAnnotatedType tree) {
scan(tree.annotations);
scan(tree.underlyingType);
}
public void visitErroneous(JCErroneous tree) {
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -139,6 +139,7 @@ public class TreeTranslator extends JCTree.Visitor {
tree.mods = translate(tree.mods);
tree.restype = translate(tree.restype);
tree.typarams = translateTypeParams(tree.typarams);
tree.recvparam = translate(tree.recvparam);
tree.params = translateVarDefs(tree.params);
tree.thrown = translate(tree.thrown);
tree.body = translate(tree.body);
@ -289,6 +290,11 @@ public class TreeTranslator extends JCTree.Visitor {
}
public void visitNewArray(JCNewArray tree) {
tree.annotations = translate(tree.annotations);
List<List<JCAnnotation>> dimAnnos = List.nil();
for (List<JCAnnotation> origDimAnnos : tree.dimAnnotations)
dimAnnos = dimAnnos.append(translate(origDimAnnos));
tree.dimAnnotations = dimAnnos;
tree.elemtype = translate(tree.elemtype);
tree.dims = translate(tree.dims);
tree.elems = translate(tree.elems);
@ -385,6 +391,7 @@ public class TreeTranslator extends JCTree.Visitor {
}
public void visitTypeParameter(JCTypeParameter tree) {
tree.annotations = translate(tree.annotations);
tree.bounds = translate(tree.bounds);
result = tree;
}
@ -422,6 +429,12 @@ public class TreeTranslator extends JCTree.Visitor {
result = tree;
}
public void visitAnnotatedType(JCAnnotatedType tree) {
tree.annotations = translate(tree.annotations);
tree.underlyingType = translate(tree.underlyingType);
result = tree;
}
public void visitTree(JCTree tree) {
throw new AssertionError(tree);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -388,7 +388,7 @@ public class JCDiagnostic implements Diagnostic<JavaFileObject> {
this.source = source;
this.position = pos;
this.key = key;
this.args = args;
this.args = args;
int n = (pos == null ? Position.NOPOS : pos.getPreferredPosition());
if (n == Position.NOPOS || source == null)

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, 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
@ -217,7 +217,7 @@ public class Log extends AbstractLog {
private JavacMessages messages;
/**
+ * Handler for initial dispatch of diagnostics.
* Handler for initial dispatch of diagnostics.
*/
private DiagnosticHandler diagnosticHandler;
@ -385,14 +385,17 @@ public class Log extends AbstractLog {
noticeWriter = warnWriter = errWriter = pw;
}
public void setWriters(Log other) {
/**
* Propagate the previous log's information.
*/
public void initRound(Log other) {
this.noticeWriter = other.noticeWriter;
this.warnWriter = other.warnWriter;
this.errWriter = other.errWriter;
}
public void setSourceMap(Log other) {
this.sourceMap = other.sourceMap;
this.recorded = other.recorded;
this.nerrors = other.nerrors;
this.nwarnings = other.nwarnings;
}
/**

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -104,4 +104,8 @@ abstract class AbstractTypeImpl implements com.sun.javadoc.Type {
public AnnotationTypeDoc asAnnotationTypeDoc() {
return null;
}
public AnnotatedType asAnnotatedType() {
return null;
}
}

View File

@ -0,0 +1,125 @@
/*
* Copyright (c) 2003, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.javadoc;
import com.sun.javadoc.*;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Attribute.TypeCompound;
import com.sun.tools.javac.util.List;
/**
* Implementation of <code>AnnotatedType</code>, which
* represents an annotated type.
*
* @author Mahmood Ali
* @since 1.8
*/
public class AnnotatedTypeImpl
extends AbstractTypeImpl implements AnnotatedType {
AnnotatedTypeImpl(DocEnv env, com.sun.tools.javac.code.Type.AnnotatedType type) {
super(env, type);
}
/**
* Get the annotations of this program element.
* Return an empty array if there are none.
*/
@Override
public AnnotationDesc[] annotations() {
List<TypeCompound> tas = ((com.sun.tools.javac.code.Type.AnnotatedType)type).typeAnnotations;
if (tas == null ||
tas.isEmpty()) {
return new AnnotationDesc[0];
}
AnnotationDesc res[] = new AnnotationDesc[tas.length()];
int i = 0;
for (Attribute.Compound a : tas) {
res[i++] = new AnnotationDescImpl(env, a);
}
return res;
}
@Override
public com.sun.javadoc.Type underlyingType() {
return TypeMaker.getType(env, ((com.sun.tools.javac.code.Type.AnnotatedType)type).underlyingType, true, false);
}
@Override
public AnnotatedType asAnnotatedType() {
return this;
}
@Override
public String toString() {
return typeName();
}
@Override
public String typeName() {
return this.underlyingType().typeName();
}
@Override
public String qualifiedTypeName() {
return this.underlyingType().qualifiedTypeName();
}
@Override
public String simpleTypeName() {
return this.underlyingType().simpleTypeName();
}
@Override
public String dimension() {
return this.underlyingType().dimension();
}
@Override
public boolean isPrimitive() {
return this.underlyingType().isPrimitive();
}
@Override
public ClassDoc asClassDoc() {
return this.underlyingType().asClassDoc();
}
@Override
public TypeVariable asTypeVariable() {
return this.underlyingType().asTypeVariable();
}
@Override
public WildcardType asWildcardType() {
return this.underlyingType().asWildcardType();
}
@Override
public ParameterizedType asParameterizedType() {
return this.underlyingType().asParameterizedType();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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
@ -1185,6 +1185,13 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
return null;
}
/**
* Returns null, as this is not an annotated type.
*/
public AnnotatedType asAnnotatedType() {
return null;
}
/**
* Return false, as this is not a primitive type.
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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
@ -28,10 +28,14 @@ package com.sun.tools.javadoc;
import java.lang.reflect.Modifier;
import java.text.CollationKey;
import javax.lang.model.type.TypeKind;
import com.sun.javadoc.*;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Attribute.Compound;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.util.List;
@ -195,6 +199,24 @@ public abstract class ExecutableMemberDocImpl
return result;
}
public AnnotationDesc[] receiverAnnotations() {
// TODO: change how receiver annotations are output!
Type recvtype = sym.type.asMethodType().recvtype;
if (recvtype == null) {
return new AnnotationDesc[0];
}
if (recvtype.getKind() != TypeKind.ANNOTATED) {
return new AnnotationDesc[0];
}
List<? extends Compound> typeAnnos = ((com.sun.tools.javac.code.Type.AnnotatedType)recvtype).typeAnnotations;
AnnotationDesc result[] = new AnnotationDesc[typeAnnos.length()];
int i = 0;
for (Attribute.Compound a : typeAnnos) {
result[i++] = new AnnotationDescImpl(env, a);
}
return result;
}
/**
* Return the formal type parameters of this method or constructor.
* Return an empty array if there are none.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2001, 2013, 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
@ -121,12 +121,19 @@ class PrimitiveType implements com.sun.javadoc.Type {
}
/**
* Return null, as this is not a wildcard type;
* Return null, as this is not a wildcard type.
*/
public WildcardType asWildcardType() {
return null;
}
/**
* Return null, as this is not an annotated type.
*/
public AnnotatedType asAnnotatedType() {
return null;
}
/**
* Returns a string representation of the type.
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, 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
@ -25,6 +25,8 @@
package com.sun.tools.javadoc;
import javax.lang.model.type.TypeKind;
import com.sun.javadoc.*;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
@ -51,12 +53,27 @@ public class TypeMaker {
* @param errToClassDoc if true, ERROR type results in a ClassDoc;
* false preserves legacy behavior
*/
public static com.sun.javadoc.Type getType(DocEnv env, Type t,
boolean errorToClassDoc) {
return getType(env, t, errorToClassDoc, true);
}
@SuppressWarnings("fallthrough")
public static com.sun.javadoc.Type getType(DocEnv env, Type t,
boolean errToClassDoc) {
boolean errToClassDoc, boolean considerAnnotations) {
if (env.legacyDoclet) {
t = env.types.erasure(t);
}
if (considerAnnotations
&& t.getKind() == TypeKind.ANNOTATED) {
return new AnnotatedTypeImpl(env, (com.sun.tools.javac.code.Type.AnnotatedType) t);
}
if (t.getKind() == TypeKind.ANNOTATED) {
Type.AnnotatedType at = (Type.AnnotatedType) t;
return new AnnotatedTypeImpl(env, at);
}
switch (t.getTag()) {
case CLASS:
if (ClassDocImpl.isGeneric((ClassSymbol)t.tsym)) {
@ -129,6 +146,11 @@ public class TypeMaker {
* Class names are qualified if "full" is true.
*/
static String getTypeString(DocEnv env, Type t, boolean full) {
// TODO: should annotations be included here?
if (t.getKind() == TypeKind.ANNOTATED) {
Type.AnnotatedType at = (Type.AnnotatedType)t;
t = at.underlyingType;
}
switch (t.getTag()) {
case ARRAY:
StringBuilder s = new StringBuilder();
@ -281,6 +303,13 @@ public class TypeMaker {
return null;
}
/**
* Return null, as there are no annotations of the type
*/
public AnnotatedType asAnnotatedType() {
return null;
}
/**
* Return this type as an <code>AnnotationTypeDoc</code> if it
* represents an annotation type. Array dimensions are ignored.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2013, 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
@ -25,8 +25,12 @@
package com.sun.tools.javadoc;
import javax.lang.model.type.TypeKind;
import com.sun.javadoc.*;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.Attribute.TypeCompound;
import com.sun.tools.javac.code.Kinds;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
@ -120,11 +124,30 @@ public class TypeVariableImpl extends AbstractTypeImpl implements TypeVariable {
* Get the bounds of a type variable as listed in the "extends" clause.
*/
private static List<Type> getBounds(TypeVar v, DocEnv env) {
Name boundname = v.getUpperBound().tsym.getQualifiedName();
if (boundname == boundname.table.names.java_lang_Object) {
final Type upperBound = v.getUpperBound();
Name boundname = upperBound.tsym.getQualifiedName();
if (boundname == boundname.table.names.java_lang_Object
&& upperBound.getKind() != TypeKind.ANNOTATED) {
return List.nil();
} else {
return env.types.getBounds(v);
}
}
/**
* Get the annotations of this program element.
* Return an empty array if there are none.
*/
public AnnotationDesc[] annotations() {
if (type.getKind() != TypeKind.ANNOTATED) {
return new AnnotationDesc[0];
}
List<TypeCompound> tas = ((com.sun.tools.javac.code.Type.AnnotatedType) type).typeAnnotations;
AnnotationDesc res[] = new AnnotationDesc[tas.length()];
int i = 0;
for (Attribute.Compound a : tas) {
res[i++] = new AnnotationDescImpl(env, a);
}
return res;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2013, 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
@ -26,6 +26,7 @@
package com.sun.tools.javap;
import com.sun.tools.classfile.Annotation;
import com.sun.tools.classfile.TypeAnnotation;
import com.sun.tools.classfile.Annotation.Annotation_element_value;
import com.sun.tools.classfile.Annotation.Array_element_value;
import com.sun.tools.classfile.Annotation.Class_element_value;
@ -76,6 +77,124 @@ public class AnnotationWriter extends BasicWriter {
print(")");
}
public void write(TypeAnnotation annot) {
write(annot, true, false);
}
public void write(TypeAnnotation annot, boolean showOffsets, boolean resolveIndices) {
write(annot.annotation, resolveIndices);
print(": ");
write(annot.position, showOffsets);
}
public void write(TypeAnnotation.Position pos, boolean showOffsets) {
print(pos.type);
switch (pos.type) {
// type cast
case CAST:
// instanceof
case INSTANCEOF:
// new expression
case NEW:
if (showOffsets) {
print(", offset=");
print(pos.offset);
}
break;
// local variable
case LOCAL_VARIABLE:
// resource variable
case RESOURCE_VARIABLE:
if (pos.lvarOffset == null) {
print(", lvarOffset is Null!");
break;
}
print(", {");
for (int i = 0; i < pos.lvarOffset.length; ++i) {
if (i != 0) print("; ");
if (showOffsets) {
print("start_pc=");
print(pos.lvarOffset[i]);
}
print(", length=");
print(pos.lvarLength[i]);
print(", index=");
print(pos.lvarIndex[i]);
}
print("}");
break;
// exception parameter
case EXCEPTION_PARAMETER:
print(", exception_index=");
print(pos.exception_index);
break;
// method receiver
case METHOD_RECEIVER:
// Do nothing
break;
// type parameter
case CLASS_TYPE_PARAMETER:
case METHOD_TYPE_PARAMETER:
print(", param_index=");
print(pos.parameter_index);
break;
// type parameter bound
case CLASS_TYPE_PARAMETER_BOUND:
case METHOD_TYPE_PARAMETER_BOUND:
print(", param_index=");
print(pos.parameter_index);
print(", bound_index=");
print(pos.bound_index);
break;
// class extends or implements clause
case CLASS_EXTENDS:
print(", type_index=");
print(pos.type_index);
break;
// throws
case THROWS:
print(", type_index=");
print(pos.type_index);
break;
// method parameter
case METHOD_FORMAL_PARAMETER:
print(", param_index=");
print(pos.parameter_index);
break;
// method/constructor/reference type argument
case CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT:
case METHOD_INVOCATION_TYPE_ARGUMENT:
case METHOD_REFERENCE_TYPE_ARGUMENT:
if (showOffsets) {
print(", offset=");
print(pos.offset);
}
print(", type_index=");
print(pos.type_index);
break;
// We don't need to worry about these
case METHOD_RETURN:
case FIELD:
break;
// lambda formal parameter
case LAMBDA_FORMAL_PARAMETER:
print(", param_index=");
print(pos.parameter_index);
break;
case UNKNOWN:
throw new AssertionError("AnnotationWriter: UNKNOWN target type should never occur!");
default:
throw new AssertionError("AnnotationWriter: Unknown target type for position: " + pos);
}
// Append location data for generics/arrays.
if (!pos.location.isEmpty()) {
print(", location=");
print(pos.location);
}
}
public void write(Annotation.element_value_pair pair) {
write(pair, false);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2013, 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
@ -49,8 +49,10 @@ import com.sun.tools.classfile.LocalVariableTypeTable_attribute;
import com.sun.tools.classfile.MethodParameters_attribute;
import com.sun.tools.classfile.RuntimeInvisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleParameterAnnotations_attribute;
import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleParameterAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
import com.sun.tools.classfile.Signature_attribute;
import com.sun.tools.classfile.SourceDebugExtension_attribute;
import com.sun.tools.classfile.SourceFile_attribute;
@ -433,6 +435,30 @@ public class AttributeWriter extends BasicWriter
return null;
}
public Void visitRuntimeVisibleTypeAnnotations(RuntimeVisibleTypeAnnotations_attribute attr, Void ignore) {
println("RuntimeVisibleTypeAnnotations:");
indent(+1);
for (int i = 0; i < attr.annotations.length; i++) {
print(i + ": ");
annotationWriter.write(attr.annotations[i]);
println();
}
indent(-1);
return null;
}
public Void visitRuntimeInvisibleTypeAnnotations(RuntimeInvisibleTypeAnnotations_attribute attr, Void ignore) {
println("RuntimeInvisibleTypeAnnotations:");
indent(+1);
for (int i = 0; i < attr.annotations.length; i++) {
print(i + ": ");
annotationWriter.write(attr.annotations[i]);
println();
}
indent(-1);
return null;
}
public Void visitRuntimeVisibleParameterAnnotations(RuntimeVisibleParameterAnnotations_attribute attr, Void ignore) {
println("RuntimeVisibleParameterAnnotations:");
indent(+1);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2007, 2013, 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
@ -64,6 +64,7 @@ public class CodeWriter extends BasicWriter {
stackMapWriter = StackMapWriter.instance(context);
localVariableTableWriter = LocalVariableTableWriter.instance(context);
localVariableTypeTableWriter = LocalVariableTypeTableWriter.instance(context);
typeAnnotationWriter = TypeAnnotationWriter.instance(context);
options = Options.instance(context);
}
@ -265,6 +266,11 @@ public class CodeWriter extends BasicWriter {
detailWriters.add(tryBlockWriter);
}
if (options.details.contains(InstructionDetailWriter.Kind.TYPE_ANNOS)) {
typeAnnotationWriter.reset(attr);
detailWriters.add(typeAnnotationWriter);
}
return detailWriters;
}
@ -273,6 +279,7 @@ public class CodeWriter extends BasicWriter {
private ConstantWriter constantWriter;
private LocalVariableTableWriter localVariableTableWriter;
private LocalVariableTypeTableWriter localVariableTypeTableWriter;
private TypeAnnotationWriter typeAnnotationWriter;
private SourceWriter sourceWriter;
private StackMapWriter stackMapWriter;
private TryBlockWriter tryBlockWriter;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2009, 2013, 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
@ -42,10 +42,13 @@ public abstract class InstructionDetailWriter extends BasicWriter {
LOCAL_VAR_TYPES("localVariableTypes"),
SOURCE("source"),
STACKMAPS("stackMaps"),
TRY_BLOCKS("tryBlocks");
TRY_BLOCKS("tryBlocks"),
TYPE_ANNOS("typeAnnotations");
Kind(String option) {
this.option = option;
}
final String option;
}

View File

@ -0,0 +1,126 @@
/*
* Copyright (c) 2009, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package com.sun.tools.javap;
import com.sun.tools.classfile.Attribute;
import com.sun.tools.classfile.Code_attribute;
import com.sun.tools.classfile.TypeAnnotation;
import com.sun.tools.classfile.TypeAnnotation.Position;
import com.sun.tools.classfile.Instruction;
import com.sun.tools.classfile.Method;
import com.sun.tools.classfile.RuntimeInvisibleTypeAnnotations_attribute;
import com.sun.tools.classfile.RuntimeTypeAnnotations_attribute;
import com.sun.tools.classfile.RuntimeVisibleTypeAnnotations_attribute;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Annotate instructions with details about type annotations.
*
* <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.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
public class TypeAnnotationWriter extends InstructionDetailWriter {
public enum NoteKind { VISIBLE, INVISIBLE };
public static class Note {
Note(NoteKind kind, TypeAnnotation anno) {
this.kind = kind;
this.anno = anno;
}
public final NoteKind kind;
public final TypeAnnotation anno;
}
static TypeAnnotationWriter instance(Context context) {
TypeAnnotationWriter instance = context.get(TypeAnnotationWriter.class);
if (instance == null)
instance = new TypeAnnotationWriter(context);
return instance;
}
protected TypeAnnotationWriter(Context context) {
super(context);
context.put(TypeAnnotationWriter.class, this);
annotationWriter = AnnotationWriter.instance(context);
classWriter = ClassWriter.instance(context);
}
public void reset(Code_attribute attr) {
Method m = classWriter.getMethod();
pcMap = new HashMap<Integer, List<Note>>();
check(NoteKind.VISIBLE, (RuntimeVisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeVisibleTypeAnnotations));
check(NoteKind.INVISIBLE, (RuntimeInvisibleTypeAnnotations_attribute) m.attributes.get(Attribute.RuntimeInvisibleTypeAnnotations));
}
private void check(NoteKind kind, RuntimeTypeAnnotations_attribute attr) {
if (attr == null)
return;
for (TypeAnnotation anno: attr.annotations) {
Position p = anno.position;
Note note = null;
if (p.offset != -1)
addNote(p.offset, note = new Note(kind, anno));
if (p.lvarOffset != null) {
for (int i = 0; i < p.lvarOffset.length; i++) {
if (note == null)
note = new Note(kind, anno);
addNote(p.lvarOffset[i], note);
}
}
}
}
private void addNote(int pc, Note note) {
List<Note> list = pcMap.get(pc);
if (list == null)
pcMap.put(pc, list = new ArrayList<Note>());
list.add(note);
}
@Override
void writeDetails(Instruction instr) {
String indent = space(2); // get from Options?
int pc = instr.getPC();
List<Note> notes = pcMap.get(pc);
if (notes != null) {
for (Note n: notes) {
print(indent);
print("@");
annotationWriter.write(n.anno, false, true);
print(", ");
println(n.kind.toString().toLowerCase());
}
}
}
private AnnotationWriter annotationWriter;
private ClassWriter classWriter;
private Map<Integer, List<Note>> pcMap;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -46,7 +46,7 @@ import java.util.HashSet;
*/
public enum SourceVersion {
/*
* Summary of language evoluation
* Summary of language evolution
* 1.1: nested classes
* 1.2: strictfp
* 1.3: no changes

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2012, 2013, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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.
*/
package javax.lang.model.type;
import java.util.List;
import javax.lang.model.element.AnnotationMirror;
/**
* Represents an annotated type.
*
* As of the {@link javax.lang.model.SourceVersion#RELEASE_8
* RELEASE_8} source version, annotated types can appear for all
* type uses.
*
* @author Werner Dietl
* @since 1.8
*/
public interface AnnotatedType extends TypeMirror,
DeclaredType, TypeVariable, WildcardType,
PrimitiveType, ArrayType {
List<? extends AnnotationMirror> getAnnotations();
TypeMirror getUnderlyingType();
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -77,6 +77,14 @@ public interface ExecutableType extends TypeMirror {
*/
List<? extends TypeMirror> getParameterTypes();
/**
* Returns the type of this executable's receiver parameter.
*
* @return the type of this executable's receiver parameter
* TODO: null if none specified or always a valid value?
*/
TypeMirror getReceiverType();
/**
* Returns the exceptions and other throwables listed in this
* executable's {@code throws} clause.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -151,7 +151,14 @@ public enum TypeKind {
*
* @since 1.8
*/
INTERSECTION;
INTERSECTION,
/**
* An annotated type.
*
* @since 1.8
*/
ANNOTATED;
/**
* Returns {@code true} if this kind corresponds to a primitive

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -182,4 +182,14 @@ public interface TypeVisitor<R, P> {
* @since 1.8
*/
R visitIntersection(IntersectionType t, P p);
/**
* Visits an annotated type.
*
* @param t the type to visit
* @param p a visitor-specified parameter
* @return a visitor-specified result
* @since 1.8
*/
R visitAnnotated(AnnotatedType t, P p);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -124,6 +124,23 @@ public abstract class AbstractTypeVisitor6<R, P> implements TypeVisitor<R, P> {
return visitUnknown(t, p);
}
/**
* Visits an {@code AnnotatedType} element by calling {@code
* visit} on the underlying type.
* @param t {@inheritDoc}
* @param p {@inheritDoc}
* @return the result of calling {@code visit} on the underlying type
*
* @since 1.8
*
* TODO: should xxxVisitor8 subclasses override this and call
* the defaultAction?
*/
public R visitAnnotated(AnnotatedType t, P p) {
return visit(t.getUnderlyingType(), p);
}
/**
* {@inheritDoc}
*

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, 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
@ -25,6 +25,9 @@
package javax.lang.model.util;
import java.lang.annotation.Annotation;
import java.lang.annotation.AnnotationTypeMismatchException;
import java.lang.annotation.IncompleteAnnotationException;
import java.util.List;
import javax.lang.model.element.*;
import javax.lang.model.type.*;
@ -298,4 +301,116 @@ public interface Types {
* for the given type
*/
TypeMirror asMemberOf(DeclaredType containing, Element element);
/**
* Returns the annotations targeting the type.
*
* @param type the targeted type
* @return the type annotations targeting the type
*/
List<? extends AnnotationMirror> typeAnnotationsOf(TypeMirror type);
/**
* Returns the type's annotation for the specified type if
* such an annotation is present, else {@code null}. The
* annotation has to be directly present on this
* element.
*
* <p> The annotation returned by this method could contain an element
* whose value is of type {@code Class}.
* This value cannot be returned directly: information necessary to
* locate and load a class (such as the class loader to use) is
* not available, and the class might not be loadable at all.
* Attempting to read a {@code Class} object by invoking the relevant
* method on the returned annotation
* will result in a {@link MirroredTypeException},
* from which the corresponding {@link TypeMirror} may be extracted.
* Similarly, attempting to read a {@code Class[]}-valued element
* will result in a {@link MirroredTypesException}.
*
* <blockquote>
* <i>Note:</i> This method is unlike others in this and related
* interfaces. It operates on runtime reflective information &mdash;
* representations of annotation types currently loaded into the
* VM &mdash; rather than on the representations defined by and used
* throughout these interfaces. Consequently, calling methods on
* the returned annotation object can throw many of the exceptions
* that can be thrown when calling methods on an annotation object
* returned by core reflection. This method is intended for
* callers that are written to operate on a known, fixed set of
* annotation types.
* </blockquote>
*
* @param <A> the annotation type
* @param type the targeted type
* @param annotationType the {@code Class} object corresponding to
* the annotation type
* @return the type's annotation for the specified annotation
* type if present on the type, else {@code null}
*
* @see Element#getAnnotationMirrors()
* @see EnumConstantNotPresentException
* @see AnnotationTypeMismatchException
* @see IncompleteAnnotationException
* @see MirroredTypeException
* @see MirroredTypesException
*/
<A extends Annotation> A typeAnnotationOf(TypeMirror type, Class<A> annotationType);
/**
* Returns the annotations targeting the method receiver type.
*
* @param type the targeted type
* @return the receiver type of the executable type
*/
TypeMirror receiverTypeOf(ExecutableType type);
/**
* Returns the type's annotation for the specified executable type
* receiver if such an annotation is present, else {@code null}. The
* annotation has to be directly present on this
* element.
*
* <p> The annotation returned by this method could contain an element
* whose value is of type {@code Class}.
* This value cannot be returned directly: information necessary to
* locate and load a class (such as the class loader to use) is
* not available, and the class might not be loadable at all.
* Attempting to read a {@code Class} object by invoking the relevant
* method on the returned annotation
* will result in a {@link MirroredTypeException},
* from which the corresponding {@link TypeMirror} may be extracted.
* Similarly, attempting to read a {@code Class[]}-valued element
* will result in a {@link MirroredTypesException}.
*
* <blockquote>
* <i>Note:</i> This method is unlike others in this and related
* interfaces. It operates on runtime reflective information &mdash;
* representations of annotation types currently loaded into the
* VM &mdash; rather than on the representations defined by and used
* throughout these interfaces. Consequently, calling methods on
* the returned annotation object can throw many of the exceptions
* that can be thrown when calling methods on an annotation object
* returned by core reflection. This method is intended for
* callers that are written to operate on a known, fixed set of
* annotation types.
* </blockquote>
*
* @param <A> the annotation type
* @param type the method type
* @param annotationType the {@code Class} object corresponding to
* the annotation type
* @return the type's annotation for the specified annotation
* type if present on the type, else {@code null}
*
* @see Element#getAnnotationMirrors()
* @see EnumConstantNotPresentException
* @see AnnotationTypeMismatchException
* @see IncompleteAnnotationException
* @see MirroredTypeException
* @see MirroredTypesException
*/
// TODO: no longer needed?
// <A extends Annotation> A receiverTypeAnnotationOf(ExecutableType type, Class<A> annotationType);
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2009 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
* @summary Make sure that annotations types with optional elements has
* element headers
* @author Mahmood Ali
* @library ../lib/
* @build JavadocTester
* @build TestAnnotationOptional
* @run main TestAnnotationOptional
*/
public class TestAnnotationOptional extends JavadocTester {
//Test information.
private static final String BUG_ID = "NO_BUG_ID_YET";
//Javadoc arguments.
private static final String[] ARGS = new String[] {
"-d", BUG_ID, "-sourcepath", SRC_DIR, "-source", "1.5", "pkg"
};
//Input for string search tests.
private static final String[][] TEST = {
{BUG_ID + FS + "pkg" + FS + "AnnotationOptional.html",
"<a name=\"annotation_type_element_detail\">"
}
};
private static final String[][] NEGATED_TEST = NO_TEST;
/**
* The entry point of the test.
* @param args the array of command line arguments.
*/
public static void main(String[] args) {
TestAnnotationOptional tester = new TestAnnotationOptional();
run(tester, ARGS, TEST, NEGATED_TEST);
tester.printSummary();
}
/**
* {@inheritDoc}
*/
public String getBugId() {
return BUG_ID;
}
/**
* {@inheritDoc}
*/
public String getBugName() {
return getClass().getName();
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2009 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.
*/
package pkg;
import java.lang.annotation.*;
/**
* This is just a test annotation type with optional value element.
*
* @author Mahmood Ali
* @since 1.5
*/
@Documented public @interface AnnotationOptional {
String value() default "";
}

View File

@ -0,0 +1,114 @@
/*
* Copyright (c) 2010 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 8006735
* @ignore
* @summary Smoke test for ensuring that annotations are emited to javadoc
*
* @author Mahmood Ali <mali>
* @library ../../lib/
* @build JavadocTester
* @build TestSmoke
* @run main TestSmoke
*/
public class TestSmoke extends JavadocTester {
//Test information.
private static final String BUG_ID = "NOT_SPECIFIED_YET";
//Javadoc arguments.
private static final String[] ARGS = new String[] {
"-d", BUG_ID, "-private", "-sourcepath", SRC_DIR, "pkg"
};
//Input for string search tests.
private static final String[][] TEST = {
{BUG_ID + FS + "pkg" + FS + "T0x1C.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x1D.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x0D.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x06.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x0B.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x0F.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x20.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x22.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x10.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x10A.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x12.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x11.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x13.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x15.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x14.html", "@DA"},
{BUG_ID + FS + "pkg" + FS + "T0x16.html", "@DA"}
};
private static final String[][] NEGATED_TEST = {
{BUG_ID + FS + "pkg" + FS + "T0x1C.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x1D.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x00.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x01.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x02.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x04.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x08.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x0D.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x06.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x0B.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x0F.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x20.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x22.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x10.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x10A.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x12.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x11.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x13.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x15.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x14.html", "@A"},
{BUG_ID + FS + "pkg" + FS + "T0x16.html", "@A"}
};
/**
* The entry point of the test.
* @param args the array of command line arguments.
*/
public static void main(String[] args) {
TestSmoke tester = new TestSmoke();
run(tester, ARGS, TEST, NEGATED_TEST);
tester.printSummary();
}
/**
* {@inheritDoc}
*/
public String getBugId() {
return BUG_ID;
}
/**
* {@inheritDoc}
*/
public String getBugName() {
return getClass().getName();
}
}

View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 2010 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.
*/
package pkg;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
import java.util.*;
import java.io.*;
/*
* @summary compiler accepts all values
* @author Mahmood Ali
* @author Yuri Gaevsky
*/
@Target({TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@interface A {}
@Target({TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@interface DA {}
/** wildcard bound */
class T0x1C {
void m0x1C(List<? extends @A @DA String> lst) {}
}
/** wildcard bound generic/array */
class T0x1D<T> {
void m0x1D(List<? extends @A @DA List<int[]>> lst) {}
}
/** typecast */
class T0x00 {
void m0x00(Long l1) {
Object l2 = (@A @DA Long) l1;
}
}
/** typecast generic/array */
class T0x01<T> {
void m0x01(List<T> list) {
List<T> l = (List<@A @DA T>) list;
}
}
/** instanceof */
class T0x02 {
boolean m0x02(String s) {
return (s instanceof @A @DA String);
}
}
/** object creation (new) */
class T0x04 {
void m0x04() {
new @A @DA ArrayList<String>();
}
}
/** local variable */
class T0x08 {
void m0x08() {
@A @DA String s = null;
}
}
/** method parameter generic/array */
class T0x0D {
void m0x0D(HashMap<@A @DA Object, List<@A @DA List<@A @DA Class>>> s1) {}
}
/** method receiver */
class T0x06 {
void m0x06(@A @DA T0x06 this) {}
}
/** method return type generic/array */
class T0x0B {
Class<@A @DA Object> m0x0B() { return null; }
}
/** field generic/array */
class T0x0F {
HashMap<@A @DA Object, @A @DA Object> c1;
}
/** method type parameter */
class T0x20<T, U> {
<@A @DA T, @A @DA U> void m0x20() {}
}
/** class type parameter */
class T0x22<@A @DA T, @A @DA U> {
}
/** class type parameter bound */
class T0x10<T extends @A @DA Cloneable> {
}
class T0x10A<T extends @A @DA Object> {
}
/** method type parameter bound */
class T0x12<T> {
<T extends @A @DA Cloneable> void m0x12() {}
}
/** class type parameter bound generic/array */
class T0x11<T extends List<@A @DA T>> {
}
/** method type parameter bound generic/array */
class T0x13 {
static <T extends Comparable<@A @DA T>> T m0x13() {
return null;
}
}
/** class extends/implements generic/array */
class T0x15<T> extends ArrayList<@A @DA T> {
}
/** type test (instanceof) generic/array */
class T0x03<T> {
void m0x03(T typeObj, Object obj) {
boolean ok = obj instanceof String @A @DA [];
}
}
/** object creation (new) generic/array */
class T0x05<T> {
void m0x05() {
new ArrayList<@A @DA T>();
}
}
/** local variable generic/array */
class T0x09<T> {
void g() {
List<@A @DA String> l = null;
}
void a() {
String @A @DA [] as = null;
}
}
/** type argument in constructor call generic/array */
class T0x19 {
<T> T0x19() {}
void g() {
new <List<@A @DA String>> T0x19();
}
}
/** type argument in method call generic/array */
class T0x1B<T> {
void m0x1B() {
Collections.<T @A @DA []>emptyList();
}
}
/** type argument in constructor call */
class T0x18<T> {
<T> T0x18() {}
void m() {
new <@A @DA Integer> T0x18();
}
}
/** type argument in method call */
class T0x1A<T,U> {
public static <T, U> T m() { return null; }
static void m0x1A() {
T0x1A.<@A @DA Integer, @A @DA Short>m();
}
}
/** class extends/implements */
class T0x14 extends @A @DA Thread implements @A @DA Serializable, @A @DA Cloneable {
}
/** exception type in throws */
class T0x16 {
void m0x16() throws @A @DA Exception {}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2013, 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
@ -30,7 +30,7 @@
* @build JavacTestingAbstractProcessor
* @compile/fail/ref=NegTest.ref -XDrawDiagnostics TestImportStar.java
* @compile Anno.java AnnoProcessor.java
* @compile/ref=TestImportStar.ref -XDrawDiagnostics -processor AnnoProcessor -proc:only TestImportStar.java
* @compile/fail/ref=TestImportStar.ref -XDrawDiagnostics -processor AnnoProcessor -proc:only TestImportStar.java
*/
//The @compile/fail... verifies that the fix doesn't break the normal compilation of import xxx.*

View File

@ -1,3 +1,4 @@
- compiler.note.proc.messager: RUNNING - lastRound = false
TestImportStar.java:39:1: compiler.err.doesnt.exist: xxx
- compiler.note.proc.messager: RUNNING - lastRound = true
1 error

View File

@ -19,8 +19,8 @@ public class T6873845 {
if (out.contains("sunapi"))
throw new Exception("unexpected output for -X");
String warn1 = "T6873845.java:72:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline;
String warn2 = "T6873845.java:77:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline;
String warn1 = "T6873845.java:73:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline;
String warn2 = "T6873845.java:78:9: compiler.warn.sun.proprietary: sun.misc.Unsafe" + newline;
String note1 = "- compiler.note.sunapi.filename: T6873845.java" + newline;
String note2 = "- compiler.note.sunapi.recompile" + newline;
@ -52,7 +52,8 @@ public class T6873845 {
args.add(0, "-XDrawDiagnostics");
String out = compile(args);
if (!out.equals(expect))
throw new Exception("unexpected output from compiler");
throw new Exception("unexpected output from compiler; expected: " + expect +
"\n found: " + out);
}
String compile(List<String> args) throws Exception{

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2010, 2013, 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 6985181
* @summary Annotations lost from classfile
*/
import java.io.*;
import java.util.*;
public class T6985181 {
public static void main(String... args) throws Exception{
new T6985181().run();
}
public void run() throws Exception {
String code = "@java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_PARAMETER)\n" +
"@interface Simple { }\n" +
"interface Test<@Simple T> { }";
File srcFile = writeFile("Test.java", code);
File classesDir = new File("classes");
classesDir.mkdirs();
compile("-d", classesDir.getPath(), srcFile.getPath());
String out = javap(new File(classesDir, srcFile.getName().replace(".java", ".class")));
if (!out.contains("RuntimeInvisibleTypeAnnotations"))
throw new Exception("RuntimeInvisibleTypeAnnotations not found");
}
void compile(String... args) throws Exception {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
int rc = com.sun.tools.javac.Main.compile(args, pw);
pw.close();
String out = sw.toString();
if (out.length() > 0)
System.err.println(out);
if (rc != 0)
throw new Exception("Compilation failed: rc=" + rc);
}
String javap(File classFile) throws Exception {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
String[] args = { "-v", classFile.getPath() };
int rc = com.sun.tools.javap.Main.run(args, pw);
pw.close();
String out = sw.toString();
if (out.length() > 0)
System.err.println(out);
if (rc != 0)
throw new Exception("javap failed: rc=" + rc);
return out;
}
File writeFile(String path, String body) throws IOException {
File f = new File(path);
FileWriter out = new FileWriter(f);
try {
out.write(body);
} finally {
out.close();
}
return f;
}
}

View File

@ -1,3 +1,6 @@
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
/*
* @test /nodynamiccopyright/
* @bug 6881115 6976649
@ -6,15 +9,18 @@
* @compile/fail/ref=T6881115.out -XDrawDiagnostics T6881115.java
*/
@Target({ElementType.TYPE, ElementType.TYPE_PARAMETER, ElementType.ANNOTATION_TYPE})
@interface A {
B b() default @B(b2 = 1, b2 = 2);
B[] b_arr() default {@B(), @B(b2 = 1, b2 = 2)};
}
@interface B {
String b1();
int b2();
}
@A(b = @B(b2 = 1, b2 = 2),
b_arr = {@B(), @B(b2 = 1, b2 = 2)})
class T6881115</*308 @A(b = @B(b2 = 1, b2 = 2),
b_arr = {@B(), @B(b2 = 1, b2 = 2)})*/ X> {}
class T6881115<@A(b = @B(b2 = 1, b2 = 2),
b_arr = {@B(), @B(b2 = 1, b2 = 2)}) X> {}

View File

@ -1,11 +1,16 @@
T6881115.java:10:30: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:10:19: compiler.err.annotation.missing.default.value: B, b1
T6881115.java:11:26: compiler.err.annotation.missing.default.value.1: B, b1,b2
T6881115.java:11:43: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:11:32: compiler.err.annotation.missing.default.value: B, b1
T6881115.java:17:19: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:17:8: compiler.err.annotation.missing.default.value: B, b1
T6881115.java:18:13: compiler.err.annotation.missing.default.value.1: B, b1,b2
T6881115.java:18:30: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:18:19: compiler.err.annotation.missing.default.value: B, b1
10 errors
T6881115.java:14:30: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:14:19: compiler.err.annotation.missing.default.value: B, b1
T6881115.java:15:26: compiler.err.annotation.missing.default.value.1: B, b1,b2
T6881115.java:15:43: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:15:32: compiler.err.annotation.missing.default.value: B, b1
T6881115.java:23:19: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:23:8: compiler.err.annotation.missing.default.value: B, b1
T6881115.java:24:13: compiler.err.annotation.missing.default.value.1: B, b1,b2
T6881115.java:24:30: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:24:19: compiler.err.annotation.missing.default.value: B, b1
T6881115.java:25:34: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:25:23: compiler.err.annotation.missing.default.value: B, b1
T6881115.java:26:28: compiler.err.annotation.missing.default.value.1: B, b1,b2
T6881115.java:26:45: compiler.err.duplicate.annotation.member.value: b2, B
T6881115.java:26:34: compiler.err.annotation.missing.default.value: B, b1
15 errors

Some files were not shown because too many files have changed in this diff Show More