This commit is contained in:
Lana Steuck 2013-05-06 11:53:44 -07:00
commit 23b301d6d8
34 changed files with 1980 additions and 654 deletions

View File

@ -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

View File

@ -716,6 +716,29 @@
<target name="sjavac" depends="build-sjavac,jtreg-sjavac,findbugs-sjavac"/>
<!--
**** crules targets.
-->
<target name="build-crules" depends="-def-compilecrules,-def-build-jar-with-services">
<compilecrules/>
<build-jar-with-services
name="crules"
includes="crules/* crules/resources/*"
classes.dir="${build.toolclasses.dir}"
lib.dir="${build.toolclasses.dir}"
jarmainclass=""
jarclasspath="crules.jar"
service.type="com.sun.source.util.Plugin"
service.provider="crules.MutableFieldsAnalyzer"/>
<build-tool name="crules"/>
</target>
<target name="check-coding-rules" depends="build-bootstrap-javac,-create-import-jdk-stubs,build-crules">
<build-classes includes="${javac.includes}"
plugin.options="-J-Xbootclasspath/a:${build.toolclasses.dir}/crules.jar -Xplugin:mutable_fields_analyzer" />
</target>
<!--
**** Create import JDK stubs.
-->
@ -811,6 +834,31 @@
</macrodef>
</target>
<target name="-def-build-jar-with-services">
<macrodef name="build-jar-with-services">
<attribute name="name"/>
<attribute name="includes"/>
<attribute name="classes.dir" default="${build.classes.dir}"/>
<attribute name="lib.dir" default="${dist.lib.dir}"/>
<attribute name="jarmainclass" default="com.sun.tools.@{name}.Main"/>
<attribute name="jarclasspath" default=""/>
<attribute name="service.type" default=""/>
<attribute name="service.provider" default=""/>
<sequential>
<mkdir dir="${build.toolclasses.dir}"/>
<jar destfile="@{lib.dir}/@{name}.jar"
basedir="@{classes.dir}"
includes="@{includes}">
<service type="@{service.type}" provider="@{service.provider}"/>
<manifest>
<attribute name="Main-Class" value="@{jarmainclass}"/>
<attribute name="Class-Path" value="@{jarclasspath}"/>
</manifest>
</jar>
</sequential>
</macrodef>
</target>
<target name="-def-build-classes" depends="-def-pcompile">
<macrodef name="build-classes">
<attribute name="includes"/>
@ -826,6 +874,7 @@
<attribute name="target" default="${javac.target}"/>
<attribute name="release" default="${release}"/>
<attribute name="full.version" default="${full.version}"/>
<attribute name="plugin.options" default=""/>
<sequential>
<echo level="verbose" message="build-classes: excludes=@{excludes}"/>
<echo level="verbose" message="build-classes: bootclasspath.opt=@{bootclasspath.opt}"/>
@ -868,6 +917,7 @@
<compilerarg line="${javac.no.jdk.warnings}"/>
<compilerarg line="${javac.version.opt}"/>
<compilerarg line="${javac.lint.opts}"/>
<compilerarg line="@{plugin.options}"/>
</javac>
<copy todir="@{classes.dir}" includeemptydirs="false">
<fileset dir="${src.classes.dir}" includes="@{includes}" excludes="@{excludes}">
@ -935,6 +985,32 @@
classpath="${build.toolclasses.dir}/"/>
</target>
<target name="-def-compilecrules">
<macrodef name="compilecrules">
<sequential>
<mkdir dir="${build.toolclasses.dir}"/>
<javac fork="true"
source="${boot.javac.source}"
target="${boot.javac.target}"
executable="${boot.java.home}/bin/javac"
srcdir="${make.tools.dir}"
includes="crules/*"
destdir="${build.toolclasses.dir}/"
classpath="${ant.core.lib}"
bootclasspath="${boot.java.home}/jre/lib/rt.jar"
includeantruntime="false">
<compilerarg value="-Xbootclasspath/p:${build.bootstrap.dir}/classes"/>
<compilerarg line="${javac.lint.opts}"/>
</javac>
<copy todir="${build.toolclasses.dir}/" includeemptydirs="false">
<fileset dir="${make.tools.dir}">
<include name="**/*.properties"/>
</fileset>
</copy>
</sequential>
</macrodef>
</target>
<target name="-def-genstubs" depends="build-bootstrap-javac" if="require.import.jdk.stubs">
<mkdir dir="${build.toolclasses.dir}"/>
<javac fork="true"

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -67,7 +67,7 @@
</folders>
<ide-actions>
<!--
Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -96,7 +96,7 @@
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<!--
<!--
This file defines the standard actions accepted by langtools projects.
It is normally included as an entity into a project's project.xml file.
@ -104,7 +104,7 @@
- NetBeans: Setting Up Projects
at http://www.netbeans.org/kb/55/using-netbeans/project_setup.html
- NetBeans: Advanced Freeform Project Configuration
at http://www.netbeans.org/kb/41/freeform-config.html
at http://www.netbeans.org/kb/41/freeform-config.html
-->
<action name="build">
<target>build</target>
@ -144,7 +144,7 @@
</arity>
</context>
</action>
<!--
<!--
Note: NetBeans does not appear to support context menu items
on shell scripts :-(
-->
@ -178,7 +178,7 @@
</arity>
</context>
</action>
<!--
<!--
Note: NetBeans does not appear to support context menu items
on shell scripts :-(
-->
@ -239,10 +239,6 @@
<label>Build files</label>
<location>${root}/make</location>
</source-folder>
<source-folder style="packages">
<label>Source files</label>
<location>${root}/src/share/classes</location>
</source-folder>
<source-file>
<label>README</label>
<location>README</location>
@ -250,7 +246,7 @@
</items>
<context-menu>
<!--
Copyright (c) 2007, 2009, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
@ -279,7 +275,7 @@
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<!--
<!--
This file defines the actions that will appear on the project's context
menu, in the Projects viewer.
It is normally included as an entity into a project's project.xml file.
@ -288,7 +284,7 @@
- NetBeans: Setting Up Projects
at http://www.netbeans.org/kb/55/using-netbeans/project_setup.html
- NetBeans: Advanced Freeform Project Configuration
at http://www.netbeans.org/kb/41/freeform-config.html
at http://www.netbeans.org/kb/41/freeform-config.html
-->
<ide-action name="select-tool"/>
<separator/>
@ -305,11 +301,11 @@
</view>
<subprojects/>
</general-data>
<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/2">
<java-data xmlns="http://www.netbeans.org/ns/freeform-project-java/3">
<compilation-unit>
<package-root>${root}/src/share/classes</package-root>
<built-to>${root}/build/classes</built-to>
<source-level>1.5</source-level>
<source-level>1.7</source-level>
</compilation-unit>
</java-data>
</configuration>

View File

@ -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);
}
}
}

View File

@ -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<String> 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<String, List<String>> classFieldsToIgnoreMap =
new HashMap<String, List<String>>();
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"));
}
}

View File

@ -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

View File

@ -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:
*
* <p>
* {@code tree.getStartPosition() <= subtree.getStartPosition()} or <br>
* {@code tree.getStartPosition() == NOPOS} or <br>
* {@code subtree.getStartPosition() == NOPOS}
* </p>
*
* @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:
*
* <p>
* {@code tree.getEndPosition() >= subtree.getEndPosition()} or <br>
* {@code tree.getEndPosition() == NOPOS} or <br>
* {@code subtree.getEndPosition() == NOPOS}
* </p>
*
* In addition, the following must hold:
*
* <p>
* {@code tree.getStartPosition() <= tree.getEndPosition()} or <br>
* {@code tree.getStartPosition() == NOPOS} or <br>
* {@code tree.getEndPosition() == NOPOS}
* </p>
*
* @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);
}

View File

@ -72,6 +72,8 @@ public abstract class DocTrees extends Trees {
*/
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

View File

@ -59,7 +59,7 @@ public interface SourcePositions {
/**
* 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:

View File

@ -315,7 +315,7 @@ public class Dependencies {
static class SimpleLocation implements Location {
public SimpleLocation(String name) {
this.name = name;
this.className = name.replace('/', '.').replace('$', '.');
this.className = name.replace('/', '.');
}
public String getName() {

View File

@ -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<CPRefInfo> 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<Integer> cprefs = new ArrayList<Integer>();
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<Integer> ids = new HashSet<Integer>();
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<CPRefInfo> refInfos = new ArrayList<CPRefInfo>(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<Boolean,ConstantPool> cpVisitor =
new ConstantPool.Visitor<Boolean,ConstantPool>()
{
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<Integer, List<Integer>> codeVisitor =
new Instruction.KindVisitor<Integer, List<Integer>>()
{
public Integer visitNoOperands(Instruction instr, List<Integer> p) {
return 0;
}
public Integer visitArrayType(Instruction instr, TypeKind kind, List<Integer> p) {
return 0;
}
public Integer visitBranch(Instruction instr, int offset, List<Integer> p) {
return 0;
}
public Integer visitConstantPoolRef(Instruction instr, int index, List<Integer> p) {
return p.contains(index) ? index : 0;
}
public Integer visitConstantPoolRefAndValue(Instruction instr, int index, int value, List<Integer> p) {
return p.contains(index) ? index : 0;
}
public Integer visitLocal(Instruction instr, int index, List<Integer> p) {
return 0;
}
public Integer visitLocalAndValue(Instruction instr, int index, int value, List<Integer> p) {
return 0;
}
public Integer visitLookupSwitch(Instruction instr, int default_, int npairs, int[] matches, int[] offsets, List<Integer> p) {
return 0;
}
public Integer visitTableSwitch(Instruction instr, int default_, int low, int high, int[] offsets, List<Integer> p) {
return 0;
}
public Integer visitValue(Instruction instr, int value, List<Integer> p) {
return 0;
}
public Integer visitUnknown(Instruction instr, List<Integer> p) {
return 0;
}
};
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -43,14 +43,16 @@ import javax.tools.JavaCompiler;
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.comp.Resolve;
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.Log;
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 @@ public class JavacTrees extends DocTrees {
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 @@ public class JavacTrees extends DocTrees {
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<Void, Void>() {
@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);
}

View File

@ -465,18 +465,11 @@ public abstract class Symbol implements Element {
* This is the implementation for {@code
* javax.lang.model.element.Element.getAnnotationMirrors()}.
*/
public final List<? extends AnnotationMirror> getAnnotationMirrors() {
@Override
public List<Attribute.Compound> getAnnotationMirrors() {
return getRawAttributes();
}
/**
* TODO: Should there be a {@code
* javax.lang.model.element.Element.getTypeAnnotationMirrors()}.
*/
public final List<Attribute.TypeCompound> getTypeAnnotationMirrors() {
return getRawTypeAttributes();
}
/**
* @deprecated this method should never be used by javac internally.
*/
@ -656,6 +649,24 @@ public abstract class Symbol implements Element {
}
}
@Override
public List<Attribute.Compound> getAnnotationMirrors() {
return onlyTypeVariableAnnotations(owner.getRawTypeAttributes());
}
private List<Attribute.Compound> onlyTypeVariableAnnotations(
List<Attribute.TypeCompound> candidates) {
// Declaration annotations on TypeParameters are stored in type attributes
List<Attribute.Compound> 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, P> R accept(ElementVisitor<R, P> v, P p) {
return v.visitTypeParameter(this, p);

View File

@ -206,7 +206,7 @@ public class TypeAnnotations {
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());
}
}

View File

@ -1078,7 +1078,8 @@ public class Check {
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:

View File

@ -35,7 +35,6 @@ import com.sun.tools.javac.util.*;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.code.Symbol.*;
import com.sun.tools.javac.comp.Resolve;
import com.sun.tools.javac.tree.JCTree.*;
import static com.sun.tools.javac.code.Flags.*;
@ -276,6 +275,15 @@ public class Flow {
allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses();
}
/**
* 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 @@ public class Flow {
/** 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 @@ public class Flow {
* 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 @@ public class Flow {
/** 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 @@ public class Flow {
/** 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 @@ public class Flow {
void scanExpr(JCTree tree) {
if (tree != null) {
scan(tree);
if (inits == null) merge();
if (inits.isReset()) merge();
}
}
@ -1518,28 +1537,29 @@ public class Flow {
*/
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 class Flow {
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 @@ public class Flow {
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 @@ public class Flow {
ListBuffer<AssignPendingExit> 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<AssignPendingExit>();
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 @@ public class Flow {
ListBuffer<AssignPendingExit> 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<AssignPendingExit>();
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 @@ public class Flow {
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<AssignPendingExit>();
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 @@ public class Flow {
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 @@ public class Flow {
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<AssignPendingExit>();
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 @@ public class Flow {
pendingExits = new ListBuffer<AssignPendingExit>();
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<JCCase> 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 @@ public class Flow {
}
// where
/** Add any variables defined in stats to inits and uninits. */
private void addVars(List<JCStatement> stats, Bits inits,
Bits uninits) {
private void addVars(List<JCStatement> 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 class Flow {
public void visitTry(JCTry tree) {
ListBuffer<JCVariableDecl> resourceVarDecls = ListBuffer.lb();
Bits uninitsTryPrev = uninitsTry;
final Bits uninitsTryPrev = new Bits(uninitsTry);
ListBuffer<AssignPendingExit> prevPendingExits = pendingExits;
pendingExits = new ListBuffer<AssignPendingExit>();
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 @@ public class Flow {
}
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 @@ public class Flow {
for (List<JCCatch> 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 @@ public class Flow {
nextadr = nextadrCatch;
}
if (tree.finalizer != null) {
inits = initsTry.dup();
uninits = uninitsTry.dup();
inits.assign(initsTry);
uninits.assign(uninitsTry);
ListBuffer<AssignPendingExit> exits = pendingExits;
pendingExits = prevPendingExits;
scan(tree.finalizer);
@ -1958,8 +1978,8 @@ public class Flow {
inits.orSet(initsEnd);
}
} else {
inits = initsEnd;
uninits = uninitsEnd;
inits.assign(initsEnd);
uninits.assign(uninitsEnd);
ListBuffer<AssignPendingExit> exits = pendingExits;
pendingExits = prevPendingExits;
while (exits.nonEmpty()) pendingExits.append(exits.next());
@ -1969,10 +1989,10 @@ public class Flow {
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 @@ public class Flow {
// 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 @@ public class Flow {
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 class Flow {
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 @@ public class Flow {
@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<AssignPendingExit> prevPending = pendingExits;
try {
@ -2076,8 +2096,8 @@ public class Flow {
}
finally {
returnadr = returnadrPrev;
uninits = prevUninits;
inits = prevInits;
uninits.assign(prevUninits);
inits.assign(prevInits);
pendingExits = prevPending;
}
}
@ -2088,17 +2108,17 @@ public class Flow {
}
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 @@ public class Flow {
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 @@ public class Flow {
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 @@ public class Flow {
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 @@ public class Flow {
} 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<vars.length; i++)
vars[i] = null;
firstadr = 0;

View File

@ -40,10 +40,9 @@ import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.ClassType;
import com.sun.tools.javac.code.Type.MethodType;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzer.*;
import com.sun.tools.javac.comp.LambdaToMethod.LambdaAnalyzerPreprocessor.*;
import com.sun.tools.javac.comp.Lower.BasicFreeVarCollector;
import com.sun.tools.javac.jvm.*;
import com.sun.tools.javac.util.*;
@ -81,7 +80,7 @@ public class LambdaToMethod extends TreeTranslator {
private Env<AttrContext> attrEnv;
/** the analyzer scanner */
private LambdaAnalyzer analyzer;
private LambdaAnalyzerPreprocessor analyzer;
/** map from lambda trees to translation contexts */
private Map<JCTree, TranslationContext<?>> contextMap;
@ -156,7 +155,7 @@ public class LambdaToMethod extends TreeTranslator {
make = TreeMaker.instance(context);
types = Types.instance(context);
transTypes = TransTypes.instance(context);
analyzer = new LambdaAnalyzer();
analyzer = new LambdaAnalyzerPreprocessor();
}
// </editor-fold>
@ -206,7 +205,7 @@ public class LambdaToMethod extends TreeTranslator {
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 @@ public class LambdaToMethod extends TreeTranslator {
/** 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<JCExpression> args) {
JCNewClass makeNewClass(Type ctype, List<JCExpression> 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.<Type>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<JCExpression> args) {
return makeNewClass(ctype, args,
rs.resolveConstructor(null, attrEnv, ctype, TreeInfo.types(args), List.<Type>nil()));
}
private void addDeserializationCase(int implMethodKind, Symbol refSym, Type targetType, MethodSymbol samSym,
DiagnosticPosition pos, List<Object> staticArgs, MethodType indyType) {
String functionalInterfaceClass = classSig(targetType);
@ -1019,8 +1027,9 @@ public class LambdaToMethod extends TreeTranslator {
* 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<Frame> frameStack;
@ -1047,10 +1056,10 @@ public class LambdaToMethod extends TreeTranslator {
private Map<ClassSymbol, Symbol> clinits =
new HashMap<ClassSymbol, Symbol>();
private void analyzeClass(JCClassDecl tree) {
private JCClassDecl analyzeAndPreprocessClass(JCClassDecl tree) {
frameStack = List.nil();
localClassDefs = new HashMap<Symbol, JCClassDecl>();
scan(tree);
return translate(tree);
}
@Override
@ -1154,7 +1163,7 @@ public class LambdaToMethod extends TreeTranslator {
frameStack.head.addLocal(param.sym);
}
contextMap.put(tree, context);
scan(tree.body);
super.visitLambda(tree);
context.complete();
}
finally {
@ -1220,12 +1229,47 @@ public class LambdaToMethod extends TreeTranslator {
};
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<Type> ptypes = ((MethodType) consSym.type).getParameterTypes();
Type classType = consSym.owner.type;
// Make new-class call
List<JCVariableDecl> 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 @@ public class LambdaToMethod extends TreeTranslator {
}
localContext = localContext.prev;
}
scan(tree.selected);
} else {
super.visitSelect(tree);
}
super.visitSelect(tree);
}
@Override

View File

@ -1647,7 +1647,7 @@ public class Code {
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 @@ public class Code {
}
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<stacksize; ) {
@ -1887,7 +1887,7 @@ public class Code {
/** Set the current variable defined state. */
public void setDefined(Bits newDefined) {
if (alive && newDefined != state.defined) {
Bits diff = state.defined.dup().xorSet(newDefined);
Bits diff = new Bits(state.defined).xorSet(newDefined);
for (int adr = diff.nextBit(0);
adr >= 0;
adr = diff.nextBit(adr+1)) {

View File

@ -33,10 +33,13 @@ import com.sun.tools.javac.code.Attribute;
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 @@ public class JavacAnnoConstructs {
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);
}
@ -82,6 +89,24 @@ public class JavacAnnoConstructs {
return null;
}
// Helper to getAnnotation[s]
private static <A extends Annotation> Attribute.Compound
getAttributeOnTypeVariable(TypeVariableSymbol annotated, Class<A> annoType) {
String name = annoType.getName();
// Declaration annotations on type variables are stored in type attributes
// on the owner of the TypeVariableSymbol
List<Attribute.Compound> res = List.nil();
List<Attribute.TypeCompound> 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 <A extends Annotation> Attribute.Compound getAttributeOnClass(ClassSymbol annotated,
Class<A> annoType) {

View File

@ -402,9 +402,10 @@ public class JavacElements implements Elements {
* @param e the element being examined
* @return all annotations of the element
*/
@Override
public List<Attribute.Compound> getAllAnnotationMirrors(Element e) {
Symbol sym = cast(Symbol.class, e);
List<Attribute.Compound> annos = sym.getRawAttributes();
List<Attribute.Compound> annos = sym.getAnnotationMirrors();
while (sym.getKind() == ElementKind.CLASS) {
Type sup = ((ClassSymbol) sym).getSuperclass();
if (!sup.hasTag(CLASS) || sup.isErroneous() ||
@ -413,7 +414,7 @@ public class JavacElements implements Elements {
}
sym = sup.tsym;
List<Attribute.Compound> oldAnnos = annos;
List<Attribute.Compound> newAnnos = sym.getRawAttributes();
List<Attribute.Compound> newAnnos = sym.getAnnotationMirrors();
for (Attribute.Compound anno : newAnnos) {
if (isInherited(anno.type) &&
!containsAnnoOfType(oldAnnos, anno.type)) {

View File

@ -41,6 +41,7 @@ import com.sun.tools.javac.tree.DCTree;
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 @@ public class DocCommentParser {
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 @@ public class DocCommentParser {
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 @@ public class DocCommentParser {
}
if (ch == '>') {
nextChar();
return m.at(p).StartElement(name, attrs, selfClosing);
return m.at(p).StartElement(name, attrs, selfClosing).setEndPos(bp);
}
}
} else if (ch == '/') {

View File

@ -36,6 +36,7 @@ import com.sun.tools.javac.util.JCDiagnostic;
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 @@ public abstract class DCTree implements DocTree {
return s.toString();
}
public static abstract class DCEndPosTree<T extends DCEndPosTree<T>> 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<DCTree> firstSentence;
public final List<DCTree> body;
@ -125,7 +142,7 @@ public abstract class DCTree implements DocTree {
}
}
public static abstract class DCInlineTag extends DCTree implements InlineTagTree {
public static abstract class DCInlineTag extends DCEndPosTree<DCInlineTag> implements InlineTagTree {
public String getTagName() {
return getKind().tagName;
}
@ -345,6 +362,7 @@ public abstract class DCTree implements DocTree {
public int getEndPosition(EndPosTable endPosTable) {
return pos + body.length();
}
}
public static class DCIdentifier extends DCTree implements IdentifierTree {
@ -478,7 +496,7 @@ public abstract class DCTree implements DocTree {
}
}
public static class DCReference extends DCTree implements ReferenceTree {
public static class DCReference extends DCEndPosTree<DCReference> implements ReferenceTree {
public final String signature;
// The following are not directly exposed through ReferenceTree
@ -663,7 +681,7 @@ public abstract class DCTree implements DocTree {
}
}
public static class DCStartElement extends DCTree implements StartElementTree {
public static class DCStartElement extends DCEndPosTree<DCStartElement> implements StartElementTree {
public final Name name;
public final List<DCTree> attrs;
public final boolean selfClosing;

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,8 @@ package com.sun.tools.javac.util;
import java.util.Arrays;
import static com.sun.tools.javac.util.Bits.BitsOpKind.*;
/** A class for extensible, mutable bit sets.
*
* <p><b>This is NOT part of any supported API.
@ -36,31 +38,114 @@ import java.util.Arrays;
*/
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 @@ public class Bits {
/** 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 @@ public class Bits {
/** {@literal this set = this set & xs}.
*/
public Bits andSet(Bits xs) {
sizeTo(xs.bits.length);
for (int i = 0; i < xs.bits.length; i++)
bits[i] = bits[i] & xs.bits[i];
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++) {
bits[i] = bits[i] & xs.bits[i];
}
}
/** 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 class Bits {
* }</pre>
*/
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 @@ public class Bits {
/** 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 {

View File

@ -341,9 +341,14 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
* </pre>
*/
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.
* <pre>
@ -354,9 +359,14 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
* </pre>
*/
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.
* <p>
@ -380,9 +390,14 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
* 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.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -252,13 +252,23 @@ public class FieldDocImpl extends MemberDocImpl implements FieldDoc {
}
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.

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -203,13 +203,23 @@ public class MethodDocImpl
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

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -334,12 +334,17 @@ public class PackageDocImpl extends DocImpl implements PackageDoc {
* 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
*/

View File

@ -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 @@ public class TestJavacTaskScanner extends ToolTester {
System.out.println("#allMembers: " + numAllMembers);
check(numTokens, "#Tokens", 1222);
check(numParseTypeElements, "#parseTypeElements", 136);
check(numParseTypeElements, "#parseTypeElements", 158);
check(numAllMembers, "#allMembers", 52);
}

View File

@ -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<String> 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() {}
}
}

View File

@ -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<? extends TypeElement> 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<Void, Void>() {
@Override public Void visitMethod(MethodTree node, Void p) {
final DocCommentTree docCommentTree = trees.getDocCommentTree(getCurrentPath());
if (docCommentTree != null) {
System.out.println(node.getName() + ":");
new DocTreeScanner<Void, Void>() {
@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();
}
}

View File

@ -0,0 +1,99 @@
valid:
DOC_COMMENT:First sentence.
*
* <p>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:<p>
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.
*
* <p>Description with {@link}, {@link java.util.List}, {@link
*
* @param
* @param second
* @return
* @throws
* @throws IllegalStateException
* @since
* @see
TEXT:First sentence.
START_ELEMENT:<p>
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.
*
* <p>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:<p>
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

View File

@ -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.
*
* <p>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.
*
* <p>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.
*
* <p>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;
}
}

View File

@ -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");
}
}

View File

@ -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<? extends TypeElement> 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<Integer,Void> {
@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<? extends TypeParameterElement> 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<? extends AnnotationMirror> 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 {}