mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
Merge
This commit is contained in:
commit
f018e9352d
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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();
|
||||
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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}.
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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,
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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\
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 &lt;, which is used in type parameters. Override this
|
||||
* if your doclet uses something different.
|
||||
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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>
|
||||
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 × S → 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
@ -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); }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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.*;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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())
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
}*/
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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); }
|
||||
|
||||
|
||||
@ -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 + ")");
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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) {
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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 &&
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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.
|
||||
*/
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user