This commit is contained in:
Lana Steuck 2013-01-26 19:24:46 -08:00
commit f018e9352d
612 changed files with 29930 additions and 2250 deletions

View File

@ -29,18 +29,18 @@
# Override this path as needed, either on the command line or in
# one of the standard user build.properties files (see build.xml)
# boot.java.home = /opt/jdk/1.6.0
# boot.java.home = /opt/jdk/1.7.0
boot.java = ${boot.java.home}/bin/java
boot.javac = ${boot.java.home}/bin/javac
boot.javac.source = 6
boot.javac.target = 6
boot.javac.source = 7
boot.javac.target = 7
# This is the JDK used to run the product version of the tools,
# for example, for testing. If you're building a complete JDK, specify that.
# Override this path as needed, either on the command line or in
# one of the standard user build.properties files (see build.xml)
# target.java.home = /opt/jdk/1.7.0
# target.java.home = /opt/jdk/1.8.0
target.java = ${target.java.home}/bin/java
# Version info -- override as needed
@ -161,6 +161,14 @@ javap.tests = \
#
sjavac.includes = \
com/sun/tools/sjavac/
sjavac.tests = \
tools/sjavac
#
# The following files require the latest JDK to be available.
# The API can be provided by using a suitable boot.java.home
# or by setting import.jdk

View File

@ -241,15 +241,15 @@
</target>
<target name="build-bootstrap-tools"
depends="build-bootstrap-javac,build-bootstrap-javadoc,build-bootstrap-doclets,build-bootstrap-javah"
depends="build-bootstrap-javac,build-bootstrap-javadoc,build-bootstrap-doclets,build-bootstrap-javah,build-bootstrap-sjavac"
/>
<target name="build-all-tools"
depends="build-javac,build-javadoc,build-doclets,build-javah,build-javap"
depends="build-javac,build-javadoc,build-doclets,build-javah,build-javap,build-sjavac"
/>
<target name="build-all-classes" depends="build-bootstrap-javac,-create-import-jdk-stubs">
<build-classes includes="${javac.includes} ${javadoc.includes} ${doclets.includes} ${javah.includes} ${javap.includes}"/>
<build-classes includes="${javac.includes} ${javadoc.includes} ${doclets.includes} ${javah.includes} ${javap.includes} ${sjavac.includes}"/>
</target>
<!-- clean -->
@ -656,6 +656,40 @@
<target name="javap" depends="build-javap,jtreg-javap,findbugs-javap"/>
<!--
**** sjavac targets.
-->
<target name="build-bootstrap-sjavac"
depends="-def-build-bootstrap-classes,-def-build-bootstrap-jar,-def-build-bootstrap-tool">
<build-bootstrap-classes includes="${sjavac.includes}"/>
<build-bootstrap-jar name="sjavac" includes="${sjavac.includes}"
jarmainclass="com.sun.tools.sjavac.Main"/>
<build-bootstrap-tool name="sjavac"/>
</target>
<target name="build-classes-sjavac" depends="build-classes-javac">
<build-classes includes="${sjavac.includes}"/>
</target>
<target name="build-sjavac" depends="build-classes-sjavac">
<build-jar name="sjavac" includes="${sjavac.includes}"
jarmainclass="com.sun.tools.sjavac.Main"
jarclasspath="sjavac.jar"/>
<build-tool name="sjavac"/>
</target>
<!-- (no javadoc for javap) -->
<target name="jtreg-sjavac" depends="build-sjavac,-def-jtreg">
<jtreg-tool name="sjavac" tests="${sjavac.tests}"/>
</target>
<target name="findbugs-sjavac" depends="build-sjavac,-def-findbugs">
<findbugs-tool name="sjavac"/>
</target>
<target name="sjavac" depends="build-sjavac,jtreg-sjavac,findbugs-sjavac"/>
<!--
**** Create import JDK stubs.

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) 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
@ -33,8 +33,10 @@ import javax.tools.JavaFileManager;
import com.sun.javadoc.*;
import com.sun.tools.doclets.internal.toolkit.*;
import com.sun.tools.doclets.internal.toolkit.util.*;
import com.sun.tools.doclint.DocLint;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javadoc.RootDocImpl;
/**
* Configure the output based on the command line options.
@ -171,6 +173,11 @@ public class ConfigurationImpl extends Configuration {
*/
public boolean createoverview = false;
/**
* Collected set of doclint options
*/
public Set<String> doclintOpts = new LinkedHashSet<String>();
/**
* Unique Resource Handler for this package.
*/
@ -255,6 +262,10 @@ public class ConfigurationImpl extends Configuration {
nooverview = true;
} else if (opt.equals("-overview")) {
overview = true;
} else if (opt.equals("-xdoclint")) {
doclintOpts.add(null);
} else if (opt.startsWith("-xdoclint:")) {
doclintOpts.add(opt.substring(opt.indexOf(":") + 1));
}
}
if (root.specifiedClasses().length > 0) {
@ -270,6 +281,10 @@ public class ConfigurationImpl extends Configuration {
}
setCreateOverview();
setTopFile(root);
if (root instanceof RootDocImpl) {
((RootDocImpl) root).initDocLint(doclintOpts);
}
}
/**
@ -303,7 +318,9 @@ public class ConfigurationImpl extends Configuration {
option.equals("-serialwarn") ||
option.equals("-use") ||
option.equals("-nonavbar") ||
option.equals("-nooverview")) {
option.equals("-nooverview") ||
option.equals("-xdoclint") ||
option.startsWith("-xdoclint:")) {
return 1;
} else if (option.equals("-help")) {
System.out.println(getText("doclet.usage"));
@ -410,6 +427,16 @@ public class ConfigurationImpl extends Configuration {
return false;
}
noindex = true;
} else if (opt.startsWith("-xdoclint:")) {
if (opt.contains("/")) {
reporter.printError(getText("doclet.Option_doclint_no_qualifiers"));
return false;
}
if (!DocLint.isValidOption(
opt.replace("-xdoclint:", DocLint.XMSGS_CUSTOM_PREFIX))) {
reporter.printError(getText("doclet.Option_doclint_invalid_arg"));
return false;
}
}
}
return true;
@ -506,8 +533,8 @@ public class ConfigurationImpl extends Configuration {
*/
@Override
public Locale getLocale() {
if (root instanceof com.sun.tools.javadoc.RootDocImpl)
return ((com.sun.tools.javadoc.RootDocImpl)root).getLocale();
if (root instanceof RootDocImpl)
return ((RootDocImpl)root).getLocale();
else
return Locale.getDefault();
}
@ -518,8 +545,8 @@ public class ConfigurationImpl extends Configuration {
@Override
public JavaFileManager getFileManager() {
if (fileManager == null) {
if (root instanceof com.sun.tools.javadoc.RootDocImpl)
fileManager = ((com.sun.tools.javadoc.RootDocImpl)root).getFileManager();
if (root instanceof RootDocImpl)
fileManager = ((RootDocImpl) root).getFileManager();
else
fileManager = new JavacFileManager(new Context(), false, null);
}
@ -527,4 +554,12 @@ public class ConfigurationImpl extends Configuration {
}
private JavaFileManager fileManager;
@Override
public boolean showMessage(SourcePosition pos, String key) {
if (root instanceof RootDocImpl) {
return pos == null || ((RootDocImpl) root).showTagMessages();
}
return true;
}
}

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) 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
@ -781,4 +781,6 @@ public abstract class Configuration {
sourcetab = n;
tabSpaces = String.format("%" + n + "s", "");
}
public abstract boolean showMessage(SourcePosition pos, String key);
}

View File

@ -11,6 +11,8 @@ doclet.Class_0_implements_serializable=Class {0} implements Serializable
doclet.Class_0_extends_implements_serializable=Class {0} extends {1} implements Serializable
doclet.Option_conflict=Option {0} conflicts with {1}
doclet.Option_reuse=Option reused: {0}
doclet.Option_doclint_no_qualifiers=Access qualifiers not permitted for -Xdoclint arguments
doclet.Option_doclint_invalid_arg=Invalid argument for -Xdoclint option
doclet.exception_encountered= {0} encountered \n\
\twhile attempting to create file: {1}
doclet.perform_copy_exception_encountered= {0} encountered while \n\

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
@ -60,9 +60,9 @@ public class MessageRetriever {
private ResourceBundle messageRB;
/**
* Initilize the ResourceBundle with the given resource.
* Initialize the ResourceBundle with the given resource.
*
* @param rb the esource bundle to read.
* @param rb the resource bundle to read.
*/
public MessageRetriever(ResourceBundle rb) {
this.configuration = null;
@ -71,7 +71,7 @@ public class MessageRetriever {
}
/**
* Initilize the ResourceBundle with the given resource.
* Initialize the ResourceBundle with the given resource.
*
* @param configuration the configuration
* @param resourcelocation Resource.
@ -189,7 +189,8 @@ public class MessageRetriever {
* @param args arguments to be replaced in the message.
*/
public void warning(SourcePosition pos, String key, Object... args) {
printWarning(pos, getText(key, args));
if (configuration.showMessage(pos, key))
printWarning(pos, getText(key, args));
}
/**

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

@ -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
@ -25,6 +25,7 @@
package com.sun.tools.doclint;
import com.sun.source.doctree.LiteralTree;
import java.util.regex.Matcher;
import com.sun.source.doctree.LinkTree;
import java.net.URI;
@ -91,10 +92,11 @@ public class Checker extends DocTreeScanner<Void, Void> {
boolean foundInheritDoc = false;
boolean foundReturn = false;
enum Flag {
public enum Flag {
TABLE_HAS_CAPTION,
HAS_ELEMENT,
HAS_TEXT
HAS_TEXT,
REPORTED_BAD_INLINE
}
static class TagStackItem {
@ -194,7 +196,8 @@ public class Checker extends DocTreeScanner<Void, Void> {
@Override
public Void visitText(TextTree tree, Void ignore) {
if (!tree.getBody().trim().isEmpty()) {
if (hasNonWhitespace(tree)) {
checkAllowsText(tree);
markEnclosingTag(Flag.HAS_TEXT);
}
return null;
@ -202,6 +205,7 @@ public class Checker extends DocTreeScanner<Void, Void> {
@Override
public Void visitEntity(EntityTree tree, Void ignore) {
checkAllowsText(tree);
markEnclosingTag(Flag.HAS_TEXT);
String name = tree.getName().toString();
if (name.startsWith("#")) {
@ -217,6 +221,18 @@ public class Checker extends DocTreeScanner<Void, Void> {
return null;
}
void checkAllowsText(DocTree tree) {
TagStackItem top = tagStack.peek();
if (top != null
&& top.tree.getKind() == DocTree.Kind.START_ELEMENT
&& !top.tag.acceptsText()) {
if (top.flags.add(Flag.REPORTED_BAD_INLINE)) {
env.messages.error(HTML, tree, "dc.text.not.allowed",
((StartElementTree) top.tree).getName());
}
}
}
// </editor-fold>
// <editor-fold defaultstate="collapsed" desc="HTML elements">
@ -229,53 +245,22 @@ public class Checker extends DocTreeScanner<Void, Void> {
if (t == null) {
env.messages.error(HTML, tree, "dc.tag.unknown", treeName);
} else {
for (TagStackItem tsi: tagStack) {
if (tsi.tag.accepts(t)) {
while (tagStack.peek() != tsi) tagStack.pop();
break;
} else if (tsi.tag.endKind != HtmlTag.EndKind.OPTIONAL)
break;
}
checkStructure(tree, t);
// tag specific checks
switch (t) {
// check for out of sequence headers, such as <h1>...</h1> <h3>...</h3>
case H1: case H2: case H3: case H4: case H5: case H6:
checkHeader(tree, t);
break;
// <p> inside <pre>
case P:
TagStackItem top = tagStack.peek();
if (top != null && top.tag == HtmlTag.PRE)
env.messages.warning(HTML, tree, "dc.tag.p.in.pre");
break;
}
// check that only block tags and inline tags are used,
// and that blocks tags are not used within inline tags
switch (t.blockType) {
case INLINE:
break;
case BLOCK:
TagStackItem top = tagStack.peek();
if (top != null && top.tag != null && top.tag.blockType == HtmlTag.BlockType.INLINE) {
switch (top.tree.getKind()) {
case START_ELEMENT: {
Name name = ((StartElementTree) top.tree).getName();
env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.element",
treeName, name);
break;
}
case LINK:
case LINK_PLAIN: {
String name = top.tree.getKind().tagName;
env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.tag",
treeName, name);
break;
}
default:
env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.other",
treeName);
}
}
break;
case OTHER:
env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
break;
default:
throw new AssertionError();
}
if (t.flags.contains(HtmlTag.Flag.NO_NEST)) {
@ -323,6 +308,58 @@ public class Checker extends DocTreeScanner<Void, Void> {
}
}
private void checkStructure(StartElementTree tree, HtmlTag t) {
Name treeName = tree.getName();
TagStackItem top = tagStack.peek();
switch (t.blockType) {
case BLOCK:
if (top == null || top.tag.accepts(t))
return;
switch (top.tree.getKind()) {
case START_ELEMENT: {
if (top.tag.blockType == HtmlTag.BlockType.INLINE) {
Name name = ((StartElementTree) top.tree).getName();
env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.element",
treeName, name);
return;
}
}
break;
case LINK:
case LINK_PLAIN: {
String name = top.tree.getKind().tagName;
env.messages.error(HTML, tree, "dc.tag.not.allowed.inline.tag",
treeName, name);
return;
}
}
break;
case INLINE:
if (top == null || top.tag.accepts(t))
return;
break;
case LIST_ITEM:
case TABLE_ITEM:
if (top != null) {
// reset this flag so subsequent bad inline content gets reported
top.flags.remove(Flag.REPORTED_BAD_INLINE);
if (top.tag.accepts(t))
return;
}
break;
case OTHER:
env.messages.error(HTML, tree, "dc.tag.not.allowed", treeName);
return;
}
env.messages.error(HTML, tree, "dc.tag.not.allowed.here", treeName);
}
private void checkHeader(StartElementTree tree, HtmlTag tag) {
// verify the new tag
if (getHeaderLevel(tag) > getHeaderLevel(currHeaderTag) + 1) {
@ -359,9 +396,8 @@ public class Checker extends DocTreeScanner<Void, Void> {
env.messages.error(HTML, tree, "dc.tag.unknown", treeName);
} else if (t.endKind == HtmlTag.EndKind.NONE) {
env.messages.error(HTML, tree, "dc.tag.end.not.permitted", treeName);
} else if (tagStack.isEmpty()) {
env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName);
} else {
boolean done = false;
while (!tagStack.isEmpty()) {
TagStackItem top = tagStack.peek();
if (t == top.tag) {
@ -378,11 +414,8 @@ public class Checker extends DocTreeScanner<Void, Void> {
&& !top.flags.contains(Flag.HAS_ELEMENT)) {
env.messages.warning(HTML, tree, "dc.tag.empty", treeName);
}
if (t.flags.contains(HtmlTag.Flag.NO_TEXT)
&& top.flags.contains(Flag.HAS_TEXT)) {
env.messages.error(HTML, tree, "dc.text.not.allowed", treeName);
}
tagStack.pop();
done = true;
break;
} else if (top.tag == null || top.tag.endKind != HtmlTag.EndKind.REQUIRED) {
tagStack.pop();
@ -400,10 +433,15 @@ public class Checker extends DocTreeScanner<Void, Void> {
tagStack.pop();
} else {
env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName);
done = true;
break;
}
}
}
if (!done && tagStack.isEmpty()) {
env.messages.error(HTML, tree, "dc.tag.end.unexpected", treeName);
}
}
return super.visitEndElement(tree, ignore);
@ -447,14 +485,18 @@ public class Checker extends DocTreeScanner<Void, Void> {
if (currTag != HtmlTag.A) {
break;
}
// fallthrough
// fallthrough
case ID:
String value = getAttrValue(tree);
if (!validName.matcher(value).matches()) {
env.messages.error(HTML, tree, "dc.invalid.anchor", value);
}
if (!foundAnchors.add(value)) {
env.messages.error(HTML, tree, "dc.anchor.already.defined", value);
if (value == null) {
env.messages.error(HTML, tree, "dc.anchor.value.missing");
} else {
if (!validName.matcher(value).matches()) {
env.messages.error(HTML, tree, "dc.invalid.anchor", value);
}
if (!foundAnchors.add(value)) {
env.messages.error(HTML, tree, "dc.anchor.already.defined", value);
}
}
break;
@ -541,6 +583,19 @@ public class Checker extends DocTreeScanner<Void, Void> {
}
}
@Override
public Void visitLiteral(LiteralTree tree, Void ignore) {
if (tree.getKind() == DocTree.Kind.CODE) {
for (TagStackItem tsi: tagStack) {
if (tsi.tag == HtmlTag.CODE) {
env.messages.warning(HTML, tree, "dc.tag.code.within.code");
break;
}
}
}
return super.visitLiteral(tree, ignore);
}
@Override
public Void visitParam(ParamTree tree, Void ignore) {
boolean typaram = tree.isTypeParameter();
@ -740,7 +795,7 @@ public class Checker extends DocTreeScanner<Void, Void> {
for (DocTree d: list) {
switch (d.getKind()) {
case TEXT:
if (!((TextTree) d).getBody().trim().isEmpty())
if (hasNonWhitespace((TextTree) d))
return;
break;
default:
@ -749,6 +804,16 @@ public class Checker extends DocTreeScanner<Void, Void> {
}
env.messages.warning(SYNTAX, tree, "dc.empty", tree.getKind().tagName);
}
boolean hasNonWhitespace(TextTree tree) {
String s = tree.getBody();
for (int i = 0; i < s.length(); i++) {
if (!Character.isWhitespace(s.charAt(i)))
return true;
}
return false;
}
// </editor-fold>
}

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
@ -122,7 +122,7 @@ public class DocLint implements Plugin {
if (javacFiles.isEmpty()) {
if (!needHelp)
System.out.println("no files given");
out.println("no files given");
}
JavacTool tool = JavacTool.create();
@ -179,11 +179,11 @@ public class DocLint implements Plugin {
}
} else if (arg.equals(STATS)) {
env.messages.setStatsEnabled(true);
} else if (arg.matches("-bootclasspath") && i + 1 < args.length) {
} else if (arg.equals("-bootclasspath") && i + 1 < args.length) {
javacBootClassPath = splitPath(args[++i]);
} else if (arg.matches("-classpath") && i + 1 < args.length) {
} else if (arg.equals("-classpath") && i + 1 < args.length) {
javacClassPath = splitPath(args[++i]);
} else if (arg.matches("-sourcepath") && i + 1 < args.length) {
} else if (arg.equals("-sourcepath") && i + 1 < args.length) {
javacSourcePath = splitPath(args[++i]);
} else if (arg.equals(XMSGS_OPTION)) {
env.messages.setOptions(null);
@ -234,6 +234,8 @@ public class DocLint implements Plugin {
out.println(" equivalent to -Xmsgs:all/protected, meaning that");
out.println(" all messages are reported for protected and public");
out.println(" declarations only. ");
out.println(" -stats");
out.println(" Report statistics on the reported issues.");
out.println(" -h -help --help -usage -?");
out.println(" Show this message.");
out.println("");
@ -247,7 +249,7 @@ public class DocLint implements Plugin {
List<File> splitPath(String path) {
List<File> files = new ArrayList<File>();
for (String f: path.split(File.separator)) {
for (String f: path.split(File.pathSeparator)) {
if (f.length() > 0)
files.add(new File(f));
}

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
@ -43,7 +43,7 @@ import java.util.Map;
* risk. This code and its internal interfaces are subject to change
* or deletion without notice.</b></p>
*/
enum Entity {
public enum Entity {
nbsp(160),
iexcl(161),
cent(162),

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
* 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
@ -57,16 +57,22 @@ public enum HtmlTag {
B(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
BLOCKQUOTE,
BIG(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT)),
BLOCKQUOTE(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
BODY(BlockType.OTHER, EndKind.REQUIRED),
BR(BlockType.INLINE, EndKind.NONE,
attrs(AttrKind.USE_CSS, CLEAR)),
CAPTION(EnumSet.of(Flag.EXPECT_CONTENT)),
CAPTION(BlockType.TABLE_ITEM, EndKind.REQUIRED,
EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
CENTER,
CENTER(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
CITE(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
@ -74,17 +80,23 @@ public enum HtmlTag {
CODE(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
DD(BlockType.BLOCK, EndKind.OPTIONAL,
EnumSet.of(Flag.EXPECT_CONTENT)),
DD(BlockType.LIST_ITEM, EndKind.OPTIONAL,
EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
DIV,
DIV(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
DL(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
attrs(AttrKind.USE_CSS, COMPACT)),
EnumSet.of(Flag.EXPECT_CONTENT),
attrs(AttrKind.USE_CSS, COMPACT)) {
@Override
public boolean accepts(HtmlTag t) {
return (t == DT) || (t == DD);
}
},
DT(BlockType.BLOCK, EndKind.OPTIONAL,
EnumSet.of(Flag.EXPECT_CONTENT)),
DT(BlockType.LIST_ITEM, EndKind.OPTIONAL,
EnumSet.of(Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)),
EM(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.NO_NEST)),
@ -97,12 +109,12 @@ public enum HtmlTag {
FRAMESET(BlockType.OTHER, EndKind.REQUIRED),
H1,
H2,
H3,
H4,
H5,
H6,
H1(BlockType.BLOCK, EndKind.REQUIRED),
H2(BlockType.BLOCK, EndKind.REQUIRED),
H3(BlockType.BLOCK, EndKind.REQUIRED),
H4(BlockType.BLOCK, EndKind.REQUIRED),
H5(BlockType.BLOCK, EndKind.REQUIRED),
H6(BlockType.BLOCK, EndKind.REQUIRED),
HEAD(BlockType.OTHER, EndKind.REQUIRED),
@ -118,31 +130,54 @@ public enum HtmlTag {
attrs(AttrKind.OBSOLETE, NAME),
attrs(AttrKind.USE_CSS, ALIGN, HSPACE, VSPACE, BORDER)),
LI(BlockType.BLOCK, EndKind.OPTIONAL),
LI(BlockType.LIST_ITEM, EndKind.OPTIONAL,
EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)),
LINK(BlockType.OTHER, EndKind.NONE),
MENU,
MENU(BlockType.BLOCK, EndKind.REQUIRED) {
@Override
public boolean accepts(HtmlTag t) {
return (t == LI);
}
},
META(BlockType.OTHER, EndKind.NONE),
NOFRAMES(BlockType.OTHER, EndKind.REQUIRED),
NOSCRIPT(BlockType.OTHER, EndKind.REQUIRED),
NOSCRIPT(BlockType.BLOCK, EndKind.REQUIRED),
OL(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
attrs(AttrKind.USE_CSS, START, TYPE)),
EnumSet.of(Flag.EXPECT_CONTENT),
attrs(AttrKind.USE_CSS, START, TYPE)){
@Override
public boolean accepts(HtmlTag t) {
return (t == LI);
}
},
P(BlockType.BLOCK, EndKind.OPTIONAL,
EnumSet.of(Flag.EXPECT_CONTENT),
attrs(AttrKind.USE_CSS, ALIGN)),
PRE(EnumSet.of(Flag.EXPECT_CONTENT)),
PRE(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT)) {
@Override
public boolean accepts(HtmlTag t) {
switch (t) {
case IMG: case BIG: case SMALL: case SUB: case SUP:
return false;
default:
return (t.blockType == BlockType.INLINE);
}
}
},
SCRIPT(BlockType.OTHER, EndKind.REQUIRED),
SMALL(BlockType.INLINE, EndKind.REQUIRED),
SMALL(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT)),
SPAN(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT)),
@ -157,37 +192,70 @@ public enum HtmlTag {
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
TABLE(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
EnumSet.of(Flag.EXPECT_CONTENT),
attrs(AttrKind.OK, SUMMARY, Attr.FRAME, RULES, BORDER,
CELLPADDING, CELLSPACING),
attrs(AttrKind.USE_CSS, ALIGN, WIDTH, BGCOLOR)),
attrs(AttrKind.USE_CSS, ALIGN, WIDTH, BGCOLOR)) {
@Override
public boolean accepts(HtmlTag t) {
switch (t) {
case CAPTION:
case THEAD: case TBODY: case TFOOT:
case TR: // HTML 3.2
return true;
default:
return false;
}
}
},
TBODY(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)),
TBODY(BlockType.TABLE_ITEM, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT),
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
@Override
public boolean accepts(HtmlTag t) {
return (t == TR);
}
},
TD(BlockType.BLOCK, EndKind.OPTIONAL,
TD(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
ALIGN, CHAR, CHAROFF, VALIGN),
attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
TFOOT(BlockType.BLOCK, EndKind.REQUIRED,
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)),
TFOOT(BlockType.TABLE_ITEM, EndKind.REQUIRED,
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
@Override
public boolean accepts(HtmlTag t) {
return (t == TR);
}
},
TH(BlockType.BLOCK, EndKind.OPTIONAL,
TH(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE),
attrs(AttrKind.OK, COLSPAN, ROWSPAN, HEADERS, SCOPE, ABBR, AXIS,
ALIGN, CHAR, CHAROFF, VALIGN),
attrs(AttrKind.USE_CSS, WIDTH, BGCOLOR, HEIGHT, NOWRAP)),
THEAD(BlockType.BLOCK, EndKind.REQUIRED,
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)),
THEAD(BlockType.TABLE_ITEM, EndKind.REQUIRED,
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN)) {
@Override
public boolean accepts(HtmlTag t) {
return (t == TR);
}
},
TITLE(BlockType.OTHER, EndKind.REQUIRED),
TR(BlockType.BLOCK, EndKind.OPTIONAL,
EnumSet.of(Flag.NO_TEXT),
TR(BlockType.TABLE_ITEM, EndKind.OPTIONAL,
attrs(AttrKind.OK, ALIGN, CHAR, CHAROFF, VALIGN),
attrs(AttrKind.USE_CSS, BGCOLOR)),
attrs(AttrKind.USE_CSS, BGCOLOR)) {
@Override
public boolean accepts(HtmlTag t) {
return (t == TH) || (t == TD);
}
},
TT(BlockType.INLINE, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
@ -196,8 +264,13 @@ public enum HtmlTag {
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)),
UL(BlockType.BLOCK, EndKind.REQUIRED,
EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_TEXT),
attrs(AttrKind.USE_CSS, COMPACT, TYPE)),
EnumSet.of(Flag.EXPECT_CONTENT),
attrs(AttrKind.USE_CSS, COMPACT, TYPE)){
@Override
public boolean accepts(HtmlTag t) {
return (t == LI);
}
},
VAR(BlockType.INLINE, EndKind.REQUIRED);
@ -207,6 +280,8 @@ public enum HtmlTag {
public static enum BlockType {
BLOCK,
INLINE,
LIST_ITEM,
TABLE_ITEM,
OTHER;
}
@ -220,9 +295,10 @@ public enum HtmlTag {
}
public static enum Flag {
ACCEPTS_BLOCK,
ACCEPTS_INLINE,
EXPECT_CONTENT,
NO_NEST,
NO_TEXT
NO_NEST
}
public static enum Attr {
@ -273,7 +349,7 @@ public enum HtmlTag {
static final Map<String,Attr> index = new HashMap<String,Attr>();
static {
for (Attr t: values()) {
index.put(t.name().toLowerCase(), t);
index.put(t.getText(), t);
}
}
}
@ -300,22 +376,14 @@ public enum HtmlTag {
public final Set<Flag> flags;
private final Map<Attr,AttrKind> attrs;
HtmlTag() {
this(BlockType.BLOCK, EndKind.REQUIRED);
}
HtmlTag(Set<Flag> flags) {
this(BlockType.BLOCK, EndKind.REQUIRED, flags);
}
HtmlTag(BlockType blockType, EndKind endKind, AttrMap... attrMaps) {
this(blockType, endKind, Collections.<Flag>emptySet(), attrMaps);
}
HtmlTag(BlockType blockType, EndKind endKind, Set<Flag> flags, AttrMap... attrMaps) {
this.blockType = blockType;
this.endKind = endKind;this.flags = flags;
this.endKind = endKind;
this.flags = flags;
this.attrs = new EnumMap<Attr,AttrKind>(Attr.class);
for (Map<Attr,AttrKind> m: attrMaps)
this.attrs.putAll(m);
@ -324,6 +392,35 @@ public enum HtmlTag {
attrs.put(Attr.STYLE, AttrKind.OK);
}
public boolean accepts(HtmlTag t) {
if (flags.contains(Flag.ACCEPTS_BLOCK) && flags.contains(Flag.ACCEPTS_INLINE)) {
return (t.blockType == BlockType.BLOCK) || (t.blockType == BlockType.INLINE);
} else if (flags.contains(Flag.ACCEPTS_BLOCK)) {
return (t.blockType == BlockType.BLOCK);
} else if (flags.contains(Flag.ACCEPTS_INLINE)) {
return (t.blockType == BlockType.INLINE);
} else
switch (blockType) {
case BLOCK:
case INLINE:
return (t.blockType == BlockType.INLINE);
case OTHER:
// OTHER tags are invalid in doc comments, and will be
// reported separately, so silently accept/ignore any content
return true;
default:
// any combination which could otherwise arrive here
// ought to have been handled in an overriding method
throw new AssertionError(this + ":" + t);
}
}
public boolean acceptsText() {
// generally, anywhere we can put text we can also put inline tag
// so check if a typical inline tag is allowed
return accepts(B);
}
public String getText() {
return name().toLowerCase();
}
@ -346,7 +443,7 @@ public enum HtmlTag {
private static final Map<String,HtmlTag> index = new HashMap<String,HtmlTag>();
static {
for (HtmlTag t: values()) {
index.put(t.name().toLowerCase(), t);
index.put(t.getText(), t);
}
}

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
@ -24,6 +24,7 @@
#
dc.anchor.already.defined = anchor already defined: {0}
dc.anchor.value.missing = no value given for anchor
dc.attr.lacks.value = attribute lacks value
dc.attr.obsolete = attribute obsolete: {0}
dc.attr.obsolete.use.css = attribute obsolete, use CSS instead: {0}
@ -47,12 +48,14 @@ dc.no.alt.attr.for.image = no "alt" attribute for image
dc.no.summary.or.caption.for.table=no summary or caption for table
dc.param.name.not.found = @param name not found
dc.ref.not.found = reference not found
dc.tag.code.within.code = '{@code'} within <code>
dc.tag.empty = empty <{0}> tag
dc.tag.end.not.permitted = invalid end tag: </{0}>
dc.tag.end.unexpected = unexpected end tag: </{0}>
dc.tag.header.sequence.1 = header used out of sequence: <{0}>
dc.tag.header.sequence.2 = header used out of sequence: <{0}>
dc.tag.nested.not.allowed=nested tag not allowed: <{0}>
dc.tag.not.allowed.here = tag not allowed here: <{0}>
dc.tag.not.allowed = element not allowed in documentation comments: <{0}>
dc.tag.not.allowed.inline.element = block element not allowed within inline element <{1}>: {0}
dc.tag.not.allowed.inline.tag = block element not allowed within @{1}: {0}

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
@ -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
@ -126,19 +157,18 @@ public class Annotations {
//
// We need to do this in two passes because when creating
// a container for a repeating annotation we must
// guarantee that the @ContainedBy on the
// guarantee that the @Repeatable on the
// contained annotation is fully annotated
//
// The way we force this order is to do all repeating
// annotations in a pass after all non-repeating are
// finished. This will work because @ContainedBy
// finished. This will work because @Repeatable
// is non-repeating and therefore will be annotated in the
// fist pass.
// 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,68 +278,100 @@ 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.containedby.annotation.repeated.and.container.present",
log.error(ctx.pos.get(manualContainer.first()), "invalid.repeatable.annotation.repeated.and.container.present",
manualContainer.first().type.tsym);
}
}
// 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;
@ -280,7 +280,7 @@ public class Flags {
SYNCHRONIZED | FINAL | STRICTFP;
public static final long
ExtendedStandardFlags = (long)StandardFlags | DEFAULT,
InterfaceDefaultMethodMask = ABSTRACT | PUBLIC | STRICTFP | SYNCHRONIZED | DEFAULT,
InterfaceMethodMask = ABSTRACT | STATIC | PUBLIC | STRICTFP | DEFAULT,
LocalVarFlags = FINAL | PARAMETER;

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;
}
@ -206,18 +203,30 @@ public enum Source {
public boolean allowDefaultMethods() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowStaticInterfaceMethods() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowStrictMethodClashCheck() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowEffectivelyFinalInInnerClasses() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowTypeAnnotations() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowRepeatedAnnotations() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowIntersectionTypesInCast() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowEarlyReturnConstraints() {
return compareTo(JDK1_8) >= 0;
}
public boolean allowStructuralMostSpecific() {
return compareTo(JDK1_8) >= 0;
}
public static SourceVersion toSourceVersion(Source source) {
switch(source) {
case JDK1_2:

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
@ -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. */
@ -450,10 +458,18 @@ public abstract class Symbol implements Element {
* This is the implementation for {@code
* javax.lang.model.element.Element.getAnnotationMirrors()}.
*/
public final List<Attribute.Compound> getAnnotationMirrors() {
public final List<? extends AnnotationMirror> getAnnotationMirrors() {
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.
*/
@ -462,6 +478,11 @@ public abstract class Symbol implements Element {
return JavacElements.getAnnotation(this, annoType);
}
// This method is part of the javax.lang.model API, do not use this in javac code.
public <A extends java.lang.annotation.Annotation> A[] getAnnotations(Class<A> annoType) {
return JavacElements.getAnnotations(this, annoType);
}
// TODO: getEnclosedElements should return a javac List, fix in FilteredMemberList
public java.util.List<Symbol> getEnclosedElements() {
return List.nil();
@ -790,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()),
@ -1228,7 +1255,8 @@ public abstract class Symbol implements Element {
case Flags.PRIVATE:
return false;
case Flags.PUBLIC:
return true;
return !this.owner.isInterface() ||
(flags_field & STATIC) == 0;
case Flags.PROTECTED:
return (origin.flags() & INTERFACE) == 0;
case 0:
@ -1242,6 +1270,18 @@ public abstract class Symbol implements Element {
}
}
@Override
public boolean isInheritedIn(Symbol clazz, Types types) {
switch ((int)(flags_field & Flags.AccessFlags)) {
case PUBLIC:
return !this.owner.isInterface() ||
clazz == owner ||
(flags_field & STATIC) == 0;
default:
return super.isInheritedIn(clazz, types);
}
}
/** The implementation of this (abstract) symbol in class origin;
* null if none exists. Synthetic methods are not considered
* as possible implementations.
@ -1369,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) 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
@ -161,10 +161,10 @@ public class Symtab {
public final Type autoCloseableType;
public final Type trustMeType;
public final Type lambdaMetafactory;
public final Type containedByType;
public final Type containerForType;
public final Type repeatableType;
public final Type documentedType;
public final Type elementTypeType;
public final Type functionalInterfaceType;
/** The symbol representing the length field of an array.
*/
@ -494,8 +494,7 @@ public class Symtab {
deprecatedType = enterClass("java.lang.Deprecated");
suppressWarningsType = enterClass("java.lang.SuppressWarnings");
inheritedType = enterClass("java.lang.annotation.Inherited");
containedByType = enterClass("java.lang.annotation.ContainedBy");
containerForType = enterClass("java.lang.annotation.ContainerFor");
repeatableType = enterClass("java.lang.annotation.Repeatable");
documentedType = enterClass("java.lang.annotation.Documented");
elementTypeType = enterClass("java.lang.annotation.ElementType");
systemType = enterClass("java.lang.System");
@ -509,6 +508,7 @@ public class Symtab {
nativeHeaderType = enterClass("java.lang.annotation.Native");
nativeHeaderType_old = enterClass("javax.tools.annotation.GenerateNativeHeader");
lambdaMetafactory = enterClass("java.lang.invoke.LambdaMetafactory");
functionalInterfaceType = enterClass("java.lang.FunctionalInterface");
synthesizeEmptyInterfaceIfMissing(autoCloseableType);
synthesizeEmptyInterfaceIfMissing(cloneableType);

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.*;
@ -354,8 +355,29 @@ public class Types {
return descSym;
}
public Type getType(Type origin) {
return memberType(origin, descSym);
public Type getType(Type site) {
if (capture(site) != site) {
Type formalInterface = site.tsym.type;
ListBuffer<Type> typeargs = ListBuffer.lb();
List<Type> actualTypeargs = site.getTypeArguments();
//simply replace the wildcards with its bound
for (Type t : formalInterface.getTypeArguments()) {
if (actualTypeargs.head.hasTag(WILDCARD)) {
WildcardType wt = (WildcardType)actualTypeargs.head;
typeargs.append(wt.type);
} else {
typeargs.append(actualTypeargs.head);
}
actualTypeargs = actualTypeargs.tail;
}
site = subst(formalInterface, formalInterface.getTypeArguments(), typeargs.toList());
if (!chk.checkValidGenericType(site)) {
//if the inferred functional interface type is not well-formed,
//or if it's not a subtype of the original target, issue an error
throw failure(diags.fragment("no.suitable.functional.intf.inst", site));
}
}
return memberType(site, descSym);
}
}
@ -392,9 +414,9 @@ public class Types {
* Compute the function descriptor associated with a given functional interface
*/
public FunctionDescriptor findDescriptorInternal(TypeSymbol origin, CompoundScope membersCache) throws FunctionDescriptorLookupError {
if (!origin.isInterface()) {
if (!origin.isInterface() || (origin.flags() & ANNOTATION) != 0) {
//t must be an interface
throw failure("not.a.functional.intf");
throw failure("not.a.functional.intf", origin);
}
final ListBuffer<Symbol> abstracts = ListBuffer.lb();
@ -406,13 +428,13 @@ public class Types {
abstracts.append(sym);
} else {
//the target method(s) should be the only abstract members of t
throw failure("not.a.functional.intf.1",
throw failure("not.a.functional.intf.1", origin,
diags.fragment("incompatible.abstracts", Kinds.kindName(origin), origin));
}
}
if (abstracts.isEmpty()) {
//t must define a suitable non-generic method
throw failure("not.a.functional.intf.1",
throw failure("not.a.functional.intf.1", origin,
diags.fragment("no.abstracts", Kinds.kindName(origin), origin));
} else if (abstracts.size() == 1) {
return new FunctionDescriptor(abstracts.first());
@ -553,6 +575,15 @@ public class Types {
return false;
}
}
public boolean isFunctionalInterface(Type site) {
try {
findDescriptorType(site);
return true;
} catch (FunctionDescriptorLookupError ex) {
return false;
}
}
// </editor-fold>
/**
@ -654,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 {
@ -679,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) {
@ -709,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;
@ -1653,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);
@ -1981,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") {
@ -2923,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;
@ -3624,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;
@ -4142,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

@ -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
@ -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.containedby.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
}
@ -414,11 +469,11 @@ public class Annotate {
Type origAnnoType = currentAnno.type;
TypeSymbol origAnnoDecl = origAnnoType.tsym;
// Fetch the ContainedBy annotation from the current
// Fetch the Repeatable annotation from the current
// annotation's declaration, or null if it has none
Attribute.Compound ca = origAnnoDecl.attribute(syms.containedByType.tsym);
if (ca == null) { // has no ContainedBy annotation
log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.containedByType);
Attribute.Compound ca = origAnnoDecl.attribute(syms.repeatableType.tsym);
if (ca == null) { // has no Repeatable annotation
log.error(pos, "duplicate.annotation.missing.container", origAnnoType, syms.repeatableType);
return null;
}
@ -440,23 +495,23 @@ public class Annotate {
DiagnosticPosition pos,
TypeSymbol annoDecl)
{
// The next three checks check that the ContainedBy annotation
// The next three checks check that the Repeatable annotation
// on the declaration of the annotation type that is repeating is
// valid.
// ContainedBy must have at least one element
// Repeatable must have at least one element
if (ca.values.isEmpty()) {
log.error(pos, "invalid.containedby.annotation", annoDecl);
log.error(pos, "invalid.repeatable.annotation", annoDecl);
return null;
}
Pair<MethodSymbol,Attribute> p = ca.values.head;
Name name = p.fst.name;
if (name != names.value) { // should contain only one element, named "value"
log.error(pos, "invalid.containedby.annotation", annoDecl);
log.error(pos, "invalid.repeatable.annotation", annoDecl);
return null;
}
if (!(p.snd instanceof Attribute.Class)) { // check that the value of "value" is an Attribute.Class
log.error(pos, "invalid.containedby.annotation", annoDecl);
log.error(pos, "invalid.repeatable.annotation", annoDecl);
return null;
}
@ -491,13 +546,13 @@ public class Annotate {
}
if (error) {
log.error(pos,
"invalid.containedby.annotation.multiple.values",
"invalid.repeatable.annotation.multiple.values",
targetContainerType,
nr_value_elems);
return null;
} else if (nr_value_elems == 0) {
log.error(pos,
"invalid.containedby.annotation.no.value",
"invalid.repeatable.annotation.no.value",
targetContainerType);
return null;
}
@ -506,7 +561,7 @@ public class Annotate {
// probably "impossible" to fail this
if (containerValueSymbol.kind != Kinds.MTH) {
log.error(pos,
"invalid.containedby.annotation.invalid.value",
"invalid.repeatable.annotation.invalid.value",
targetContainerType);
fatalError = true;
}
@ -518,7 +573,7 @@ public class Annotate {
if (!(types.isArray(valueRetType) &&
types.isSameType(expectedType, valueRetType))) {
log.error(pos,
"invalid.containedby.annotation.value.return",
"invalid.repeatable.annotation.value.return",
targetContainerType,
valueRetType,
expectedType);
@ -528,10 +583,7 @@ public class Annotate {
fatalError = true;
}
// Explicitly no check for/validity of @ContainerFor. That is
// done on declaration of the container, and at reflect time.
// The rest of the conditions for a valid containing annotation are made
// The conditions for a valid containing annotation are made
// in Check.validateRepeatedAnnotaton();
return fatalError ? null : containerValueSymbol;

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,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,9 +45,9 @@ 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.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.List;
@ -879,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);
@ -922,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
@ -953,8 +969,7 @@ public class Attr extends JCTree.Visitor {
// Empty bodies are only allowed for
// abstract, native, or interface methods, or for methods
// in a retrofit signature class.
if (isDefaultMethod || ((owner.flags() & INTERFACE) == 0 &&
(tree.mods.flags & (ABSTRACT | NATIVE)) == 0) &&
if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 &&
!relax)
log.error(tree.pos(), "missing.meth.body.or.decl.abstract");
if (tree.defaultValue != null) {
@ -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.
@ -1376,18 +1407,19 @@ public class Attr extends JCTree.Visitor {
public void visitConditional(JCConditional tree) {
Type condtype = attribExpr(tree.cond, env, syms.booleanType);
boolean standaloneConditional = !allowPoly ||
tree.polyKind = (!allowPoly ||
pt().hasTag(NONE) && pt() != Type.recoveryType ||
isBooleanOrNumeric(env, tree);
isBooleanOrNumeric(env, tree)) ?
PolyKind.STANDALONE : PolyKind.POLY;
if (!standaloneConditional && resultInfo.pt.hasTag(VOID)) {
if (tree.polyKind == PolyKind.POLY && resultInfo.pt.hasTag(VOID)) {
//cannot get here (i.e. it means we are returning from void method - which is already an error)
resultInfo.checkContext.report(tree, diags.fragment("conditional.target.cant.be.void"));
result = tree.type = types.createErrorType(resultInfo.pt);
return;
}
ResultInfo condInfo = standaloneConditional ?
ResultInfo condInfo = tree.polyKind == PolyKind.STANDALONE ?
unknownExprInfo :
resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
//this will use enclosing check context to check compatibility of
@ -1402,7 +1434,7 @@ public class Attr extends JCTree.Visitor {
Type truetype = attribTree(tree.truepart, env, condInfo);
Type falsetype = attribTree(tree.falsepart, env, condInfo);
Type owntype = standaloneConditional ? condType(tree, truetype, falsetype) : pt();
Type owntype = (tree.polyKind == PolyKind.STANDALONE) ? condType(tree, truetype, falsetype) : pt();
if (condtype.constValue() != null &&
truetype.constValue() != null &&
falsetype.constValue() != null &&
@ -1424,12 +1456,30 @@ public class Attr extends JCTree.Visitor {
JCConditional condTree = (JCConditional)tree;
return isBooleanOrNumeric(env, condTree.truepart) &&
isBooleanOrNumeric(env, condTree.falsepart);
case APPLY:
JCMethodInvocation speculativeMethodTree =
(JCMethodInvocation)deferredAttr.attribSpeculative(tree, env, unknownExprInfo);
Type owntype = TreeInfo.symbol(speculativeMethodTree.meth).type.getReturnType();
return types.unboxedTypeOrType(owntype).isPrimitive();
case NEWCLASS:
JCExpression className =
removeClassParams.translate(((JCNewClass)tree).clazz);
JCExpression speculativeNewClassTree =
(JCExpression)deferredAttr.attribSpeculative(className, env, unknownTypeInfo);
return types.unboxedTypeOrType(speculativeNewClassTree.type).isPrimitive();
default:
Type speculativeType = deferredAttr.attribSpeculative(tree, env, unknownExprInfo).type;
speculativeType = types.unboxedTypeOrType(speculativeType);
return speculativeType.isPrimitive();
}
}
//where
TreeTranslator removeClassParams = new TreeTranslator() {
@Override
public void visitTypeApply(JCTypeApply tree) {
result = translate(tree.clazz);
}
};
/** Compute the type of a conditional expression, after
* checking that it exists. See JLS 15.25. Does not take into
@ -1828,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
@ -1846,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
@ -1870,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");
@ -2173,17 +2256,18 @@ public class Attr extends JCTree.Visitor {
boolean needsRecovery =
resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK;
try {
Type target = pt();
List<Type> explicitParamTypes = null;
if (TreeInfo.isExplicitLambda(that)) {
if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) {
//attribute lambda parameters
attribStats(that.params, localEnv);
explicitParamTypes = TreeInfo.types(that.params);
target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext);
}
Type target;
Type lambdaType;
if (pt() != Type.recoveryType) {
target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), explicitParamTypes, resultInfo.checkContext);
target = checkIntersectionTarget(that, target, resultInfo.checkContext);
lambdaType = types.findDescriptorType(target);
chk.checkFunctionalInterface(that, target);
} else {
@ -2191,6 +2275,8 @@ public class Attr extends JCTree.Visitor {
lambdaType = fallbackDescriptorType(that);
}
setFunctionalInfo(that, pt(), lambdaType, resultInfo.checkContext.inferenceContext());
if (lambdaType.hasTag(FORALL)) {
//lambda expression target desc cannot be a generic method
resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target",
@ -2199,7 +2285,7 @@ public class Attr extends JCTree.Visitor {
return;
}
if (!TreeInfo.isExplicitLambda(that)) {
if (that.paramKind == JCLambda.ParameterKind.IMPLICIT) {
//add param type info in the AST
List<Type> actuals = lambdaType.getParameterTypes();
List<JCVariableDecl> params = that.params;
@ -2282,8 +2368,7 @@ public class Attr extends JCTree.Visitor {
}
}
private Type checkIntersectionTarget(DiagnosticPosition pos, ResultInfo resultInfo) {
Type pt = resultInfo.pt;
private Type checkIntersectionTarget(DiagnosticPosition pos, Type pt, CheckContext checkContext) {
if (pt != Type.recoveryType && pt.isCompound()) {
IntersectionClassType ict = (IntersectionClassType)pt;
List<Type> bounds = ict.allInterfaces ?
@ -2292,7 +2377,7 @@ public class Attr extends JCTree.Visitor {
types.findDescriptorType(bounds.head); //propagate exception outwards!
for (Type bound : bounds.tail) {
if (!types.isMarkerInterface(bound)) {
resultInfo.checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound));
checkContext.report(pos, diags.fragment("secondary.bound.must.be.marker.intf", bound));
}
}
//for now (translation doesn't support intersection types)
@ -2355,9 +2440,9 @@ public class Attr extends JCTree.Visitor {
@Override
public boolean compatible(Type found, Type req, Warner warn) {
//return type must be compatible in both current context and assignment context
return types.isAssignable(found, inferenceContext().asFree(req, types), warn) &&
super.compatible(found, req, warn);
return chk.basicHandler.compatible(found, inferenceContext().asFree(req, types), warn);
}
@Override
public void report(DiagnosticPosition pos, JCDiagnostic details) {
enclosingContext.report(pos, diags.fragment("incompatible.ret.type.in.lambda", details));
@ -2473,7 +2558,7 @@ public class Attr extends JCTree.Visitor {
Type target;
Type desc;
if (pt() != Type.recoveryType) {
target = infer.instantiateFunctionalInterface(that, checkIntersectionTarget(that, resultInfo), null, resultInfo.checkContext);
target = checkIntersectionTarget(that, pt(), resultInfo.checkContext);
desc = types.findDescriptorType(target);
chk.checkFunctionalInterface(that, target);
} else {
@ -2481,12 +2566,11 @@ public class Attr extends JCTree.Visitor {
desc = fallbackDescriptorType(that);
}
setFunctionalInfo(that, pt(), desc, resultInfo.checkContext.inferenceContext());
List<Type> argtypes = desc.getParameterTypes();
boolean allowBoxing =
resultInfo.checkContext.deferredAttrContext().phase.isBoxingRequired();
Pair<Symbol, Resolve.ReferenceLookupHelper> refResult = rs.resolveMemberReference(that.pos(), localEnv, that,
that.expr.type, that.name, argtypes, typeargtypes, allowBoxing);
that.expr.type, that.name, argtypes, typeargtypes, true);
Symbol refSym = refResult.fst;
Resolve.ReferenceLookupHelper lookupHelper = refResult.snd;
@ -2635,6 +2719,34 @@ public class Attr extends JCTree.Visitor {
}
}
/**
* Set functional type info on the underlying AST. Note: as the target descriptor
* might contain inference variables, we might need to register an hook in the
* current inference context.
*/
private void setFunctionalInfo(final JCFunctionalExpression fExpr, final Type pt, final Type descriptorType, InferenceContext inferenceContext) {
if (inferenceContext.free(descriptorType)) {
inferenceContext.addFreeTypeListener(List.of(pt, descriptorType), new FreeTypeListener() {
public void typesInferred(InferenceContext inferenceContext) {
setFunctionalInfo(fExpr, pt, inferenceContext.asInstType(descriptorType, types), inferenceContext);
}
});
} else {
ListBuffer<TypeSymbol> targets = ListBuffer.lb();
if (pt.hasTag(CLASS)) {
if (pt.isCompound()) {
for (Type t : ((IntersectionClassType)pt()).interfaces_field) {
targets.append(t.tsym);
}
} else {
targets.append(pt.tsym);
}
}
fExpr.targets = targets.toList();
fExpr.descriptorType = descriptorType;
}
}
public void visitParens(JCParens tree) {
Type owntype = attribTree(tree.expr, env, resultInfo);
result = check(tree, owntype, pkind(), resultInfo);
@ -3207,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)
@ -3432,6 +3554,15 @@ public class Attr extends JCTree.Visitor {
env.info.defaultSuperCallSite = null;
}
if (sym.isStatic() && site.isInterface()) {
Assert.check(env.tree.hasTag(APPLY));
JCMethodInvocation app = (JCMethodInvocation)env.tree;
if (app.meth.hasTag(SELECT) &&
!TreeInfo.isStaticSelector(((JCFieldAccess)app.meth).selected, names)) {
log.error(env.tree.pos(), "illegal.static.intf.meth.call", site);
}
}
// Compute the identifier's instantiated type.
// For methods, we need to compute the instance type by
// Resolve.instantiate from the symbol's type as well as
@ -3587,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);
@ -3684,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)
@ -3844,24 +4020,14 @@ public class Attr extends JCTree.Visitor {
log.error(tree.typarams.head.pos(),
"intf.annotation.cant.have.type.params");
// If this annotation has a @ContainedBy, validate
Attribute.Compound containedBy = c.attribute(syms.containedByType.tsym);
if (containedBy != null) {
// get diagnositc position for error reporting
DiagnosticPosition cbPos = getDiagnosticPosition(tree, containedBy.type);
// If this annotation has a @Repeatable, validate
Attribute.Compound repeatable = c.attribute(syms.repeatableType.tsym);
if (repeatable != null) {
// get diagnostic position for error reporting
DiagnosticPosition cbPos = getDiagnosticPosition(tree, repeatable.type);
Assert.checkNonNull(cbPos);
chk.validateContainedBy(c, containedBy, cbPos);
}
// If this annotation has a @ContainerFor, validate
Attribute.Compound containerFor = c.attribute(syms.containerForType.tsym);
if (containerFor != null) {
// get diagnositc position for error reporting
DiagnosticPosition cfPos = getDiagnosticPosition(tree, containerFor.type);
Assert.checkNonNull(cfPos);
chk.validateContainerFor(c, containerFor, cfPos);
chk.validateRepeatable(c, repeatable, cbPos);
}
} else {
// Check that all extended classes and interfaces
@ -3925,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 */
@ -3982,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">
/**
@ -4087,12 +4347,29 @@ public class Attr extends JCTree.Visitor {
super.visitUnary(that);
}
@Override
public void visitLambda(JCLambda that) {
super.visitLambda(that);
if (that.descriptorType == null) {
that.descriptorType = syms.unknownType;
}
if (that.targets == null) {
that.targets = List.nil();
}
}
@Override
public void visitReference(JCMemberReference that) {
super.visitReference(that);
if (that.sym == null) {
that.sym = new MethodSymbol(0, names.empty, syms.unknownType, syms.noSymbol);
}
if (that.descriptorType == null) {
that.descriptorType = syms.unknownType;
}
if (that.targets == null) {
that.targets = List.nil();
}
}
}
// </editor-fold>

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,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.*;
@ -36,7 +36,6 @@ import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.code.Lint;
import com.sun.tools.javac.code.Lint.LintCategory;
import com.sun.tools.javac.code.Type.*;
@ -44,6 +43,8 @@ import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.DeferredAttr.DeferredAttrContext;
import com.sun.tools.javac.comp.Infer.InferenceContext;
import com.sun.tools.javac.comp.Infer.InferenceContext.FreeTypeListener;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
import static com.sun.tools.javac.code.Flags.*;
import static com.sun.tools.javac.code.Flags.ANNOTATION;
@ -100,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);
@ -571,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
@ -634,25 +631,40 @@ public class Check {
}
}
Type checkClassOrArrayType(DiagnosticPosition pos, Type t) {
if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) {
return typeTagError(pos,
diags.fragment("type.req.class.array"),
asTypeParam(t));
} else {
return t;
}
}
/** Check that type is a class or interface type.
* @param pos Position to be used for error reporting.
* @param t The type to be checked.
*/
Type checkClassType(DiagnosticPosition pos, Type t) {
if (!t.hasTag(CLASS) && !t.hasTag(ERROR))
if (!t.hasTag(CLASS) && !t.hasTag(ERROR)) {
return typeTagError(pos,
diags.fragment("type.req.class"),
(t.hasTag(TYPEVAR))
? diags.fragment("type.parameter", t)
: t);
else
asTypeParam(t));
} else {
return t;
}
}
//where
private Object asTypeParam(Type t) {
return (t.hasTag(TYPEVAR))
? diags.fragment("type.parameter", t)
: t;
}
/** Check that type is a valid qualifier for a constructor reference expression
*/
Type checkConstructorRefType(DiagnosticPosition pos, Type t) {
t = checkClassType(pos, t);
t = checkClassOrArrayType(pos, t);
if (t.hasTag(CLASS)) {
if ((t.tsym.flags() & (ABSTRACT | INTERFACE)) != 0) {
log.error(pos, "abstract.cant.be.instantiated");
@ -690,11 +702,8 @@ public class Check {
* @param t The type to be checked.
*/
Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) {
if (!t.hasTag(CLASS) && !t.hasTag(ARRAY) && !t.hasTag(ERROR)) {
return typeTagError(pos,
diags.fragment("type.req.class.array"),
t);
} else if (!types.isReifiable(t)) {
t = checkClassOrArrayType(pos, t);
if (!t.isErroneous() && !types.isReifiable(t)) {
log.error(pos, "illegal.generic.type.for.instof");
return types.createErrorType(t);
} else {
@ -840,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;
@ -888,7 +897,6 @@ public class Check {
syms.methodClass);
}
if (useVarargs) {
JCTree tree = env.tree;
Type argtype = owntype.getParameterTypes().last();
if (!types.isReifiable(argtype) &&
(!allowSimplifiedVarargs ||
@ -899,22 +907,13 @@ public class Check {
argtype);
}
if (!((MethodSymbol)sym.baseSymbol()).isSignaturePolymorphic(types)) {
Type elemtype = types.elemtype(argtype);
switch (tree.getTag()) {
case APPLY:
((JCMethodInvocation) tree).varargsElement = elemtype;
break;
case NEWCLASS:
((JCNewClass) tree).varargsElement = elemtype;
break;
case REFERENCE:
((JCMemberReference) tree).varargsElement = elemtype;
break;
default:
throw new AssertionError(""+tree);
}
TreeInfo.setVarargsElement(env.tree, types.elemtype(argtype));
}
}
PolyKind pkind = (sym.type.hasTag(FORALL) &&
sym.type.getReturnType().containsAny(((ForAll)sym.type).tvars)) ?
PolyKind.POLY : PolyKind.STANDALONE;
TreeInfo.setPolyKind(env.tree, pkind);
return owntype;
}
//where
@ -1055,9 +1054,12 @@ public class Check {
} else
mask = ConstructorFlags;
} else if ((sym.owner.flags_field & INTERFACE) != 0) {
if ((flags & DEFAULT) != 0) {
mask = InterfaceDefaultMethodMask;
implicit = PUBLIC | ABSTRACT;
if ((flags & (DEFAULT | STATIC)) != 0) {
mask = InterfaceMethodMask;
implicit = PUBLIC;
if ((flags & DEFAULT) != 0) {
implicit |= ABSTRACT;
}
} else {
mask = implicit = InterfaceMethodFlags;
}
@ -1126,6 +1128,10 @@ public class Check {
ABSTRACT,
PRIVATE | STATIC | DEFAULT))
&&
checkDisjoint(pos, flags,
STATIC,
DEFAULT)
&&
checkDisjoint(pos, flags,
ABSTRACT | INTERFACE,
FINAL | NATIVE | SYNCHRONIZED)
@ -1316,6 +1322,11 @@ public class Check {
}
}
@Override
public void visitAnnotatedType(JCAnnotatedType tree) {
tree.underlyingType.accept(this);
}
/** Default visitor method: do nothing.
*/
@Override
@ -2236,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.
*/
@ -2577,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) {
@ -2589,33 +2607,53 @@ public class Check {
if (!isOverrider(s))
log.error(a.pos(), "method.does.not.override.superclass");
}
if (a.annotationType.type.tsym == syms.functionalInterfaceType.tsym) {
if (s.kind != TYP) {
log.error(a.pos(), "bad.functional.intf.anno");
} else {
try {
types.findDescriptorSymbol((TypeSymbol)s);
} catch (Types.FunctionDescriptorLookupError ex) {
log.error(a.pos(), "bad.functional.intf.anno.1", ex.getDiagnostic());
}
}
}
}
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 'containedBy' on the
* Validate the proposed container 'repeatable' on the
* annotation type symbol 's'. Report errors at position
* 'pos'.
*
* @param s The (annotation)type declaration annotated with a @ContainedBy
* @param containedBy the @ContainedBy on 's'
* @param s The (annotation)type declaration annotated with a @Repeatable
* @param repeatable the @Repeatable on 's'
* @param pos where to report errors
*/
public void validateContainedBy(TypeSymbol s, Attribute.Compound containedBy, DiagnosticPosition pos) {
Assert.check(types.isSameType(containedBy.type, syms.containedByType));
public void validateRepeatable(TypeSymbol s, Attribute.Compound repeatable, DiagnosticPosition pos) {
Assert.check(types.isSameType(repeatable.type, syms.repeatableType));
Type t = null;
List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
List<Pair<MethodSymbol,Attribute>> l = repeatable.values;
if (!l.isEmpty()) {
Assert.check(l.head.fst.name == names.value);
t = ((Attribute.Class)l.head.snd).getValue();
}
if (t == null) {
log.error(pos, "invalid.container.wrong.containedby", s, containedBy);
// errors should already have been reported during Annotate
return;
}
validateHasContainerFor(t.tsym, s, pos);
validateValue(t.tsym, s, pos);
validateRetention(t.tsym, s, pos);
validateDocumented(t.tsym, s, pos);
validateInherited(t.tsym, s, pos);
@ -2623,79 +2661,18 @@ public class Check {
validateDefault(t.tsym, s, pos);
}
/**
* Validate the proposed container 'containerFor' on the
* annotation type symbol 's'. Report errors at position
* 'pos'.
*
* @param s The (annotation)type declaration annotated with a @ContainerFor
* @param containerFor the @ContainedFor on 's'
* @param pos where to report errors
*/
public void validateContainerFor(TypeSymbol s, Attribute.Compound containerFor, DiagnosticPosition pos) {
Assert.check(types.isSameType(containerFor.type, syms.containerForType));
Type t = null;
List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
if (!l.isEmpty()) {
Assert.check(l.head.fst.name == names.value);
t = ((Attribute.Class)l.head.snd).getValue();
private void validateValue(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
Scope.Entry e = container.members().lookup(names.value);
if (e.scope != null && e.sym.kind == MTH) {
MethodSymbol m = (MethodSymbol) e.sym;
Type ret = m.getReturnType();
if (!(ret.hasTag(ARRAY) && types.isSameType(((ArrayType)ret).elemtype, contained.type))) {
log.error(pos, "invalid.repeatable.annotation.value.return",
container, ret, types.makeArrayType(contained.type));
}
} else {
log.error(pos, "invalid.repeatable.annotation.no.value", container);
}
if (t == null) {
log.error(pos, "invalid.container.wrong.containerfor", s, containerFor);
return;
}
validateHasContainedBy(t.tsym, s, pos);
}
private void validateHasContainedBy(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
Attribute.Compound containedBy = container.attribute(syms.containedByType.tsym);
if (containedBy == null) {
log.error(pos, "invalid.container.no.containedby", container, syms.containedByType.tsym);
return;
}
Type t = null;
List<Pair<MethodSymbol,Attribute>> l = containedBy.values;
if (!l.isEmpty()) {
Assert.check(l.head.fst.name == names.value);
t = ((Attribute.Class)l.head.snd).getValue();
}
if (t == null) {
log.error(pos, "invalid.container.wrong.containedby", container, contained);
return;
}
if (!types.isSameType(t, contained.type))
log.error(pos, "invalid.container.wrong.containedby", t.tsym, contained);
}
private void validateHasContainerFor(TypeSymbol container, TypeSymbol contained, DiagnosticPosition pos) {
Attribute.Compound containerFor = container.attribute(syms.containerForType.tsym);
if (containerFor == null) {
log.error(pos, "invalid.container.no.containerfor", container, syms.containerForType.tsym);
return;
}
Type t = null;
List<Pair<MethodSymbol,Attribute>> l = containerFor.values;
if (!l.isEmpty()) {
Assert.check(l.head.fst.name == names.value);
t = ((Attribute.Class)l.head.snd).getValue();
}
if (t == null) {
log.error(pos, "invalid.container.wrong.containerfor", container, contained);
return;
}
if (!types.isSameType(t, contained.type))
log.error(pos, "invalid.container.wrong.containerfor", t.tsym, contained);
}
private void validateRetention(Symbol container, Symbol contained, DiagnosticPosition pos) {
@ -2715,7 +2692,7 @@ public class Check {
}
}
if (error ) {
log.error(pos, "invalid.containedby.annotation.retention",
log.error(pos, "invalid.repeatable.annotation.retention",
container, containerRetention,
contained, containedRetention);
}
@ -2724,7 +2701,7 @@ public class Check {
private void validateDocumented(Symbol container, Symbol contained, DiagnosticPosition pos) {
if (contained.attribute(syms.documentedType.tsym) != null) {
if (container.attribute(syms.documentedType.tsym) == null) {
log.error(pos, "invalid.containedby.annotation.not.documented", container, contained);
log.error(pos, "invalid.repeatable.annotation.not.documented", container, contained);
}
}
}
@ -2732,7 +2709,7 @@ public class Check {
private void validateInherited(Symbol container, Symbol contained, DiagnosticPosition pos) {
if (contained.attribute(syms.inheritedType.tsym) != null) {
if (container.attribute(syms.inheritedType.tsym) == null) {
log.error(pos, "invalid.containedby.annotation.not.inherited", container, contained);
log.error(pos, "invalid.repeatable.annotation.not.inherited", container, contained);
}
}
}
@ -2752,7 +2729,7 @@ public class Check {
// contained has target, but container has not, error
Attribute.Array containerTarget = getAttributeTargetAttribute(container);
if (containerTarget == null) {
log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained);
return;
}
@ -2775,7 +2752,7 @@ public class Check {
}
if (!isTargetSubset(containedTargets, containerTargets)) {
log.error(pos, "invalid.containedby.annotation.incompatible.target", container, contained);
log.error(pos, "invalid.repeatable.annotation.incompatible.target", container, contained);
}
}
@ -2809,7 +2786,7 @@ public class Check {
elm.kind == Kinds.MTH &&
((MethodSymbol)elm).defaultValue == null) {
log.error(pos,
"invalid.containedby.annotation.elem.nondefault",
"invalid.repeatable.annotation.elem.nondefault",
container,
elm);
}
@ -2834,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
@ -2891,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

@ -65,6 +65,7 @@ public class DeferredAttr extends JCTree.Visitor {
final Attr attr;
final Check chk;
final JCDiagnostic.Factory diags;
final Enter enter;
final Infer infer;
final Log log;
@ -83,14 +84,20 @@ public class DeferredAttr extends JCTree.Visitor {
context.put(deferredAttrKey, this);
attr = Attr.instance(context);
chk = Check.instance(context);
diags = JCDiagnostic.Factory.instance(context);
enter = Enter.instance(context);
infer = Infer.instance(context);
log = Log.instance(context);
syms = Symtab.instance(context);
make = TreeMaker.instance(context);
types = Types.instance(context);
Names names = Names.instance(context);
stuckTree = make.Ident(names.empty).setType(Type.noType);
}
/** shared tree for stuck expressions */
final JCTree stuckTree;
/**
* This type represents a deferred type. A deferred type starts off with
* no information on the underlying expression type. Such info needs to be
@ -356,12 +363,11 @@ public class DeferredAttr extends JCTree.Visitor {
//scan a defensive copy of the node list - this is because a deferred
//attribution round can add new nodes to the list
for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
if (!deferredAttrNode.isStuck()) {
deferredAttrNode.process();
if (!deferredAttrNode.process()) {
stuckVars.addAll(deferredAttrNode.stuckVars);
} else {
deferredAttrNodes.remove(deferredAttrNode);
progress = true;
} else {
stuckVars.addAll(deferredAttrNode.stuckVars);
}
}
if (!progress) {
@ -403,22 +409,89 @@ public class DeferredAttr extends JCTree.Visitor {
resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt, types));
}
/**
* is this node stuck?
*/
boolean isStuck() {
return stuckVars.nonEmpty();
}
/**
* Process a deferred attribution node.
* Invariant: a stuck node cannot be processed.
*/
void process() {
if (isStuck()) {
throw new IllegalStateException("Cannot process a stuck deferred node");
@SuppressWarnings("fallthrough")
boolean process() {
switch (mode) {
case SPECULATIVE:
dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
return true;
case CHECK:
if (stuckVars.nonEmpty()) {
return false;
} else {
dt.check(resultInfo, stuckVars, basicCompleter);
return true;
}
default:
throw new AssertionError("Bad mode");
}
}
/**
* Structural checker for stuck expressions
*/
class StructuralStuckChecker extends TreeScanner implements DeferredTypeCompleter {
ResultInfo resultInfo;
public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
this.resultInfo = resultInfo;
dt.tree.accept(this);
dt.speculativeCache.put(msym, stuckTree, phase);
return Type.noType;
}
@Override
public void visitLambda(JCLambda tree) {
Check.CheckContext checkContext = resultInfo.checkContext;
Type pt = resultInfo.pt;
if (inferenceContext.inferencevars.contains(pt)) {
//ok
return;
} else {
//must be a functional descriptor
try {
Type desc = types.findDescriptorType(pt);
if (desc.getParameterTypes().length() != tree.params.length()) {
checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
}
} catch (Types.FunctionDescriptorLookupError ex) {
checkContext.report(null, ex.getDiagnostic());
}
}
}
@Override
public void visitNewClass(JCNewClass tree) {
//do nothing
}
@Override
public void visitApply(JCMethodInvocation tree) {
//do nothing
}
@Override
public void visitReference(JCMemberReference tree) {
Check.CheckContext checkContext = resultInfo.checkContext;
Type pt = resultInfo.pt;
if (inferenceContext.inferencevars.contains(pt)) {
//ok
return;
} else {
try {
//TODO: we should speculative determine if there's a match
//based on arity - if yes, method is applicable.
types.findDescriptorType(pt);
} catch (Types.FunctionDescriptorLookupError ex) {
checkContext.report(null, ex.getDiagnostic());
}
}
}
dt.check(resultInfo);
}
}
}
@ -624,12 +697,12 @@ public class DeferredAttr extends JCTree.Visitor {
if (inferenceContext.inferenceVars().contains(pt)) {
stuckVars.add(pt);
}
if (!types.isFunctionalInterface(pt.tsym)) {
if (!types.isFunctionalInterface(pt)) {
return;
}
Type descType = types.findDescriptorType(pt);
List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
if (!TreeInfo.isExplicitLambda(tree) &&
if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
freeArgVars.nonEmpty()) {
stuckVars.addAll(freeArgVars);
}
@ -643,7 +716,7 @@ public class DeferredAttr extends JCTree.Visitor {
stuckVars.add(pt);
return;
}
if (!types.isFunctionalInterface(pt.tsym)) {
if (!types.isFunctionalInterface(pt)) {
return;
}

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
@ -131,7 +131,11 @@ public class Enter extends JCTree.Visitor {
predefClassDef = make.ClassDef(
make.Modifiers(PUBLIC),
syms.predefClass.name, null, null, null, null);
syms.predefClass.name,
List.<JCTypeParameter>nil(),
null,
List.<JCExpression>nil(),
List.<JCTree>nil());
predefClassDef.sym = syms.predefClass;
todo = Todo.instance(context);
fileManager = context.get(JavaFileManager.class);

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

@ -66,6 +66,9 @@ public class Infer {
Log log;
JCDiagnostic.Factory diags;
/** Should we inject return-type constraints earlier? */
boolean allowEarlyReturnConstraints;
public static Infer instance(Context context) {
Infer instance = context.get(inferKey);
if (instance == null)
@ -83,6 +86,7 @@ public class Infer {
chk = Check.instance(context);
diags = JCDiagnostic.Factory.instance(context);
inferenceException = new InferenceException(diags);
allowEarlyReturnConstraints = Source.instance(context).allowEarlyReturnConstraints();
}
/**
@ -188,19 +192,6 @@ public class Infer {
MethodType mtype,
Attr.ResultInfo resultInfo,
Warner warn) throws InferenceException {
Type to = resultInfo.pt;
if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
to = mtype.getReturnType().isPrimitiveOrVoid() ?
mtype.getReturnType() : syms.objectType;
}
Type qtype1 = inferenceContext.asFree(mtype.getReturnType(), types);
if (!types.isSubtype(qtype1,
qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to)) {
throw inferenceException
.setMessage("infer.no.conforming.instance.exists",
inferenceContext.restvars(), mtype.getReturnType(), to);
}
while (true) {
boolean stuck = true;
for (Type t : inferenceContext.undetvars) {
@ -283,6 +274,11 @@ public class Infer {
try {
methodCheck.argumentsAcceptable(env, deferredAttrContext, argtypes, mt.getParameterTypes(), warn);
if (resultInfo != null && allowEarlyReturnConstraints &&
!warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
generateReturnConstraints(mt, inferenceContext, resultInfo);
}
deferredAttrContext.complete();
// minimize as yet undetermined type variables
@ -298,6 +294,9 @@ public class Infer {
if (!restvars.isEmpty()) {
if (resultInfo != null && !warn.hasNonSilentLint(Lint.LintCategory.UNCHECKED)) {
if (!allowEarlyReturnConstraints) {
generateReturnConstraints(mt, inferenceContext, resultInfo);
}
instantiateUninferred(env.tree.pos(), inferenceContext, mt, resultInfo, warn);
checkWithinBounds(inferenceContext, warn);
mt = (MethodType)inferenceContext.asInstType(mt, types);
@ -313,6 +312,25 @@ public class Infer {
inferenceContext.notifyChange(types);
}
}
//where
void generateReturnConstraints(Type mt, InferenceContext inferenceContext, Attr.ResultInfo resultInfo) {
if (resultInfo != null) {
Type to = resultInfo.pt;
if (to.hasTag(NONE) || resultInfo.checkContext.inferenceContext().free(resultInfo.pt)) {
to = mt.getReturnType().isPrimitiveOrVoid() ?
mt.getReturnType() : syms.objectType;
}
Type qtype1 = inferenceContext.asFree(mt.getReturnType(), types);
Warner retWarn = new Warner();
if (!resultInfo.checkContext.compatible(qtype1, qtype1.hasTag(UNDETVAR) ? types.boxedTypeOrType(to) : to, retWarn) ||
//unchecked conversion is not allowed
retWarn.hasLint(Lint.LintCategory.UNCHECKED)) {
throw inferenceException
.setMessage("infer.no.conforming.instance.exists",
inferenceContext.restvars(), mt.getReturnType(), to);
}
}
}
/** check that type parameters are within their bounds.
*/
@ -461,52 +479,40 @@ public class Infer {
Type formalInterface = funcInterface.tsym.type;
InferenceContext funcInterfaceContext =
new InferenceContext(funcInterface.tsym.type.getTypeArguments(), this, false);
if (paramTypes != null) {
//get constraints from explicit params (this is done by
//checking that explicit param types are equal to the ones
//in the functional interface descriptors)
List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
if (descParameterTypes.size() != paramTypes.size()) {
checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
Assert.check(paramTypes != null);
//get constraints from explicit params (this is done by
//checking that explicit param types are equal to the ones
//in the functional interface descriptors)
List<Type> descParameterTypes = types.findDescriptorType(formalInterface).getParameterTypes();
if (descParameterTypes.size() != paramTypes.size()) {
checkContext.report(pos, diags.fragment("incompatible.arg.types.in.lambda"));
return types.createErrorType(funcInterface);
}
for (Type p : descParameterTypes) {
if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
return types.createErrorType(funcInterface);
}
for (Type p : descParameterTypes) {
if (!types.isSameType(funcInterfaceContext.asFree(p, types), paramTypes.head)) {
checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
return types.createErrorType(funcInterface);
}
paramTypes = paramTypes.tail;
}
for (Type t : funcInterfaceContext.undetvars) {
UndetVar uv = (UndetVar)t;
minimizeInst(uv, types.noWarnings);
if (uv.inst == null &&
Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
maximizeInst(uv, types.noWarnings);
}
}
formalInterface = funcInterfaceContext.asInstType(formalInterface, types);
paramTypes = paramTypes.tail;
}
ListBuffer<Type> typeargs = ListBuffer.lb();
List<Type> actualTypeargs = funcInterface.getTypeArguments();
//for remaining uninferred type-vars in the functional interface type,
//simply replace the wildcards with its bound
for (Type t : formalInterface.getTypeArguments()) {
if (actualTypeargs.head.hasTag(WILDCARD)) {
WildcardType wt = (WildcardType)actualTypeargs.head;
typeargs.append(wt.type);
} else {
typeargs.append(actualTypeargs.head);
for (Type t : funcInterfaceContext.undetvars) {
UndetVar uv = (UndetVar)t;
minimizeInst(uv, types.noWarnings);
if (uv.inst == null &&
Type.filter(uv.getBounds(InferenceBound.UPPER), boundFilter).nonEmpty()) {
maximizeInst(uv, types.noWarnings);
}
if (uv.inst == null) {
uv.inst = actualTypeargs.head;
}
actualTypeargs = actualTypeargs.tail;
}
Type owntype = types.subst(formalInterface, funcInterfaceContext.inferenceVars(), typeargs.toList());
Type owntype = funcInterfaceContext.asInstType(formalInterface, types);
if (!chk.checkValidGenericType(owntype)) {
//if the inferred functional interface type is not well-formed,
//or if it's not a subtype of the original target, issue an error
checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
return types.createErrorType(funcInterface);
}
return owntype;
}

View File

@ -253,7 +253,7 @@ public class LambdaToMethod extends TreeTranslator {
int refKind = referenceKind(sym);
//convert to an invokedynamic call
result = makeMetaFactoryIndyCall(tree, tree.targetType, refKind, sym, indy_args);
result = makeMetaFactoryIndyCall(tree, refKind, sym, indy_args);
}
private JCIdent makeThis(Type type, Symbol owner) {
@ -302,6 +302,7 @@ public class LambdaToMethod extends TreeTranslator {
case UNBOUND: /** Type :: instMethod */
case STATIC: /** Type :: staticMethod */
case TOPLEVEL: /** Top level :: new */
case ARRAY_CTOR: /** ArrayType :: new */
init = null;
break;
@ -313,7 +314,7 @@ public class LambdaToMethod extends TreeTranslator {
//build a sam instance using an indy call to the meta-factory
result = makeMetaFactoryIndyCall(tree, tree.targetType, localContext.referenceKind(), refSym, indy_args);
result = makeMetaFactoryIndyCall(tree, localContext.referenceKind(), refSym, indy_args);
}
/**
@ -502,19 +503,6 @@ public class LambdaToMethod extends TreeTranslator {
// </editor-fold>
private MethodSymbol makeSamDescriptor(Type targetType) {
return (MethodSymbol)types.findDescriptorSymbol(targetType.tsym);
}
private Type makeFunctionalDescriptorType(Type targetType, MethodSymbol samDescriptor, boolean erased) {
Type descType = types.memberType(targetType, samDescriptor);
return erased ? types.erasure(descType) : descType;
}
private Type makeFunctionalDescriptorType(Type targetType, boolean erased) {
return makeFunctionalDescriptorType(targetType, makeSamDescriptor(targetType), erased);
}
/**
* Generate an adapter method "bridge" for a method reference which cannot
* be used directly.
@ -645,24 +633,33 @@ public class LambdaToMethod extends TreeTranslator {
* to the first bridge synthetic parameter
*/
private JCExpression bridgeExpressionNew() {
JCExpression encl = null;
switch (tree.kind) {
case UNBOUND:
case IMPLICIT_INNER:
encl = make.Ident(params.first());
}
if (tree.kind == ReferenceKind.ARRAY_CTOR) {
//create the array creation expression
JCNewArray newArr = make.NewArray(make.Type(types.elemtype(tree.getQualifierExpression().type)),
List.of(make.Ident(params.first())),
null);
newArr.type = tree.getQualifierExpression().type;
return newArr;
} else {
JCExpression encl = null;
switch (tree.kind) {
case UNBOUND:
case IMPLICIT_INNER:
encl = make.Ident(params.first());
}
//create the instance creation expression
JCNewClass newClass = make.NewClass(encl,
List.<JCExpression>nil(),
make.Type(tree.getQualifierExpression().type),
convertArgs(tree.sym, args.toList(), tree.varargsElement),
null);
newClass.constructor = tree.sym;
newClass.constructorType = tree.sym.erasure(types);
newClass.type = tree.getQualifierExpression().type;
setVarargsIfNeeded(newClass, tree.varargsElement);
return newClass;
//create the instance creation expression
JCNewClass newClass = make.NewClass(encl,
List.<JCExpression>nil(),
make.Type(tree.getQualifierExpression().type),
convertArgs(tree.sym, args.toList(), tree.varargsElement),
null);
newClass.constructor = tree.sym;
newClass.constructorType = tree.sym.erasure(types);
newClass.type = tree.getQualifierExpression().type;
setVarargsIfNeeded(newClass, tree.varargsElement);
return newClass;
}
}
private VarSymbol addParameter(String name, Type p, boolean genArg) {
@ -688,12 +685,12 @@ public class LambdaToMethod extends TreeTranslator {
/**
* Generate an indy method call to the meta factory
*/
private JCExpression makeMetaFactoryIndyCall(JCExpression tree, Type targetType, int refKind, Symbol refSym, List<JCExpression> indy_args) {
private JCExpression makeMetaFactoryIndyCall(JCFunctionalExpression tree, int refKind, Symbol refSym, List<JCExpression> indy_args) {
//determine the static bsm args
Type mtype = makeFunctionalDescriptorType(targetType, true);
Type mtype = types.erasure(tree.descriptorType);
MethodSymbol samSym = (MethodSymbol) types.findDescriptorSymbol(tree.type.tsym);
List<Object> staticArgs = List.<Object>of(
new Pool.MethodHandle(ClassFile.REF_invokeInterface,
types.findDescriptorSymbol(targetType.tsym), types),
new Pool.MethodHandle(ClassFile.REF_invokeInterface, types.findDescriptorSymbol(tree.type.tsym), types),
new Pool.MethodHandle(refKind, refSym, types),
new MethodType(mtype.getParameterTypes(),
mtype.getReturnType(),
@ -862,8 +859,8 @@ public class LambdaToMethod extends TreeTranslator {
finally {
frameStack = prevStack;
}
if (frameStack.nonEmpty() && enclosingLambda() != null) {
// Any class defined within a lambda is an implicit 'this' reference
if (!tree.sym.isStatic() && frameStack.nonEmpty() && enclosingLambda() != null) {
// Any (non-static) class defined within a lambda is an implicit 'this' reference
// because its constructor will reference the enclosing class
((LambdaTranslationContext) context()).addSymbol(tree.sym.type.getEnclosingType().tsym, CAPTURED_THIS);
}
@ -997,6 +994,11 @@ public class LambdaToMethod extends TreeTranslator {
* (required to skip synthetic lambda symbols)
*/
private Symbol owner() {
return owner(false);
}
@SuppressWarnings("fallthrough")
private Symbol owner(boolean skipLambda) {
List<Frame> frameStack2 = frameStack;
while (frameStack2.nonEmpty()) {
switch (frameStack2.head.tree.getTag()) {
@ -1015,7 +1017,8 @@ public class LambdaToMethod extends TreeTranslator {
case METHODDEF:
return ((JCMethodDecl)frameStack2.head.tree).sym;
case LAMBDA:
return ((LambdaTranslationContext)contextMap.get(frameStack2.head.tree)).translatedSym;
if (!skipLambda)
return ((LambdaTranslationContext)contextMap.get(frameStack2.head.tree)).translatedSym;
default:
frameStack2 = frameStack2.tail;
}
@ -1155,7 +1158,7 @@ public class LambdaToMethod extends TreeTranslator {
* This class is used to store important information regarding translation of
* lambda expression/method references (see subclasses).
*/
private abstract class TranslationContext<T extends JCTree> {
private abstract class TranslationContext<T extends JCFunctionalExpression> {
/** the underlying (untranslated) tree */
T tree;
@ -1314,12 +1317,13 @@ public class LambdaToMethod extends TreeTranslator {
}
Type enclosingType() {
//local inner classes defined inside a lambda are always non-static
return owner.enclClass().type;
return owner.isStatic() ?
Type.noType :
owner.enclClass().type;
}
Type generatedLambdaSig() {
return types.erasure(types.findDescriptorType(tree.targetType));
return types.erasure(tree.descriptorType);
}
}
@ -1375,7 +1379,7 @@ public class LambdaToMethod extends TreeTranslator {
}
Type bridgedRefSig() {
return types.erasure(types.findDescriptorSymbol(tree.targetType.tsym).type);
return types.erasure(types.findDescriptorSymbol(tree.targets.head).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
@ -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
@ -41,6 +41,7 @@ import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.JCTree.JCMemberReference.ReferenceKind;
import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@ -54,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;
@ -92,6 +92,7 @@ public class Resolve {
public final boolean varargsEnabled; // = source.allowVarargs();
public final boolean allowMethodHandles;
public final boolean allowDefaultMethods;
public final boolean allowStructuralMostSpecific;
private final boolean debugResolve;
final EnumSet<VerboseResolutionMode> verboseResolutionMode;
@ -127,6 +128,7 @@ public class Resolve {
Target target = Target.instance(context);
allowMethodHandles = target.hasMethodHandles();
allowDefaultMethods = source.allowDefaultMethods();
allowStructuralMostSpecific = source.allowStructuralMostSpecific();
polymorphicSignatureScope = new Scope(syms.noSymbol);
inapplicableMethodException = new InapplicableMethodException(diags);
@ -693,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) {
@ -704,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) {
@ -721,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;
@ -745,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);
}
}
}
@ -758,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);
@ -835,6 +837,213 @@ public class Resolve {
}
}
/**
* Most specific method applicability routine. Given a list of actual types A,
* a list of formal types F1, and a list of formal types F2, the routine determines
* as to whether the types in F1 can be considered more specific than those in F2 w.r.t.
* argument types A.
*/
class MostSpecificCheck implements MethodCheck {
boolean strict;
List<Type> actuals;
MostSpecificCheck(boolean strict, List<Type> actuals) {
this.strict = strict;
this.actuals = actuals;
}
@Override
public void argumentsAcceptable(final Env<AttrContext> env,
DeferredAttrContext deferredAttrContext,
List<Type> formals1,
List<Type> formals2,
Warner warn) {
formals2 = adjustArgs(formals2, deferredAttrContext.msym, formals1.length(), deferredAttrContext.phase.isVarargsRequired());
while (formals2.nonEmpty()) {
ResultInfo mresult = methodCheckResult(formals2.head, deferredAttrContext, warn, actuals.head);
mresult.check(null, formals1.head);
formals1 = formals1.tail;
formals2 = formals2.tail;
actuals = actuals.isEmpty() ? actuals : actuals.tail;
}
}
/**
* Create a method check context to be used during the most specific applicability check
*/
ResultInfo methodCheckResult(Type to, DeferredAttr.DeferredAttrContext deferredAttrContext,
Warner rsWarner, Type actual) {
return attr.new ResultInfo(Kinds.VAL, to,
new MostSpecificCheckContext(strict, deferredAttrContext, rsWarner, actual));
}
/**
* Subclass of method check context class that implements most specific
* method conversion. If the actual type under analysis is a deferred type
* a full blown structural analysis is carried out.
*/
class MostSpecificCheckContext extends MethodCheckContext {
Type actual;
public MostSpecificCheckContext(boolean strict, DeferredAttrContext deferredAttrContext, Warner rsWarner, Type actual) {
super(strict, deferredAttrContext, rsWarner);
this.actual = actual;
}
public boolean compatible(Type found, Type req, Warner warn) {
if (!allowStructuralMostSpecific || actual == null) {
return super.compatible(found, req, warn);
} else {
switch (actual.getTag()) {
case DEFERRED:
DeferredType dt = (DeferredType) actual;
DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
return (e == null || e.speculativeTree == deferredAttr.stuckTree)
? false : mostSpecific(found, req, e.speculativeTree, warn);
default:
return standaloneMostSpecific(found, req, actual, warn);
}
}
}
private boolean mostSpecific(Type t, Type s, JCTree tree, Warner warn) {
MostSpecificChecker msc = new MostSpecificChecker(t, s, warn);
msc.scan(tree);
return msc.result;
}
boolean polyMostSpecific(Type t1, Type t2, Warner warn) {
return (!t1.isPrimitive() && t2.isPrimitive())
? true : super.compatible(t1, t2, warn);
}
boolean standaloneMostSpecific(Type t1, Type t2, Type exprType, Warner warn) {
return (exprType.isPrimitive() == t1.isPrimitive()
&& exprType.isPrimitive() != t2.isPrimitive())
? true : super.compatible(t1, t2, warn);
}
/**
* Structural checker for most specific.
*/
class MostSpecificChecker extends DeferredAttr.PolyScanner {
final Type t;
final Type s;
final Warner warn;
boolean result;
MostSpecificChecker(Type t, Type s, Warner warn) {
this.t = t;
this.s = s;
this.warn = warn;
result = true;
}
@Override
void skip(JCTree tree) {
result &= standaloneMostSpecific(t, s, tree.type, warn);
}
@Override
public void visitConditional(JCConditional tree) {
if (tree.polyKind == PolyKind.STANDALONE) {
result &= standaloneMostSpecific(t, s, tree.type, warn);
} else {
super.visitConditional(tree);
}
}
@Override
public void visitApply(JCMethodInvocation tree) {
result &= (tree.polyKind == PolyKind.STANDALONE)
? standaloneMostSpecific(t, s, tree.type, warn)
: polyMostSpecific(t, s, warn);
}
@Override
public void visitNewClass(JCNewClass tree) {
result &= (tree.polyKind == PolyKind.STANDALONE)
? standaloneMostSpecific(t, s, tree.type, warn)
: polyMostSpecific(t, s, warn);
}
@Override
public void visitReference(JCMemberReference tree) {
if (types.isFunctionalInterface(t.tsym) &&
types.isFunctionalInterface(s.tsym) &&
types.asSuper(t, s.tsym) == null &&
types.asSuper(s, t.tsym) == null) {
Type desc_t = types.findDescriptorType(t);
Type desc_s = types.findDescriptorType(s);
if (types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
if (!desc_s.getReturnType().hasTag(VOID)) {
//perform structural comparison
Type ret_t = desc_t.getReturnType();
Type ret_s = desc_s.getReturnType();
result &= ((tree.refPolyKind == PolyKind.STANDALONE)
? standaloneMostSpecific(ret_t, ret_s, tree.type, warn)
: polyMostSpecific(ret_t, ret_s, warn));
} else {
return;
}
} else {
result &= false;
}
} else {
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
}
}
@Override
public void visitLambda(JCLambda tree) {
if (types.isFunctionalInterface(t.tsym) &&
types.isFunctionalInterface(s.tsym) &&
types.asSuper(t, s.tsym) == null &&
types.asSuper(s, t.tsym) == null) {
Type desc_t = types.findDescriptorType(t);
Type desc_s = types.findDescriptorType(s);
if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT
|| types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
if (!desc_s.getReturnType().hasTag(VOID)) {
//perform structural comparison
Type ret_t = desc_t.getReturnType();
Type ret_s = desc_s.getReturnType();
scanLambdaBody(tree, ret_t, ret_s);
} else {
return;
}
} else {
result &= false;
}
} else {
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
}
}
//where
void scanLambdaBody(JCLambda lambda, final Type t, final Type s) {
if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
result &= MostSpecificCheckContext.this.mostSpecific(t, s, lambda.body, warn);
} else {
DeferredAttr.LambdaReturnScanner lambdaScanner =
new DeferredAttr.LambdaReturnScanner() {
@Override
public void visitReturn(JCReturn tree) {
if (tree.expr != null) {
result &= MostSpecificCheckContext.this.mostSpecific(t, s, tree.expr, warn);
}
}
};
lambdaScanner.scan(lambda.body);
}
}
}
}
}
public static class InapplicableMethodException extends RuntimeException {
private static final long serialVersionUID = 0;
@ -1142,153 +1351,32 @@ public class Resolve {
}
//where
private boolean signatureMoreSpecific(List<Type> actuals, Env<AttrContext> env, Type site, Symbol m1, Symbol m2, boolean allowBoxing, boolean useVarargs) {
Symbol m12 = adjustVarargs(m1, m2, useVarargs);
Symbol m22 = adjustVarargs(m2, m1, useVarargs);
Type mtype1 = types.memberType(site, m12);
Type mtype2 = types.memberType(site, m22);
//check if invocation is more specific
if (invocationMoreSpecific(env, site, m22, mtype1.getParameterTypes(), allowBoxing, useVarargs)) {
return true;
}
//perform structural check
List<Type> formals1 = mtype1.getParameterTypes();
Type lastFormal1 = formals1.last();
List<Type> formals2 = mtype2.getParameterTypes();
Type lastFormal2 = formals2.last();
ListBuffer<Type> newFormals = ListBuffer.lb();
boolean hasStructuralPoly = false;
for (Type actual : actuals) {
//perform formal argument adaptation in case actuals > formals (varargs)
Type f1 = formals1.isEmpty() ?
lastFormal1 : formals1.head;
Type f2 = formals2.isEmpty() ?
lastFormal2 : formals2.head;
//is this a structural actual argument?
boolean isStructuralPoly = actual.hasTag(DEFERRED) &&
(((DeferredType)actual).tree.hasTag(LAMBDA) ||
((DeferredType)actual).tree.hasTag(REFERENCE));
Type newFormal = f1;
if (isStructuralPoly) {
//for structural arguments only - check that corresponding formals
//are related - if so replace formal with <null>
hasStructuralPoly = true;
DeferredType dt = (DeferredType)actual;
Type t1 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m1, currentResolutionContext.step).apply(dt);
Type t2 = deferredAttr.new DeferredTypeMap(AttrMode.SPECULATIVE, m2, currentResolutionContext.step).apply(dt);
if (t1.isErroneous() || t2.isErroneous() || !isStructuralSubtype(t1, t2)) {
//not structural subtypes - simply fail
return false;
} else {
newFormal = syms.botType;
}
}
newFormals.append(newFormal);
if (newFormals.length() > mtype2.getParameterTypes().length()) {
//expand m2's type so as to fit the new formal arity (varargs)
m22.type = types.createMethodTypeWithParameters(m22.type, m22.type.getParameterTypes().append(f2));
}
formals1 = formals1.isEmpty() ? formals1 : formals1.tail;
formals2 = formals2.isEmpty() ? formals2 : formals2.tail;
}
if (!hasStructuralPoly) {
//if no structural actual was found, we're done
return false;
}
//perform additional adaptation if actuals < formals (varargs)
for (Type t : formals1) {
newFormals.append(t);
}
//check if invocation (with tweaked args) is more specific
return invocationMoreSpecific(env, site, m22, newFormals.toList(), allowBoxing, useVarargs);
noteWarner.clear();
int maxLength = Math.max(
Math.max(m1.type.getParameterTypes().length(), actuals.length()),
m2.type.getParameterTypes().length());
Type mst = instantiate(env, site, m2, null,
adjustArgs(types.lowerBounds(types.memberType(site, m1).getParameterTypes()), m1, maxLength, useVarargs), null,
allowBoxing, useVarargs, new MostSpecificCheck(!allowBoxing, actuals), noteWarner);
return mst != null &&
!noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
}
//where
private boolean invocationMoreSpecific(Env<AttrContext> env, Type site, Symbol m2, List<Type> argtypes1, boolean allowBoxing, boolean useVarargs) {
MethodResolutionContext prevContext = currentResolutionContext;
try {
currentResolutionContext = new MethodResolutionContext();
currentResolutionContext.step = allowBoxing ? BOX : BASIC;
noteWarner.clear();
Type mst = instantiate(env, site, m2, null,
types.lowerBounds(argtypes1), null,
allowBoxing, false, resolveMethodCheck, noteWarner);
return mst != null &&
!noteWarner.hasLint(Lint.LintCategory.UNCHECKED);
} finally {
currentResolutionContext = prevContext;
}
}
//where
private Symbol adjustVarargs(Symbol to, Symbol from, boolean useVarargs) {
List<Type> fromArgs = from.type.getParameterTypes();
List<Type> toArgs = to.type.getParameterTypes();
if (useVarargs &&
(from.flags() & VARARGS) != 0 &&
(to.flags() & VARARGS) != 0) {
Type varargsTypeFrom = fromArgs.last();
Type varargsTypeTo = toArgs.last();
ListBuffer<Type> args = ListBuffer.lb();
if (toArgs.length() < fromArgs.length()) {
//if we are checking a varargs method 'from' against another varargs
//method 'to' (where arity of 'to' < arity of 'from') then expand signature
//of 'to' to 'fit' arity of 'from' (this means adding fake formals to 'to'
//until 'to' signature has the same arity as 'from')
while (fromArgs.head != varargsTypeFrom) {
args.append(toArgs.head == varargsTypeTo ? types.elemtype(varargsTypeTo) : toArgs.head);
fromArgs = fromArgs.tail;
toArgs = toArgs.head == varargsTypeTo ?
toArgs :
toArgs.tail;
}
} else {
//formal argument list is same as original list where last
//argument (array type) is removed
args.appendList(toArgs.reverse().tail.reverse());
private List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) {
if ((msym.flags() & VARARGS) != 0 && allowVarargs) {
Type varargsElem = types.elemtype(args.last());
if (varargsElem == null) {
Assert.error("Bad varargs = " + args.last() + " " + msym);
}
//append varargs element type as last synthetic formal
args.append(types.elemtype(varargsTypeTo));
Type mtype = types.createMethodTypeWithParameters(to.type, args.toList());
return new MethodSymbol(to.flags_field & ~VARARGS, to.name, mtype, to.owner);
List<Type> newArgs = args.reverse().tail.prepend(varargsElem).reverse();
while (newArgs.length() < length) {
newArgs = newArgs.append(newArgs.last());
}
return newArgs;
} else {
return to;
return args;
}
}
//where
boolean isStructuralSubtype(Type s, Type t) {
Type ret_s = types.findDescriptorType(s).getReturnType();
Type ret_t = types.findDescriptorType(t).getReturnType();
//covariant most specific check for function descriptor return type
if (!types.isSubtype(ret_s, ret_t)) {
return false;
}
List<Type> args_s = types.findDescriptorType(s).getParameterTypes();
List<Type> args_t = types.findDescriptorType(t).getParameterTypes();
//arity must be identical
if (args_s.length() != args_t.length()) {
return false;
}
//invariant most specific check for function descriptor parameter types
if (!types.isSameTypes(args_t, args_s)) {
return false;
}
return true;
}
//where
Type mostSpecificReturnType(Type mt1, Type mt2) {
Type rt1 = mt1.getReturnType();
Type rt2 = mt2.getReturnType();
@ -2386,10 +2474,23 @@ public class Resolve {
List<Type> typeargtypes,
boolean boxingAllowed) {
MethodResolutionPhase maxPhase = boxingAllowed ? VARARITY : BASIC;
ReferenceLookupHelper boundLookupHelper;
if (!name.equals(names.init)) {
//method reference
boundLookupHelper =
new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
} else if (site.hasTag(ARRAY)) {
//array constructor reference
boundLookupHelper =
new ArrayConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
} else {
//class constructor reference
boundLookupHelper =
new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase);
}
//step 1 - bound lookup
ReferenceLookupHelper boundLookupHelper = name.equals(names.init) ?
new ConstructorReferenceLookupHelper(referenceTree, site, argtypes, typeargtypes, maxPhase) :
new MethodReferenceLookupHelper(referenceTree, name, site, argtypes, typeargtypes, maxPhase);
Env<AttrContext> boundEnv = env.dup(env.tree, env.info.dup());
Symbol boundSym = lookupMethod(boundEnv, env.tree.pos(), site.tsym, boundLookupHelper);
@ -2626,6 +2727,33 @@ public class Resolve {
}
}
/**
* Helper class for array constructor lookup; an array constructor lookup
* is simulated by looking up a method that returns the array type specified
* as qualifier, and that accepts a single int parameter (size of the array).
*/
class ArrayConstructorReferenceLookupHelper extends ReferenceLookupHelper {
ArrayConstructorReferenceLookupHelper(JCMemberReference referenceTree, Type site, List<Type> argtypes,
List<Type> typeargtypes, MethodResolutionPhase maxPhase) {
super(referenceTree, names.init, site, argtypes, typeargtypes, maxPhase);
}
@Override
protected Symbol lookup(Env<AttrContext> env, MethodResolutionPhase phase) {
Scope sc = new Scope(syms.arrayClass);
MethodSymbol arrayConstr = new MethodSymbol(PUBLIC, name, null, site.tsym);
arrayConstr.type = new MethodType(List.of(syms.intType), site, List.<Type>nil(), syms.methodClass);
sc.enter(arrayConstr);
return findMethodInScope(env, site, name, argtypes, typeargtypes, sc, methodNotFound, phase.isBoxingRequired(), phase.isVarargsRequired(), false, false);
}
@Override
ReferenceKind referenceKind(Symbol sym) {
return ReferenceKind.ARRAY_CTOR;
}
}
/**
* Helper class for constructor reference lookup. The lookup logic is based
* upon either Resolve.findMethod or Resolve.findDiamond - depending on
@ -3381,7 +3509,10 @@ public class Resolve {
@Override
protected Symbol access(Name name, TypeSymbol location) {
return ambiguousSyms.last();
Symbol firstAmbiguity = ambiguousSyms.last();
return firstAmbiguity.kind == TYP ?
types.createErrorType(name, location, firstAmbiguity.type).tsym :
firstAmbiguity;
}
}

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);
@ -549,9 +550,6 @@ public class TransTypes extends TreeTranslator {
currentMethod = null;
tree.params = translate(tree.params);
tree.body = translate(tree.body, null);
//save non-erased target
tree.targetType = tree.type;
Assert.check(!tree.targetType.isCompound(), "Intersection-type targets not supported yet!");
tree.type = erasure(tree.type);
result = tree;
}
@ -785,9 +783,6 @@ public class TransTypes extends TreeTranslator {
public void visitReference(JCMemberReference tree) {
tree.expr = translate(tree.expr, null);
//save non-erased target
tree.targetType = tree.type;
Assert.check(!tree.targetType.isCompound(), "Intersection-type targets not supported yet!");
tree.type = erasure(tree.type);
result = tree;
}

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
@ -27,6 +27,8 @@ package com.sun.tools.javac.model;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import javax.lang.model.SourceVersion;
@ -96,32 +98,43 @@ public class JavacElements implements Elements {
enter = Enter.instance(context);
}
/**
* An internal-use utility that creates a reified annotation.
* An internal-use utility that creates a runtime view of an
* annotation. This is the implementation of
* Element.getAnnotation(Class).
*/
public static <A extends Annotation> A getAnnotation(Symbol annotated,
Class<A> annoType) {
if (!annoType.isAnnotation())
throw new IllegalArgumentException("Not an annotation type: "
+ annoType);
String name = annoType.getName();
for (Attribute.Compound anno : annotated.getAnnotationMirrors())
if (name.equals(anno.type.tsym.flatName().toString()))
return AnnotationProxyMaker.generateAnnotation(anno, annoType);
return null;
Attribute.Compound c;
if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) {
c = getAttributeOnClass((ClassSymbol)annotated, annoType);
} else {
c = getAttribute(annotated, annoType);
}
return c == null ? null : AnnotationProxyMaker.generateAnnotation(c, annoType);
}
/**
* An internal-use utility that creates a reified annotation.
* This overloaded version take annotation inheritance into account.
*/
public static <A extends Annotation> A getAnnotation(ClassSymbol annotated,
Class<A> annoType) {
// Helper to getAnnotation[s]
private static <A extends Annotation> Attribute.Compound getAttribute(Symbol annotated,
Class<A> annoType) {
String name = annoType.getName();
for (Attribute.Compound anno : annotated.getRawAttributes())
if (name.equals(anno.type.tsym.flatName().toString()))
return anno;
return null;
}
// Helper to getAnnotation[s]
private static <A extends Annotation> Attribute.Compound getAttributeOnClass(ClassSymbol annotated,
Class<A> annoType) {
boolean inherited = annoType.isAnnotationPresent(Inherited.class);
A result = null;
Attribute.Compound result = null;
while (annotated.name != annotated.name.table.names.java_lang_Object) {
result = getAnnotation((Symbol)annotated, annoType);
result = getAttribute(annotated, annoType);
if (result != null || !inherited)
break;
Type sup = annotated.getSuperclass();
@ -132,6 +145,189 @@ public class JavacElements implements Elements {
return result;
}
/**
* An internal-use utility that creates a runtime view of
* annotations. This is the implementation of
* Element.getAnnotations(Class).
*/
public static <A extends Annotation> A[] getAnnotations(Symbol annotated,
Class<A> annoType) {
if (!annoType.isAnnotation())
throw new IllegalArgumentException("Not an annotation type: "
+ annoType);
// If annoType does not declare a container this is equivalent to wrapping
// getAnnotation(...) in an array.
Class <? extends Annotation> containerType = getContainer(annoType);
if (containerType == null) {
A res = getAnnotation(annotated, annoType);
int size;
if (res == null) {
size = 0;
} else {
size = 1;
}
@SuppressWarnings("unchecked") // annoType is the Class for A
A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size);
if (res != null)
arr[0] = res;
return arr;
}
// So we have a containing type
String name = annoType.getName();
String annoTypeName = annoType.getSimpleName();
String containerTypeName = containerType.getSimpleName();
int directIndex = -1, containerIndex = -1;
Attribute.Compound direct = null, container = null;
Attribute.Compound[] rawAttributes = annotated.getRawAttributes().toArray(new Attribute.Compound[0]);
// Find directly present annotations
for (int i = 0; i < rawAttributes.length; i++) {
if (annoTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) {
directIndex = i;
direct = rawAttributes[i];
} else if(containerTypeName != null &&
containerTypeName.equals(rawAttributes[i].type.tsym.flatName().toString())) {
containerIndex = i;
container = rawAttributes[i];
}
}
// Deal with inherited annotations
if (annotated.kind == Kinds.TYP &&
(annotated instanceof ClassSymbol)) {
ClassSymbol s = (ClassSymbol)annotated;
if (direct == null && container == null) {
direct = getAttributeOnClass(s, annoType);
container = getAttributeOnClass(s, containerType);
// both are inherited and found, put container last
if (direct != null && container != null) {
directIndex = 0;
containerIndex = 1;
} else if (direct != null) {
directIndex = 0;
} else {
containerIndex = 0;
}
} else if (direct == null) {
direct = getAttributeOnClass(s, annoType);
if (direct != null)
directIndex = containerIndex + 1;
} else if (container == null) {
container = getAttributeOnClass(s, containerType);
if (container != null)
containerIndex = directIndex + 1;
}
}
// Pack them in an array
Attribute[] contained0 = new Attribute[0];
if (container != null)
contained0 = unpackAttributes(container);
ListBuffer<Attribute.Compound> compounds = ListBuffer.lb();
for (Attribute a : contained0)
if (a instanceof Attribute.Compound)
compounds = compounds.append((Attribute.Compound)a);
Attribute.Compound[] contained = compounds.toArray(new Attribute.Compound[0]);
int size = (direct == null ? 0 : 1) + contained.length;
@SuppressWarnings("unchecked") // annoType is the Class for A
A[] arr = (A[])java.lang.reflect.Array.newInstance(annoType, size);
// if direct && container, which is first?
int insert = -1;
int length = arr.length;
if (directIndex >= 0 && containerIndex >= 0) {
if (directIndex < containerIndex) {
arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
insert = 1;
} else {
arr[arr.length - 1] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
insert = 0;
length--;
}
} else if (directIndex >= 0) {
arr[0] = AnnotationProxyMaker.generateAnnotation(direct, annoType);
return arr;
} else {
// Only container
insert = 0;
}
for (int i = 0; i + insert < length; i++)
arr[insert + i] = AnnotationProxyMaker.generateAnnotation(contained[i], annoType);
return arr;
}
// Needed to unpack the runtime view of containing annotations
private static final Class<? extends Annotation> REPEATABLE_CLASS = initRepeatable();
private static final Method VALUE_ELEMENT_METHOD = initValueElementMethod();
private static Class<? extends Annotation> initRepeatable() {
try {
// Repeatable will not be available when bootstrapping on
// JDK 7 so use a reflective lookup instead of a class
// literal for Repeatable.class.
return Class.forName("java.lang.annotation.Repeatable").asSubclass(Annotation.class);
} catch (ClassNotFoundException e) {
return null;
} catch (SecurityException e) {
return null;
}
}
private static Method initValueElementMethod() {
if (REPEATABLE_CLASS == null)
return null;
Method m = null;
try {
m = REPEATABLE_CLASS.getMethod("value");
if (m != null)
m.setAccessible(true);
return m;
} catch (NoSuchMethodException e) {
return null;
}
}
// Helper to getAnnotations
private static Class<? extends Annotation> getContainer(Class<? extends Annotation> annoType) {
// Since we can not refer to java.lang.annotation.Repeatable until we are
// bootstrapping with java 8 we need to get the Repeatable annotation using
// reflective invocations instead of just using its type and element method.
if (REPEATABLE_CLASS != null &&
VALUE_ELEMENT_METHOD != null) {
// Get the Repeatable instance on the annotations declaration
Annotation repeatable = (Annotation)annoType.getAnnotation(REPEATABLE_CLASS);
if (repeatable != null) {
try {
// Get the value element, it should be a class
// indicating the containing annotation type
@SuppressWarnings("unchecked")
Class<? extends Annotation> containerType = (Class)VALUE_ELEMENT_METHOD.invoke(repeatable);
if (containerType == null)
return null;
return containerType;
} catch (ClassCastException e) {
return null;
} catch (IllegalAccessException e) {
return null;
} catch (InvocationTargetException e ) {
return null;
}
}
}
return null;
}
// Helper to getAnnotations
private static Attribute[] unpackAttributes(Attribute.Compound container) {
// We now have an instance of the container,
// unpack it returning an instance of the
// contained type or null
return ((Attribute.Array)container.member(container.type.tsym.name.table.names.value)).values;
}
public PackageSymbol getPackageElement(CharSequence name) {
String strName = name.toString();
@ -238,8 +434,10 @@ public class JavacElements implements Elements {
tree.accept(vis);
if (vis.result == null)
return null;
List<Attribute.Compound> annos = sym.getRawAttributes();
return matchAnnoToTree(cast(Attribute.Compound.class, findme),
sym.getAnnotationMirrors(),
annos,
vis.result);
}
@ -442,7 +640,7 @@ public class JavacElements implements Elements {
*/
public List<Attribute.Compound> getAllAnnotationMirrors(Element e) {
Symbol sym = cast(Symbol.class, e);
List<Attribute.Compound> annos = sym.getAnnotationMirrors();
List<Attribute.Compound> annos = sym.getRawAttributes();
while (sym.getKind() == ElementKind.CLASS) {
Type sup = ((ClassSymbol) sym).getSuperclass();
if (!sup.hasTag(CLASS) || sup.isErroneous() ||
@ -451,7 +649,8 @@ public class JavacElements implements Elements {
}
sym = sup.tsym;
List<Attribute.Compound> oldAnnos = annos;
for (Attribute.Compound anno : sym.getAnnotationMirrors()) {
List<Attribute.Compound> newAnnos = sym.getRawAttributes();
for (Attribute.Compound anno : newAnnos) {
if (isInherited(anno.type) &&
!containsAnnoOfType(oldAnnos, anno.type)) {
annos = annos.prepend(anno);
@ -465,11 +664,7 @@ public class JavacElements implements Elements {
* Tests whether an annotation type is @Inherited.
*/
private boolean isInherited(Type annotype) {
for (Attribute.Compound anno : annotype.tsym.getAnnotationMirrors()) {
if (anno.type.tsym == syms.inheritedType.tsym)
return true;
}
return false;
return annotype.tsym.attribute(syms.inheritedType.tsym) != null;
}
/**

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

@ -33,6 +33,7 @@ import com.sun.tools.javac.parser.Tokens.Token.Tag;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.Name;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.Filter;
import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Names;
@ -74,7 +75,6 @@ public class Tokens {
protected Tokens(Context context) {
context.put(tokensKey, this);
names = Names.instance(context);
for (TokenKind t : TokenKind.values()) {
if (t.name != null)
enterKeyword(t.name, t);
@ -113,7 +113,7 @@ public class Tokens {
* This enum defines all tokens used by the javac scanner. A token is
* optionally associated with a name.
*/
public enum TokenKind implements Formattable {
public enum TokenKind implements Formattable, Filter<TokenKind> {
EOF(),
ERROR(),
IDENTIFIER(Tag.NAMED),
@ -176,6 +176,7 @@ public class Tokens {
TRUE("true", Tag.NAMED),
FALSE("false", Tag.NAMED),
NULL("null", Tag.NAMED),
UNDERSCORE("_", Tag.NAMED),
ARROW("->"),
COLCOL("::"),
LPAREN("("),
@ -283,6 +284,11 @@ public class Tokens {
public String toString(Locale locale, Messages messages) {
return name != null ? toString() : messages.getLocalizedString(locale, "compiler.misc." + toString());
}
@Override
public boolean accepts(TokenKind that) {
return this == that;
}
}
public interface Comment {

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

@ -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
@ -178,14 +178,23 @@ compiler.misc.no.abstracts=\
compiler.misc.incompatible.abstracts=\
multiple non-overriding abstract methods found in {0} {1}
compiler.misc.not.a.functional.intf=\
the target type must be a functional interface
compiler.err.bad.functional.intf.anno=\
Unexpected @FunctionalInterface annotation
# 0: message segment
compiler.misc.not.a.functional.intf.1=\
the target type must be a functional interface\n\
compiler.err.bad.functional.intf.anno.1=\
Unexpected @FunctionalInterface annotation\n\
{0}
# 0: symbol
compiler.misc.not.a.functional.intf=\
{0} is not a functional interface
# 0: symbol, 1: message segment
compiler.misc.not.a.functional.intf.1=\
{0} is not a functional interface\n\
{1}
# 0: symbol, 1: symbol kind, 2: symbol
compiler.misc.invalid.generic.lambda.target=\
invalid functional descriptor for lambda expression\n\
@ -319,64 +328,48 @@ compiler.err.duplicate.annotation.member.value=\
compiler.err.duplicate.annotation.missing.container=\
duplicate annotation, the declaration of {0} does not have a valid {1} annotation
# 0: type, 1: type
compiler.err.invalid.container.no.containedby=\
invalid contained repeatable annotation, {0} is not annotated with {1}
# 0: type, 1: type
compiler.err.invalid.container.wrong.containedby=\
invalid contained repeatable annotation, {0} does not match {1}
# 0: type, 1: type
compiler.err.invalid.container.no.containerfor=\
invalid container for repeating annotations, {0} is not annotated with {1}
# 0: type, 1: type
compiler.err.invalid.container.wrong.containerfor=\
invalid container for repeating annotations, {0} does not match {1}
# 0: type
compiler.err.invalid.repeatable.annotation=\
duplicate annotation, {0} is annotated with an invalid Repeatable annotation
# 0: type
compiler.err.invalid.containedby.annotation=\
duplicate annotation, {0} is annotated with an invalid ContainedBy annotation
# 0: type
compiler.err.invalid.containedby.annotation.no.value=\
duplicate annotation, {0} is not a valid ContainedBy, no value element method declared
compiler.err.invalid.repeatable.annotation.no.value=\
duplicate annotation, {0} is not a valid Repeatable, no value element method declared
# 0: type, 1: number
compiler.err.invalid.containedby.annotation.multiple.values=\
duplicate annotation, {0} is not a valid ContainedBy, {1} value element methods declared
compiler.err.invalid.repeatable.annotation.multiple.values=\
duplicate annotation, {0} is not a valid Repeatable, {1} value element methods declared
# 0: type
compiler.err.invalid.containedby.annotation.invalid.value=\
duplicate annotation, {0} is not a valid ContainedBy, invalid value element, need a method
compiler.err.invalid.repeatable.annotation.invalid.value=\
duplicate annotation, {0} is not a valid Repeatable, invalid value element, need a method
# 0: type, 1: type, 2: type
compiler.err.invalid.containedby.annotation.value.return=\
compiler.err.invalid.repeatable.annotation.value.return=\
duplicate annotation, value element of containing annotation {0} should have type {2}, found {1}
# 0: type, 1: symbol
compiler.err.invalid.containedby.annotation.elem.nondefault=\
compiler.err.invalid.repeatable.annotation.elem.nondefault=\
containing annotation {0} does not have a default value for element {1}
# 0: symbol, 1: type, 2: symbol, 3: type
compiler.err.invalid.containedby.annotation.retention=\
compiler.err.invalid.repeatable.annotation.retention=\
containing annotation {0} has shorter retention ({1}) than the contained annotation {2} with retention {3}
# 0: symbol, 1: symbol
compiler.err.invalid.containedby.annotation.not.documented=\
compiler.err.invalid.repeatable.annotation.not.documented=\
containing annotation type, {0}, is not @Documented while repeated annotation type, {1}, is
# 0: symbol, 1: symbol
compiler.err.invalid.containedby.annotation.not.inherited=\
compiler.err.invalid.repeatable.annotation.not.inherited=\
containing annotation type, {0}, is not @Inherited while repeated annotation type, {1}, is
# 0: symbol, 1: symbol
compiler.err.invalid.containedby.annotation.incompatible.target=\
compiler.err.invalid.repeatable.annotation.incompatible.target=\
target of container annotation {0} is not a subset of target of repeated annotation {1}
# 0: symbol
compiler.err.invalid.containedby.annotation.repeated.and.container.present=\
compiler.err.invalid.repeatable.annotation.repeated.and.container.present=\
container {0} must not be present at the same time as the element it contains
# 0: name
@ -955,6 +948,11 @@ compiler.err.types.incompatible.abstract.default=\
compiler.err.default.overrides.object.member=\
default method {0} in {1} {2} overrides a member of java.lang.Object
# 0: type
compiler.err.illegal.static.intf.meth.call=\
illegal static interface method call\n\
the receiver expression should be replaced with the type qualifier ''{0}''
# 0: type, 1: message segment
compiler.err.illegal.default.super.call=\
bad type qualifier {0} in default super call\n\
@ -1668,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}
@ -2139,6 +2140,10 @@ compiler.warn.assert.as.identifier=\
as of release 1.4, ''assert'' is a keyword, and may not be used as an identifier\n\
(use -source 1.4 or higher to use ''assert'' as a keyword)
compiler.warn.underscore.as.identifier=\
''_'' used as an identifier\n\
(use of ''_'' as an identifier might not be supported in future releases)
compiler.err.enum.as.identifier=\
as of release 5, ''enum'' is a keyword, and may not be used as an identifier\n\
(use -source 1.4 or lower to use ''enum'' as an identifier)
@ -2147,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\
@ -2162,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=\
@ -2216,6 +2239,11 @@ compiler.err.intersection.types.in.cast.not.supported.in.source=\
intersection types in cast are not supported in -source {0}\n\
(use -source 8 or higher to enable default methods)
# 0: string
compiler.err.static.intf.methods.not.supported.in.source=\
static interface methods are not supported in -source {0}\n\
(use -source 8 or higher to enable static interface methods)
########################################
# Diagnostics for verbose resolution
# used by Resolve (debug only)

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.
@ -606,6 +612,42 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
}
/**
* Common supertype for all poly expression trees (lambda, method references,
* conditionals, method and constructor calls)
*/
public static abstract class JCPolyExpression extends JCExpression {
/**
* A poly expression can only be truly 'poly' in certain contexts
*/
public enum PolyKind {
/** poly expression to be treated as a standalone expression */
STANDALONE,
/** true poly expression */
POLY;
}
/** is this poly expression a 'true' poly expression? */
public PolyKind polyKind;
}
/**
* Common supertype for all functional expression trees (lambda and method references)
*/
public static abstract class JCFunctionalExpression extends JCPolyExpression {
public JCFunctionalExpression() {
//a functional expression is always a 'true' poly
polyKind = PolyKind.POLY;
}
/** target descriptor inferred for this functional expression. */
public Type descriptorType;
/** list of target types inferred for this functional expression. */
public List<TypeSymbol> targets;
}
/**
* A class definition.
*/
@ -689,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 */
@ -703,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,
@ -714,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;
@ -732,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;
}
@ -1147,7 +1196,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/**
* A ( ) ? ( ) : ( ) conditional expression
*/
public static class JCConditional extends JCExpression implements ConditionalExpressionTree {
public static class JCConditional extends JCPolyExpression implements ConditionalExpressionTree {
public JCExpression cond;
public JCExpression truepart;
public JCExpression falsepart;
@ -1373,7 +1422,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/**
* A method invocation
*/
public static class JCMethodInvocation extends JCExpression implements MethodInvocationTree {
public static class JCMethodInvocation extends JCPolyExpression implements MethodInvocationTree {
public List<JCExpression> typeargs;
public JCExpression meth;
public List<JCExpression> args;
@ -1416,7 +1465,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/**
* A new(...) operation.
*/
public static class JCNewClass extends JCExpression implements NewClassTree {
public static class JCNewClass extends JCPolyExpression implements NewClassTree {
public JCExpression encl;
public List<JCExpression> typeargs;
public JCExpression clazz;
@ -1469,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,
@ -1476,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
@ -1502,18 +1557,29 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/**
* A lambda expression.
*/
public static class JCLambda extends JCExpression implements LambdaExpressionTree {
public static class JCLambda extends JCFunctionalExpression implements LambdaExpressionTree {
public enum ParameterKind {
IMPLICIT,
EXPLICIT;
}
public List<JCVariableDecl> params;
public JCTree body;
public Type targetType;
public boolean canCompleteNormally = true;
public List<Type> inferredThrownTypes;
public ParameterKind paramKind;
public JCLambda(List<JCVariableDecl> params,
JCTree body) {
this.params = params;
this.body = body;
if (params.isEmpty() ||
params.head.vartype != null) {
paramKind = ParameterKind.EXPLICIT;
} else {
paramKind = ParameterKind.IMPLICIT;
}
}
@Override
public Tag getTag() {
@ -1812,15 +1878,15 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/**
* Selects a member expression.
*/
public static class JCMemberReference extends JCExpression implements MemberReferenceTree {
public static class JCMemberReference extends JCFunctionalExpression implements MemberReferenceTree {
public ReferenceMode mode;
public ReferenceKind kind;
public Name name;
public JCExpression expr;
public List<JCExpression> typeargs;
public Type targetType;
public Symbol sym;
public Type varargsElement;
public PolyKind refPolyKind;
/**
* Javac-dependent classification for member references, based
@ -1838,7 +1904,9 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
/** Inner # new */
IMPLICIT_INNER(ReferenceMode.NEW, false),
/** Toplevel # new */
TOPLEVEL(ReferenceMode.NEW, false);
TOPLEVEL(ReferenceMode.NEW, false),
/** ArrayType # new */
ARRAY_CTOR(ReferenceMode.NEW, false);
final ReferenceMode mode;
final boolean unbound;
@ -2103,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); }
@ -2115,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);
@ -2181,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;
@ -2201,7 +2286,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
}
@Override
public Tag getTag() {
return ANNOTATION;
return tag;
}
}
@ -2232,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;
@ -2298,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,
@ -2423,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);
}
@ -946,7 +981,7 @@ public class Pretty extends JCTree.Visitor {
public void visitLambda(JCLambda tree) {
try {
print("(");
if (TreeInfo.isExplicitLambda(tree)) {
if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT) {
printExprs(tree.params);
} else {
String sep = "";
@ -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
@ -32,6 +32,7 @@ import com.sun.tools.javac.code.*;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.tree.JCTree.JCPolyExpression.*;
import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import static com.sun.tools.javac.code.Flags.*;
@ -264,9 +265,38 @@ public class TreeInfo {
}
}
public static boolean isExplicitLambda(JCLambda lambda) {
return lambda.params.isEmpty() ||
lambda.params.head.vartype != null;
/** set 'polyKind' on given tree */
public static void setPolyKind(JCTree tree, PolyKind pkind) {
switch (tree.getTag()) {
case APPLY:
((JCMethodInvocation)tree).polyKind = pkind;
break;
case NEWCLASS:
((JCNewClass)tree).polyKind = pkind;
break;
case REFERENCE:
((JCMemberReference)tree).refPolyKind = pkind;
break;
default:
throw new AssertionError("Unexpected tree: " + tree);
}
}
/** set 'varargsElement' on given tree */
public static void setVarargsElement(JCTree tree, Type varargsElement) {
switch (tree.getTag()) {
case APPLY:
((JCMethodInvocation)tree).varargsElement = varargsElement;
break;
case NEWCLASS:
((JCNewClass)tree).varargsElement = varargsElement;
break;
case REFERENCE:
((JCMemberReference)tree).varargsElement = varargsElement;
break;
default:
throw new AssertionError("Unexpected tree: " + tree);
}
}
/** Return true if the tree corresponds to an expression statement */
@ -423,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)
@ -530,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())
@ -769,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;
}
@ -1006,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 */
@ -1024,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

@ -288,7 +288,7 @@ public class RichDiagnosticFormatter extends
public String simplify(Symbol s) {
String name = s.getQualifiedName().toString();
if (!s.type.isCompound()) {
if (!s.type.isCompound() && !s.type.isPrimitive()) {
List<Symbol> conflicts = nameClashes.get(s.getSimpleName());
if (conflicts == null ||
(conflicts.size() == 1 &&

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) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2000, 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,8 +31,10 @@ import java.util.*;
import javax.tools.JavaFileManager;
import com.sun.javadoc.*;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreePath;
import com.sun.tools.javac.api.JavacTrees;
import com.sun.tools.doclint.DocLint;
import com.sun.tools.javac.api.BasicJavacTask;
import com.sun.tools.javac.code.*;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.code.Type.ClassType;
@ -105,6 +107,7 @@ public class DocEnv {
Types types;
JavaFileManager fileManager;
Context context;
DocLint doclint;
WeakHashMap<JCTree, TreePath> treePaths = new WeakHashMap<JCTree, TreePath>();
@ -400,6 +403,9 @@ public class DocEnv {
public void warning(DocImpl doc, String key, String a1) {
if (silent)
return;
// suppress messages that have (probably) been covered by doclint
if (doclint != null && doc != null && key.startsWith("tag"))
return;
messager.warning(doc==null ? null : doc.position(), key, a1);
}
@ -732,9 +738,15 @@ public class DocEnv {
return p;
}
TreePath getTreePath(JCCompilationUnit toplevel, JCTree tree) {
// don't bother to cache paths for classes and members
return new TreePath(getTreePath(toplevel), tree);
TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl tree) {
TreePath p = treePaths.get(tree);
if (p == null)
treePaths.put(tree, p = new TreePath(getTreePath(toplevel), tree));
return p;
}
TreePath getTreePath(JCCompilationUnit toplevel, JCClassDecl cdecl, JCTree tree) {
return new TreePath(getTreePath(toplevel, cdecl), tree);
}
/**
@ -781,4 +793,25 @@ public class DocEnv {
result |= Modifier.VOLATILE;
return result;
}
void initDoclint(Collection<String> opts) {
ArrayList<String> doclintOpts = new ArrayList<String>();
for (String opt: opts) {
doclintOpts.add(opt == null ? DocLint.XMSGS_OPTION : DocLint.XMSGS_CUSTOM_PREFIX + opt);
}
if (doclintOpts.size() == 1
&& doclintOpts.get(0).equals(DocLint.XMSGS_CUSTOM_PREFIX + "none")) {
return;
}
JavacTask t = BasicJavacTask.instance(context);
doclint = new DocLint();
doclint.init(t, doclintOpts.toArray(new String[doclintOpts.size()]), false);
}
boolean showTagMessages() {
return (doclint == null);
}
}

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
@ -126,7 +126,13 @@ public abstract class DocImpl implements Doc, Comparable<Object> {
*/
Comment comment() {
if (comment == null) {
comment = new Comment(this, documentation());
String d = documentation();
if (env.doclint != null
&& treePath != null
&& d.equals(getCommentText(treePath))) {
env.doclint.scan(treePath);
}
comment = new Comment(this, d);
}
return comment;
}

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) 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
@ -72,7 +72,7 @@ public class JavadocMemberEnter extends MemberEnter {
super.visitMethodDef(tree);
MethodSymbol meth = tree.sym;
if (meth == null || meth.kind != Kinds.MTH) return;
TreePath treePath = docenv.getTreePath(env.toplevel, tree);
TreePath treePath = docenv.getTreePath(env.toplevel, env.enclClass, tree);
if (meth.isConstructor())
docenv.makeConstructorDoc(meth, treePath);
else if (isAnnotationTypeElement(meth))
@ -90,7 +90,7 @@ public class JavadocMemberEnter extends MemberEnter {
if (tree.sym != null &&
tree.sym.kind == Kinds.VAR &&
!isParameter(tree.sym)) {
docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, tree));
docenv.makeFieldDoc(tree.sym, docenv.getTreePath(env.toplevel, env.enclClass, tree));
}
}

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
@ -26,13 +26,14 @@
package com.sun.tools.javadoc;
import java.io.IOException;
import java.util.Collection;
import java.util.Locale;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import com.sun.javadoc.*;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
@ -375,4 +376,12 @@ public class RootDocImpl extends DocImpl implements RootDoc {
public JavaFileManager getFileManager() {
return env.fileManager;
}
public void initDocLint(Collection<String> opts) {
env.initDoclint(opts);
}
public boolean showTagMessages() {
return env.showTagMessages();
}
}

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.

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