# HG changeset patch # User lana # Date 1367866424 25200 # Node ID ec434cfd2752a7742c875c2fe7d556d8b81c0f3a # Parent adec2a5d510ae2669bae25ee519969d82a19c8b5# Parent 8e27e84de2e92d8d4b108499fecc3a5a3082622e Merge diff -r adec2a5d510a -r ec434cfd2752 make/Makefile-classic --- a/make/Makefile-classic Thu May 02 13:35:55 2013 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,396 +0,0 @@ -# -# Copyright (c) 2007, 2012, Oracle and/or its affiliates. All rights reserved. -# 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. -# - -# -# Makefile for building the langtools workspace. -# - -# -# On Solaris, the standard 'make' utility will not work with these makefiles. -# This little rule is only understood by Solaris make, and is harmless -# when seen by the GNU make tool. If using Solaris make, this causes the -# make command to fail. -# -SUN_MAKE_TEST:sh = @echo "ERROR: PLEASE USE GNU VERSION OF MAKE"; exit 33 - -#----- cancel implicit rules - -%: %.o -%: %.obj -%: %.dll -%: %.c -%: %.cc -%: %.C -%: %.p -%: %.f -%: %.s -%: %.F -%: %.r -%: %.S -%: %.mod -%: %.sh -%: %,v -%: RCS/%,v - -#----- imports - -ifdef ALT_BOOT_JAVA_HOME - BOOT_JAVA_HOME = $(ALT_BOOT_JAVA_HOME) -else - ifdef ALT_BOOTDIR - BOOT_JAVA_HOME = $(ALT_BOOTDIR) - else - BOOT_JAVA_HOME=/java/re/jdk/1.5.0/archive/fcs/binaries/solaris-sparc - endif -endif - -BOOT_JAVA=$(BOOT_JAVA_HOME)/bin/java -BOOT_JAVAC=$(BOOT_JAVA_HOME)/bin/javac -BOOTJAR=$(BOOT_JAVA_HOME)/bin/jar - -ifdef ALT_TESTJAVA_HOME - TESTJAVA_HOME = $(ALT_TESTJAVA_HOME) -else - TESTJAVA_HOME=/java/re/jdk/1.6.0/archive/fcs/binaries/solaris-sparc -endif - -TESTJAVA=$(TESTJAVA_HOME)/bin/java - -ifdef ALT_FINDBUGS_HOME - FINDBUGS_HOME = $(ALT_FINDBUGS_HOME) -else - FINDBUGS_HOME = /java/devtools/share/findbugs/1.1.2-rc4 -endif - -FINDBUGS = $(FINDBUGS_HOME)/bin/findbugs - -#----- commands - -CHMOD = chmod -CP = cp -ECHO = echo # FIXME -FIND = find -MKDIR = mkdir -SED = sed -ZIP = zip - -#----- locations and deliverables - -TOPDIR = .. -SRC_BIN_DIR = $(TOPDIR)/src/share/bin -SRC_CLASSES_DIR = $(TOPDIR)/src/share/classes - -BUILD_DIR = $(TOPDIR)/build - -CLASSES_DIR = $(BUILD_DIR)/classes -GENSRC_DIR = $(BUILD_DIR)/gensrc - -DIST_DIR = $(TOPDIR)/dist -BIN_DIR = $(DIST_DIR)/bin -LIB_DIR = $(DIST_DIR)/lib - -JAVAC_JAR = $(LIB_DIR)/javac.jar -JAVADOC_JAR = $(LIB_DIR)/javadoc.jar -JAVAH_JAR = $(LIB_DIR)/javah.jar -JAVAP_JAR = $(LIB_DIR)/javap.jar - -CLASSES_JAR = $(DIST_DIR)/classes.jar -SRC_ZIP = $(DIST_DIR)/src.zip - -BUILDTOOLSRC_DIR = tools -BUILDTOOLCLASSES_DIR = $(BUILD_DIR)/toolclasses - -#----- - -ifndef JDK_MAJOR_VERSION - JDK_MAJOR_VERSION = 1 -endif - -ifndef JDK_MINOR_VERSION - JDK_MINOR_VERSION = 7 -endif - -ifndef JDK_MICRO_VERSION - JDK_MICRO_VERSION = 0 -endif - -ifndef JDK_VERSION - JDK_VERSION = $(JDK_MAJOR_VERSION).$(JDK_MINOR_VERSION).$(JDK_MICRO_VERSION) -endif - -ifndef MILESTONE - MILESTONE = internal -endif - -# RELEASE is JDK_VERSION and -MILESTONE if MILESTONE is set -ifneq ($(MILESTONE),fcs) - RELEASE = $(JDK_VERSION)-$(MILESTONE)$(BUILD_VARIANT_RELEASE) -else - RELEASE = $(JDK_VERSION)$(BUILD_VARIANT_RELEASE) -endif - -# FULL_VERSION is RELEASE and -BUILD_NUMBER if BUILD_NUMBER is set -ifdef BUILD_NUMBER - FULL_VERSION = $(RELEASE)-$(BUILD_NUMBER) -else - BUILD_NUMBER = b00 - USER_RELEASE_SUFFIX := $(shell echo $(USER)_`date '+%d_%b_%Y_%H_%M' | tr "A-Z" "a-z"`) - FULL_VERSION = $(RELEASE)-$(USER_RELEASE_SUFFIX)-$(BUILD_NUMBER) -endif - -#----- useful macros - -TOOLS = javac javadoc javah javap - -SOURCE_LEVEL = 5 -BOOTSTRAP_TARGET_LEVEL = 5 -TARGET_LEVEL = 6 - -ifndef TARGET_JAVA - TARGET_JAVA = java -endif - -NO_PROPRIETARY_API_WARNINGS = -XDignore.symbol.file=true - -SELF = $(lastword $(MAKEFILE_LIST)) - -#----- - -# the default is to generate the following: -# dist/{bin,lib}: -# lang tools compiled to run on the target JDK - -default: - $(MAKE) -f $(SELF) \ - MILESTONE=bootstrap \ - TARGET_LEVEL=$(BOOTSTRAP_TARGET_LEVEL) \ - TARGET_JAVA=$(BOOT_JAVA_HOME)/bin/java \ - GENSRC_DIR=$(BUILD_DIR)/bootstrap/gensrc \ - CLASSES_DIR=$(BUILD_DIR)/bootstrap/classes \ - BIN_DIR=$(BUILD_DIR)/bootstrap/bin \ - LIB_DIR=$(BUILD_DIR)/bootstrap/lib \ - $(BUILD_DIR)/bootstrap/lib/javac.jar \ - $(BUILD_DIR)/bootstrap/bin/javac - $(MAKE) -f $(SELF) \ - BOOT_JAVAC=$(BUILD_DIR)/bootstrap/bin/javac \ - tools - -# for jdk, we generate the following: -# dist/bootstrap/{bin,lib}: -# lang tools compiled to run on the boot JDK -# dist/lib/classes.jar: -# lang tools recompiled to run on the target JDK, -# ready for inclusion in rt.jar and tools.jar -# dist/lib/src.zip -# .properties and .java files for classes in classes.jar, -# ready for jdk src.zip - -jdk: - $(MAKE) -f $(SELF) \ - MILESTONE=bootstrap \ - TARGET_LEVEL=$(BOOTSTRAP_TARGET_LEVEL) \ - TARGET_JAVA=$(BOOT_JAVA_HOME)/bin/java \ - GENSRC_DIR=$(BUILD_DIR)/bootstrap/gensrc \ - CLASSES_DIR=$(BUILD_DIR)/bootstrap/classes \ - BIN_DIR=$(DIST_DIR)/bootstrap/bin \ - LIB_DIR=$(DIST_DIR)/bootstrap/lib \ - tools - $(MAKE) -f $(SELF) \ - BOOT_JAVAC=$(DIST_DIR)/bootstrap/bin/javac \ - LIB_DIR=$(BUILD_DIR)/jdk/lib \ - $(DIST_DIR)/lib/classes.jar \ - $(DIST_DIR)/lib/src.zip - -tools: $(TOOLS:%=$(LIB_DIR)/%.jar) $(TOOLS:%=$(BIN_DIR)/%) - -clean: - $(RM) -r $(BUILD_DIR) - -really-clean: clean - $(RM) -r $(DIST_DIR) - -jprt_product_build \ -jprt_debug_build \ -jprt_fastdebug_build: lib - -#----- javac - -JAVAC_DIRS = \ - javax/annotation/processing \ - javax/lang/model \ - javax/tools \ - jdk/ \ - com/sun/source \ - com/sun/tools/javac - -JAVAC_RESOURCE_FILES = \ - $(shell find $(patsubst %,$(SRC_CLASSES_DIR)/%,$(JAVAC_DIRS)) -name SCCS -prune -o -name \*.properties -print ) - -JAVAC_JAVA_FILES = \ - $(shell find $(patsubst %,$(SRC_CLASSES_DIR)/%,$(JAVAC_DIRS)) -name SCCS -prune -o -name \*.java -print ) \ - $(patsubst $(SRC_CLASSES_DIR)/%.properties,$(GENSRC_DIR)/%.java,$(JAVAC_RESOURCE_FILES)) \ - $(GENSRC_DIR)/com/sun/tools/javac/resources/version.java - -$(JAVAC_JAR): $(JAVAC_JAVA_FILES) - $(MKDIR) -p $(CLASSES_DIR) $(@D) - $(BOOT_JAVAC) -d $(CLASSES_DIR) -target $(TARGET_LEVEL) $(NO_PROPRIETARY_API_WARNINGS) $(JAVAC_JAVA_FILES) - ( $(ECHO) Main-Class: com.sun.tools.javac.Main ) > $(BUILD_DIR)/javac.mf - $(BOOTJAR) -cfm $@ $(BUILD_DIR)/javac.mf $(patsubst %,-C $(CLASSES_DIR) %, $(JAVAC_DIRS)) - -#----- javadoc - -### FIXME -- javadoc has a couple of extra non-property resource files -### that need to be included - -JAVADOC_DIRS = \ - com/sun/javadoc \ - com/sun/tools/doclets \ - com/sun/tools/javadoc - -JAVADOC_RESOURCE_FILES = \ - $(shell find $(patsubst %,$(SRC_CLASSES_DIR)/%,$(JAVADOC_DIRS)) -name SCCS -prune -o -name \*.properties -print ) - -JAVADOC_JAVA_FILES = \ - $(shell find $(patsubst %,$(SRC_CLASSES_DIR)/%,$(JAVADOC_DIRS)) -name SCCS -prune -o -name \*.java -print ) \ - $(patsubst $(SRC_CLASSES_DIR)/%.properties,$(GENSRC_DIR)/%.java,$(JAVADOC_RESOURCE_FILES)) - -$(JAVADOC_JAR): $(JAVADOC_JAVA_FILES) $(JAVAC_JAR) - $(MKDIR) -p $(CLASSES_DIR) $(@D) - $(BOOT_JAVAC) -sourcepath "" -classpath $(JAVAC_JAR) -d $(CLASSES_DIR) -target $(TARGET_LEVEL) $(JAVADOC_JAVA_FILES) - ( $(ECHO) Main-Class: com.sun.tools.javadoc.Main ; $(ECHO) Class-Path: javac.jar ) > $(BUILD_DIR)/javadoc.mf - $(BOOTJAR) -cfm $@ $(BUILD_DIR)/javadoc.mf $(patsubst %,-C $(CLASSES_DIR) %, $(JAVADOC_DIRS)) - -#----- javah - -JAVAH_DIRS = \ - com/sun/tools/javah - -JAVAH_RESOURCE_FILES = \ - $(shell find $(patsubst %,$(SRC_CLASSES_DIR)/%,$(JAVAH_DIRS)) -name SCCS -prune -o -name \*.properties -print ) - -JAVAH_JAVA_FILES = \ - $(shell find $(patsubst %,$(SRC_CLASSES_DIR)/%,$(JAVAH_DIRS)) -name SCCS -prune -o -name \*.java -print ) \ - $(patsubst $(SRC_CLASSES_DIR)/%.properties,$(GENSRC_DIR)/%.java,$(JAVAH_RESOURCE_FILES)) - -$(JAVAH_JAR): $(JAVAH_JAVA_FILES) $(JAVADOC_JAR) - $(MKDIR) -p $(CLASSES_DIR) $(@D) - $(BOOT_JAVAC) -sourcepath "" -classpath $(CLASSES_DIR) -d $(CLASSES_DIR) -target $(TARGET_LEVEL) $(JAVAH_JAVA_FILES) - ( $(ECHO) Main-Class: com.sun.tools.javah.Main ; $(ECHO) Class-Path: javadoc.jar ) > $(BUILD_DIR)/javah.mf - $(BOOTJAR) -cfm $@ $(BUILD_DIR)/javah.mf $(patsubst %,-C $(CLASSES_DIR) %, $(JAVAH_DIRS)) - -#----- javap - -JAVAP_DIRS = \ - sun/tools/javap - -JAVAP_RESOURCE_FILES = \ - $(shell find $(patsubst %,$(SRC_CLASSES_DIR)/%,$(JAVAP_DIRS)) -name SCCS -prune -o -name \*.properties -print ) - -JAVAP_JAVA_FILES = \ - $(shell find $(patsubst %,$(SRC_CLASSES_DIR)/%,$(JAVAP_DIRS)) -name SCCS -prune -o -name \*.java -print ) \ - $(patsubst $(SRC_CLASSES_DIR)/%.properties,$(GENSRC_DIR)/%.java,$(JAVAP_RESOURCE_FILES)) - -$(JAVAP_JAR): $(JAVAP_JAVA_FILES) \ - $(patsubst $(SRC_CLASSES_DIR)/%.properties,$(GENSRC_DIR)/%.java,$(JAVAP_RESOURCE_FILES)) - $(MKDIR) -p $(CLASSES_DIR) - $(BOOT_JAVAC) -sourcepath "" -classpath $(CLASSES_DIR) -d $(CLASSES_DIR) -target $(TARGET_LEVEL) $(JAVAP_JAVA_FILES) - ( $(ECHO) Main-Class: sun.tools.javap.Main ) > $(BUILD_DIR)/javap.mf - $(BOOTJAR) -cfm $@ $(BUILD_DIR)/javap.mf $(patsubst %,-C $(CLASSES_DIR) %, $(JAVAP_DIRS)) - -#----- - -build-tools: $(BUILDTOOLCLASSES_DIR)/CompileProperties/CompileProperties.class - -$(GENSRC_DIR)/%.java: $(SRC_CLASSES_DIR)/%.properties $(BUILDTOOLCLASSES_DIR)/CompileProperties/CompileProperties.class - $(MKDIR) -p $(@D) - $(BOOT_JAVA) -cp $(BUILDTOOLCLASSES_DIR)/CompileProperties CompileProperties $< $(patsubst $(CLASSES_DIR)/%.class,$(GENSRC_DIR)/%.java,$@) - -$(GENSRC_DIR)/%.java: $(GENSRC_DIR)/%.properties $(BUILDTOOLCLASSES_DIR)/CompileProperties/CompileProperties.class - $(MKDIR) -p $(@D) - $(BOOT_JAVA) -cp $(BUILDTOOLCLASSES_DIR)/CompileProperties CompileProperties $< $(patsubst $(CLASSES_DIR)/%.class,$(GENSRC_DIR)/%.java,$@) - -$(GENSRC_DIR)/%.properties: $(SRC_CLASSES_DIR)/%.properties-template - $(MKDIR) -p $(@D) - $(SED) -e 's/$$(JDK_VERSION)/$(JDK_VERSION)/' \ - -e 's/$$(FULL_VERSION)/$(FULL_VERSION)/' \ - -e 's/$$(RELEASE)/$(RELEASE)/' \ - < $< > $@ - -$(BUILDTOOLCLASSES_DIR)/%.class : $(BUILDTOOLSRC_DIR)/%.java - $(MKDIR) -p $(@D) - $(BOOT_JAVAC) -d $(@D) $< - -#----- all classes - -$(DIST_DIR)/%/classes.jar: $(JAVAC_JAR) $(JAVADOC_JAR) $(JAVAH_JAR) $(JAVAP_JAR) - $(MKDIR) -p $(@D) - $(BOOTJAR) -cf $@ -C $(CLASSES_DIR) . - -#----- src.zip - -SRC_ZIP_FILES = $(shell $(FIND) $(SRC_CLASSES_DIR) \( -name SCCS -o -name \*-template \) -prune -o -type f -print ) - -$(DIST_DIR)/%/src.zip: $(SRC_ZIP_FILES) - abs_src_zip=`cd $(@D) ; pwd`/$(@F) ; \ - ( cd $(SRC_CLASSES_DIR) ; $(FIND) . \( -name SCCS -o -name \*-template \) -prune -o -type f -print | $(ZIP) -q $$abs_src_zip -@ ) ; \ - ( cd $(SRC_CLASSES_DIR) ; $(FIND) . -name SCCS -prune -o -name \*-template -print | $(SED) -e 's/-template//' ) | ( cd $(GENSRC_DIR) ; $(ZIP) -q $$abs_src_zip -@ ) - -#----- bin files - -$(BIN_DIR)/%: $(SRC_BIN_DIR)/launcher.sh-template - $(MKDIR) -p $(@D) - $(SED) -e 's|#PROGRAM#|$(@F)|' -e 's|#TARGET_JAVA#|$(TARGET_JAVA)|' $< > $@ - $(CHMOD) +x $@ - -#----- - -findbugs: $(BUILD_DIR)/findbugs.txt - -$(BUILD_DIR)/findbugs.txt: $(CLASSES_JAR) - $(MKDIR) -p $(@D) - $(FINDBUGS) -textui -javahome $(BOOT_JAVA_HOME) -high -emacs -outputFile $@ $< - -#----- - -quick-check: $(patsubst %, $(DIST_LIB_DIR)/%.jar, $(TOOLS)) - $(TESTJAVA) -jar $(JAVAC_JAR) -version - - $(TESTJAVA) -jar $(JAVADOC_JAR) -version - $(TESTJAVA) -jar $(JAVAH_JAR) -version - - $(TESTJAVA) -jar $(JAVAP_JAR) -version - -#----- - -.PHONY: \ - all \ - build \ - build-tools \ - clean \ - default \ - findbugs \ - jprt_product_build \ - jprt_debug_build \ - jprt_fastdebug_build \ - tools - diff -r adec2a5d510a -r ec434cfd2752 make/build.xml --- a/make/build.xml Thu May 02 13:35:55 2013 -0700 +++ b/make/build.xml Mon May 06 11:53:44 2013 -0700 @@ -717,6 +717,29 @@ + + + + + + + + + + + + @@ -811,6 +834,31 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -826,6 +874,7 @@ + @@ -868,6 +917,7 @@ + @@ -935,6 +985,32 @@ classpath="${build.toolclasses.dir}/"/> + + + + + + + + + + + + + + + + + - build @@ -144,7 +144,7 @@ - @@ -178,7 +178,7 @@ - @@ -239,10 +239,6 @@ ${root}/make - - - ${root}/src/share/classes - README @@ -250,7 +246,7 @@ - @@ -305,11 +301,11 @@ - + ${root}/src/share/classes ${root}/build/classes - 1.5 + 1.7 diff -r adec2a5d510a -r ec434cfd2752 make/tools/crules/AbstractCodingRulesAnalyzer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/crules/AbstractCodingRulesAnalyzer.java Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package crules; + +import java.text.MessageFormat; +import java.util.Locale; +import java.util.ResourceBundle; + +import javax.lang.model.element.TypeElement; +import javax.tools.JavaFileObject; + +import com.sun.source.tree.Tree; +import com.sun.source.util.JavacTask; +import com.sun.source.util.Plugin; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.BasicJavacTask; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Log; + +import static com.sun.source.util.TaskEvent.Kind; + +public abstract class AbstractCodingRulesAnalyzer implements Plugin { + + protected Log log; + protected Trees trees; + protected TreeScanner treeVisitor; + protected Kind eventKind; + protected Messages messages; + + public void init(JavacTask task, String... args) { + BasicJavacTask impl = (BasicJavacTask)task; + Context context = impl.getContext(); + log = Log.instance(context); + trees = Trees.instance(task); + messages = new Messages(); + task.addTaskListener(new PostAnalyzeTaskListener()); + } + + public class PostAnalyzeTaskListener implements TaskListener { + + @Override + public void started(TaskEvent taskEvent) {} + + @Override + public void finished(TaskEvent taskEvent) { + if (taskEvent.getKind().equals(eventKind)) { + TypeElement typeElem = taskEvent.getTypeElement(); + Tree tree = trees.getTree(typeElem); + if (tree != null) { + JavaFileObject prevSource = log.currentSourceFile(); + try { + log.useSource(taskEvent.getCompilationUnit().getSourceFile()); + treeVisitor.scan((JCTree)tree); + } finally { + log.useSource(prevSource); + } + } + } + } + } + + class Messages { + ResourceBundle bundle; + + Messages() { + String name = getClass().getPackage().getName() + ".resources.crules"; + bundle = ResourceBundle.getBundle(name, Locale.ENGLISH); + } + + public void error(JCTree tree, String code, Object... args) { + String msg = (code == null) ? (String) args[0] : localize(code, args); + log.error(tree, "proc.messager", msg.toString()); + } + + private String localize(String code, Object... args) { + String msg = bundle.getString(code); + if (msg == null) { + StringBuilder sb = new StringBuilder(); + sb.append("message file broken: code=").append(code); + if (args.length > 0) { + sb.append(" arguments={0}"); + for (int i = 1; i < args.length; i++) { + sb.append(", {").append(i).append("}"); + } + } + msg = sb.toString(); + } + return MessageFormat.format(msg, args); + } + } + +} diff -r adec2a5d510a -r ec434cfd2752 make/tools/crules/MutableFieldsAnalyzer.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/crules/MutableFieldsAnalyzer.java Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package crules; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.sun.tools.javac.code.Kinds; +import com.sun.tools.javac.tree.TreeScanner; + +import static com.sun.source.util.TaskEvent.Kind; +import static com.sun.tools.javac.code.Flags.*; +import static com.sun.tools.javac.tree.JCTree.JCVariableDecl; + +public class MutableFieldsAnalyzer extends AbstractCodingRulesAnalyzer { + + public MutableFieldsAnalyzer() { + treeVisitor = new MutableFieldsVisitor(); + eventKind = Kind.ANALYZE; + } + + public String getName() { + return "mutable_fields_analyzer"; + } + + private boolean ignoreField(String className, String field) { + List currentFieldsToIgnore = + classFieldsToIgnoreMap.get(className); + if (currentFieldsToIgnore != null) { + for (String fieldToIgnore : currentFieldsToIgnore) { + if (field.equals(fieldToIgnore)) { + return true; + } + } + } + return false; + } + + class MutableFieldsVisitor extends TreeScanner { + + @Override + public void visitVarDef(JCVariableDecl tree) { + boolean isJavacPack = tree.sym.outermostClass().fullname.toString() + .contains(packageToCheck); + if (isJavacPack && + (tree.sym.flags() & SYNTHETIC) == 0 && + tree.sym.owner.kind == Kinds.TYP) { + if (!ignoreField(tree.sym.owner.flatName().toString(), + tree.getName().toString())) { + boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0; + boolean nonFinalStaticEnumField = + (tree.sym.flags() & (ENUM | FINAL)) == 0; + boolean nonFinalStaticField = + (tree.sym.flags() & STATIC) != 0 && + (tree.sym.flags() & FINAL) == 0; + if (enumClass ? nonFinalStaticEnumField : nonFinalStaticField) { + messages.error(tree, "crules.err.var.must.be.final", tree); + } + } + } + super.visitVarDef(tree); + } + + } + + private static final String packageToCheck = "com.sun.tools.javac"; + + private static final Map> classFieldsToIgnoreMap = + new HashMap>(); + + static { + classFieldsToIgnoreMap. + put("com.sun.tools.javac.util.JCDiagnostic", + Arrays.asList("fragmentFormatter")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.util.JavacMessages", + Arrays.asList("defaultBundle", "defaultMessages")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.file.ZipFileIndexCache", + Arrays.asList("sharedInstance")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.main.JavaCompiler", + Arrays.asList("versionRB")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.code.Type", + Arrays.asList("moreInfo")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.util.SharedNameTable", + Arrays.asList("freelist")); + classFieldsToIgnoreMap. + put("com.sun.tools.javac.util.Log", + Arrays.asList("useRawMessages")); + } + +} diff -r adec2a5d510a -r ec434cfd2752 make/tools/crules/resources/crules.properties --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/tools/crules/resources/crules.properties Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,28 @@ +# +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# 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. +# + +# 0: symbol +crules.err.var.must.be.final=\ + Static variable {0} must be final diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/source/util/DocSourcePositions.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/source/util/DocSourcePositions.java Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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.util; + +import com.sun.source.doctree.DocCommentTree; +import com.sun.source.doctree.DocTree; +import com.sun.source.tree.CompilationUnitTree; + +/** + * Provides methods to obtain the position of a DocTree within a javadoc comment. + * A position is defined as a simple character offset from the start of a + * CompilationUnit where the first character is at offset 0. + * + * @since 1.8 + */ +@jdk.Supported +public interface DocSourcePositions extends SourcePositions { + + /** + * Gets the starting position of the tree within the comment within the file. If tree is not found within + * file, or if the starting position is not available, + * return {@link javax.tools.Diagnostic#NOPOS}. + * The given tree should be under the given comment tree, and the given documentation + * comment tree should be returned from a {@link DocTrees#getDocCommentTree(com.sun.source.util.TreePath) } + * for a tree under the given file. + * The returned position must be at the start of the yield of this tree, that + * is for any sub-tree of this tree, the following must hold: + * + *

+ * {@code tree.getStartPosition() <= subtree.getStartPosition()} or
+ * {@code tree.getStartPosition() == NOPOS} or
+ * {@code subtree.getStartPosition() == NOPOS} + *

+ * + * @param file CompilationUnit in which to find tree. + * @param comment the comment tree that encloses the tree for which the + * position is being sought + * @param tree tree for which a position is sought. + * @return the start position of tree. + */ + long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree); + + /** + * Gets the ending position of the tree within the comment within the file. If tree is not found within + * file, or if the ending position is not available, + * return {@link javax.tools.Diagnostic#NOPOS}. + * The given tree should be under the given comment tree, and the given documentation + * comment tree should be returned from a {@link DocTrees#getDocCommentTree(com.sun.source.util.TreePath) } + * for a tree under the given file. + * The returned position must be at the end of the yield of this tree, + * that is for any sub-tree of this tree, the following must hold: + * + *

+ * {@code tree.getEndPosition() >= subtree.getEndPosition()} or
+ * {@code tree.getEndPosition() == NOPOS} or
+ * {@code subtree.getEndPosition() == NOPOS} + *

+ * + * In addition, the following must hold: + * + *

+ * {@code tree.getStartPosition() <= tree.getEndPosition()} or
+ * {@code tree.getStartPosition() == NOPOS} or
+ * {@code tree.getEndPosition() == NOPOS} + *

+ * + * @param file CompilationUnit in which to find tree. + * @param comment the comment tree that encloses the tree for which the + * position is being sought + * @param tree tree for which a position is sought. + * @return the start position of tree. + */ + long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree); + +} diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/source/util/DocTrees.java --- a/src/share/classes/com/sun/source/util/DocTrees.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/source/util/DocTrees.java Mon May 06 11:53:44 2013 -0700 @@ -72,6 +72,8 @@ */ public abstract Element getElement(TreePath path, ReferenceTree reference); + public abstract DocSourcePositions getSourcePositions(); + /** * Prints a message of the specified kind at the location of the * tree within the provided compilation unit diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/source/util/SourcePositions.java --- a/src/share/classes/com/sun/source/util/SourcePositions.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/source/util/SourcePositions.java Mon May 06 11:53:44 2013 -0700 @@ -59,7 +59,7 @@ /** * Gets the ending position of tree within file. If tree is not found within - * file, or if the starting position is not available, + * file, or if the ending position is not available, * return {@link javax.tools.Diagnostic#NOPOS}. * The returned position must be at the end of the yield of this tree, * that is for any sub-tree of this tree, the following must hold: diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/classfile/Dependencies.java --- a/src/share/classes/com/sun/tools/classfile/Dependencies.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/classfile/Dependencies.java Mon May 06 11:53:44 2013 -0700 @@ -315,7 +315,7 @@ static class SimpleLocation implements Location { public SimpleLocation(String name) { this.name = name; - this.className = name.replace('/', '.').replace('$', '.'); + this.className = name.replace('/', '.'); } public String getName() { diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/classfile/ReferenceFinder.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/share/classes/com/sun/tools/classfile/ReferenceFinder.java Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import com.sun.tools.classfile.Instruction.TypeKind; +import static com.sun.tools.classfile.ConstantPool.*; + +/** + * A utility class to find where in a ClassFile references + * a {@link CONSTANT_Methodref_info method}, + * a {@link CONSTANT_InterfaceMethodref_info interface method, + * or a {@link CONSTANT_Fieldref_info field}. + */ +public final class ReferenceFinder { + /** + * Filter for ReferenceFinder of what constant pool entries for reference lookup. + */ + public interface Filter { + /** + * Decides if the given CPRefInfo entry should be accepted or filtered. + * + * @param cpool ConstantPool of the ClassFile being parsed + * @param cpref constant pool entry representing a reference to + * a fields method, and interface method. + * @return {@code true} if accepted; otherwise {@code false} + */ + boolean accept(ConstantPool cpool, CPRefInfo cpref); + } + + /** + * Visitor of individual method of a ClassFile that references the + * accepted field, method, or interface method references. + */ + public interface Visitor { + /** + * Invoked for a method containing one or more accepted CPRefInfo entries + * + * @param cf ClassFile + * @param method Method that does the references the accepted references + * @param refs Accepted constant pool method/field reference + */ + void visit(ClassFile cf, Method method, List refConstantPool); + } + + private final Filter filter; + private final Visitor visitor; + + /** + * Constructor. + */ + public ReferenceFinder(Filter filter, Visitor visitor) { + this.filter = Objects.requireNonNull(filter); + this.visitor = Objects.requireNonNull(visitor); + } + + /** + * Parses a given ClassFile and invoke the visitor if there is any reference + * to the constant pool entries referencing field, method, or + * interface method that are accepted. This method will return + * {@code true} if there is one or more accepted constant pool entries + * to lookup; otherwise, it will return {@code false}. + * + * @param cf ClassFile + * @return {@code true} if the given class file is processed to lookup + * references + * @throws ConstantPoolException if an error of the constant pool + */ + public boolean parse(ClassFile cf) throws ConstantPoolException { + List cprefs = new ArrayList(); + int index = 1; + for (ConstantPool.CPInfo cpInfo : cf.constant_pool.entries()) { + if (cpInfo.accept(cpVisitor, cf.constant_pool)) { + cprefs.add(index); + } + index += cpInfo.size(); + } + + if (cprefs.isEmpty()) { + return false; + } + + for (Method m : cf.methods) { + Set ids = new HashSet(); + Code_attribute c_attr = (Code_attribute) m.attributes.get(Attribute.Code); + if (c_attr != null) { + for (Instruction instr : c_attr.getInstructions()) { + int idx = instr.accept(codeVisitor, cprefs); + if (idx > 0) { + ids.add(idx); + } + } + } + if (ids.size() > 0) { + List refInfos = new ArrayList(ids.size()); + for (int id : ids) { + refInfos.add(CPRefInfo.class.cast(cf.constant_pool.get(id))); + } + visitor.visit(cf, m, refInfos); + } + } + return true; + } + + private ConstantPool.Visitor cpVisitor = + new ConstantPool.Visitor() + { + public Boolean visitClass(CONSTANT_Class_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info info, ConstantPool cpool) { + return filter.accept(cpool, info); + } + + public Boolean visitMethodref(CONSTANT_Methodref_info info, ConstantPool cpool) { + return filter.accept(cpool, info); + } + + public Boolean visitFieldref(CONSTANT_Fieldref_info info, ConstantPool cpool) { + return filter.accept(cpool, info); + } + + public Boolean visitDouble(CONSTANT_Double_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitFloat(CONSTANT_Float_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitInteger(CONSTANT_Integer_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitInvokeDynamic(CONSTANT_InvokeDynamic_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitLong(CONSTANT_Long_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitNameAndType(CONSTANT_NameAndType_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitMethodHandle(CONSTANT_MethodHandle_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitMethodType(CONSTANT_MethodType_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitString(CONSTANT_String_info info, ConstantPool cpool) { + return false; + } + + public Boolean visitUtf8(CONSTANT_Utf8_info info, ConstantPool cpool) { + return false; + } + }; + + private Instruction.KindVisitor> codeVisitor = + new Instruction.KindVisitor>() + { + public Integer visitNoOperands(Instruction instr, List p) { + return 0; + } + + public Integer visitArrayType(Instruction instr, TypeKind kind, List p) { + return 0; + } + + public Integer visitBranch(Instruction instr, int offset, List p) { + return 0; + } + + public Integer visitConstantPoolRef(Instruction instr, int index, List p) { + return p.contains(index) ? index : 0; + } + + public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List p) { + return p.contains(index) ? index : 0; + } + + public Integer visitLocal(Instruction instr, int index, List p) { + return 0; + } + + public Integer visitLocalAndValue(Instruction instr, int index, int value, List p) { + return 0; + } + + public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List p) { + return 0; + } + + public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List p) { + return 0; + } + + public Integer visitValue(Instruction instr, int value, List p) { + return 0; + } + + public Integer visitUnknown(Instruction instr, List p) { + return 0; + } + }; +} + diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/api/JavacTrees.java --- a/src/share/classes/com/sun/tools/javac/api/JavacTrees.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/api/JavacTrees.java Mon May 06 11:53:44 2013 -0700 @@ -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 @@ -43,14 +43,16 @@ import javax.tools.JavaFileObject; import com.sun.source.doctree.DocCommentTree; +import com.sun.source.doctree.DocTree; import com.sun.source.doctree.ReferenceTree; import com.sun.source.tree.CatchTree; import com.sun.source.tree.CompilationUnitTree; import com.sun.source.tree.Scope; import com.sun.source.tree.Tree; +import com.sun.source.util.DocSourcePositions; +import com.sun.source.util.DocTreeScanner; import com.sun.source.util.DocTrees; import com.sun.source.util.JavacTask; -import com.sun.source.util.SourcePositions; import com.sun.source.util.TreePath; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Kinds; @@ -76,8 +78,14 @@ import com.sun.tools.javac.model.JavacElements; import com.sun.tools.javac.processing.JavacProcessingEnvironment; import com.sun.tools.javac.tree.DCTree; +import com.sun.tools.javac.tree.DCTree.DCBlockTag; import com.sun.tools.javac.tree.DCTree.DCDocComment; +import com.sun.tools.javac.tree.DCTree.DCEndPosTree; +import com.sun.tools.javac.tree.DCTree.DCErroneous; +import com.sun.tools.javac.tree.DCTree.DCIdentifier; +import com.sun.tools.javac.tree.DCTree.DCParam; import com.sun.tools.javac.tree.DCTree.DCReference; +import com.sun.tools.javac.tree.DCTree.DCText; import com.sun.tools.javac.tree.EndPosTable; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.*; @@ -94,6 +102,7 @@ import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Pair; +import com.sun.tools.javac.util.Position; import static com.sun.tools.javac.code.TypeTag.*; /** @@ -166,8 +175,8 @@ javacTaskImpl = (JavacTaskImpl) t; } - public SourcePositions getSourcePositions() { - return new SourcePositions() { + public DocSourcePositions getSourcePositions() { + return new DocSourcePositions() { public long getStartPosition(CompilationUnitTree file, Tree tree) { return TreeInfo.getStartPos((JCTree) tree); } @@ -176,9 +185,80 @@ EndPosTable endPosTable = ((JCCompilationUnit) file).endPositions; return TreeInfo.getEndPos((JCTree) tree, endPosTable); } + + public long getStartPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { + return ((DCTree) tree).getSourcePosition((DCDocComment) comment); + } + @SuppressWarnings("fallthrough") + public long getEndPosition(CompilationUnitTree file, DocCommentTree comment, DocTree tree) { + DCDocComment dcComment = (DCDocComment) comment; + if (tree instanceof DCEndPosTree) { + int endPos = ((DCEndPosTree) tree).getEndPos(dcComment); + + if (endPos != Position.NOPOS) { + return endPos; + } + } + int correction = 0; + switch (tree.getKind()) { + case TEXT: + DCText text = (DCText) tree; + + return dcComment.comment.getSourcePos(text.pos + text.text.length()); + case ERRONEOUS: + DCErroneous err = (DCErroneous) tree; + + return dcComment.comment.getSourcePos(err.pos + err.body.length()); + case IDENTIFIER: + DCIdentifier ident = (DCIdentifier) tree; + + return dcComment.comment.getSourcePos(ident.pos + (ident.name != names.error ? ident.name.length() : 0)); + case PARAM: + DCParam param = (DCParam) tree; + + if (param.isTypeParameter && param.getDescription().isEmpty()) { + correction = 1; + } + case AUTHOR: case DEPRECATED: case RETURN: case SEE: + case SERIAL: case SERIAL_DATA: case SERIAL_FIELD: case SINCE: + case THROWS: case UNKNOWN_BLOCK_TAG: case VERSION: { + DocTree last = getLastChild(tree); + + if (last != null) { + return getEndPosition(file, comment, last) + correction; + } + + DCBlockTag block = (DCBlockTag) tree; + + return dcComment.comment.getSourcePos(block.pos + block.getTagName().length() + 1); + } + default: + DocTree last = getLastChild(tree); + + if (last != null) { + return getEndPosition(file, comment, last); + } + break; + } + + return Position.NOPOS; + } }; } + private DocTree getLastChild(DocTree tree) { + final DocTree[] last = new DocTree[] {null}; + + tree.accept(new DocTreeScanner() { + @Override public Void scan(DocTree node, Void p) { + if (node != null) last[0] = node; + return null; + } + }, null); + + return last[0]; + } + public JCClassDecl getTree(TypeElement element) { return (JCClassDecl) getTree((Element) element); } diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/code/Symbol.java --- a/src/share/classes/com/sun/tools/javac/code/Symbol.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/Symbol.java Mon May 06 11:53:44 2013 -0700 @@ -465,19 +465,12 @@ * This is the implementation for {@code * javax.lang.model.element.Element.getAnnotationMirrors()}. */ - public final List getAnnotationMirrors() { + @Override + public List getAnnotationMirrors() { return getRawAttributes(); } /** - * TODO: Should there be a {@code - * javax.lang.model.element.Element.getTypeAnnotationMirrors()}. - */ - public final List getTypeAnnotationMirrors() { - return getRawTypeAttributes(); - } - - /** * @deprecated this method should never be used by javac internally. */ @Deprecated @@ -657,6 +650,24 @@ } @Override + public List getAnnotationMirrors() { + return onlyTypeVariableAnnotations(owner.getRawTypeAttributes()); + } + + private List onlyTypeVariableAnnotations( + List candidates) { + // Declaration annotations on TypeParameters are stored in type attributes + List res = List.nil(); + for (Attribute.TypeCompound a : candidates) { + if (a.position.type == TargetType.CLASS_TYPE_PARAMETER || + a.position.type == TargetType.METHOD_TYPE_PARAMETER) + res = res.prepend(a); + } + + return res = res.reverse(); + } + + @Override public R accept(ElementVisitor v, P p) { return v.visitTypeParameter(this, p); } diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java --- a/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java Mon May 06 11:53:44 2013 -0700 @@ -206,7 +206,7 @@ sym.getKind() == ElementKind.EXCEPTION_PARAMETER) { // Make sure all type annotations from the symbol are also // on the owner. - sym.owner.annotations.appendUniqueTypes(sym.getTypeAnnotationMirrors()); + sym.owner.annotations.appendUniqueTypes(sym.getRawTypeAttributes()); } } diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/comp/Check.java --- a/src/share/classes/com/sun/tools/javac/comp/Check.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Check.java Mon May 06 11:53:44 2013 -0700 @@ -1078,7 +1078,8 @@ mask = MethodFlags; } // Imply STRICTFP if owner has STRICTFP set. - if (((flags|implicit) & Flags.ABSTRACT) == 0) + if (((flags|implicit) & Flags.ABSTRACT) == 0 || + ((flags) & Flags.DEFAULT) != 0) implicit |= sym.owner.flags_field & STRICTFP; break; case TYP: diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/comp/Flow.java --- a/src/share/classes/com/sun/tools/javac/comp/Flow.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/comp/Flow.java Mon May 06 11:53:44 2013 -0700 @@ -35,7 +35,6 @@ 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.*; @@ -277,6 +276,15 @@ } /** + * Utility method to reset several Bits instances. + */ + private void resetBits(Bits... bits) { + for (Bits b : bits) { + b.reset(); + } + } + + /** * Base visitor class for all visitors implementing dataflow analysis logic. * This class define the shared logic for handling jumps (break/continue statements). */ @@ -1294,11 +1302,11 @@ /** The set of definitely assigned variables. */ - Bits inits; + final Bits inits; /** The set of definitely unassigned variables. */ - Bits uninits; + final Bits uninits; /** The set of variables that are definitely unassigned everywhere * in current try block. This variable is maintained lazily; it is @@ -1308,15 +1316,15 @@ * anywhere in current try block, intersect uninitsTry and * uninits. */ - Bits uninitsTry; + final Bits uninitsTry; /** When analyzing a condition, inits and uninits are null. * Instead we have: */ - Bits initsWhenTrue; - Bits initsWhenFalse; - Bits uninitsWhenTrue; - Bits uninitsWhenFalse; + final Bits initsWhenTrue; + final Bits initsWhenFalse; + final Bits uninitsWhenTrue; + final Bits uninitsWhenFalse; /** A mapping from addresses to variable symbols. */ @@ -1348,15 +1356,25 @@ /** The starting position of the analysed tree */ int startPos; + AssignAnalyzer() { + inits = new Bits(); + uninits = new Bits(); + uninitsTry = new Bits(); + initsWhenTrue = new Bits(true); + initsWhenFalse = new Bits(true); + uninitsWhenTrue = new Bits(true); + uninitsWhenFalse = new Bits(true); + } + class AssignPendingExit extends BaseAnalyzer.PendingExit { - Bits exit_inits; - Bits exit_uninits; + final Bits exit_inits = new Bits(true); + final Bits exit_uninits = new Bits(true); - AssignPendingExit(JCTree tree, Bits inits, Bits uninits) { + AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { super(tree); - this.exit_inits = inits.dup(); - this.exit_uninits = uninits.dup(); + this.exit_inits.assign(inits); + this.exit_uninits.assign(uninits); } void resolveJump() { @@ -1476,19 +1494,20 @@ /** Split (duplicate) inits/uninits into WhenTrue/WhenFalse sets */ void split(boolean setToNull) { - initsWhenFalse = inits.dup(); - uninitsWhenFalse = uninits.dup(); - initsWhenTrue = inits; - uninitsWhenTrue = uninits; - if (setToNull) - inits = uninits = null; + initsWhenFalse.assign(inits); + uninitsWhenFalse.assign(uninits); + initsWhenTrue.assign(inits); + uninitsWhenTrue.assign(uninits); + if (setToNull) { + resetBits(inits, uninits); + } } /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. */ void merge() { - inits = initsWhenFalse.andSet(initsWhenTrue); - uninits = uninitsWhenFalse.andSet(uninitsWhenTrue); + inits.assign(initsWhenFalse.andSet(initsWhenTrue)); + uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue)); } /* ************************************************************************ @@ -1501,7 +1520,7 @@ void scanExpr(JCTree tree) { if (tree != null) { scan(tree); - if (inits == null) merge(); + if (inits.isReset()) merge(); } } @@ -1518,28 +1537,29 @@ */ void scanCond(JCTree tree) { if (tree.type.isFalse()) { - if (inits == null) merge(); - initsWhenTrue = inits.dup(); + if (inits.isReset()) merge(); + initsWhenTrue.assign(inits); initsWhenTrue.inclRange(firstadr, nextadr); - uninitsWhenTrue = uninits.dup(); + uninitsWhenTrue.assign(uninits); uninitsWhenTrue.inclRange(firstadr, nextadr); - initsWhenFalse = inits; - uninitsWhenFalse = uninits; + initsWhenFalse.assign(inits); + uninitsWhenFalse.assign(uninits); } else if (tree.type.isTrue()) { - if (inits == null) merge(); - initsWhenFalse = inits.dup(); + if (inits.isReset()) merge(); + initsWhenFalse.assign(inits); initsWhenFalse.inclRange(firstadr, nextadr); - uninitsWhenFalse = uninits.dup(); + uninitsWhenFalse.assign(uninits); uninitsWhenFalse.inclRange(firstadr, nextadr); - initsWhenTrue = inits; - uninitsWhenTrue = uninits; + initsWhenTrue.assign(inits); + uninitsWhenTrue.assign(uninits); } else { scan(tree); - if (inits != null) + if (!inits.isReset()) split(tree.type != syms.unknownType); } - if (tree.type != syms.unknownType) - inits = uninits = null; + if (tree.type != syms.unknownType) { + resetBits(inits, uninits); + } } /* ------------ Visitor methods for various sorts of trees -------------*/ @@ -1619,8 +1639,8 @@ public void visitMethodDef(JCMethodDecl tree) { if (tree.body == null) return; - Bits initsPrev = inits.dup(); - Bits uninitsPrev = uninits.dup(); + final Bits initsPrev = new Bits(inits); + final Bits uninitsPrev = new Bits(uninits); int nextadrPrev = nextadr; int firstadrPrev = firstadr; int returnadrPrev = returnadr; @@ -1658,14 +1678,14 @@ exits = exits.tail; Assert.check(exit.tree.hasTag(RETURN), exit.tree); if (isInitialConstructor) { - inits = exit.exit_inits; + inits.assign(exit.exit_inits); for (int i = firstadr; i < nextadr; i++) checkInit(exit.tree.pos(), vars[i]); } } } finally { - inits = initsPrev; - uninits = uninitsPrev; + inits.assign(initsPrev); + uninits.assign(uninitsPrev); nextadr = nextadrPrev; firstadr = firstadrPrev; returnadr = returnadrPrev; @@ -1698,31 +1718,31 @@ ListBuffer prevPendingExits = pendingExits; FlowKind prevFlowKind = flowKind; flowKind = FlowKind.NORMAL; - Bits initsSkip = null; - Bits uninitsSkip = null; + final Bits initsSkip = new Bits(true); + final Bits uninitsSkip = new Bits(true); pendingExits = new ListBuffer(); int prevErrors = log.nerrors; do { - Bits uninitsEntry = uninits.dup(); + final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); scan(tree.body); resolveContinues(tree); scanCond(tree.cond); if (!flowKind.isFinal()) { - initsSkip = initsWhenFalse; - uninitsSkip = uninitsWhenFalse; + initsSkip.assign(initsWhenFalse); + uninitsSkip.assign(uninitsWhenFalse); } if (log.nerrors != prevErrors || flowKind.isFinal() || - uninitsEntry.dup().diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) + new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) break; - inits = initsWhenTrue; - uninits = uninitsEntry.andSet(uninitsWhenTrue); + inits.assign(initsWhenTrue); + uninits.assign(uninitsEntry.andSet(uninitsWhenTrue)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; - inits = initsSkip; - uninits = uninitsSkip; + inits.assign(initsSkip); + uninits.assign(uninitsSkip); resolveBreaks(tree, prevPendingExits); } @@ -1730,34 +1750,34 @@ ListBuffer prevPendingExits = pendingExits; FlowKind prevFlowKind = flowKind; flowKind = FlowKind.NORMAL; - Bits initsSkip = null; - Bits uninitsSkip = null; + final Bits initsSkip = new Bits(true); + final Bits uninitsSkip = new Bits(true); pendingExits = new ListBuffer(); int prevErrors = log.nerrors; - Bits uninitsEntry = uninits.dup(); + final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); do { scanCond(tree.cond); if (!flowKind.isFinal()) { - initsSkip = initsWhenFalse; - uninitsSkip = uninitsWhenFalse; + initsSkip.assign(initsWhenFalse) ; + uninitsSkip.assign(uninitsWhenFalse); } - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); scan(tree.body); resolveContinues(tree); if (log.nerrors != prevErrors || flowKind.isFinal() || - uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) + new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) break; - uninits = uninitsEntry.andSet(uninits); + uninits.assign(uninitsEntry.andSet(uninits)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; //a variable is DA/DU after the while statement, if it's DA/DU assuming the //branch is not taken AND if it's DA/DU before any break statement - inits = initsSkip; - uninits = uninitsSkip; + inits.assign(initsSkip); + uninits.assign(uninitsSkip); resolveBreaks(tree, prevPendingExits); } @@ -1767,25 +1787,25 @@ flowKind = FlowKind.NORMAL; int nextadrPrev = nextadr; scan(tree.init); - Bits initsSkip = null; - Bits uninitsSkip = null; + final Bits initsSkip = new Bits(true); + final Bits uninitsSkip = new Bits(true); pendingExits = new ListBuffer(); int prevErrors = log.nerrors; do { - Bits uninitsEntry = uninits.dup(); + final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); if (tree.cond != null) { scanCond(tree.cond); if (!flowKind.isFinal()) { - initsSkip = initsWhenFalse; - uninitsSkip = uninitsWhenFalse; + initsSkip.assign(initsWhenFalse); + uninitsSkip.assign(uninitsWhenFalse); } - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); } else if (!flowKind.isFinal()) { - initsSkip = inits.dup(); + initsSkip.assign(inits); initsSkip.inclRange(firstadr, nextadr); - uninitsSkip = uninits.dup(); + uninitsSkip.assign(uninits); uninitsSkip.inclRange(firstadr, nextadr); } scan(tree.body); @@ -1793,16 +1813,16 @@ scan(tree.step); if (log.nerrors != prevErrors || flowKind.isFinal() || - uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) + new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) break; - uninits = uninitsEntry.andSet(uninits); + uninits.assign(uninitsEntry.andSet(uninits)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; //a variable is DA/DU after a for loop, if it's DA/DU assuming the //branch is not taken AND if it's DA/DU before any break statement - inits = initsSkip; - uninits = uninitsSkip; + inits.assign(initsSkip); + uninits.assign(uninitsSkip); resolveBreaks(tree, prevPendingExits); nextadr = nextadrPrev; } @@ -1815,27 +1835,27 @@ flowKind = FlowKind.NORMAL; int nextadrPrev = nextadr; scan(tree.expr); - Bits initsStart = inits.dup(); - Bits uninitsStart = uninits.dup(); + final Bits initsStart = new Bits(inits); + final Bits uninitsStart = new Bits(uninits); letInit(tree.pos(), tree.var.sym); pendingExits = new ListBuffer(); int prevErrors = log.nerrors; do { - Bits uninitsEntry = uninits.dup(); + final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); scan(tree.body); resolveContinues(tree); if (log.nerrors != prevErrors || flowKind.isFinal() || - uninitsEntry.dup().diffSet(uninits).nextBit(firstadr) == -1) + new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) break; - uninits = uninitsEntry.andSet(uninits); + uninits.assign(uninitsEntry.andSet(uninits)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; - inits = initsStart; - uninits = uninitsStart.andSet(uninits); + inits.assign(initsStart); + uninits.assign(uninitsStart.andSet(uninits)); resolveBreaks(tree, prevPendingExits); nextadr = nextadrPrev; } @@ -1852,12 +1872,12 @@ pendingExits = new ListBuffer(); int nextadrPrev = nextadr; scanExpr(tree.selector); - Bits initsSwitch = inits; - Bits uninitsSwitch = uninits.dup(); + final Bits initsSwitch = new Bits(inits); + final Bits uninitsSwitch = new Bits(uninits); boolean hasDefault = false; for (List l = tree.cases; l.nonEmpty(); l = l.tail) { - inits = initsSwitch.dup(); - uninits = uninits.andSet(uninitsSwitch); + inits.assign(initsSwitch); + uninits.assign(uninits.andSet(uninitsSwitch)); JCCase c = l.head; if (c.pat == null) hasDefault = true; @@ -1875,8 +1895,8 @@ } // where /** Add any variables defined in stats to inits and uninits. */ - private void addVars(List stats, Bits inits, - Bits uninits) { + private void addVars(List stats, final Bits inits, + final Bits uninits) { for (;stats.nonEmpty(); stats = stats.tail) { JCTree stat = stats.head; if (stat.hasTag(VARDEF)) { @@ -1889,11 +1909,11 @@ public void visitTry(JCTry tree) { ListBuffer resourceVarDecls = ListBuffer.lb(); - Bits uninitsTryPrev = uninitsTry; + final Bits uninitsTryPrev = new Bits(uninitsTry); ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer(); - Bits initsTry = inits.dup(); - uninitsTry = uninits.dup(); + final Bits initsTry = new Bits(inits); + uninitsTry.assign(uninits); for (JCTree resource : tree.resources) { if (resource instanceof JCVariableDecl) { JCVariableDecl vdecl = (JCVariableDecl) resource; @@ -1908,8 +1928,8 @@ } scan(tree.body); uninitsTry.andSet(uninits); - Bits initsEnd = inits; - Bits uninitsEnd = uninits; + final Bits initsEnd = new Bits(inits); + final Bits uninitsEnd = new Bits(uninits); int nextadrCatch = nextadr; if (!resourceVarDecls.isEmpty() && @@ -1925,8 +1945,8 @@ for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { JCVariableDecl param = l.head.param; - inits = initsTry.dup(); - uninits = uninitsTry.dup(); + inits.assign(initsTry); + uninits.assign(uninitsTry); scan(param); inits.incl(param.sym.adr); uninits.excl(param.sym.adr); @@ -1936,8 +1956,8 @@ nextadr = nextadrCatch; } if (tree.finalizer != null) { - inits = initsTry.dup(); - uninits = uninitsTry.dup(); + inits.assign(initsTry); + uninits.assign(uninitsTry); ListBuffer exits = pendingExits; pendingExits = prevPendingExits; scan(tree.finalizer); @@ -1958,8 +1978,8 @@ inits.orSet(initsEnd); } } else { - inits = initsEnd; - uninits = uninitsEnd; + inits.assign(initsEnd); + uninits.assign(uninitsEnd); ListBuffer exits = pendingExits; pendingExits = prevPendingExits; while (exits.nonEmpty()) pendingExits.append(exits.next()); @@ -1969,10 +1989,10 @@ public void visitConditional(JCConditional tree) { scanCond(tree.cond); - Bits initsBeforeElse = initsWhenFalse; - Bits uninitsBeforeElse = uninitsWhenFalse; - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + final Bits initsBeforeElse = new Bits(initsWhenFalse); + final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); if (tree.truepart.type.hasTag(BOOLEAN) && tree.falsepart.type.hasTag(BOOLEAN)) { // if b and c are boolean valued, then @@ -1980,12 +2000,12 @@ // v is (un)assigned after b when true and // v is (un)assigned after c when true scanCond(tree.truepart); - Bits initsAfterThenWhenTrue = initsWhenTrue.dup(); - Bits initsAfterThenWhenFalse = initsWhenFalse.dup(); - Bits uninitsAfterThenWhenTrue = uninitsWhenTrue.dup(); - Bits uninitsAfterThenWhenFalse = uninitsWhenFalse.dup(); - inits = initsBeforeElse; - uninits = uninitsBeforeElse; + final Bits initsAfterThenWhenTrue = new Bits(initsWhenTrue); + final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse); + final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue); + final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse); + inits.assign(initsBeforeElse); + uninits.assign(uninitsBeforeElse); scanCond(tree.falsepart); initsWhenTrue.andSet(initsAfterThenWhenTrue); initsWhenFalse.andSet(initsAfterThenWhenFalse); @@ -1993,10 +2013,10 @@ uninitsWhenFalse.andSet(uninitsAfterThenWhenFalse); } else { scanExpr(tree.truepart); - Bits initsAfterThen = inits.dup(); - Bits uninitsAfterThen = uninits.dup(); - inits = initsBeforeElse; - uninits = uninitsBeforeElse; + final Bits initsAfterThen = new Bits(inits); + final Bits uninitsAfterThen = new Bits(uninits); + inits.assign(initsBeforeElse); + uninits.assign(uninitsBeforeElse); scanExpr(tree.falsepart); inits.andSet(initsAfterThen); uninits.andSet(uninitsAfterThen); @@ -2005,16 +2025,16 @@ public void visitIf(JCIf tree) { scanCond(tree.cond); - Bits initsBeforeElse = initsWhenFalse; - Bits uninitsBeforeElse = uninitsWhenFalse; - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + final Bits initsBeforeElse = new Bits(initsWhenFalse); + final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); scan(tree.thenpart); if (tree.elsepart != null) { - Bits initsAfterThen = inits.dup(); - Bits uninitsAfterThen = uninits.dup(); - inits = initsBeforeElse; - uninits = uninitsBeforeElse; + final Bits initsAfterThen = new Bits(inits); + final Bits uninitsAfterThen = new Bits(uninits); + inits.assign(initsBeforeElse); + uninits.assign(uninitsBeforeElse); scan(tree.elsepart); inits.andSet(initsAfterThen); uninits.andSet(uninitsAfterThen); @@ -2055,8 +2075,8 @@ @Override public void visitLambda(JCLambda tree) { - Bits prevUninits = uninits; - Bits prevInits = inits; + final Bits prevUninits = new Bits(uninits); + final Bits prevInits = new Bits(inits); int returnadrPrev = returnadr; ListBuffer prevPending = pendingExits; try { @@ -2076,8 +2096,8 @@ } finally { returnadr = returnadrPrev; - uninits = prevUninits; - inits = prevInits; + uninits.assign(prevUninits); + inits.assign(prevInits); pendingExits = prevPending; } } @@ -2088,17 +2108,17 @@ } public void visitAssert(JCAssert tree) { - Bits initsExit = inits.dup(); - Bits uninitsExit = uninits.dup(); + final Bits initsExit = new Bits(inits); + final Bits uninitsExit = new Bits(uninits); scanCond(tree.cond); uninitsExit.andSet(uninitsWhenTrue); if (tree.detail != null) { - inits = initsWhenFalse; - uninits = uninitsWhenFalse; + inits.assign(initsWhenFalse); + uninits.assign(uninitsWhenFalse); scanExpr(tree.detail); } - inits = initsExit; - uninits = uninitsExit; + inits.assign(initsExit); + uninits.assign(uninitsExit); } public void visitAssign(JCAssign tree) { @@ -2120,12 +2140,12 @@ switch (tree.getTag()) { case NOT: scanCond(tree.arg); - Bits t = initsWhenFalse; - initsWhenFalse = initsWhenTrue; - initsWhenTrue = t; - t = uninitsWhenFalse; - uninitsWhenFalse = uninitsWhenTrue; - uninitsWhenTrue = t; + final Bits t = new Bits(initsWhenFalse); + initsWhenFalse.assign(initsWhenTrue); + initsWhenTrue.assign(t); + t.assign(uninitsWhenFalse); + uninitsWhenFalse.assign(uninitsWhenTrue); + uninitsWhenTrue.assign(t); break; case PREINC: case POSTINC: case PREDEC: case POSTDEC: @@ -2141,20 +2161,20 @@ switch (tree.getTag()) { case AND: scanCond(tree.lhs); - Bits initsWhenFalseLeft = initsWhenFalse; - Bits uninitsWhenFalseLeft = uninitsWhenFalse; - inits = initsWhenTrue; - uninits = uninitsWhenTrue; + final Bits initsWhenFalseLeft = new Bits(initsWhenFalse); + final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse); + inits.assign(initsWhenTrue); + uninits.assign(uninitsWhenTrue); scanCond(tree.rhs); initsWhenFalse.andSet(initsWhenFalseLeft); uninitsWhenFalse.andSet(uninitsWhenFalseLeft); break; case OR: scanCond(tree.lhs); - Bits initsWhenTrueLeft = initsWhenTrue; - Bits uninitsWhenTrueLeft = uninitsWhenTrue; - inits = initsWhenFalse; - uninits = uninitsWhenFalse; + final Bits initsWhenTrueLeft = new Bits(initsWhenTrue); + final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue); + inits.assign(initsWhenFalse); + uninits.assign(uninitsWhenFalse); scanCond(tree.rhs); initsWhenTrue.andSet(initsWhenTrueLeft); uninitsWhenTrue.andSet(uninitsWhenTrueLeft); @@ -2200,11 +2220,7 @@ attrEnv = env; Flow.this.make = make; startPos = tree.pos().getStartPosition(); - inits = new Bits(); - uninits = new Bits(); - uninitsTry = new Bits(); - initsWhenTrue = initsWhenFalse = - uninitsWhenTrue = uninitsWhenFalse = null; + if (vars == null) vars = new VarSymbol[32]; else @@ -2219,9 +2235,8 @@ } finally { // note that recursive invocations of this method fail hard startPos = -1; - inits = uninits = uninitsTry = null; - initsWhenTrue = initsWhenFalse = - uninitsWhenTrue = uninitsWhenFalse = null; + resetBits(inits, uninits, uninitsTry, initsWhenTrue, + initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse); if (vars != null) for (int i=0; i attrEnv; /** the analyzer scanner */ - private LambdaAnalyzer analyzer; + private LambdaAnalyzerPreprocessor analyzer; /** map from lambda trees to translation contexts */ private Map> contextMap; @@ -156,7 +155,7 @@ make = TreeMaker.instance(context); types = Types.instance(context); transTypes = TransTypes.instance(context); - analyzer = new LambdaAnalyzer(); + analyzer = new LambdaAnalyzerPreprocessor(); } // @@ -206,7 +205,7 @@ public void visitClassDef(JCClassDecl tree) { if (tree.sym.owner.kind == PCK) { //analyze class - analyzer.analyzeClass(tree); + tree = analyzer.analyzeAndPreprocessClass(tree); } KlassInfo prevKlassInfo = kInfo; try { @@ -531,16 +530,25 @@ /** Make an attributed class instance creation expression. * @param ctype The class type. * @param args The constructor arguments. + * @param cons The constructor symbol */ - JCNewClass makeNewClass(Type ctype, List args) { + JCNewClass makeNewClass(Type ctype, List args, Symbol cons) { JCNewClass tree = make.NewClass(null, null, make.QualIdent(ctype.tsym), args, null); - tree.constructor = rs.resolveConstructor( - null, attrEnv, ctype, TreeInfo.types(args), List.nil()); + tree.constructor = cons; tree.type = ctype; return tree; } + /** Make an attributed class instance creation expression. + * @param ctype The class type. + * @param args The constructor arguments. + */ + JCNewClass makeNewClass(Type ctype, List args) { + return makeNewClass(ctype, args, + rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.nil())); + } + private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym, DiagnosticPosition pos, List staticArgs, MethodType indyType) { String functionalInterfaceClass = classSig(targetType); @@ -1019,8 +1027,9 @@ * This visitor collects information about translation of a lambda expression. * More specifically, it keeps track of the enclosing contexts and captured locals * accessed by the lambda being translated (as well as other useful info). + * It also translates away problems for LambdaToMethod. */ - class LambdaAnalyzer extends TreeScanner { + class LambdaAnalyzerPreprocessor extends TreeTranslator { /** the frame stack - used to reconstruct translation info about enclosing scopes */ private List frameStack; @@ -1047,10 +1056,10 @@ private Map clinits = new HashMap(); - private void analyzeClass(JCClassDecl tree) { + private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) { frameStack = List.nil(); localClassDefs = new HashMap(); - scan(tree); + return translate(tree); } @Override @@ -1154,7 +1163,7 @@ frameStack.head.addLocal(param.sym); } contextMap.put(tree, context); - scan(tree.body); + super.visitLambda(tree); context.complete(); } finally { @@ -1220,12 +1229,47 @@ }; fvc.scan(localCDef); } - } + } + /** + * Method references to local class constructors, may, if the local + * class references local variables, have implicit constructor + * parameters added in Lower; As a result, the invokedynamic bootstrap + * information added in the LambdaToMethod pass will have the wrong + * signature. Hooks between Lower and LambdaToMethod have been added to + * handle normal "new" in this case. This visitor converts potentially + * effected method references into a lambda containing a normal "new" of + * the class. + * + * @param tree + */ @Override public void visitReference(JCMemberReference tree) { - scan(tree.getQualifierExpression()); - contextMap.put(tree, makeReferenceContext(tree)); + if (tree.getMode() == ReferenceMode.NEW + && tree.kind != ReferenceKind.ARRAY_CTOR + && tree.sym.owner.isLocal()) { + MethodSymbol consSym = (MethodSymbol) tree.sym; + List ptypes = ((MethodType) consSym.type).getParameterTypes(); + Type classType = consSym.owner.type; + + // Make new-class call + List params = make.Params(ptypes, owner()); + JCNewClass nc = makeNewClass(classType, make.Idents(params)); + nc.pos = tree.pos; + + // Make lambda holding the new-class call + JCLambda slam = make.Lambda(params, nc); + slam.descriptorType = tree.descriptorType; + slam.targets = tree.targets; + slam.type = tree.type; + slam.pos = tree.pos; + + // Now it is a lambda, process as such + visitLambda(slam); + } else { + super.visitReference(tree); + contextMap.put(tree, makeReferenceContext(tree)); + } } @Override @@ -1240,10 +1284,8 @@ } localContext = localContext.prev; } - scan(tree.selected); - } else { - super.visitSelect(tree); } + super.visitSelect(tree); } @Override diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/jvm/Code.java --- a/src/share/classes/com/sun/tools/javac/jvm/Code.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/jvm/Code.java Mon May 06 11:53:44 2013 -0700 @@ -1647,7 +1647,7 @@ State dup() { try { State state = (State)super.clone(); - state.defined = defined.dup(); + state.defined = new Bits(defined); state.stack = stack.clone(); if (locks != null) state.locks = locks.clone(); if (debugCode) { @@ -1775,7 +1775,7 @@ } State join(State other) { - defined = defined.andSet(other.defined); + defined.andSet(other.defined); Assert.check(stacksize == other.stacksize && nlocks == other.nlocks); for (int i=0; i= 0; adr = diff.nextBit(adr+1)) { diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java --- a/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java Mon May 06 11:53:44 2013 -0700 @@ -33,10 +33,13 @@ import com.sun.tools.javac.code.Kinds; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.code.Symbol.ClassSymbol; +import com.sun.tools.javac.code.Symbol.TypeVariableSymbol; +import com.sun.tools.javac.code.TargetType; import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.AnnotatedType; import com.sun.tools.javac.util.ListBuffer; import static com.sun.tools.javac.code.TypeTag.CLASS; +import com.sun.tools.javac.util.List; /** * Utility methods for operating on annotated constructs. @@ -61,8 +64,12 @@ throw new IllegalArgumentException("Not an annotation type: " + annoType); Attribute.Compound c; - if (annotated.kind == Kinds.TYP && annotated instanceof ClassSymbol) { + if (annotated.kind == Kinds.TYP && + annotated instanceof ClassSymbol) { c = getAttributeOnClass((ClassSymbol)annotated, annoType); + } else if (annotated.kind == Kinds.TYP && + annotated instanceof TypeVariableSymbol) { + c = getAttributeOnTypeVariable((TypeVariableSymbol)annotated, annoType); } else { c = getAttribute(annotated, annoType); } @@ -83,6 +90,24 @@ } // Helper to getAnnotation[s] + private static Attribute.Compound + getAttributeOnTypeVariable(TypeVariableSymbol annotated, Class annoType) { + String name = annoType.getName(); + + // Declaration annotations on type variables are stored in type attributes + // on the owner of the TypeVariableSymbol + List res = List.nil(); + List candidates = annotated.owner.getRawTypeAttributes(); + for (Attribute.TypeCompound anno : candidates) + if (anno.position.type == TargetType.CLASS_TYPE_PARAMETER || + anno.position.type == TargetType.METHOD_TYPE_PARAMETER) + if (name.equals(anno.type.tsym.flatName().toString())) + return anno; + + return null; + } + + // Helper to getAnnotation[s] private static Attribute.Compound getAttributeOnClass(ClassSymbol annotated, Class annoType) { boolean inherited = annoType.isAnnotationPresent(Inherited.class); diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/model/JavacElements.java --- a/src/share/classes/com/sun/tools/javac/model/JavacElements.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/model/JavacElements.java Mon May 06 11:53:44 2013 -0700 @@ -402,9 +402,10 @@ * @param e the element being examined * @return all annotations of the element */ + @Override public List getAllAnnotationMirrors(Element e) { Symbol sym = cast(Symbol.class, e); - List annos = sym.getRawAttributes(); + List annos = sym.getAnnotationMirrors(); while (sym.getKind() == ElementKind.CLASS) { Type sup = ((ClassSymbol) sym).getSuperclass(); if (!sup.hasTag(CLASS) || sup.isErroneous() || @@ -413,7 +414,7 @@ } sym = sup.tsym; List oldAnnos = annos; - List newAnnos = sym.getRawAttributes(); + List newAnnos = sym.getAnnotationMirrors(); for (Attribute.Compound anno : newAnnos) { if (isInherited(anno.type) && !containsAnnoOfType(oldAnnos, anno.type)) { diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java --- a/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/parser/DocCommentParser.java Mon May 06 11:53:44 2013 -0700 @@ -41,6 +41,7 @@ import com.sun.tools.javac.tree.DCTree.DCAttribute; import com.sun.tools.javac.tree.DCTree.DCDocComment; import com.sun.tools.javac.tree.DCTree.DCEndElement; +import com.sun.tools.javac.tree.DCTree.DCEndPosTree; import com.sun.tools.javac.tree.DCTree.DCErroneous; import com.sun.tools.javac.tree.DCTree.DCIdentifier; import com.sun.tools.javac.tree.DCTree.DCReference; @@ -336,12 +337,12 @@ DCTree text = inlineText(); if (text != null) { nextChar(); - return m.at(p).UnknownInlineTag(name, List.of(text)); + return m.at(p).UnknownInlineTag(name, List.of(text)).setEndPos(bp); } } else if (tp.getKind() == TagParser.Kind.INLINE) { - DCTree tree = tp.parse(p); + DCEndPosTree tree = (DCEndPosTree) tp.parse(p); if (tree != null) { - return tree; + return tree.setEndPos(bp); } } else { inlineText(); // skip content @@ -509,7 +510,7 @@ fac.log.popDiagnosticHandler(deferredDiagnosticHandler); } - return m.at(pos).Reference(sig, qualExpr, member, paramTypes); + return m.at(pos).Reference(sig, qualExpr, member, paramTypes).setEndPos(bp); } JCTree parseType(String s) throws ParseException { @@ -741,7 +742,7 @@ } if (ch == '>') { nextChar(); - return m.at(p).StartElement(name, attrs, selfClosing); + return m.at(p).StartElement(name, attrs, selfClosing).setEndPos(bp); } } } else if (ch == '/') { diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/tree/DCTree.java --- a/src/share/classes/com/sun/tools/javac/tree/DCTree.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/tree/DCTree.java Mon May 06 11:53:44 2013 -0700 @@ -36,6 +36,7 @@ import com.sun.tools.javac.util.JCDiagnostic.SimpleDiagnosticPosition; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Name; +import com.sun.tools.javac.util.Position; import java.io.IOException; import java.io.StringWriter; import javax.tools.JavaFileObject; @@ -82,8 +83,24 @@ return s.toString(); } + public static abstract class DCEndPosTree> extends DCTree { + + private int endPos = Position.NOPOS; + + public int getEndPos(DCDocComment dc) { + return dc.comment.getSourcePos(endPos); + } + + @SuppressWarnings("unchecked") + public T setEndPos(int endPos) { + this.endPos = endPos; + return (T) this; + } + + } + public static class DCDocComment extends DCTree implements DocCommentTree { - final Comment comment; // required for the implicit source pos table + public final Comment comment; // required for the implicit source pos table public final List firstSentence; public final List body; @@ -125,7 +142,7 @@ } } - public static abstract class DCInlineTag extends DCTree implements InlineTagTree { + public static abstract class DCInlineTag extends DCEndPosTree implements InlineTagTree { public String getTagName() { return getKind().tagName; } @@ -345,6 +362,7 @@ public int getEndPosition(EndPosTable endPosTable) { return pos + body.length(); } + } public static class DCIdentifier extends DCTree implements IdentifierTree { @@ -478,7 +496,7 @@ } } - public static class DCReference extends DCTree implements ReferenceTree { + public static class DCReference extends DCEndPosTree implements ReferenceTree { public final String signature; // The following are not directly exposed through ReferenceTree @@ -663,7 +681,7 @@ } } - public static class DCStartElement extends DCTree implements StartElementTree { + public static class DCStartElement extends DCEndPosTree implements StartElementTree { public final Name name; public final List attrs; public final boolean selfClosing; diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javac/util/Bits.java --- a/src/share/classes/com/sun/tools/javac/util/Bits.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javac/util/Bits.java Mon May 06 11:53:44 2013 -0700 @@ -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 @@ -27,6 +27,8 @@ import java.util.Arrays; +import static com.sun.tools.javac.util.Bits.BitsOpKind.*; + /** A class for extensible, mutable bit sets. * *

This is NOT part of any supported API. @@ -36,31 +38,114 @@ */ public class Bits { + public enum BitsOpKind { + INIT, + CLEAR, + INCL_BIT, + EXCL_BIT, + ASSIGN, + AND_SET, + OR_SET, + DIFF_SET, + XOR_SET, + INCL_RANGE, + EXCL_RANGE, + } + + // ____________ reset _________ + // / UNKNOWN \ <-------- / UNINIT \ + // \____________/ | \_________/ + // | | | + // |assign | | any + // | ___________ | + // ------> / NORMAL \ <---- + // \___________/ | + // | | + // | | + // ----------- + // any + private enum BitsState { + /* A Bits instance is in UNKNOWN state if it has been explicitly reset. + * It is possible to get to this state from any other by calling the + * reset method. An instance in the UNKNOWN state can pass to the + * NORMAL state after being assigned another Bits instance. + */ + UNKNOWN, + /* A Bits instance is in UNINIT when it is created with the default + * constructor but it isn't explicitly reset. The main objective of this + * internal state is to save some memory. + */ + UNINIT, + /* The normal state is reached after creating a Bits instance from an + * existing one or after applying any operation to an instance on UNINIT + * or NORMAL state. From this state a bits instance can pass to the + * UNKNOWN state by calling the reset method. + */ + NORMAL; + + static BitsState getState(int[] someBits, boolean reset) { + if (reset) { + return UNKNOWN; + } else { + if (someBits != unassignedBits) { + return NORMAL; + } else { + return UNINIT; + } + } + } + + } private final static int wordlen = 32; private final static int wordshift = 5; private final static int wordmask = wordlen - 1; - private int[] bits; + public int[] bits = null; + // This field will store last version of bits after every change. + public int[] oldBits = null; + + public BitsOpKind lastOperation = null; + + private static final int[] unassignedBits = new int[0]; + + private BitsState currentState; /** Construct an initially empty set. */ public Bits() { - this(new int[1]); + this(false); + } + + public Bits(Bits someBits) { + this(someBits.dup().bits, BitsState.getState(someBits.bits, false)); + } + + public Bits(boolean reset) { + this(unassignedBits, BitsState.getState(unassignedBits, reset)); } /** Construct a set consisting initially of given bit vector. */ - public Bits(int[] bits) { + private Bits(int[] bits, BitsState initState) { this.bits = bits; + this.currentState = initState; + switch (initState) { + case UNKNOWN: + reset(); //this will also set current state; + break; + case NORMAL: + Assert.check(bits != unassignedBits); + lastOperation = INIT; + break; + } } - /** Construct a set consisting initially of given range. + /** This method will be called after any operation that causes a change to + * the bits. Subclasses can thus override it in order to extract information + * from the changes produced to the bits by the given operation. */ - public Bits(int start, int limit) { - this(); - inclRange(start, limit); - } + public void changed() {} private void sizeTo(int len) { if (bits.length < len) { @@ -71,57 +156,110 @@ /** This set = {}. */ public void clear() { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = CLEAR; for (int i = 0; i < bits.length; i++) bits[i] = 0; + changed(); + currentState = BitsState.NORMAL; + } + + public void reset() { + bits = null; + oldBits = null; + currentState = BitsState.UNKNOWN; + } + + public boolean isReset() { + return currentState == BitsState.UNKNOWN; + } + + public Bits assign(Bits someBits) { + lastOperation = ASSIGN; + oldBits = bits; + bits = someBits.dup().bits; + changed(); + currentState = BitsState.NORMAL; + return this; } /** Return a copy of this set. */ - public Bits dup() { - int[] newbits = new int[bits.length]; - System.arraycopy(bits, 0, newbits, 0, bits.length); - return new Bits(newbits); + private Bits dup() { + Assert.check(currentState != BitsState.UNKNOWN); + Bits tmp = new Bits(); + if (currentState != BitsState.NORMAL) { + tmp.bits = bits; + } else { + tmp.bits = new int[bits.length]; + System.arraycopy(bits, 0, tmp.bits, 0, bits.length); + } + currentState = BitsState.NORMAL; + return tmp; } /** Include x in this set. */ public void incl(int x) { + Assert.check(currentState != BitsState.UNKNOWN); Assert.check(x >= 0); + oldBits = bits; + lastOperation = INCL_BIT; sizeTo((x >>> wordshift) + 1); bits[x >>> wordshift] = bits[x >>> wordshift] | (1 << (x & wordmask)); + changed(); + currentState = BitsState.NORMAL; } /** Include [start..limit) in this set. */ public void inclRange(int start, int limit) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = INCL_RANGE; sizeTo((limit >>> wordshift) + 1); - for (int x = start; x < limit; x++) + for (int x = start; x < limit; x++) { bits[x >>> wordshift] = bits[x >>> wordshift] | (1 << (x & wordmask)); + } + changed(); + currentState = BitsState.NORMAL; } /** Exclude [start...end] from this set. */ public void excludeFrom(int start) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = EXCL_RANGE; Bits temp = new Bits(); temp.sizeTo(bits.length); temp.inclRange(0, start); - andSet(temp); + internalAndSet(temp); + changed(); + currentState = BitsState.NORMAL; } /** Exclude x from this set. */ public void excl(int x) { + Assert.check(currentState != BitsState.UNKNOWN); Assert.check(x >= 0); + oldBits = bits; + lastOperation = EXCL_BIT; sizeTo((x >>> wordshift) + 1); bits[x >>> wordshift] = bits[x >>> wordshift] & ~(1 << (x & wordmask)); + changed(); + currentState = BitsState.NORMAL; } /** Is x an element of this set? */ public boolean isMember(int x) { + Assert.check(currentState != BitsState.UNKNOWN); return 0 <= x && x < (bits.length << wordshift) && (bits[x >>> wordshift] & (1 << (x & wordmask))) != 0; @@ -130,38 +268,66 @@ /** {@literal this set = this set & xs}. */ public Bits andSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = AND_SET; + internalAndSet(xs); + changed(); + currentState = BitsState.NORMAL; + return this; + } + + private void internalAndSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); sizeTo(xs.bits.length); - for (int i = 0; i < xs.bits.length; i++) + for (int i = 0; i < xs.bits.length; i++) { bits[i] = bits[i] & xs.bits[i]; - return this; + } } /** this set = this set | xs. */ public Bits orSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = OR_SET; sizeTo(xs.bits.length); - for (int i = 0; i < xs.bits.length; i++) + for (int i = 0; i < xs.bits.length; i++) { bits[i] = bits[i] | xs.bits[i]; + } + changed(); + currentState = BitsState.NORMAL; return this; } /** this set = this set \ xs. */ public Bits diffSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = DIFF_SET; for (int i = 0; i < bits.length; i++) { if (i < xs.bits.length) { bits[i] = bits[i] & ~xs.bits[i]; } } + changed(); + currentState = BitsState.NORMAL; return this; } /** this set = this set ^ xs. */ public Bits xorSet(Bits xs) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = bits; + lastOperation = XOR_SET; sizeTo(xs.bits.length); - for (int i = 0; i < xs.bits.length; i++) + for (int i = 0; i < xs.bits.length; i++) { bits[i] = bits[i] ^ xs.bits[i]; + } + changed(); + currentState = BitsState.NORMAL; return this; } @@ -187,6 +353,7 @@ * } */ public int nextBit(int x) { + Assert.check(currentState != BitsState.UNKNOWN); int windex = x >>> wordshift; if (windex >= bits.length) return -1; int word = bits[windex] & ~((1 << (x & wordmask))-1); @@ -202,17 +369,20 @@ /** a string representation of this set. */ public String toString() { - char[] digits = new char[bits.length * wordlen]; - for (int i = 0; i < bits.length * wordlen; i++) - digits[i] = isMember(i) ? '1' : '0'; - return new String(digits); + if (bits.length > 0) { + char[] digits = new char[bits.length * wordlen]; + for (int i = 0; i < bits.length * wordlen; i++) + digits[i] = isMember(i) ? '1' : '0'; + return new String(digits); + } else { + return "[]"; + } } /** Test Bits.nextBit(int). */ public static void main(String[] args) { java.util.Random r = new java.util.Random(); Bits bits = new Bits(); - int dupCount = 0; for (int i=0; i<125; i++) { int k; do { diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java --- a/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java Mon May 06 11:53:44 2013 -0700 @@ -341,9 +341,14 @@ * */ public String name() { - return getClassName(tsym, false); + if (name == null) { + name = getClassName(tsym, false); + } + return name; } + private String name; + /** * Return the qualified class name as a String. *

@@ -354,9 +359,14 @@
      * 
*/ public String qualifiedName() { - return getClassName(tsym, true); + if (qualifiedName == null) { + qualifiedName = getClassName(tsym, true); + } + return qualifiedName; } + private String qualifiedName; + /** * Return unqualified name of type excluding any dimension information. *

@@ -380,9 +390,14 @@ * Return the simple name of this type. */ public String simpleTypeName() { - return tsym.name.toString(); + if (simpleTypeName == null) { + simpleTypeName = tsym.name.toString(); + } + return simpleTypeName; } + private String simpleTypeName; + /** * Return the qualified name and any type parameters. * Each parameter is a type variable with optional bounds. diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java --- a/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javadoc/FieldDocImpl.java Mon May 06 11:53:44 2013 -0700 @@ -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 @@ -252,13 +252,23 @@ } public String name() { - return sym.name.toString(); + if (name == null) { + name = sym.name.toString(); + } + return name; } + private String name; + public String qualifiedName() { - return sym.enclClass().getQualifiedName() + "." + name(); + if (qualifiedName == null) { + qualifiedName = sym.enclClass().getQualifiedName() + "." + name(); + } + return qualifiedName; } + private String qualifiedName; + /** * Return the source position of the entity, or null if * no position is available. diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java --- a/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javadoc/MethodDocImpl.java Mon May 06 11:53:44 2013 -0700 @@ -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 @@ -203,13 +203,23 @@ public String name() { - return sym.name.toString(); + if (name == null) { + name = sym.name.toString(); + } + return name; } + private String name; + public String qualifiedName() { - return sym.enclClass().getQualifiedName() + "." + sym.name; + if (qualifiedName == null) { + qualifiedName = sym.enclClass().getQualifiedName() + "." + sym.name; + } + return qualifiedName; } + private String qualifiedName; + /** * Returns a string representation of this method. Includes the * qualified signature, the qualified method name, and any type diff -r adec2a5d510a -r ec434cfd2752 src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java --- a/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java Thu May 02 13:35:55 2013 -0700 +++ b/src/share/classes/com/sun/tools/javadoc/PackageDocImpl.java Mon May 06 11:53:44 2013 -0700 @@ -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 @@ -334,12 +334,17 @@ * Get package name. */ public String qualifiedName() { - Name fullname = sym.getQualifiedName(); - // Some bogus tests depend on the interned "" being returned. - // See 6457276. - return fullname.isEmpty() ? "" : fullname.toString(); + if (qualifiedName == null) { + Name fullname = sym.getQualifiedName(); + // Some bogus tests depend on the interned "" being returned. + // See 6457276. + qualifiedName = fullname.isEmpty() ? "" : fullname.toString(); + } + return qualifiedName; } + private String qualifiedName; + /** * set doc path for an unzipped directory */ diff -r adec2a5d510a -r ec434cfd2752 test/tools/javac/api/TestJavacTaskScanner.java --- a/test/tools/javac/api/TestJavacTaskScanner.java Thu May 02 13:35:55 2013 -0700 +++ b/test/tools/javac/api/TestJavacTaskScanner.java Mon May 06 11:53:44 2013 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, 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 @@ -93,7 +93,7 @@ System.out.println("#allMembers: " + numAllMembers); check(numTokens, "#Tokens", 1222); - check(numParseTypeElements, "#parseTypeElements", 136); + check(numParseTypeElements, "#parseTypeElements", 158); check(numAllMembers, "#allMembers", 52); } diff -r adec2a5d510a -r ec434cfd2752 test/tools/javac/defaultMethods/CheckACC_STRICTFlagOnDefaultMethodTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/defaultMethods/CheckACC_STRICTFlagOnDefaultMethodTest.java Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/* + * @test + * @bug 8012723 + * @summary strictfp interface misses strictfp modifer on default method + * @run main CheckACC_STRICTFlagOnDefaultMethodTest + */ + +import java.util.ArrayList; +import java.util.List; +import java.io.File; +import java.io.IOException; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.Descriptor; +import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import com.sun.tools.classfile.Method; + +import static com.sun.tools.classfile.AccessFlags.ACC_STRICT; + +public class CheckACC_STRICTFlagOnDefaultMethodTest { + private static final String AssertionErrorMessage = + "All methods should have the ACC_STRICT access flag " + + "please check output"; + private static final String offendingMethodErrorMessage = + "Method %s of class %s doesn't have the ACC_STRICT access flag"; + + private List errors = new ArrayList<>(); + + public static void main(String[] args) + throws IOException, ConstantPoolException, InvalidDescriptor { + new CheckACC_STRICTFlagOnDefaultMethodTest().run(); + } + + private void run() + throws IOException, ConstantPoolException, InvalidDescriptor { + String testClasses = System.getProperty("test.classes"); + check(testClasses, + "CheckACC_STRICTFlagOnDefaultMethodTest$StrictfpInterface.class"); + if (errors.size() > 0) { + for (String error: errors) { + System.err.println(error); + } + throw new AssertionError(AssertionErrorMessage); + } + } + + void check(String dir, String... fileNames) + throws + IOException, + ConstantPoolException, + Descriptor.InvalidDescriptor { + for (String fileName : fileNames) { + ClassFile classFileToCheck = ClassFile.read(new File(dir, fileName)); + + for (Method method : classFileToCheck.methods) { + if ((method.access_flags.flags & ACC_STRICT) == 0) { + errors.add(String.format(offendingMethodErrorMessage, + method.getName(classFileToCheck.constant_pool), + classFileToCheck.getName())); + } + } + } + } + + strictfp interface StrictfpInterface { + default void default_interface_method() {} + static void static_interface_method() {} + } + +} diff -r adec2a5d510a -r ec434cfd2752 test/tools/javac/doctree/positions/TestPosition.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/doctree/positions/TestPosition.java Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8008174 + * @summary proper source positions for doc comments + * @build TestPosition + * @compile/ref=TestPosition.out -processor TestPosition -proc:only TestPositionSource.java + */ + +import com.sun.source.doctree.DocCommentTree; +import com.sun.source.doctree.DocTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.util.DocSourcePositions; +import com.sun.source.util.DocTreeScanner; +import com.sun.source.util.DocTrees; +import com.sun.source.util.TreePath; +import com.sun.source.util.TreePathScanner; +import java.io.IOException; +import java.util.Set; +import javax.annotation.processing.*; +import javax.lang.model.*; +import javax.lang.model.element.*; + +@SupportedAnnotationTypes("*") +public class TestPosition extends AbstractProcessor { + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + TypeElement source = processingEnv.getElementUtils().getTypeElement("TestPositionSource"); + + if (source == null) throw new IllegalStateException(); + + if (!roundEnv.getRootElements().contains(source)) return false; + + final DocTrees trees = DocTrees.instance(processingEnv); + final TreePath testElement = trees.getPath(source); + + if (testElement == null) throw new IllegalStateException(); + + String code; + + try { + code = testElement.getCompilationUnit().getSourceFile().getCharContent(false).toString(); + } catch ( IOException ex) { + throw new IllegalStateException(ex); + } + + new TreePathScanner() { + @Override public Void visitMethod(MethodTree node, Void p) { + final DocCommentTree docCommentTree = trees.getDocCommentTree(getCurrentPath()); + + if (docCommentTree != null) { + System.out.println(node.getName() + ":"); + new DocTreeScanner() { + @Override public Void scan(DocTree node, Void p) { + if (node != null) { + DocSourcePositions sp = (DocSourcePositions) trees.getSourcePositions(); //XXX: the cast??? + int start = (int) sp.getStartPosition(testElement.getCompilationUnit(), docCommentTree, node); + int end = (int) sp.getEndPosition(testElement.getCompilationUnit(), docCommentTree, node); + String snippet = code.substring(start, end).replace(" \n", "!trailing-whitespace!\n"); + + if (snippet.endsWith(" ")) { + snippet = snippet.substring(0, snippet.length() - 1) + "!trailing-whitespace!"; + } + System.out.println(node.getKind().name() + ":" + snippet); + } + return super.scan(node, p); + } + }.scan(docCommentTree, null); + } + + return super.visitMethod(node, p); + } + }.scan(testElement, null); + + return false; + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } +} diff -r adec2a5d510a -r ec434cfd2752 test/tools/javac/doctree/positions/TestPosition.out --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/doctree/positions/TestPosition.out Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,99 @@ +valid: +DOC_COMMENT:First sentence. + * + *

Description with {@link java.io.InputStream link} + * + * @param first description + * @param second description + * @return whatever + * @throws IllegalStateException why? + * @since 1.15 + * @see java.util.List +TEXT:First sentence. +START_ELEMENT:

+TEXT:Description with!trailing-whitespace! +LINK:{@link java.io.InputStream link} +REFERENCE:java.io.InputStream +TEXT:link +PARAM:@param first description +IDENTIFIER:first +TEXT:description +PARAM:@param second description +IDENTIFIER:second +TEXT:description +RETURN:@return whatever +TEXT:whatever +THROWS:@throws IllegalStateException why? +REFERENCE:IllegalStateException +TEXT:why? +SINCE:@since 1.15 +TEXT:1.15 +SEE:@see java.util.List +REFERENCE:java.util.List +erroneous: +DOC_COMMENT:First sentence. + * + *

Description with {@link}, {@link java.util.List}, {@link + * + * @param + * @param second + * @return + * @throws + * @throws IllegalStateException + * @since + * @see +TEXT:First sentence. +START_ELEMENT:

+TEXT:Description with!trailing-whitespace! +LINK:{@link} +TEXT:,!trailing-whitespace! +LINK:{@link java.util.List} +REFERENCE:java.util.List +TEXT:,!trailing-whitespace! +ERRONEOUS:{@link +ERRONEOUS:@param +PARAM:@param second +IDENTIFIER:second +RETURN:@return +ERRONEOUS:@throws +THROWS:@throws IllegalStateException +REFERENCE:IllegalStateException +SINCE:@since +ERRONEOUS:@see +withWhiteSpaces: +DOC_COMMENT:First sentence. + * + *

Description with {@link }, {@link java.util.List#add( int )}, + * {@link java.util.List#add( int ) some text with whitespaces}, {@link + * + * @param first + * @param second some text with trailing whitespace + * @return some return + * @throws java.lang.IllegalStateException + * @throws java.lang.IllegalStateException some text +TEXT:First sentence. +START_ELEMENT:

+TEXT:Description with!trailing-whitespace! +LINK:{@link } +TEXT:,!trailing-whitespace! +LINK:{@link java.util.List#add( int )} +REFERENCE:java.util.List#add( int ) +TEXT:, + *!trailing-whitespace! +LINK:{@link java.util.List#add( int ) some text with whitespaces} +REFERENCE:java.util.List#add( int ) +TEXT:some text with whitespaces +TEXT:,!trailing-whitespace! +ERRONEOUS:{@link +PARAM:@param first +IDENTIFIER:first +PARAM:@param second some text with trailing whitespace +IDENTIFIER:second +TEXT:some text with trailing whitespace +RETURN:@return some return +TEXT:some return +THROWS:@throws java.lang.IllegalStateException +REFERENCE:java.lang.IllegalStateException +THROWS:@throws java.lang.IllegalStateException some text +REFERENCE:java.lang.IllegalStateException +TEXT:some text \ No newline at end of file diff -r adec2a5d510a -r ec434cfd2752 test/tools/javac/doctree/positions/TestPositionSource.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/doctree/positions/TestPositionSource.java Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +public class TestPositionSource { + + /**First sentence. + * + *

Description with {@link java.io.InputStream link} + * + * @param first description + * @param second description + * @return whatever + * @throws IllegalStateException why? + * @since 1.15 + * @see java.util.List + */ + public boolean valid(int first, int second) throws IllegalStateException { + return true; + } + + /**First sentence. + * + *

Description with {@link}, {@link java.util.List}, {@link + * + * @param + * @param second + * @return + * @throws + * @throws IllegalStateException + * @since + * @see + */ + public boolean erroneous(int first, int second) throws IllegalStateException { + return true; + } + + /**First sentence. + * + *

Description with {@link }, {@link java.util.List#add( int )}, + * {@link java.util.List#add( int ) some text with whitespaces}, {@link + * + * @param first + * @param second some text with trailing whitespace + * @return some return + * @throws java.lang.IllegalStateException + * @throws java.lang.IllegalStateException some text + */ + public boolean withWhiteSpaces(int first, int second) throws IllegalStateException { + return true; + } + +} diff -r adec2a5d510a -r ec434cfd2752 test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestNewInnerImplicitArgs.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceTestNewInnerImplicitArgs.java Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * 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. + */ + +/** + * @test + * @bug 8011591 + * @summary BootstrapMethodError when capturing constructor ref to local classes + * @run testng MethodReferenceTestNewInnerImplicitArgs + */ + +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * Test the case that a constructor has implicit parameters added to + * access local variables and that this constructor is used in a + * method reference. + * @author Robert Field + */ + +@Test +public class MethodReferenceTestNewInnerImplicitArgs { + + + static class S { + String b; + S(String s, String s2) { b = s + s2; } + } + + interface I { + S m(); + } + + interface I2 { + S m(int i, int j); + } + + public static void testConstructorReferenceImplicitParameters() { + String title = "Hey"; + String a2 = "!!!"; + class MS extends S { + MS() { + super(title, a2); + } + } + + I result = MS::new; + assertEquals(result.m().b, "Hey!!!"); + + class MS2 extends S { + MS2(int x, int y) { + super(title+x, a2+y); + } + } + + I2 result2 = MS2::new; + assertEquals(result2.m(8, 4).b, "Hey8!!!4"); + } +} diff -r adec2a5d510a -r ec434cfd2752 test/tools/javac/processing/model/element/TestTypeParameterAnnotations.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/tools/javac/processing/model/element/TestTypeParameterAnnotations.java Mon May 06 11:53:44 2013 -0700 @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8011027 + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor TestTypeParameterAnnotations + * @compile -processor TestTypeParameterAnnotations -proc:only TestTypeParameterAnnotations.java + */ + +import java.util.*; +import java.lang.annotation.*; +import javax.annotation.processing.*; +import javax.lang.model.element.*; +import javax.lang.model.util.*; +import javax.tools.*; + +public class TestTypeParameterAnnotations<@Foo @Bar @Baz T> extends JavacTestingAbstractProcessor { + int round = 0; + + public boolean process(Set annotations, RoundEnvironment roundEnv) { + if (++round == 1) { + int found = (new Scanner()).scan(roundEnv.getRootElements(), null); + if (found == expect) { + ; //nop + } else { + error("unexpected number of results: expected " + expect + + ", found " + found); + } + + } + return true; + } + + class Scanner extends JavacTestingAbstractProcessor.ElementScanner { + @Override + public Integer visitExecutable(ExecutableElement e, Void p) { + super.visitExecutable(e, p); + found += check(e, e.getTypeParameters()); + return found; + } + + @Override + public Integer visitType(TypeElement e, Void p) { + super.visitType(e, p); + found += check(e, e.getTypeParameters()); + return found; + } + + int found; + } + + int check(Element e, List typarams) { + if (typarams.isEmpty()) + return 0; + if (typarams.size() != 1) + return 0; + + for (TypeParameterElement tpe: typarams) { + boolean b1 = checkAnnotationMirrors(tpe, tpe.getAnnotationMirrors()); + boolean b2 = checkAnnotationMirrors(tpe, elements.getAllAnnotationMirrors(tpe)); + boolean b3 = checkGetAnnotation(tpe); + boolean b4 = checkGetAnnotations(tpe); + return b1 && b2 && b3 && b4 ? 1 : 0; + } + return 0; + } + + boolean checkAnnotationMirrors(TypeParameterElement tpe, List l) { + if (l.size() != 3) { + error("To few annotations, got " + l.size() + + ", should be 3", tpe); + return false; + } + + AnnotationMirror m = l.get(0); + if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Foo"))) { + error("Wrong type of annotation, was expecting @Foo", m.getAnnotationType().asElement()); + return false; + } + m = l.get(1); + if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Bar"))) { + error("Wrong type of annotation, was expecting @Bar", m.getAnnotationType().asElement()); + return false; + } + m = l.get(2); + if (!m.getAnnotationType().asElement().equals(elements.getTypeElement("Baz"))) { + error("Wrong type of annotation, was expecting @Baz", m.getAnnotationType().asElement()); + return false; + } + return true; + } + + boolean checkGetAnnotation(TypeParameterElement tpe) { + Foo f = tpe.getAnnotation(Foo.class); + if (f == null) + error("Expecting @Foo to be present in getAnnotation()", tpe); + + Bar b = tpe.getAnnotation(Bar.class); + if (b == null) + error("Expecting @Bar to be present in getAnnotation()", tpe); + + Baz z = tpe.getAnnotation(Baz.class); + if (z == null) + error("Expecting @Baz to be present in getAnnotation()", tpe); + + return f != null && + b != null && + z != null; + } + + boolean checkGetAnnotations(TypeParameterElement tpe) { + Foo[] f = tpe.getAnnotationsByType(Foo.class); + if (f.length != 1) { + error("Expecting 1 @Foo to be present in getAnnotationsByType()", tpe); + return false; + } + + Bar[] b = tpe.getAnnotationsByType(Bar.class); + if (b.length != 1) { + error("Expecting 1 @Bar to be present in getAnnotationsByType()", tpe); + return false; + } + + Baz[] z = tpe.getAnnotationsByType(Baz.class); + if (z.length != 1) { + error("Expecting 1 @Baz to be present in getAnnotationsByType()", tpe); + return false; + } + + return true; + } + + void note(String msg) { + messager.printMessage(Diagnostic.Kind.NOTE, msg); + } + + void note(String msg, Element e) { + messager.printMessage(Diagnostic.Kind.NOTE, msg, e); + } + + void error(String msg, Element e) { + messager.printMessage(Diagnostic.Kind.ERROR, msg, e); + } + + void error(String msg) { + messager.printMessage(Diagnostic.Kind.ERROR, msg); + } + + // additional generic elements to test + <@Foo @Bar @Baz X> X m(X x) { return x; } + + interface Intf<@Foo @Bar @Baz X> { X m() ; } + + class Class<@Foo @Bar @Baz X> { + <@Foo @Bar @Baz Y> Class() { } + } + + final int expect = 5; // top level class, plus preceding examples +} + +@Target(ElementType.TYPE_PARAMETER) +@interface Foo {} + +@Target(ElementType.TYPE_PARAMETER) +@interface Bar {} + +@Target(ElementType.TYPE_PARAMETER) +@interface Baz {}