Merge
This commit is contained in:
commit
8ba6b5e2f1
@ -32,7 +32,7 @@ tests that the compiler performs according to the specifications in
|
||||
JLS and JVMS.
|
||||
|
||||
In addition, there is a substantial collection of regression and unit
|
||||
tests for all the tools in the maain langtools test/ directory.
|
||||
tests for all the tools in the main langtools test/ directory.
|
||||
|
||||
Finally, there is a small set of tests to do basic validation of a build
|
||||
of the langtools workspace for use by JDK. These tests check the contents
|
||||
|
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright (c) 2007, 2010, 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
|
||||
@ -55,10 +55,18 @@
|
||||
description="Build one or all langtools tools"
|
||||
/>
|
||||
|
||||
<condition property="bootstrap" value="bootstrap-" else="">
|
||||
<isset property="langtools.tool.bootstrap"/>
|
||||
</condition>
|
||||
|
||||
<condition property="bcp" value="${build.bootstrap.dir}/classes" else="${build.classes.dir}">
|
||||
<isset property="langtools.tool.bootstrap"/>
|
||||
</condition>
|
||||
|
||||
<target name="-build-tool" if="langtools.tool.name">
|
||||
<echo level="info" message="Building ${langtools.tool.name}"/>
|
||||
<echo level="info" message="Building ${bootstrap}${langtools.tool.name}"/>
|
||||
<echo level="verbose" message="(Unset langtools.tool.name to build all tools)"/>
|
||||
<antcall target="build-${langtools.tool.name}"/>
|
||||
<antcall target="build-${bootstrap}${langtools.tool.name}"/>
|
||||
</target>
|
||||
|
||||
<target name="-build-all" unless="langtools.tool.name">
|
||||
@ -89,8 +97,9 @@
|
||||
|
||||
<target name="run" depends="-check-target.java.home,build,-def-run,-get-tool-and-args"
|
||||
description="run tool">
|
||||
<echo level="info" message="Run ${langtools.tool.name} with args ${langtools.tool.args}"/>
|
||||
<run mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}"/>
|
||||
<echo level="info" message="${bcp}"/>
|
||||
<echo level="info" message="Run ${bootstrap}${langtools.tool.name} with args ${langtools.tool.args}"/>
|
||||
<run bcp="${bcp}" mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}"/>
|
||||
</target>
|
||||
|
||||
<!-- Run a selected class. (action: run.single; shift-F6) -->
|
||||
@ -136,9 +145,9 @@
|
||||
<!-- Debug tool in NetBeans. -->
|
||||
|
||||
<target name="debug" depends="-check-target.java.home,-def-run,-def-start-debugger,-get-tool-and-args,build" if="netbeans.home">
|
||||
<echo level="info" message="Debug ${langtools.tool.name} with args ${langtools.tool.args}"/>
|
||||
<echo level="info" message="Debug ${boostrap}${langtools.tool.name} with args ${langtools.tool.args}"/>
|
||||
<start-debugger/>
|
||||
<run mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}" jpda.jvmargs="${jpda.jvmargs}"/>
|
||||
<run bcp="${bcp}" mainclass="com.sun.tools.${langtools.tool.name}.Main" args="${langtools.tool.args}" jpda.jvmargs="${jpda.jvmargs}"/>
|
||||
</target>
|
||||
|
||||
<!-- Debug a selected class . -->
|
||||
@ -207,6 +216,7 @@
|
||||
<target name="-get-tool-if-set" depends="-def-select-tool">
|
||||
<select-tool
|
||||
toolproperty="langtools.tool.name"
|
||||
bootstrapproperty="langtools.tool.bootstrap"
|
||||
propertyfile="${langtools.properties}"
|
||||
askIfUnset="false"
|
||||
/>
|
||||
@ -216,6 +226,7 @@
|
||||
<select-tool
|
||||
toolproperty="langtools.tool.name"
|
||||
argsproperty="langtools.tool.args"
|
||||
bootstrapproperty="langtools.tool.bootstrap"
|
||||
propertyfile="${langtools.properties}"
|
||||
askIfUnset="true"
|
||||
/>
|
||||
@ -226,10 +237,12 @@
|
||||
<macrodef name="run">
|
||||
<attribute name="mainclass"/>
|
||||
<attribute name="args" default=""/>
|
||||
<attribute name="bcp" default="${build.classes.dir}"/>
|
||||
<attribute name="jpda.jvmargs" default=""/>
|
||||
|
||||
<sequential>
|
||||
<java fork="true" jvm="${target.java}" classname="@{mainclass}">
|
||||
<jvmarg line="-Xbootclasspath/p:${build.classes.dir}"/>
|
||||
<jvmarg line="-Xbootclasspath/p:${bcp}"/>
|
||||
<jvmarg line="@{jpda.jvmargs}"/>
|
||||
<arg line="@{args}"/>
|
||||
</java>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -43,6 +43,7 @@ import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import javax.swing.JButton;
|
||||
@ -71,6 +72,31 @@ import org.apache.tools.ant.Task;
|
||||
* is invoked to allow the user to set or reset values for use in property mode.
|
||||
*/
|
||||
public class SelectToolTask extends Task {
|
||||
|
||||
enum ToolChoices {
|
||||
NONE(""),
|
||||
JAVAC("javac"),
|
||||
JAVADOC("javadoc"),
|
||||
JAVAH("javah"),
|
||||
JAVAP("javap");
|
||||
|
||||
String toolName;
|
||||
boolean bootstrap;
|
||||
|
||||
ToolChoices(String toolName) {
|
||||
this(toolName, false);
|
||||
}
|
||||
|
||||
ToolChoices(String toolName, boolean boostrap) {
|
||||
this.toolName = toolName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toolName;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the location of the private properties file used to keep the retain
|
||||
* user preferences for this repository.
|
||||
@ -96,6 +122,14 @@ public class SelectToolTask extends Task {
|
||||
this.argsProperty = argsProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the property which will be set to the execution args of the
|
||||
* selected tool, if any. The args default to an empty string.
|
||||
*/
|
||||
public void setBootstrapProperty(String bootstrapProperty) {
|
||||
this.bootstrapProperty = bootstrapProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify whether or not to pop up a dialog if the user has not specified
|
||||
* a default value for a property.
|
||||
@ -110,6 +144,7 @@ public class SelectToolTask extends Task {
|
||||
|
||||
Properties props = readProperties(propertyFile);
|
||||
toolName = props.getProperty("tool.name");
|
||||
toolBootstrap = props.getProperty("tool.bootstrap") != null;
|
||||
if (toolName != null) {
|
||||
toolArgs = props.getProperty(toolName + ".args", "");
|
||||
}
|
||||
@ -123,6 +158,8 @@ public class SelectToolTask extends Task {
|
||||
// finally, return required values, if any
|
||||
if (toolProperty != null && !(toolName == null || toolName.equals(""))) {
|
||||
p.setProperty(toolProperty, toolName);
|
||||
if (toolBootstrap)
|
||||
p.setProperty(bootstrapProperty, "true");
|
||||
|
||||
if (argsProperty != null && toolArgs != null)
|
||||
p.setProperty(argsProperty, toolArgs);
|
||||
@ -134,14 +171,20 @@ public class SelectToolTask extends Task {
|
||||
JOptionPane p = createPane(guiProps);
|
||||
p.createDialog("Select Tool").setVisible(true);
|
||||
|
||||
toolName = (String) toolChoice.getSelectedItem();
|
||||
toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName;
|
||||
toolArgs = argsField.getText();
|
||||
|
||||
toolBootstrap = bootstrapCheckbox.isSelected();
|
||||
if (defaultCheck.isSelected()) {
|
||||
if (toolName.equals("")) {
|
||||
fileProps.remove("tool.name");
|
||||
fileProps.remove("tool.bootstrap");
|
||||
} else {
|
||||
fileProps.put("tool.name", toolName);
|
||||
if (toolBootstrap) {
|
||||
fileProps.put("tool.bootstrap", "true");
|
||||
} else {
|
||||
fileProps.remove("tool.bootstrap");
|
||||
}
|
||||
fileProps.put(toolName + ".args", toolArgs);
|
||||
}
|
||||
writeProperties(propertyFile, fileProps);
|
||||
@ -154,32 +197,38 @@ public class SelectToolTask extends Task {
|
||||
lc.insets.right = 10;
|
||||
lc.insets.bottom = 3;
|
||||
GridBagConstraints fc = new GridBagConstraints();
|
||||
fc.anchor = GridBagConstraints.WEST;
|
||||
fc.gridx = 1;
|
||||
fc.gridwidth = GridBagConstraints.REMAINDER;
|
||||
fc.gridwidth = GridBagConstraints.NONE;
|
||||
fc.insets.bottom = 3;
|
||||
|
||||
JPanel toolPane = new JPanel(new GridBagLayout());
|
||||
|
||||
JLabel toolLabel = new JLabel("Tool:");
|
||||
body.add(toolLabel, lc);
|
||||
String[] toolChoices = { "apt", "javac", "javadoc", "javah", "javap" };
|
||||
if (true || toolProperty == null) {
|
||||
// include empty value in setup mode
|
||||
List<String> l = new ArrayList<String>(Arrays.asList(toolChoices));
|
||||
l.add(0, "");
|
||||
toolChoices = l.toArray(new String[l.size()]);
|
||||
}
|
||||
toolChoice = new JComboBox(toolChoices);
|
||||
EnumSet<ToolChoices> toolChoices = toolProperty == null ?
|
||||
EnumSet.allOf(ToolChoices.class) : EnumSet.range(ToolChoices.JAVAC, ToolChoices.JAVAP);
|
||||
toolChoice = new JComboBox(toolChoices.toArray());
|
||||
if (toolName != null)
|
||||
toolChoice.setSelectedItem(toolName);
|
||||
toolChoice.setSelectedItem(ToolChoices.valueOf(toolName.toUpperCase()));
|
||||
toolChoice.addItemListener(new ItemListener() {
|
||||
public void itemStateChanged(ItemEvent e) {
|
||||
String tn = (String) e.getItem();
|
||||
String tn = ((ToolChoices)e.getItem()).toolName;
|
||||
argsField.setText(getDefaultArgsForTool(props, tn));
|
||||
if (toolProperty != null)
|
||||
okButton.setEnabled(!tn.equals(""));
|
||||
}
|
||||
});
|
||||
body.add(toolChoice, fc);
|
||||
GridBagConstraints checkConstraint = new GridBagConstraints();
|
||||
fc.anchor = GridBagConstraints.EAST;
|
||||
|
||||
GridBagConstraints toolConstraint = new GridBagConstraints();
|
||||
fc.anchor = GridBagConstraints.WEST;
|
||||
|
||||
toolPane.add(toolChoice, toolConstraint);
|
||||
bootstrapCheckbox = new JCheckBox("bootstrap", toolBootstrap);
|
||||
toolPane.add(bootstrapCheckbox, checkConstraint);
|
||||
|
||||
body.add(toolPane, fc);
|
||||
|
||||
argsField = new JTextField(getDefaultArgsForTool(props, toolName), 40);
|
||||
if (toolProperty == null || argsProperty != null) {
|
||||
@ -190,7 +239,7 @@ public class SelectToolTask extends Task {
|
||||
public void focusGained(FocusEvent e) {
|
||||
}
|
||||
public void focusLost(FocusEvent e) {
|
||||
String toolName = (String) toolChoice.getSelectedItem();
|
||||
String toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName;
|
||||
if (toolName.length() > 0)
|
||||
props.put(toolName + ".args", argsField.getText());
|
||||
}
|
||||
@ -271,16 +320,19 @@ public class SelectToolTask extends Task {
|
||||
// Ant task parameters
|
||||
private boolean askIfUnset;
|
||||
private String toolProperty;
|
||||
private String bootstrapProperty;
|
||||
private String argsProperty;
|
||||
private File propertyFile;
|
||||
|
||||
// GUI components
|
||||
private JComboBox toolChoice;
|
||||
private JCheckBox bootstrapCheckbox;
|
||||
private JTextField argsField;
|
||||
private JCheckBox defaultCheck;
|
||||
private JButton okButton;
|
||||
|
||||
// Result values for the client
|
||||
private String toolName;
|
||||
private boolean toolBootstrap;
|
||||
private String toolArgs;
|
||||
}
|
||||
|
@ -157,7 +157,7 @@ public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter {
|
||||
addAllProfilesLink(div);
|
||||
}
|
||||
body.addContent(div);
|
||||
if (configuration.showProfiles) {
|
||||
if (configuration.showProfiles && configuration.profilePackages.size() > 0) {
|
||||
Content profileSummary = configuration.getResource("doclet.Profiles");
|
||||
addProfilesList(profileSummary, body);
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter
|
||||
if (prev != null) {
|
||||
Content prevLink = getLink(new LinkInfoImpl(configuration,
|
||||
LinkInfoImpl.Kind.CLASS, prev.asClassDoc())
|
||||
.label(configuration.getText("doclet.Prev_Class")).strong(true));
|
||||
.label(prevclassLabel).strong(true));
|
||||
li = HtmlTree.LI(prevLink);
|
||||
}
|
||||
else
|
||||
@ -136,7 +136,7 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter
|
||||
if (next != null) {
|
||||
Content nextLink = getLink(new LinkInfoImpl(configuration,
|
||||
LinkInfoImpl.Kind.CLASS, next.asClassDoc())
|
||||
.label(configuration.getText("doclet.Next_Class")).strong(true));
|
||||
.label(nextclassLabel).strong(true));
|
||||
li = HtmlTree.LI(nextLink);
|
||||
}
|
||||
else
|
||||
|
@ -126,7 +126,7 @@ public class ClassWriterImpl extends SubWriterHolderWriter
|
||||
if (prev != null) {
|
||||
Content prevLink = getLink(new LinkInfoImpl(configuration,
|
||||
LinkInfoImpl.Kind.CLASS, prev)
|
||||
.label(configuration.getText("doclet.Prev_Class")).strong(true));
|
||||
.label(prevclassLabel).strong(true));
|
||||
li = HtmlTree.LI(prevLink);
|
||||
}
|
||||
else
|
||||
@ -144,7 +144,7 @@ public class ClassWriterImpl extends SubWriterHolderWriter
|
||||
if (next != null) {
|
||||
Content nextLink = getLink(new LinkInfoImpl(configuration,
|
||||
LinkInfoImpl.Kind.CLASS, next)
|
||||
.label(configuration.getText("doclet.Next_Class")).strong(true));
|
||||
.label(nextclassLabel).strong(true));
|
||||
li = HtmlTree.LI(nextLink);
|
||||
}
|
||||
else
|
||||
|
@ -205,13 +205,20 @@ public class HtmlDoclet extends AbstractDoclet {
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected void generateProfileFiles() throws Exception {
|
||||
if (configuration.showProfiles) {
|
||||
if (configuration.showProfiles && configuration.profilePackages.size() > 0) {
|
||||
ProfileIndexFrameWriter.generate(configuration);
|
||||
Profile prevProfile = null, nextProfile;
|
||||
String profileName;
|
||||
for (int i = 1; i < configuration.profiles.getProfileCount(); i++) {
|
||||
ProfilePackageIndexFrameWriter.generate(configuration, Profile.lookup(i).name);
|
||||
profileName = Profile.lookup(i).name;
|
||||
// Generate profile package pages only if there are any packages
|
||||
// in a profile to be documented. The profilePackages map will not
|
||||
// contain an entry for the profile if there are no packages to be documented.
|
||||
if (!configuration.shouldDocumentProfile(profileName))
|
||||
continue;
|
||||
ProfilePackageIndexFrameWriter.generate(configuration, profileName);
|
||||
PackageDoc[] packages = configuration.profilePackages.get(
|
||||
Profile.lookup(i).name);
|
||||
profileName);
|
||||
PackageDoc prev = null, next;
|
||||
for (int j = 0; j < packages.length; j++) {
|
||||
// if -nodeprecated option is set and the package is marked as
|
||||
|
@ -406,10 +406,7 @@ public class HtmlDocletWriter extends HtmlDocWriter {
|
||||
Content htmlDocType = DocType.TRANSITIONAL;
|
||||
Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
|
||||
Content head = new HtmlTree(HtmlTag.HEAD);
|
||||
if (!configuration.notimestamp) {
|
||||
Content headComment = new Comment(getGeneratedByString());
|
||||
head.addContent(headComment);
|
||||
}
|
||||
head.addContent(getGeneratedBy(!configuration.notimestamp));
|
||||
if (configuration.charset.length() > 0) {
|
||||
Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE,
|
||||
configuration.charset);
|
||||
@ -502,16 +499,17 @@ public class HtmlDocletWriter extends HtmlDocWriter {
|
||||
if (!configuration.nonavbar) {
|
||||
String allClassesId = "allclasses_";
|
||||
HtmlTree navDiv = new HtmlTree(HtmlTag.DIV);
|
||||
Content skipNavLinks = configuration.getResource("doclet.Skip_navigation_links");
|
||||
if (header) {
|
||||
body.addContent(HtmlConstants.START_OF_TOP_NAVBAR);
|
||||
navDiv.addStyle(HtmlStyle.topNav);
|
||||
allClassesId += "navbar_top";
|
||||
Content a = getMarkerAnchor("navbar_top");
|
||||
//WCAG - Hyperlinks should contain text or an image with alt text - for AT tools
|
||||
navDiv.addContent(a);
|
||||
Content skipLinkContent = getHyperLink(DocLink.fragment("skip-navbar_top"),
|
||||
HtmlTree.EMPTY,
|
||||
configuration.getText("doclet.Skip_navigation_links"),
|
||||
"");
|
||||
Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink(
|
||||
DocLink.fragment("skip-navbar_top"), skipNavLinks,
|
||||
skipNavLinks.toString(), ""));
|
||||
navDiv.addContent(skipLinkContent);
|
||||
} else {
|
||||
body.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR);
|
||||
@ -519,10 +517,9 @@ public class HtmlDocletWriter extends HtmlDocWriter {
|
||||
allClassesId += "navbar_bottom";
|
||||
Content a = getMarkerAnchor("navbar_bottom");
|
||||
navDiv.addContent(a);
|
||||
Content skipLinkContent = getHyperLink(DocLink.fragment("skip-navbar_bottom"),
|
||||
HtmlTree.EMPTY,
|
||||
configuration.getText("doclet.Skip_navigation_links"),
|
||||
"");
|
||||
Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink(
|
||||
DocLink.fragment("skip-navbar_bottom"), skipNavLinks,
|
||||
skipNavLinks.toString(), ""));
|
||||
navDiv.addContent(skipLinkContent);
|
||||
}
|
||||
if (header) {
|
||||
|
@ -130,10 +130,14 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter {
|
||||
String profileName;
|
||||
for (int i = 1; i < configuration.profiles.getProfileCount(); i++) {
|
||||
profileName = Profile.lookup(i).name;
|
||||
Content profileLinkContent = getTargetProfileLink("classFrame",
|
||||
new StringContent(profileName), profileName);
|
||||
Content li = HtmlTree.LI(profileLinkContent);
|
||||
ul.addContent(li);
|
||||
// If the profile has valid packages to be documented, add it to the
|
||||
// profiles list on overview-summary.html page.
|
||||
if (configuration.shouldDocumentProfile(profileName)) {
|
||||
Content profileLinkContent = getTargetProfileLink("classFrame",
|
||||
new StringContent(profileName), profileName);
|
||||
Content li = HtmlTree.LI(profileLinkContent);
|
||||
ul.addContent(li);
|
||||
}
|
||||
}
|
||||
profilesDiv.addContent(ul);
|
||||
Content div = HtmlTree.DIV(HtmlStyle.contentContainer, profilesDiv);
|
||||
|
@ -88,8 +88,13 @@ public class ProfileIndexFrameWriter extends AbstractProfileIndexWriter {
|
||||
Content div = HtmlTree.DIV(HtmlStyle.indexContainer, heading);
|
||||
HtmlTree ul = new HtmlTree(HtmlTag.UL);
|
||||
ul.setTitle(profilesLabel);
|
||||
String profileName;
|
||||
for (int i = 1; i < profiles.getProfileCount(); i++) {
|
||||
ul.addContent(getProfile(i));
|
||||
profileName = (Profile.lookup(i)).name;
|
||||
// If the profile has valid packages to be documented, add it to the
|
||||
// left-frame generated for profile index.
|
||||
if (configuration.shouldDocumentProfile(profileName))
|
||||
ul.addContent(getProfile(profileName));
|
||||
}
|
||||
div.addContent(ul);
|
||||
body.addContent(div);
|
||||
@ -98,13 +103,12 @@ public class ProfileIndexFrameWriter extends AbstractProfileIndexWriter {
|
||||
/**
|
||||
* Gets each profile name as a separate link.
|
||||
*
|
||||
* @param profile the profile being documented
|
||||
* @param profileName the profile being documented
|
||||
* @return content for the profile link
|
||||
*/
|
||||
protected Content getProfile(int profile) {
|
||||
protected Content getProfile(String profileName) {
|
||||
Content profileLinkContent;
|
||||
Content profileLabel;
|
||||
String profileName = (Profile.lookup(profile)).name;
|
||||
profileLabel = new StringContent(profileName);
|
||||
profileLinkContent = getHyperLink(DocPaths.profileFrame(profileName), profileLabel, "",
|
||||
"packageListFrame");
|
||||
|
@ -138,6 +138,7 @@ public class ProfileWriterImpl extends HtmlDocletWriter
|
||||
"classFrame", new StringContent(pkg.name()), profile.name);
|
||||
Content heading = HtmlTree.HEADING(HtmlTag.H3, pkgName);
|
||||
HtmlTree li = HtmlTree.LI(HtmlStyle.blockList, heading);
|
||||
addPackageDeprecationInfo(li, pkg);
|
||||
return li;
|
||||
}
|
||||
|
||||
@ -174,6 +175,30 @@ public class ProfileWriterImpl extends HtmlDocletWriter
|
||||
true, contentTree);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the profile package deprecation information to the documentation tree.
|
||||
*
|
||||
* @param li the content tree to which the deprecation information will be added
|
||||
* @param pkg the PackageDoc that is added
|
||||
*/
|
||||
public void addPackageDeprecationInfo(Content li, PackageDoc pkg) {
|
||||
Tag[] deprs;
|
||||
if (Util.isDeprecated(pkg)) {
|
||||
deprs = pkg.tags("deprecated");
|
||||
HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV);
|
||||
deprDiv.addStyle(HtmlStyle.deprecatedContent);
|
||||
Content deprPhrase = HtmlTree.SPAN(HtmlStyle.strong, deprecatedPhrase);
|
||||
deprDiv.addContent(deprPhrase);
|
||||
if (deprs.length > 0) {
|
||||
Tag[] commentTags = deprs[0].inlineTags();
|
||||
if (commentTags.length > 0) {
|
||||
addInlineDeprecatedComment(pkg, deprs[0], deprDiv);
|
||||
}
|
||||
}
|
||||
li.addContent(deprDiv);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "PREV PROFILE" link in the navigation bar.
|
||||
*
|
||||
|
@ -191,10 +191,7 @@ public abstract class HtmlDocWriter extends HtmlWriter {
|
||||
Content htmlDocType = DocType.FRAMESET;
|
||||
Content htmlComment = new Comment(configuration.getText("doclet.New_Page"));
|
||||
Content head = new HtmlTree(HtmlTag.HEAD);
|
||||
if (! noTimeStamp) {
|
||||
Content headComment = new Comment(getGeneratedByString());
|
||||
head.addContent(headComment);
|
||||
}
|
||||
head.addContent(getGeneratedBy(!noTimeStamp));
|
||||
if (configuration.charset.length() > 0) {
|
||||
Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE,
|
||||
configuration.charset);
|
||||
@ -210,9 +207,13 @@ public abstract class HtmlDocWriter extends HtmlWriter {
|
||||
write(htmlDocument);
|
||||
}
|
||||
|
||||
protected String getGeneratedByString() {
|
||||
Calendar calendar = new GregorianCalendar(TimeZone.getDefault());
|
||||
Date today = calendar.getTime();
|
||||
return "Generated by javadoc ("+ ConfigurationImpl.BUILD_DATE + ") on " + today;
|
||||
protected Comment getGeneratedBy(boolean timestamp) {
|
||||
String text = "Generated by javadoc"; // marker string, deliberately not localized
|
||||
if (timestamp) {
|
||||
Calendar calendar = new GregorianCalendar(TimeZone.getDefault());
|
||||
Date today = calendar.getTime();
|
||||
text += " ("+ ConfigurationImpl.BUILD_DATE + ") on " + today;
|
||||
}
|
||||
return new Comment(text);
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,7 @@ public enum HtmlStyle {
|
||||
packageSummary,
|
||||
rowColor,
|
||||
serializedFormContainer,
|
||||
skipNav,
|
||||
sourceContainer,
|
||||
sourceLineNo,
|
||||
strong,
|
||||
|
@ -203,27 +203,27 @@ public class HtmlWriter {
|
||||
useLabel = getResource("doclet.navClassUse");
|
||||
prevLabel = getResource("doclet.Prev");
|
||||
nextLabel = getResource("doclet.Next");
|
||||
prevclassLabel = getResource("doclet.Prev_Class");
|
||||
nextclassLabel = getResource("doclet.Next_Class");
|
||||
prevclassLabel = getNonBreakResource("doclet.Prev_Class");
|
||||
nextclassLabel = getNonBreakResource("doclet.Next_Class");
|
||||
summaryLabel = getResource("doclet.Summary");
|
||||
detailLabel = getResource("doclet.Detail");
|
||||
framesLabel = getResource("doclet.Frames");
|
||||
noframesLabel = getResource("doclet.No_Frames");
|
||||
noframesLabel = getNonBreakResource("doclet.No_Frames");
|
||||
treeLabel = getResource("doclet.Tree");
|
||||
classLabel = getResource("doclet.Class");
|
||||
deprecatedLabel = getResource("doclet.navDeprecated");
|
||||
deprecatedPhrase = getResource("doclet.Deprecated");
|
||||
allclassesLabel = getResource("doclet.All_Classes");
|
||||
allpackagesLabel = getResource("doclet.All_Packages");
|
||||
allprofilesLabel = getResource("doclet.All_Profiles");
|
||||
allclassesLabel = getNonBreakResource("doclet.All_Classes");
|
||||
allpackagesLabel = getNonBreakResource("doclet.All_Packages");
|
||||
allprofilesLabel = getNonBreakResource("doclet.All_Profiles");
|
||||
indexLabel = getResource("doclet.Index");
|
||||
helpLabel = getResource("doclet.Help");
|
||||
seeLabel = getResource("doclet.See");
|
||||
descriptionLabel = getResource("doclet.Description");
|
||||
prevpackageLabel = getResource("doclet.Prev_Package");
|
||||
nextpackageLabel = getResource("doclet.Next_Package");
|
||||
prevprofileLabel = getResource("doclet.Prev_Profile");
|
||||
nextprofileLabel = getResource("doclet.Next_Profile");
|
||||
prevpackageLabel = getNonBreakResource("doclet.Prev_Package");
|
||||
nextpackageLabel = getNonBreakResource("doclet.Next_Package");
|
||||
prevprofileLabel = getNonBreakResource("doclet.Prev_Profile");
|
||||
nextprofileLabel = getNonBreakResource("doclet.Next_Profile");
|
||||
packagesLabel = getResource("doclet.Packages");
|
||||
profilesLabel = getResource("doclet.Profiles");
|
||||
methodDetailsLabel = getResource("doclet.Method_Detail");
|
||||
@ -256,6 +256,27 @@ public class HtmlWriter {
|
||||
return configuration.getResource(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration string as a content, replacing spaces
|
||||
* with non-breaking spaces.
|
||||
*
|
||||
* @param key the key to look for in the configuration file
|
||||
* @return a content tree for the text
|
||||
*/
|
||||
public Content getNonBreakResource(String key) {
|
||||
String text = configuration.getText(key);
|
||||
Content c = configuration.newContent();
|
||||
int start = 0;
|
||||
int p;
|
||||
while ((p = text.indexOf(" ", start)) != -1) {
|
||||
c.addContent(text.substring(start, p));
|
||||
c.addContent(RawHtml.nbsp);
|
||||
start = p + 1;
|
||||
}
|
||||
c.addContent(text.substring(start));
|
||||
return c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the configuration string as a content.
|
||||
*
|
||||
|
@ -383,35 +383,52 @@ public abstract class Configuration {
|
||||
DocErrorReporter reporter);
|
||||
|
||||
private void initProfiles() throws IOException {
|
||||
profiles = Profiles.read(new File(profilespath));
|
||||
// Generate profiles documentation only is profilespath is set and if
|
||||
// profiles is not null and profiles count is 1 or more.
|
||||
showProfiles = (!profilespath.isEmpty() && profiles != null &&
|
||||
profiles.getProfileCount() > 0);
|
||||
}
|
||||
if (profilespath.isEmpty())
|
||||
return;
|
||||
|
||||
private void initProfilePackages() throws IOException {
|
||||
profilePackages = new HashMap<String,PackageDoc[]>();
|
||||
ArrayList<PackageDoc> results;
|
||||
Map<String,PackageDoc> packageIndex = new HashMap<String,PackageDoc>();
|
||||
for (int i = 0; i < packages.length; i++) {
|
||||
PackageDoc pkg = packages[i];
|
||||
packageIndex.put(pkg.name(), pkg);
|
||||
}
|
||||
for (int i = 1; i < profiles.getProfileCount(); i++) {
|
||||
Set<String> profPkgs = profiles.getPackages(i);
|
||||
results = new ArrayList<PackageDoc>();
|
||||
for (String packageName : profPkgs) {
|
||||
packageName = packageName.replace("/", ".");
|
||||
PackageDoc profPkg = packageIndex.get(packageName);
|
||||
if (profPkg != null) {
|
||||
results.add(profPkg);
|
||||
}
|
||||
profiles = Profiles.read(new File(profilespath));
|
||||
|
||||
// Group the packages to be documented by the lowest profile (if any)
|
||||
// in which each appears
|
||||
Map<Profile, List<PackageDoc>> interimResults =
|
||||
new EnumMap<Profile, List<PackageDoc>>(Profile.class);
|
||||
for (Profile p: Profile.values())
|
||||
interimResults.put(p, new ArrayList<PackageDoc>());
|
||||
|
||||
for (PackageDoc pkg: packages) {
|
||||
if (nodeprecated && Util.isDeprecated(pkg)) {
|
||||
continue;
|
||||
}
|
||||
// the getProfile method takes a type name, not a package name,
|
||||
// but isn't particularly fussy about the simple name -- so just use *
|
||||
int i = profiles.getProfile(pkg.name().replace(".", "/") + "/*");
|
||||
Profile p = Profile.lookup(i);
|
||||
if (p != null) {
|
||||
List<PackageDoc> pkgs = interimResults.get(p);
|
||||
pkgs.add(pkg);
|
||||
}
|
||||
Collections.sort(results);
|
||||
PackageDoc[] profilePkgs = results.toArray(new PackageDoc[]{});
|
||||
profilePackages.put(Profile.lookup(i).name, profilePkgs);
|
||||
}
|
||||
|
||||
// Build the profilePackages structure used by the doclet
|
||||
profilePackages = new HashMap<String,PackageDoc[]>();
|
||||
List<PackageDoc> prev = Collections.<PackageDoc>emptyList();
|
||||
int size;
|
||||
for (Map.Entry<Profile,List<PackageDoc>> e: interimResults.entrySet()) {
|
||||
Profile p = e.getKey();
|
||||
List<PackageDoc> pkgs = e.getValue();
|
||||
pkgs.addAll(prev); // each profile contains all lower profiles
|
||||
Collections.sort(pkgs);
|
||||
size = pkgs.size();
|
||||
// For a profile, if there are no packages to be documented, do not add
|
||||
// it to profilePackages map.
|
||||
if (size > 0)
|
||||
profilePackages.put(p.name, pkgs.toArray(new PackageDoc[pkgs.size()]));
|
||||
prev = pkgs;
|
||||
}
|
||||
|
||||
// Generate profiles documentation if any profile contains any
|
||||
// of the packages to be documented.
|
||||
showProfiles = !prev.isEmpty();
|
||||
}
|
||||
|
||||
private void initPackageArray() {
|
||||
@ -534,13 +551,10 @@ public abstract class Configuration {
|
||||
public void setOptions() throws Fault {
|
||||
initPackageArray();
|
||||
setOptions(root.options());
|
||||
if (!profilespath.isEmpty()) {
|
||||
try {
|
||||
initProfiles();
|
||||
initProfilePackages();
|
||||
} catch (Exception e) {
|
||||
throw new DocletAbortException(e);
|
||||
}
|
||||
try {
|
||||
initProfiles();
|
||||
} catch (Exception e) {
|
||||
throw new DocletAbortException(e);
|
||||
}
|
||||
setSpecificDocletOptions(root.options());
|
||||
}
|
||||
@ -712,6 +726,17 @@ public abstract class Configuration {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the validity of the given profile. Return false if there are no
|
||||
* valid packages to be documented for the profile.
|
||||
*
|
||||
* @param profileName the profile that needs to be validated.
|
||||
* @return true if the profile has valid packages to be documented.
|
||||
*/
|
||||
public boolean shouldDocumentProfile(String profileName) {
|
||||
return profilePackages.containsKey(profileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the validity of the given Source or Output File encoding on this
|
||||
* platform.
|
||||
|
@ -180,6 +180,12 @@ ul.subNavList li{
|
||||
margin: auto 5px;
|
||||
border:1px solid #c9aa44;
|
||||
}
|
||||
.skipNav {
|
||||
position:absolute;
|
||||
top:auto;
|
||||
left:-9999px;
|
||||
overflow:hidden;
|
||||
}
|
||||
/*
|
||||
Page header and footer styles
|
||||
*/
|
||||
@ -372,7 +378,6 @@ Table styles
|
||||
overflow:hidden;
|
||||
padding:0px;
|
||||
margin:0px;
|
||||
white-space:pre;
|
||||
}
|
||||
caption a:link, caption a:hover, caption a:active, caption a:visited {
|
||||
color:#FFFFFF;
|
||||
@ -381,35 +386,32 @@ caption a:link, caption a:hover, caption a:active, caption a:visited {
|
||||
white-space:nowrap;
|
||||
padding-top:8px;
|
||||
padding-left:8px;
|
||||
display:block;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
background-image:url(resources/titlebar.gif);
|
||||
height:18px;
|
||||
}
|
||||
.contentContainer ul.blockList li.blockList caption span.activeTableTab span {
|
||||
white-space:nowrap;
|
||||
padding-top:8px;
|
||||
padding-left:8px;
|
||||
display:block;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
background-image:url(resources/activetitlebar.gif);
|
||||
height:18px;
|
||||
}
|
||||
.contentContainer ul.blockList li.blockList caption span.tableTab span {
|
||||
white-space:nowrap;
|
||||
padding-top:8px;
|
||||
padding-left:8px;
|
||||
display:block;
|
||||
display:inline-block;
|
||||
float:left;
|
||||
background-image:url(resources/titlebar.gif);
|
||||
height:18px;
|
||||
}
|
||||
.contentContainer ul.blockList li.blockList caption span.tableTab, .contentContainer ul.blockList li.blockList caption span.activeTableTab {
|
||||
padding-top:0px;
|
||||
padding-left:0px;
|
||||
background-image:none;
|
||||
float:none;
|
||||
display:inline;
|
||||
display:inline-block;
|
||||
}
|
||||
.overviewSummary .tabEnd, .packageSummary .tabEnd, .contentContainer ul.blockList li.blockList .tabEnd, .summary .tabEnd, .classUseContainer .tabEnd, .constantValuesContainer .tabEnd {
|
||||
width:10px;
|
||||
|
@ -130,7 +130,13 @@ public class LegacyTaglet implements Taglet {
|
||||
public Content getTagletOutput(Doc holder, TagletWriter writer)
|
||||
throws IllegalArgumentException {
|
||||
Content output = writer.getOutputInstance();
|
||||
output.addContent(new RawHtml(legacyTaglet.toString(holder.tags(getName()))));
|
||||
Tag[] tags = holder.tags(getName());
|
||||
if (tags.length > 0) {
|
||||
String tagString = legacyTaglet.toString(tags);
|
||||
if (tagString != null) {
|
||||
output.addContent(new RawHtml(tagString));
|
||||
}
|
||||
}
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.io.Writer;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@ -221,8 +222,10 @@ class PathDocFileFactory extends DocFileFactory {
|
||||
/** If the file is a directory, list its contents. */
|
||||
public Iterable<DocFile> list() throws IOException {
|
||||
List<DocFile> files = new ArrayList<DocFile>();
|
||||
for (Path f: Files.newDirectoryStream(file)) {
|
||||
files.add(new StandardDocFile(f));
|
||||
try (DirectoryStream<Path> ds = Files.newDirectoryStream(file)) {
|
||||
for (Path f: ds) {
|
||||
files.add(new StandardDocFile(f));
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
@ -30,14 +30,6 @@ import java.io.PrintWriter;
|
||||
/**
|
||||
* The programmatic interface for the Java Programming Language
|
||||
* compiler, javac.
|
||||
*
|
||||
* <p>Except for the two methods
|
||||
* {@link #compile(java.lang.String[])}
|
||||
* {@link #compile(java.lang.String[],java.io.PrintWriter)},
|
||||
* nothing described in this source file is part of any supported
|
||||
* API. If you write code that depends on this, you do so at your own
|
||||
* risk. This code and its internal interfaces are subject to change
|
||||
* or deletion without notice.
|
||||
*/
|
||||
@jdk.Supported
|
||||
public class Main {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -28,6 +28,8 @@ package com.sun.tools.javac.code;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.sun.tools.javac.tree.EndPosTable;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.util.Assert;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
@ -53,10 +55,13 @@ public class DeferredLintHandler {
|
||||
|
||||
protected DeferredLintHandler(Context context) {
|
||||
context.put(deferredLintHandlerKey, this);
|
||||
this.currentPos = IMMEDIATE_POSITION;
|
||||
}
|
||||
|
||||
private DeferredLintHandler() {}
|
||||
|
||||
/**An interface for deferred lint reporting - loggers passed to
|
||||
* {@link #report(LintLogger) } will be called when
|
||||
* {@link #flush(DiagnosticPosition) } is invoked.
|
||||
*/
|
||||
public interface LintLogger {
|
||||
void report();
|
||||
}
|
||||
@ -64,12 +69,26 @@ public class DeferredLintHandler {
|
||||
private DiagnosticPosition currentPos;
|
||||
private Map<DiagnosticPosition, ListBuffer<LintLogger>> loggersQueue = new HashMap<DiagnosticPosition, ListBuffer<LintLogger>>();
|
||||
|
||||
/**Associate the given logger with the current position as set by {@link #setPos(DiagnosticPosition) }.
|
||||
* Will be invoked when {@link #flush(DiagnosticPosition) } will be invoked with the same position.
|
||||
* <br>
|
||||
* Will invoke the logger synchronously if {@link #immediate() } was called
|
||||
* instead of {@link #setPos(DiagnosticPosition) }.
|
||||
*/
|
||||
public void report(LintLogger logger) {
|
||||
ListBuffer<LintLogger> loggers = loggersQueue.get(currentPos);
|
||||
Assert.checkNonNull(loggers);
|
||||
loggers.append(logger);
|
||||
if (currentPos == IMMEDIATE_POSITION) {
|
||||
logger.report();
|
||||
} else {
|
||||
ListBuffer<LintLogger> loggers = loggersQueue.get(currentPos);
|
||||
if (loggers == null) {
|
||||
loggersQueue.put(currentPos, loggers = ListBuffer.<LintLogger>lb());
|
||||
}
|
||||
loggers.append(logger);
|
||||
}
|
||||
}
|
||||
|
||||
/**Invoke all {@link LintLogger}s that were associated with the provided {@code pos}.
|
||||
*/
|
||||
public void flush(DiagnosticPosition pos) {
|
||||
ListBuffer<LintLogger> loggers = loggersQueue.get(pos);
|
||||
if (loggers != null) {
|
||||
@ -80,16 +99,46 @@ public class DeferredLintHandler {
|
||||
}
|
||||
}
|
||||
|
||||
public DeferredLintHandler setPos(DiagnosticPosition currentPos) {
|
||||
/**Sets the current position to the provided {@code currentPos}. {@link LintLogger}s
|
||||
* passed to subsequent invocations of {@link #report(LintLogger) } will be associated
|
||||
* with the given position.
|
||||
*/
|
||||
public DiagnosticPosition setPos(DiagnosticPosition currentPos) {
|
||||
DiagnosticPosition prevPosition = this.currentPos;
|
||||
this.currentPos = currentPos;
|
||||
loggersQueue.put(currentPos, ListBuffer.<LintLogger>lb());
|
||||
return this;
|
||||
return prevPosition;
|
||||
}
|
||||
|
||||
public static final DeferredLintHandler immediateHandler = new DeferredLintHandler() {
|
||||
/**{@link LintLogger}s passed to subsequent invocations of
|
||||
* {@link #report(LintLogger) } will be invoked immediately.
|
||||
*/
|
||||
public DiagnosticPosition immediate() {
|
||||
return setPos(IMMEDIATE_POSITION);
|
||||
}
|
||||
|
||||
private static final DiagnosticPosition IMMEDIATE_POSITION = new DiagnosticPosition() {
|
||||
@Override
|
||||
public void report(LintLogger logger) {
|
||||
logger.report();
|
||||
public JCTree getTree() {
|
||||
Assert.error();
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartPosition() {
|
||||
Assert.error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPreferredPosition() {
|
||||
Assert.error();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndPosition(EndPosTable endPosTable) {
|
||||
Assert.error();
|
||||
return -1;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -97,7 +97,6 @@ public class Flags {
|
||||
public static final int MANDATED = 1<<15;
|
||||
|
||||
public static final int StandardFlags = 0x0fff;
|
||||
public static final int ModifierFlags = StandardFlags & ~INTERFACE;
|
||||
|
||||
// Because the following access flags are overloaded with other
|
||||
// bit positions, we translate them when reading and writing class
|
||||
@ -266,6 +265,11 @@ public class Flags {
|
||||
*/
|
||||
public static final long THROWS = 1L<<47;
|
||||
|
||||
/**
|
||||
* Flag that marks potentially ambiguous overloads
|
||||
*/
|
||||
public static final long POTENTIALLY_AMBIGUOUS = 1L<<48;
|
||||
|
||||
/** Modifier masks.
|
||||
*/
|
||||
public static final int
|
||||
@ -282,7 +286,9 @@ public class Flags {
|
||||
SYNCHRONIZED | FINAL | STRICTFP;
|
||||
public static final long
|
||||
ExtendedStandardFlags = (long)StandardFlags | DEFAULT,
|
||||
ModifierFlags = ((long)StandardFlags & ~INTERFACE) | DEFAULT,
|
||||
InterfaceMethodMask = ABSTRACT | STATIC | PUBLIC | STRICTFP | DEFAULT,
|
||||
AnnotationTypeElementMask = FINAL | ABSTRACT | PUBLIC | STRICTFP,
|
||||
LocalVarFlags = FINAL | PARAMETER;
|
||||
|
||||
|
||||
|
@ -33,9 +33,6 @@ import com.sun.tools.javac.util.List;
|
||||
import com.sun.tools.javac.util.Options;
|
||||
import com.sun.tools.javac.util.Pair;
|
||||
|
||||
import static com.sun.tools.javac.code.Flags.*;
|
||||
|
||||
|
||||
/**
|
||||
* A class for handling -Xlint suboptions and @SuppresssWarnings.
|
||||
*
|
||||
@ -81,7 +78,6 @@ public class Lint
|
||||
return l;
|
||||
}
|
||||
|
||||
|
||||
private final AugmentVisitor augmentor;
|
||||
|
||||
private final EnumSet<LintCategory> values;
|
||||
@ -90,7 +86,6 @@ public class Lint
|
||||
private static final Map<String, LintCategory> map =
|
||||
new java.util.concurrent.ConcurrentHashMap<String, LintCategory>(20);
|
||||
|
||||
|
||||
protected Lint(Context context) {
|
||||
// initialize values according to the lint options
|
||||
Options options = Options.instance(context);
|
||||
@ -174,6 +169,11 @@ public class Lint
|
||||
*/
|
||||
OPTIONS("options"),
|
||||
|
||||
/**
|
||||
* Warn about issues regarding method overloads.
|
||||
*/
|
||||
OVERLOADS("overloads"),
|
||||
|
||||
/**
|
||||
* Warn about issues regarding method overrides.
|
||||
*/
|
||||
|
@ -46,6 +46,7 @@ import static com.sun.tools.javac.code.Kinds.*;
|
||||
import static com.sun.tools.javac.code.TypeTag.CLASS;
|
||||
import static com.sun.tools.javac.code.TypeTag.FORALL;
|
||||
import static com.sun.tools.javac.code.TypeTag.TYPEVAR;
|
||||
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
|
||||
|
||||
/** Root class for Java symbols. It contains subclasses
|
||||
* for specific sorts of symbols, such as variables, methods and operators,
|
||||
@ -98,9 +99,9 @@ public abstract class Symbol implements Element {
|
||||
// <editor-fold defaultstate="collapsed" desc="annotations">
|
||||
|
||||
/** The attributes of this symbol are contained in this
|
||||
* Annotations. The Annotations instance is NOT immutable.
|
||||
* SymbolMetadata. The SymbolMetadata instance is NOT immutable.
|
||||
*/
|
||||
protected Annotations annotations;
|
||||
protected SymbolMetadata annotations;
|
||||
|
||||
/** An accessor method for the attributes of this symbol.
|
||||
* Attributes of class symbols should be accessed through the accessor
|
||||
@ -217,19 +218,19 @@ public abstract class Symbol implements Element {
|
||||
public void setTypeAttributes(List<Attribute.TypeCompound> a) {
|
||||
if (annotations != null || a.nonEmpty()) {
|
||||
if (annotations == null)
|
||||
annotations = new Annotations(this);
|
||||
annotations = new SymbolMetadata(this);
|
||||
annotations.setTypeAttributes(a);
|
||||
}
|
||||
}
|
||||
|
||||
private Annotations initedAnnos() {
|
||||
private SymbolMetadata initedAnnos() {
|
||||
if (annotations == null)
|
||||
annotations = new Annotations(this);
|
||||
annotations = new SymbolMetadata(this);
|
||||
return annotations;
|
||||
}
|
||||
|
||||
/** This method is intended for debugging only. */
|
||||
public Annotations getAnnotations() {
|
||||
public SymbolMetadata getAnnotations() {
|
||||
return annotations;
|
||||
}
|
||||
|
||||
@ -852,7 +853,7 @@ public abstract class Symbol implements Element {
|
||||
private void mergeAttributes() {
|
||||
if (annotations == null &&
|
||||
package_info.annotations != null) {
|
||||
annotations = new Annotations(this);
|
||||
annotations = new SymbolMetadata(this);
|
||||
annotations.setAttributes(package_info.annotations);
|
||||
}
|
||||
}
|
||||
@ -1167,11 +1168,11 @@ public abstract class Symbol implements Element {
|
||||
|
||||
public void setLazyConstValue(final Env<AttrContext> env,
|
||||
final Attr attr,
|
||||
final JCTree.JCExpression initializer)
|
||||
final JCVariableDecl variable)
|
||||
{
|
||||
setData(new Callable<Object>() {
|
||||
public Object call() {
|
||||
return attr.attribLazyConstantValue(env, initializer, type);
|
||||
return attr.attribLazyConstantValue(env, variable, type);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ import static com.sun.tools.javac.code.Kinds.PCK;
|
||||
* later. You can reset to IN_PROGRESS. While IN_PROGRESS you can set the list
|
||||
* of attributes (and this moves out of the IN_PROGRESS state).
|
||||
*
|
||||
* "unnamed" this Annotations contains some attributes, possibly the final set.
|
||||
* "unnamed" this SymbolMetadata contains some attributes, possibly the final set.
|
||||
* While in this state you can only prepend or append to the attributes not set
|
||||
* it directly. You can also move back to the IN_PROGRESS state using reset().
|
||||
*
|
||||
@ -65,7 +65,7 @@ import static com.sun.tools.javac.code.Kinds.PCK;
|
||||
* on this, you do so at your own risk. This code and its internal interfaces
|
||||
* are subject to change or deletion without notice.</b>
|
||||
*/
|
||||
public class Annotations {
|
||||
public class SymbolMetadata {
|
||||
|
||||
private static final List<Attribute.Compound> DECL_NOT_STARTED = List.of(null);
|
||||
private static final List<Attribute.Compound> DECL_IN_PROGRESS = List.of(null);
|
||||
@ -94,11 +94,11 @@ public class Annotations {
|
||||
private List<Attribute.TypeCompound> clinit_type_attributes = List.<Attribute.TypeCompound>nil();
|
||||
|
||||
/*
|
||||
* The Symbol this Annotations instance belongs to
|
||||
* The Symbol this SymbolMetadata instance belongs to
|
||||
*/
|
||||
private final Symbol sym;
|
||||
|
||||
public Annotations(Symbol sym) {
|
||||
public SymbolMetadata(Symbol sym) {
|
||||
this.sym = sym;
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ public class Annotations {
|
||||
clinit_type_attributes = a;
|
||||
}
|
||||
|
||||
public void setAttributes(Annotations other) {
|
||||
public void setAttributes(SymbolMetadata other) {
|
||||
if (other == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
@ -221,7 +221,7 @@ public class Annotations {
|
||||
return buf.reverse();
|
||||
}
|
||||
|
||||
public Annotations reset() {
|
||||
public SymbolMetadata reset() {
|
||||
attributes = DECL_IN_PROGRESS;
|
||||
return this;
|
||||
}
|
||||
@ -240,7 +240,7 @@ public class Annotations {
|
||||
return attributes == DECL_IN_PROGRESS;
|
||||
}
|
||||
|
||||
public Annotations append(List<Attribute.Compound> l) {
|
||||
public SymbolMetadata append(List<Attribute.Compound> l) {
|
||||
attributes = filterDeclSentinels(attributes);
|
||||
|
||||
if (l.isEmpty()) {
|
||||
@ -253,7 +253,7 @@ public class Annotations {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Annotations appendUniqueTypes(List<Attribute.TypeCompound> l) {
|
||||
public SymbolMetadata appendUniqueTypes(List<Attribute.TypeCompound> l) {
|
||||
if (l.isEmpty()) {
|
||||
; // no-op
|
||||
} else if (type_attributes.isEmpty()) {
|
||||
@ -269,7 +269,7 @@ public class Annotations {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Annotations appendInitTypeAttributes(List<Attribute.TypeCompound> l) {
|
||||
public SymbolMetadata appendInitTypeAttributes(List<Attribute.TypeCompound> l) {
|
||||
if (l.isEmpty()) {
|
||||
; // no-op
|
||||
} else if (init_type_attributes.isEmpty()) {
|
||||
@ -280,7 +280,7 @@ public class Annotations {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Annotations appendClassInitTypeAttributes(List<Attribute.TypeCompound> l) {
|
||||
public SymbolMetadata appendClassInitTypeAttributes(List<Attribute.TypeCompound> l) {
|
||||
if (l.isEmpty()) {
|
||||
; // no-op
|
||||
} else if (clinit_type_attributes.isEmpty()) {
|
||||
@ -291,7 +291,7 @@ public class Annotations {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Annotations prepend(List<Attribute.Compound> l) {
|
||||
public SymbolMetadata prepend(List<Attribute.Compound> l) {
|
||||
attributes = filterDeclSentinels(attributes);
|
||||
|
||||
if (l.isEmpty()) {
|
||||
@ -367,7 +367,7 @@ public class Annotations {
|
||||
|
||||
type_attributes = result.reverse();
|
||||
|
||||
Assert.check(Annotations.this.getTypePlaceholders().isEmpty());
|
||||
Assert.check(SymbolMetadata.this.getTypePlaceholders().isEmpty());
|
||||
} else {
|
||||
Assert.check(!pendingCompletion());
|
||||
|
||||
@ -391,7 +391,7 @@ public class Annotations {
|
||||
|
||||
attributes = result.reverse();
|
||||
|
||||
Assert.check(Annotations.this.getPlaceholders().isEmpty());
|
||||
Assert.check(SymbolMetadata.this.getPlaceholders().isEmpty());
|
||||
}
|
||||
} finally {
|
||||
log.useSource(oldSource);
|
@ -3055,7 +3055,7 @@ public class Types {
|
||||
/**
|
||||
* Does t have the same bounds for quantified variables as s?
|
||||
*/
|
||||
boolean hasSameBounds(ForAll t, ForAll s) {
|
||||
public boolean hasSameBounds(ForAll t, ForAll s) {
|
||||
List<Type> l1 = t.tvars;
|
||||
List<Type> l2 = s.tvars;
|
||||
while (l1.nonEmpty() && l2.nonEmpty() &&
|
||||
|
@ -748,19 +748,11 @@ public class Attr extends JCTree.Visitor {
|
||||
* @see VarSymbol#setLazyConstValue
|
||||
*/
|
||||
public Object attribLazyConstantValue(Env<AttrContext> env,
|
||||
JCTree.JCExpression initializer,
|
||||
JCVariableDecl variable,
|
||||
Type type) {
|
||||
|
||||
/* When this env was created, it didn't have the correct lint nor had
|
||||
* annotations has been processed.
|
||||
* But now at this phase we have already processed annotations and the
|
||||
* correct lint must have been set in chk, so we should use that one to
|
||||
* attribute the initializer.
|
||||
*/
|
||||
Lint prevLint = env.info.lint;
|
||||
env.info.lint = chk.getLint();
|
||||
|
||||
JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile);
|
||||
DiagnosticPosition prevLintPos
|
||||
= deferredLintHandler.setPos(variable.pos());
|
||||
|
||||
try {
|
||||
// Use null as symbol to not attach the type annotation to any symbol.
|
||||
@ -768,17 +760,16 @@ public class Attr extends JCTree.Visitor {
|
||||
// to the symbol.
|
||||
// This prevents having multiple type annotations, just because of
|
||||
// lazy constant value evaluation.
|
||||
memberEnter.typeAnnotate(initializer, env, null);
|
||||
memberEnter.typeAnnotate(variable.init, env, null, variable.pos());
|
||||
annotate.flush();
|
||||
Type itype = attribExpr(initializer, env, type);
|
||||
Type itype = attribExpr(variable.init, env, type);
|
||||
if (itype.constValue() != null) {
|
||||
return coerce(itype, type).constValue();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} finally {
|
||||
env.info.lint = prevLint;
|
||||
log.useSource(prevSource);
|
||||
deferredLintHandler.setPos(prevLintPos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1012,7 +1003,7 @@ public class Attr extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
// Attribute all type annotations in the body
|
||||
memberEnter.typeAnnotate(tree.body, localEnv, m);
|
||||
memberEnter.typeAnnotate(tree.body, localEnv, m, null);
|
||||
annotate.flush();
|
||||
|
||||
// Attribute method body.
|
||||
@ -1042,7 +1033,7 @@ public class Attr extends JCTree.Visitor {
|
||||
} else {
|
||||
if (tree.init != null) {
|
||||
// Field initializer expression need to be entered.
|
||||
memberEnter.typeAnnotate(tree.init, env, tree.sym);
|
||||
memberEnter.typeAnnotate(tree.init, env, tree.sym, tree.pos());
|
||||
annotate.flush();
|
||||
}
|
||||
}
|
||||
@ -1056,18 +1047,16 @@ public class Attr extends JCTree.Visitor {
|
||||
((JCLambda)env.tree).paramKind == JCLambda.ParameterKind.IMPLICIT &&
|
||||
(tree.sym.flags() & PARAMETER) != 0;
|
||||
chk.validate(tree.vartype, env, !isImplicitLambdaParameter);
|
||||
deferredLintHandler.flush(tree.pos());
|
||||
|
||||
try {
|
||||
v.getConstValue(); // ensure compile-time constant initializer is evaluated
|
||||
deferredLintHandler.flush(tree.pos());
|
||||
chk.checkDeprecatedAnnotation(tree.pos(), v);
|
||||
|
||||
if (tree.init != null) {
|
||||
if ((v.flags_field & FINAL) != 0 &&
|
||||
memberEnter.needsLazyConstValue(tree.init)) {
|
||||
// In this case, `v' is final. Ensure that it's initializer is
|
||||
// evaluated.
|
||||
v.getConstValue(); // ensure initializer is evaluated
|
||||
} else {
|
||||
if ((v.flags_field & FINAL) == 0 ||
|
||||
!memberEnter.needsLazyConstValue(tree.init)) {
|
||||
// Not a compile-time constant
|
||||
// Attribute initializer in a new environment
|
||||
// with the declared variable as owner.
|
||||
// Check that initializer conforms to variable's declared type.
|
||||
@ -1106,7 +1095,7 @@ public class Attr extends JCTree.Visitor {
|
||||
if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++;
|
||||
|
||||
// Attribute all type annotations in the block
|
||||
memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner);
|
||||
memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner, null);
|
||||
annotate.flush();
|
||||
|
||||
{
|
||||
@ -2319,30 +2308,37 @@ public class Attr extends JCTree.Visitor {
|
||||
boolean needsRecovery =
|
||||
resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK;
|
||||
try {
|
||||
Type target = pt();
|
||||
Type currentTarget = pt();
|
||||
List<Type> explicitParamTypes = null;
|
||||
if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) {
|
||||
//attribute lambda parameters
|
||||
attribStats(that.params, localEnv);
|
||||
explicitParamTypes = TreeInfo.types(that.params);
|
||||
target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext);
|
||||
}
|
||||
|
||||
Type lambdaType;
|
||||
if (pt() != Type.recoveryType) {
|
||||
target = targetChecker.visit(target, that);
|
||||
lambdaType = types.findDescriptorType(target);
|
||||
/* We need to adjust the target. If the target is an
|
||||
* intersection type, for example: SAM & I1 & I2 ...
|
||||
* the target will be updated to SAM
|
||||
*/
|
||||
currentTarget = targetChecker.visit(currentTarget, that);
|
||||
if (explicitParamTypes != null) {
|
||||
currentTarget = infer.instantiateFunctionalInterface(that,
|
||||
currentTarget, explicitParamTypes, resultInfo.checkContext);
|
||||
}
|
||||
lambdaType = types.findDescriptorType(currentTarget);
|
||||
} else {
|
||||
target = Type.recoveryType;
|
||||
currentTarget = Type.recoveryType;
|
||||
lambdaType = fallbackDescriptorType(that);
|
||||
}
|
||||
|
||||
setFunctionalInfo(localEnv, that, pt(), lambdaType, target, resultInfo.checkContext);
|
||||
setFunctionalInfo(localEnv, that, pt(), lambdaType, currentTarget, resultInfo.checkContext);
|
||||
|
||||
if (lambdaType.hasTag(FORALL)) {
|
||||
//lambda expression target desc cannot be a generic method
|
||||
resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target",
|
||||
lambdaType, kindName(target.tsym), target.tsym));
|
||||
lambdaType, kindName(currentTarget.tsym), currentTarget.tsym));
|
||||
result = that.type = types.createErrorType(pt());
|
||||
return;
|
||||
}
|
||||
@ -2376,7 +2372,7 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
if (arityMismatch) {
|
||||
resultInfo.checkContext.report(that, diags.fragment("incompatible.arg.types.in.lambda"));
|
||||
result = that.type = types.createErrorType(target);
|
||||
result = that.type = types.createErrorType(currentTarget);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2396,38 +2392,14 @@ public class Attr extends JCTree.Visitor {
|
||||
new ResultInfo(VAL, lambdaType.getReturnType(), funcContext);
|
||||
localEnv.info.returnResult = bodyResultInfo;
|
||||
|
||||
Log.DeferredDiagnosticHandler lambdaDeferredHandler = new Log.DeferredDiagnosticHandler(log);
|
||||
try {
|
||||
if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
|
||||
attribTree(that.getBody(), localEnv, bodyResultInfo);
|
||||
} else {
|
||||
JCBlock body = (JCBlock)that.body;
|
||||
attribStats(body.stats, localEnv);
|
||||
}
|
||||
|
||||
if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE) {
|
||||
//check for errors in lambda body
|
||||
for (JCDiagnostic deferredDiag : lambdaDeferredHandler.getDiagnostics()) {
|
||||
if (deferredDiag.getKind() == JCDiagnostic.Kind.ERROR) {
|
||||
resultInfo.checkContext
|
||||
.report(that, diags.fragment("bad.arg.types.in.lambda", TreeInfo.types(that.params),
|
||||
deferredDiag)); //hidden diag parameter
|
||||
//we mark the lambda as erroneous - this is crucial in the recovery step
|
||||
//as parameter-dependent type error won't be reported in that stage,
|
||||
//meaning that a lambda will be deemed erroeneous only if there is
|
||||
//a target-independent error (which will cause method diagnostic
|
||||
//to be skipped).
|
||||
result = that.type = types.createErrorType(target);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
lambdaDeferredHandler.reportDeferredDiagnostics();
|
||||
log.popDiagnosticHandler(lambdaDeferredHandler);
|
||||
if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) {
|
||||
attribTree(that.getBody(), localEnv, bodyResultInfo);
|
||||
} else {
|
||||
JCBlock body = (JCBlock)that.body;
|
||||
attribStats(body.stats, localEnv);
|
||||
}
|
||||
|
||||
result = check(that, target, VAL, resultInfo);
|
||||
result = check(that, currentTarget, VAL, resultInfo);
|
||||
|
||||
boolean isSpeculativeRound =
|
||||
resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE;
|
||||
@ -2435,12 +2407,20 @@ public class Attr extends JCTree.Visitor {
|
||||
preFlow(that);
|
||||
flow.analyzeLambda(env, that, make, isSpeculativeRound);
|
||||
|
||||
checkLambdaCompatible(that, lambdaType, resultInfo.checkContext, isSpeculativeRound);
|
||||
checkLambdaCompatible(that, lambdaType, resultInfo.checkContext);
|
||||
|
||||
if (!isSpeculativeRound) {
|
||||
checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, target);
|
||||
//add thrown types as bounds to the thrown types free variables if needed:
|
||||
if (resultInfo.checkContext.inferenceContext().free(lambdaType.getThrownTypes())) {
|
||||
List<Type> inferredThrownTypes = flow.analyzeLambdaThrownTypes(env, that, make);
|
||||
List<Type> thrownTypes = resultInfo.checkContext.inferenceContext().asFree(lambdaType.getThrownTypes());
|
||||
|
||||
chk.unhandled(inferredThrownTypes, thrownTypes);
|
||||
}
|
||||
|
||||
checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, currentTarget);
|
||||
}
|
||||
result = check(that, target, VAL, resultInfo);
|
||||
result = check(that, currentTarget, VAL, resultInfo);
|
||||
} catch (Types.FunctionDescriptorLookupError ex) {
|
||||
JCDiagnostic cause = ex.getDiagnostic();
|
||||
resultInfo.checkContext.report(that, cause);
|
||||
@ -2604,10 +2584,9 @@ public class Attr extends JCTree.Visitor {
|
||||
* Lambda compatibility. Check that given return types, thrown types, parameter types
|
||||
* are compatible with the expected functional interface descriptor. This means that:
|
||||
* (i) parameter types must be identical to those of the target descriptor; (ii) return
|
||||
* types must be compatible with the return type of the expected descriptor;
|
||||
* (iii) finish inference of thrown types if required.
|
||||
* types must be compatible with the return type of the expected descriptor.
|
||||
*/
|
||||
private void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext, boolean speculativeAttr) {
|
||||
private void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext) {
|
||||
Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType());
|
||||
|
||||
//return values have already been checked - but if lambda has no return
|
||||
@ -2624,11 +2603,6 @@ public class Attr extends JCTree.Visitor {
|
||||
if (!types.isSameTypes(argTypes, TreeInfo.types(tree.params))) {
|
||||
checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda"));
|
||||
}
|
||||
|
||||
if (!speculativeAttr) {
|
||||
List<Type> thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes());
|
||||
chk.unhandled(tree.inferredThrownTypes == null ? List.<Type>nil() : tree.inferredThrownTypes, thrownTypes);
|
||||
}
|
||||
}
|
||||
|
||||
private Env<AttrContext> lambdaEnv(JCLambda that, Env<AttrContext> env) {
|
||||
@ -2664,6 +2638,13 @@ public class Attr extends JCTree.Visitor {
|
||||
|
||||
if (that.getMode() == JCMemberReference.ReferenceMode.NEW) {
|
||||
exprType = chk.checkConstructorRefType(that.expr, exprType);
|
||||
if (!exprType.isErroneous() &&
|
||||
exprType.isRaw() &&
|
||||
that.typeargs != null) {
|
||||
log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()),
|
||||
diags.fragment("mref.infer.and.explicit.params"));
|
||||
exprType = types.createErrorType(exprType);
|
||||
}
|
||||
}
|
||||
|
||||
if (exprType.isErroneous()) {
|
||||
@ -3731,7 +3712,7 @@ public class Attr extends JCTree.Visitor {
|
||||
* Check that method arguments conform to its instantiation.
|
||||
**/
|
||||
public Type checkMethod(Type site,
|
||||
Symbol sym,
|
||||
final Symbol sym,
|
||||
ResultInfo resultInfo,
|
||||
Env<AttrContext> env,
|
||||
final List<JCExpression> argtrees,
|
||||
@ -3820,8 +3801,19 @@ public class Attr extends JCTree.Visitor {
|
||||
resultInfo.checkContext.report(env.tree.pos(), ex.getDiagnostic());
|
||||
return types.createErrorType(site);
|
||||
} catch (Resolve.InapplicableMethodException ex) {
|
||||
Assert.error(ex.getDiagnostic().getMessage(Locale.getDefault()));
|
||||
return null;
|
||||
final JCDiagnostic diag = ex.getDiagnostic();
|
||||
Resolve.InapplicableSymbolError errSym = rs.new InapplicableSymbolError(null) {
|
||||
@Override
|
||||
protected Pair<Symbol, JCDiagnostic> errCandidate() {
|
||||
return new Pair<Symbol, JCDiagnostic>(sym, diag);
|
||||
}
|
||||
};
|
||||
List<Type> argtypes2 = Type.map(argtypes,
|
||||
rs.new ResolveDeferredRecoveryMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase));
|
||||
JCDiagnostic errDiag = errSym.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR,
|
||||
env.tree, sym, site, sym.name, argtypes2, typeargtypes);
|
||||
log.report(errDiag);
|
||||
return types.createErrorType(site);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4206,6 +4198,7 @@ public class Attr extends JCTree.Visitor {
|
||||
ResultInfo prevReturnRes = env.info.returnResult;
|
||||
|
||||
try {
|
||||
deferredLintHandler.flush(env.tree);
|
||||
env.info.returnResult = null;
|
||||
// java.lang.Enum may not be subclassed by a non-enum
|
||||
if (st.tsym == syms.enumSym &&
|
||||
|
@ -148,7 +148,7 @@ public class Check {
|
||||
sunApiHandler = new MandatoryWarningHandler(log, verboseSunApi,
|
||||
enforceMandatoryWarnings, "sunapi", null);
|
||||
|
||||
deferredLintHandler = DeferredLintHandler.immediateHandler;
|
||||
deferredLintHandler = DeferredLintHandler.instance(context);
|
||||
}
|
||||
|
||||
/** Switch: generics enabled?
|
||||
@ -218,20 +218,6 @@ public class Check {
|
||||
return prev;
|
||||
}
|
||||
|
||||
/* This idiom should be used only in cases when it is needed to set the lint
|
||||
* of an environment that has been created in a phase previous to annotations
|
||||
* processing.
|
||||
*/
|
||||
Lint getLint() {
|
||||
return lint;
|
||||
}
|
||||
|
||||
DeferredLintHandler setDeferredLintHandler(DeferredLintHandler newDeferredLintHandler) {
|
||||
DeferredLintHandler prev = deferredLintHandler;
|
||||
deferredLintHandler = newDeferredLintHandler;
|
||||
return prev;
|
||||
}
|
||||
|
||||
MethodSymbol setMethod(MethodSymbol newMethod) {
|
||||
MethodSymbol prev = method;
|
||||
method = newMethod;
|
||||
@ -582,14 +568,19 @@ public class Check {
|
||||
/** Check for redundant casts (i.e. where source type is a subtype of target type)
|
||||
* The problem should only be reported for non-292 cast
|
||||
*/
|
||||
public void checkRedundantCast(Env<AttrContext> env, JCTypeCast tree) {
|
||||
if (!tree.type.isErroneous() &&
|
||||
(env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST))
|
||||
public void checkRedundantCast(Env<AttrContext> env, final JCTypeCast tree) {
|
||||
if (!tree.type.isErroneous()
|
||||
&& types.isSameType(tree.expr.type, tree.clazz.type)
|
||||
&& !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz))
|
||||
&& !is292targetTypeCast(tree)) {
|
||||
log.warning(Lint.LintCategory.CAST,
|
||||
tree.pos(), "redundant.cast", tree.expr.type);
|
||||
deferredLintHandler.report(new DeferredLintHandler.LintLogger() {
|
||||
@Override
|
||||
public void report() {
|
||||
if (lint.isEnabled(Lint.LintCategory.CAST))
|
||||
log.warning(Lint.LintCategory.CAST,
|
||||
tree.pos(), "redundant.cast", tree.expr.type);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
//where
|
||||
@ -1050,6 +1041,7 @@ public class Check {
|
||||
long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) {
|
||||
long mask;
|
||||
long implicit = 0;
|
||||
|
||||
switch (sym.kind) {
|
||||
case VAR:
|
||||
if (sym.owner.kind != TYP)
|
||||
@ -1070,7 +1062,10 @@ public class Check {
|
||||
} else
|
||||
mask = ConstructorFlags;
|
||||
} else if ((sym.owner.flags_field & INTERFACE) != 0) {
|
||||
if ((flags & (DEFAULT | STATIC)) != 0) {
|
||||
if ((sym.owner.flags_field & ANNOTATION) != 0) {
|
||||
mask = AnnotationTypeElementMask;
|
||||
implicit = PUBLIC | ABSTRACT;
|
||||
} else if ((flags & (DEFAULT | STATIC)) != 0) {
|
||||
mask = InterfaceMethodMask;
|
||||
implicit = PUBLIC;
|
||||
if ((flags & DEFAULT) != 0) {
|
||||
@ -1079,8 +1074,7 @@ public class Check {
|
||||
} else {
|
||||
mask = implicit = InterfaceMethodFlags;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
mask = MethodFlags;
|
||||
}
|
||||
// Imply STRICTFP if owner has STRICTFP set.
|
||||
@ -2368,7 +2362,10 @@ public class Check {
|
||||
//for each method m1 that is overridden (directly or indirectly)
|
||||
//by method 'sym' in 'site'...
|
||||
for (Symbol m1 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
|
||||
if (!sym.overrides(m1, site.tsym, types, false)) continue;
|
||||
if (!sym.overrides(m1, site.tsym, types, false)) {
|
||||
checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)m1);
|
||||
continue;
|
||||
}
|
||||
//...check each method m2 that is a member of 'site'
|
||||
for (Symbol m2 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) {
|
||||
if (m2 == m1) continue;
|
||||
@ -2406,14 +2403,17 @@ public class Check {
|
||||
for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) {
|
||||
//if (i) the signature of 'sym' is not a subsignature of m1 (seen as
|
||||
//a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error
|
||||
if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck) &&
|
||||
types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
|
||||
log.error(pos,
|
||||
"name.clash.same.erasure.no.hide",
|
||||
sym, sym.location(),
|
||||
s, s.location());
|
||||
return;
|
||||
}
|
||||
if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) {
|
||||
if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) {
|
||||
log.error(pos,
|
||||
"name.clash.same.erasure.no.hide",
|
||||
sym, sym.location(),
|
||||
s, s.location());
|
||||
return;
|
||||
} else {
|
||||
checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2496,6 +2496,62 @@ public class Check {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report warnings for potentially ambiguous method declarations. Two declarations
|
||||
* are potentially ambiguous if they feature two unrelated functional interface
|
||||
* in same argument position (in which case, a call site passing an implicit
|
||||
* lambda would be ambiguous).
|
||||
*/
|
||||
void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site,
|
||||
MethodSymbol msym1, MethodSymbol msym2) {
|
||||
if (msym1 != msym2 &&
|
||||
allowDefaultMethods &&
|
||||
lint.isEnabled(LintCategory.OVERLOADS) &&
|
||||
(msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 &&
|
||||
(msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) {
|
||||
Type mt1 = types.memberType(site, msym1);
|
||||
Type mt2 = types.memberType(site, msym2);
|
||||
//if both generic methods, adjust type variables
|
||||
if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) &&
|
||||
types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) {
|
||||
mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars);
|
||||
}
|
||||
//expand varargs methods if needed
|
||||
int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length());
|
||||
List<Type> args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true);
|
||||
List<Type> args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true);
|
||||
//if arities don't match, exit
|
||||
if (args1.length() != args2.length()) return;
|
||||
boolean potentiallyAmbiguous = false;
|
||||
while (args1.nonEmpty() && args2.nonEmpty()) {
|
||||
Type s = args1.head;
|
||||
Type t = args2.head;
|
||||
if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) {
|
||||
if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) &&
|
||||
types.findDescriptorType(s).getParameterTypes().length() > 0 &&
|
||||
types.findDescriptorType(s).getParameterTypes().length() ==
|
||||
types.findDescriptorType(t).getParameterTypes().length()) {
|
||||
potentiallyAmbiguous = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
args1 = args1.tail;
|
||||
args2 = args2.tail;
|
||||
}
|
||||
if (potentiallyAmbiguous) {
|
||||
//we found two incompatible functional interfaces with same arity
|
||||
//this means a call site passing an implicit lambda would be ambigiuous
|
||||
msym1.flags_field |= POTENTIALLY_AMBIGUOUS;
|
||||
msym2.flags_field |= POTENTIALLY_AMBIGUOUS;
|
||||
log.warning(LintCategory.OVERLOADS, pos, "potentially.ambiguous.overload",
|
||||
msym1, msym1.location(),
|
||||
msym2, msym2.location());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Report a conflict between a user symbol and a synthetic symbol.
|
||||
*/
|
||||
private void syntheticError(DiagnosticPosition pos, Symbol sym) {
|
||||
@ -3275,7 +3331,9 @@ public class Check {
|
||||
(e.sym.flags() & CLASH) == 0 &&
|
||||
sym.kind == e.sym.kind &&
|
||||
sym.name != names.error &&
|
||||
(sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) {
|
||||
(sym.kind != MTH ||
|
||||
types.hasSameArgs(sym.type, e.sym.type) ||
|
||||
types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) {
|
||||
if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) {
|
||||
varargsDuplicateError(pos, sym, e.sym);
|
||||
return true;
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
package com.sun.tools.javac.comp;
|
||||
|
||||
import com.sun.source.tree.MemberReferenceTree;
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.tree.*;
|
||||
import com.sun.tools.javac.util.*;
|
||||
@ -39,7 +40,9 @@ import com.sun.tools.javac.tree.JCTree.*;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -98,7 +101,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
emptyDeferredAttrContext =
|
||||
new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) {
|
||||
@Override
|
||||
void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List<Type> stuckVars) {
|
||||
void addDeferredAttrNode(DeferredType dt, ResultInfo ri, DeferredStuckPolicy deferredStuckPolicy) {
|
||||
Assert.error("Empty deferred context!");
|
||||
}
|
||||
@Override
|
||||
@ -149,15 +152,15 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
|
||||
class Entry {
|
||||
JCTree speculativeTree;
|
||||
Resolve.MethodResolutionPhase phase;
|
||||
ResultInfo resultInfo;
|
||||
|
||||
public Entry(JCTree speculativeTree, MethodResolutionPhase phase) {
|
||||
public Entry(JCTree speculativeTree, ResultInfo resultInfo) {
|
||||
this.speculativeTree = speculativeTree;
|
||||
this.phase = phase;
|
||||
this.resultInfo = resultInfo;
|
||||
}
|
||||
|
||||
boolean matches(Resolve.MethodResolutionPhase phase) {
|
||||
return this.phase == phase;
|
||||
boolean matches(MethodResolutionPhase phase) {
|
||||
return resultInfo.checkContext.deferredAttrContext().phase == phase;
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,12 +181,13 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
* Stores a speculative cache entry corresponding to given symbol
|
||||
* and resolution phase
|
||||
*/
|
||||
void put(Symbol msym, JCTree speculativeTree, MethodResolutionPhase phase) {
|
||||
void put(JCTree speculativeTree, ResultInfo resultInfo) {
|
||||
Symbol msym = resultInfo.checkContext.deferredAttrContext().msym;
|
||||
List<Entry> entries = cache.get(msym);
|
||||
if (entries == null) {
|
||||
entries = List.nil();
|
||||
}
|
||||
cache.put(msym, entries.prepend(new Entry(speculativeTree, phase)));
|
||||
cache.put(msym, entries.prepend(new Entry(speculativeTree, resultInfo)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -203,15 +207,24 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
* attribution round must follow one or more speculative rounds.
|
||||
*/
|
||||
Type check(ResultInfo resultInfo) {
|
||||
return check(resultInfo, stuckVars(tree, env, resultInfo), basicCompleter);
|
||||
DeferredStuckPolicy deferredStuckPolicy;
|
||||
if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
|
||||
deferredStuckPolicy = dummyStuckPolicy;
|
||||
} else if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE) {
|
||||
deferredStuckPolicy = new OverloadStuckPolicy(resultInfo, this);
|
||||
} else {
|
||||
deferredStuckPolicy = new CheckStuckPolicy(resultInfo, this);
|
||||
}
|
||||
return check(resultInfo, deferredStuckPolicy, basicCompleter);
|
||||
}
|
||||
|
||||
Type check(ResultInfo resultInfo, List<Type> stuckVars, DeferredTypeCompleter deferredTypeCompleter) {
|
||||
private Type check(ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy,
|
||||
DeferredTypeCompleter deferredTypeCompleter) {
|
||||
DeferredAttrContext deferredAttrContext =
|
||||
resultInfo.checkContext.deferredAttrContext();
|
||||
Assert.check(deferredAttrContext != emptyDeferredAttrContext);
|
||||
if (stuckVars.nonEmpty()) {
|
||||
deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars);
|
||||
if (deferredStuckPolicy.isStuck()) {
|
||||
deferredAttrContext.addDeferredAttrNode(this, resultInfo, deferredStuckPolicy);
|
||||
return Type.noType;
|
||||
} else {
|
||||
try {
|
||||
@ -236,6 +249,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A basic completer for deferred types. This completer type-checks a deferred type
|
||||
* using attribution; depending on the attribution mode, this could be either standard
|
||||
@ -249,7 +263,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
//speculative rounds...
|
||||
Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE);
|
||||
JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo);
|
||||
dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase);
|
||||
dt.speculativeCache.put(speculativeTree, resultInfo);
|
||||
return speculativeTree.type;
|
||||
case CHECK:
|
||||
Assert.check(dt.mode != null);
|
||||
@ -267,6 +281,45 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Policy for detecting stuck expressions. Different criteria might cause
|
||||
* an expression to be judged as stuck, depending on whether the check
|
||||
* is performed during overload resolution or after most specific.
|
||||
*/
|
||||
interface DeferredStuckPolicy {
|
||||
/**
|
||||
* Has the policy detected that a given expression should be considered stuck?
|
||||
*/
|
||||
boolean isStuck();
|
||||
/**
|
||||
* Get the set of inference variables a given expression depends upon.
|
||||
*/
|
||||
Set<Type> stuckVars();
|
||||
/**
|
||||
* Get the set of inference variables which might get new constraints
|
||||
* if a given expression is being type-checked.
|
||||
*/
|
||||
Set<Type> depVars();
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic stuck policy; an expression is never considered to be stuck.
|
||||
*/
|
||||
DeferredStuckPolicy dummyStuckPolicy = new DeferredStuckPolicy() {
|
||||
@Override
|
||||
public boolean isStuck() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public Set<Type> stuckVars() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
@Override
|
||||
public Set<Type> depVars() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The 'mode' in which the deferred type is to be type-checked
|
||||
*/
|
||||
@ -388,8 +441,9 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
* Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable
|
||||
* Nodes added this way act as 'roots' for the out-of-order method checking process.
|
||||
*/
|
||||
void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
|
||||
deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, stuckVars));
|
||||
void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo,
|
||||
DeferredStuckPolicy deferredStuckPolicy) {
|
||||
deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, deferredStuckPolicy));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -400,23 +454,52 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
*/
|
||||
void complete() {
|
||||
while (!deferredAttrNodes.isEmpty()) {
|
||||
Set<Type> stuckVars = new LinkedHashSet<Type>();
|
||||
Map<Type, Set<Type>> depVarsMap = new LinkedHashMap<Type, Set<Type>>();
|
||||
List<Type> stuckVars = List.nil();
|
||||
boolean progress = false;
|
||||
//scan a defensive copy of the node list - this is because a deferred
|
||||
//attribution round can add new nodes to the list
|
||||
for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) {
|
||||
if (!deferredAttrNode.process(this)) {
|
||||
stuckVars.addAll(deferredAttrNode.stuckVars);
|
||||
List<Type> restStuckVars =
|
||||
List.from(deferredAttrNode.deferredStuckPolicy.stuckVars())
|
||||
.intersect(inferenceContext.restvars());
|
||||
stuckVars = stuckVars.prependList(restStuckVars);
|
||||
//update dependency map
|
||||
for (Type t : List.from(deferredAttrNode.deferredStuckPolicy.depVars())
|
||||
.intersect(inferenceContext.restvars())) {
|
||||
Set<Type> prevDeps = depVarsMap.get(t);
|
||||
if (prevDeps == null) {
|
||||
prevDeps = new LinkedHashSet<Type>();
|
||||
depVarsMap.put(t, prevDeps);
|
||||
}
|
||||
prevDeps.addAll(restStuckVars);
|
||||
}
|
||||
} else {
|
||||
deferredAttrNodes.remove(deferredAttrNode);
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
if (!progress) {
|
||||
DeferredAttrContext dac = this;
|
||||
while (dac != emptyDeferredAttrContext) {
|
||||
if (dac.mode == AttrMode.SPECULATIVE) {
|
||||
//unsticking does not take place during overload
|
||||
break;
|
||||
}
|
||||
dac = dac.parent;
|
||||
}
|
||||
//remove all variables that have already been instantiated
|
||||
//from the list of stuck variables
|
||||
inferenceContext.solveAny(List.from(stuckVars), warn);
|
||||
inferenceContext.notifyChange();
|
||||
try {
|
||||
inferenceContext.solveAny(stuckVars, depVarsMap, warn);
|
||||
inferenceContext.notifyChange();
|
||||
} catch (Infer.GraphStrategy.NodeNotFoundException ex) {
|
||||
//this means that we are in speculative mode and the
|
||||
//set of contraints are too tight for progess to be made.
|
||||
//Just leave the remaining expressions as stuck.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -426,7 +509,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
* Class representing a deferred attribution node. It keeps track of
|
||||
* a deferred type, along with the expected target type information.
|
||||
*/
|
||||
class DeferredAttrNode implements Infer.FreeTypeListener {
|
||||
class DeferredAttrNode {
|
||||
|
||||
/** underlying deferred type */
|
||||
DeferredType dt;
|
||||
@ -434,22 +517,13 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
/** underlying target type information */
|
||||
ResultInfo resultInfo;
|
||||
|
||||
/** list of uninferred inference variables causing this node to be stuck */
|
||||
List<Type> stuckVars;
|
||||
/** stuck policy associated with this node */
|
||||
DeferredStuckPolicy deferredStuckPolicy;
|
||||
|
||||
DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List<Type> stuckVars) {
|
||||
DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy) {
|
||||
this.dt = dt;
|
||||
this.resultInfo = resultInfo;
|
||||
this.stuckVars = stuckVars;
|
||||
if (!stuckVars.isEmpty()) {
|
||||
resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void typesInferred(InferenceContext inferenceContext) {
|
||||
stuckVars = List.nil();
|
||||
resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
|
||||
this.deferredStuckPolicy = deferredStuckPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -457,24 +531,41 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
* Invariant: a stuck node cannot be processed.
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
boolean process(DeferredAttrContext deferredAttrContext) {
|
||||
boolean process(final DeferredAttrContext deferredAttrContext) {
|
||||
switch (deferredAttrContext.mode) {
|
||||
case SPECULATIVE:
|
||||
dt.check(resultInfo, List.<Type>nil(), new StructuralStuckChecker());
|
||||
return true;
|
||||
if (deferredStuckPolicy.isStuck()) {
|
||||
dt.check(resultInfo, dummyStuckPolicy, new StructuralStuckChecker());
|
||||
return true;
|
||||
} else {
|
||||
Assert.error("Cannot get here");
|
||||
}
|
||||
case CHECK:
|
||||
if (stuckVars.nonEmpty()) {
|
||||
if (deferredStuckPolicy.isStuck()) {
|
||||
//stuck expression - see if we can propagate
|
||||
if (deferredAttrContext.parent != emptyDeferredAttrContext &&
|
||||
Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, List.from(stuckVars))) {
|
||||
deferredAttrContext.parent.deferredAttrNodes.add(this);
|
||||
dt.check(resultInfo, List.<Type>nil(), dummyCompleter);
|
||||
Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars,
|
||||
List.from(deferredStuckPolicy.stuckVars()))) {
|
||||
deferredAttrContext.parent.addDeferredAttrNode(dt,
|
||||
resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) {
|
||||
@Override
|
||||
public InferenceContext inferenceContext() {
|
||||
return deferredAttrContext.parent.inferenceContext;
|
||||
}
|
||||
@Override
|
||||
public DeferredAttrContext deferredAttrContext() {
|
||||
return deferredAttrContext.parent;
|
||||
}
|
||||
}), deferredStuckPolicy);
|
||||
dt.tree.type = Type.stuckType;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
dt.check(resultInfo, stuckVars, basicCompleter);
|
||||
ResultInfo instResultInfo =
|
||||
resultInfo.dup(deferredAttrContext.inferenceContext.asInstType(resultInfo.pt));
|
||||
dt.check(instResultInfo, dummyStuckPolicy, basicCompleter);
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
@ -489,12 +580,14 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
|
||||
ResultInfo resultInfo;
|
||||
InferenceContext inferenceContext;
|
||||
Env<AttrContext> env;
|
||||
|
||||
public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) {
|
||||
this.resultInfo = resultInfo;
|
||||
this.inferenceContext = deferredAttrContext.inferenceContext;
|
||||
this.env = dt.env;
|
||||
dt.tree.accept(this);
|
||||
dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase);
|
||||
dt.speculativeCache.put(stuckTree, resultInfo);
|
||||
return Type.noType;
|
||||
}
|
||||
|
||||
@ -541,15 +634,25 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
} catch (Types.FunctionDescriptorLookupError ex) {
|
||||
checkContext.report(null, ex.getDiagnostic());
|
||||
}
|
||||
switch (tree.sym.kind) {
|
||||
Env<AttrContext> localEnv = env.dup(tree);
|
||||
JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
|
||||
attr.memberReferenceQualifierResult(tree));
|
||||
ListBuffer<Type> argtypes = ListBuffer.lb();
|
||||
for (Type t : types.findDescriptorType(pt).getParameterTypes()) {
|
||||
argtypes.append(Type.noType);
|
||||
}
|
||||
JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
|
||||
mref2.expr = exprTree;
|
||||
Pair<Symbol, ?> lookupRes =
|
||||
rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
|
||||
tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, inferenceContext);
|
||||
switch (lookupRes.fst.kind) {
|
||||
//note: as argtypes are erroneous types, type-errors must
|
||||
//have been caused by arity mismatch
|
||||
case Kinds.ABSENT_MTH:
|
||||
case Kinds.WRONG_MTH:
|
||||
case Kinds.WRONG_MTHS:
|
||||
case Kinds.STATICERR:
|
||||
case Kinds.MISSING_ENCL:
|
||||
checkContext.report(null, diags.fragment("incompatible.arg.types.in.mref"));
|
||||
checkContext.report(tree, diags.fragment("incompatible.arg.types.in.mref"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -575,18 +678,12 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
infer.emptyContext, emptyDeferredAttrContext, types.noWarnings);
|
||||
}
|
||||
|
||||
protected boolean validState(DeferredType dt) {
|
||||
return dt.mode != null &&
|
||||
deferredAttrContext.mode.ordinal() <= dt.mode.ordinal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type apply(Type t) {
|
||||
if (!t.hasTag(DEFERRED)) {
|
||||
return t.map(this);
|
||||
} else {
|
||||
DeferredType dt = (DeferredType)t;
|
||||
Assert.check(validState(dt));
|
||||
return typeOf(dt);
|
||||
}
|
||||
}
|
||||
@ -623,11 +720,6 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
recover(dt) : owntype;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean validState(DeferredType dt) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Synthesize a type for a deferred type that hasn't been previously
|
||||
* reduced to an ordinary type. Functional deferred types and conditionals
|
||||
@ -646,25 +738,6 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of inference variables that need to be inferred before
|
||||
* an AST node can be type-checked
|
||||
*/
|
||||
@SuppressWarnings("fallthrough")
|
||||
List<Type> stuckVars(JCTree tree, Env<AttrContext> env, ResultInfo resultInfo) {
|
||||
if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) {
|
||||
return List.nil();
|
||||
} else {
|
||||
return stuckVarsInternal(tree, resultInfo.pt, env, resultInfo.checkContext.inferenceContext());
|
||||
}
|
||||
}
|
||||
//where
|
||||
private List<Type> stuckVarsInternal(JCTree tree, Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
|
||||
StuckChecker sc = new StuckChecker(pt, env, inferenceContext);
|
||||
sc.scan(tree);
|
||||
return List.from(sc.stuckVars);
|
||||
}
|
||||
|
||||
/**
|
||||
* A special tree scanner that would only visit portions of a given tree.
|
||||
* The set of nodes visited by the scanner can be customized at construction-time.
|
||||
@ -737,17 +810,41 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
* inferring types that make some of the nested expressions incompatible
|
||||
* with their corresponding instantiated target
|
||||
*/
|
||||
class StuckChecker extends PolyScanner {
|
||||
class CheckStuckPolicy extends PolyScanner implements DeferredStuckPolicy, Infer.FreeTypeListener {
|
||||
|
||||
Type pt;
|
||||
Env<AttrContext> env;
|
||||
Infer.InferenceContext inferenceContext;
|
||||
Set<Type> stuckVars = new LinkedHashSet<Type>();
|
||||
Set<Type> depVars = new LinkedHashSet<Type>();
|
||||
|
||||
StuckChecker(Type pt, Env<AttrContext> env, Infer.InferenceContext inferenceContext) {
|
||||
this.pt = pt;
|
||||
this.env = env;
|
||||
this.inferenceContext = inferenceContext;
|
||||
@Override
|
||||
public boolean isStuck() {
|
||||
return !stuckVars.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Type> stuckVars() {
|
||||
return stuckVars;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Type> depVars() {
|
||||
return depVars;
|
||||
}
|
||||
|
||||
public CheckStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
|
||||
this.pt = resultInfo.pt;
|
||||
this.inferenceContext = resultInfo.checkContext.inferenceContext();
|
||||
scan(dt.tree);
|
||||
if (!stuckVars.isEmpty()) {
|
||||
resultInfo.checkContext.inferenceContext()
|
||||
.addFreeTypeListener(List.from(stuckVars), this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void typesInferred(InferenceContext inferenceContext) {
|
||||
stuckVars.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -763,6 +860,7 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT &&
|
||||
freeArgVars.nonEmpty()) {
|
||||
stuckVars.addAll(freeArgVars);
|
||||
depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
|
||||
}
|
||||
scanLambdaBody(tree, descType.getReturnType());
|
||||
}
|
||||
@ -780,41 +878,34 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
|
||||
Type descType = types.findDescriptorType(pt);
|
||||
List<Type> freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes());
|
||||
Env<AttrContext> localEnv = env.dup(tree, env.info.dup());
|
||||
if (freeArgVars.nonEmpty()) {
|
||||
//perform arity-based check
|
||||
JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
|
||||
attr.memberReferenceQualifierResult(tree));
|
||||
ListBuffer<Type> argtypes = ListBuffer.lb();
|
||||
for (Type t : descType.getParameterTypes()) {
|
||||
argtypes.append(Type.noType);
|
||||
}
|
||||
JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
|
||||
mref2.expr = exprTree;
|
||||
Pair<Symbol, ReferenceLookupHelper> lookupRes =
|
||||
rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
|
||||
tree.name, argtypes.toList(), null, true, rs.arityMethodCheck,
|
||||
inferenceContext);
|
||||
Symbol res = tree.sym = lookupRes.fst;
|
||||
if (res.kind >= Kinds.ERRONEOUS ||
|
||||
res.type.hasTag(FORALL) ||
|
||||
(res.flags() & Flags.VARARGS) != 0 ||
|
||||
(TreeInfo.isStaticSelector(exprTree, tree.name.table.names) &&
|
||||
exprTree.type.isRaw())) {
|
||||
stuckVars.addAll(freeArgVars);
|
||||
}
|
||||
if (freeArgVars.nonEmpty() &&
|
||||
tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) {
|
||||
stuckVars.addAll(freeArgVars);
|
||||
depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType()));
|
||||
}
|
||||
}
|
||||
|
||||
void scanLambdaBody(JCLambda lambda, final Type pt) {
|
||||
if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) {
|
||||
stuckVars.addAll(stuckVarsInternal(lambda.body, pt, env, inferenceContext));
|
||||
Type prevPt = this.pt;
|
||||
try {
|
||||
this.pt = pt;
|
||||
scan(lambda.body);
|
||||
} finally {
|
||||
this.pt = prevPt;
|
||||
}
|
||||
} else {
|
||||
LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() {
|
||||
@Override
|
||||
public void visitReturn(JCReturn tree) {
|
||||
if (tree.expr != null) {
|
||||
stuckVars.addAll(stuckVarsInternal(tree.expr, pt, env, inferenceContext));
|
||||
Type prevPt = CheckStuckPolicy.this.pt;
|
||||
try {
|
||||
CheckStuckPolicy.this.pt = pt;
|
||||
CheckStuckPolicy.this.scan(tree.expr);
|
||||
} finally {
|
||||
CheckStuckPolicy.this.pt = prevPt;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -823,6 +914,42 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This visitor is used to check that structural expressions conform
|
||||
* to their target - this step is required as inference could end up
|
||||
* inferring types that make some of the nested expressions incompatible
|
||||
* with their corresponding instantiated target
|
||||
*/
|
||||
class OverloadStuckPolicy extends CheckStuckPolicy implements DeferredStuckPolicy {
|
||||
|
||||
boolean stuck;
|
||||
|
||||
@Override
|
||||
public boolean isStuck() {
|
||||
return super.isStuck() || stuck;
|
||||
}
|
||||
|
||||
public OverloadStuckPolicy(ResultInfo resultInfo, DeferredType dt) {
|
||||
super(resultInfo, dt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLambda(JCLambda tree) {
|
||||
super.visitLambda(tree);
|
||||
if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT) {
|
||||
stuck = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReference(JCMemberReference tree) {
|
||||
super.visitReference(tree);
|
||||
if (tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) {
|
||||
stuck = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the argument expression {@code expr} need speculative type-checking?
|
||||
*/
|
||||
@ -904,6 +1031,26 @@ public class DeferredAttr extends JCTree.Visitor {
|
||||
|
||||
@Override
|
||||
public void visitReference(JCMemberReference tree) {
|
||||
//perform arity-based check
|
||||
Env<AttrContext> localEnv = env.dup(tree);
|
||||
JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv,
|
||||
attr.memberReferenceQualifierResult(tree));
|
||||
JCMemberReference mref2 = new TreeCopier<Void>(make).copy(tree);
|
||||
mref2.expr = exprTree;
|
||||
Pair<Symbol, ReferenceLookupHelper> lookupRes =
|
||||
rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type,
|
||||
tree.name, List.<Type>nil(), null, true, rs.nilMethodCheck,
|
||||
infer.emptyContext);
|
||||
Symbol res = tree.sym = lookupRes.fst;
|
||||
if (res.kind >= Kinds.ERRONEOUS ||
|
||||
res.type.hasTag(FORALL) ||
|
||||
(res.flags() & Flags.VARARGS) != 0 ||
|
||||
(TreeInfo.isStaticSelector(exprTree, tree.name.table.names) &&
|
||||
exprTree.type.isRaw())) {
|
||||
tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED;
|
||||
} else {
|
||||
tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED;
|
||||
}
|
||||
//a method reference is always a poly expression
|
||||
result = ArgumentExpressionKind.POLY;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,17 +40,17 @@ import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph;
|
||||
import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node;
|
||||
import com.sun.tools.javac.comp.Resolve.InapplicableMethodException;
|
||||
import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeSet;
|
||||
import com.sun.tools.javac.util.GraphUtils.TarjanNode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.sun.tools.javac.code.TypeTag.*;
|
||||
|
||||
@ -113,6 +113,12 @@ public class Infer {
|
||||
super(diags);
|
||||
}
|
||||
|
||||
@Override
|
||||
InapplicableMethodException setMessage() {
|
||||
//no message to set
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
InapplicableMethodException setMessage(JCDiagnostic diag) {
|
||||
messages = messages.append(diag);
|
||||
@ -1006,10 +1012,24 @@ public class Infer {
|
||||
* and (ii) tell th engine when we are done fixing inference variables
|
||||
*/
|
||||
interface GraphStrategy {
|
||||
|
||||
/**
|
||||
* A NodeNotFoundException is thrown whenever an inference strategy fails
|
||||
* to pick the next node to solve in the inference graph.
|
||||
*/
|
||||
public static class NodeNotFoundException extends RuntimeException {
|
||||
private static final long serialVersionUID = 0;
|
||||
|
||||
InferenceGraph graph;
|
||||
|
||||
public NodeNotFoundException(InferenceGraph graph) {
|
||||
this.graph = graph;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Pick the next node (leaf) to solve in the graph
|
||||
*/
|
||||
Node pickNode(InferenceGraph g);
|
||||
Node pickNode(InferenceGraph g) throws NodeNotFoundException;
|
||||
/**
|
||||
* Is this the last step?
|
||||
*/
|
||||
@ -1022,7 +1042,10 @@ public class Infer {
|
||||
*/
|
||||
abstract class LeafSolver implements GraphStrategy {
|
||||
public Node pickNode(InferenceGraph g) {
|
||||
Assert.check(!g.nodes.isEmpty(), "No nodes to solve!");
|
||||
if (g.nodes.isEmpty()) {
|
||||
//should not happen
|
||||
throw new NodeNotFoundException(g);
|
||||
};
|
||||
return g.nodes.get(0);
|
||||
}
|
||||
|
||||
@ -1069,6 +1092,7 @@ public class Infer {
|
||||
*/
|
||||
abstract class BestLeafSolver extends LeafSolver {
|
||||
|
||||
/** list of ivars of which at least one must be solved */
|
||||
List<Type> varsToSolve;
|
||||
|
||||
BestLeafSolver(List<Type> varsToSolve) {
|
||||
@ -1076,54 +1100,66 @@ public class Infer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the minimum path that goes from a given node to any of the nodes
|
||||
* containing a variable in {@code varsToSolve}. For any given path, the cost
|
||||
* is computed as the total number of type-variables that should be eagerly
|
||||
* instantiated across that path.
|
||||
* Computes a path that goes from a given node to the leafs in the graph.
|
||||
* Typically this will start from a node containing a variable in
|
||||
* {@code varsToSolve}. For any given path, the cost is computed as the total
|
||||
* number of type-variables that should be eagerly instantiated across that path.
|
||||
*/
|
||||
int computeMinPath(InferenceGraph g, Node n) {
|
||||
return computeMinPath(g, n, List.<Node>nil(), 0);
|
||||
Pair<List<Node>, Integer> computeTreeToLeafs(Node n) {
|
||||
Pair<List<Node>, Integer> cachedPath = treeCache.get(n);
|
||||
if (cachedPath == null) {
|
||||
//cache miss
|
||||
if (n.isLeaf()) {
|
||||
//if leaf, stop
|
||||
cachedPath = new Pair<List<Node>, Integer>(List.of(n), n.data.length());
|
||||
} else {
|
||||
//if non-leaf, proceed recursively
|
||||
Pair<List<Node>, Integer> path = new Pair<List<Node>, Integer>(List.of(n), n.data.length());
|
||||
for (Node n2 : n.getAllDependencies()) {
|
||||
if (n2 == n) continue;
|
||||
Pair<List<Node>, Integer> subpath = computeTreeToLeafs(n2);
|
||||
path = new Pair<List<Node>, Integer>(
|
||||
path.fst.prependList(subpath.fst),
|
||||
path.snd + subpath.snd);
|
||||
}
|
||||
cachedPath = path;
|
||||
}
|
||||
//save results in cache
|
||||
treeCache.put(n, cachedPath);
|
||||
}
|
||||
return cachedPath;
|
||||
}
|
||||
|
||||
int computeMinPath(InferenceGraph g, Node n, List<Node> path, int cost) {
|
||||
if (path.contains(n)) return Integer.MAX_VALUE;
|
||||
List<Node> path2 = path.prepend(n);
|
||||
int cost2 = cost + n.data.size();
|
||||
if (!Collections.disjoint(n.data, varsToSolve)) {
|
||||
return cost2;
|
||||
} else {
|
||||
int bestPath = Integer.MAX_VALUE;
|
||||
for (Node n2 : g.nodes) {
|
||||
if (n2.deps.contains(n)) {
|
||||
int res = computeMinPath(g, n2, path2, cost2);
|
||||
if (res < bestPath) {
|
||||
bestPath = res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestPath;
|
||||
}
|
||||
}
|
||||
/** cache used to avoid redundant computation of tree costs */
|
||||
final Map<Node, Pair<List<Node>, Integer>> treeCache =
|
||||
new HashMap<Node, Pair<List<Node>, Integer>>();
|
||||
|
||||
/** constant value used to mark non-existent paths */
|
||||
final Pair<List<Node>, Integer> noPath =
|
||||
new Pair<List<Node>, Integer>(null, Integer.MAX_VALUE);
|
||||
|
||||
/**
|
||||
* Pick the leaf that minimize cost
|
||||
*/
|
||||
@Override
|
||||
public Node pickNode(final InferenceGraph g) {
|
||||
final Map<Node, Integer> leavesMap = new HashMap<Node, Integer>();
|
||||
treeCache.clear(); //graph changes at every step - cache must be cleared
|
||||
Pair<List<Node>, Integer> bestPath = noPath;
|
||||
for (Node n : g.nodes) {
|
||||
if (n.isLeaf(n)) {
|
||||
leavesMap.put(n, computeMinPath(g, n));
|
||||
if (!Collections.disjoint(n.data, varsToSolve)) {
|
||||
Pair<List<Node>, Integer> path = computeTreeToLeafs(n);
|
||||
//discard all paths containing at least a node in the
|
||||
//closure computed above
|
||||
if (path.snd < bestPath.snd) {
|
||||
bestPath = path;
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert.check(!leavesMap.isEmpty(), "No nodes to solve!");
|
||||
TreeSet<Node> orderedLeaves = new TreeSet<Node>(new Comparator<Node>() {
|
||||
public int compare(Node n1, Node n2) {
|
||||
return leavesMap.get(n1) - leavesMap.get(n2);
|
||||
}
|
||||
});
|
||||
orderedLeaves.addAll(leavesMap.keySet());
|
||||
return orderedLeaves.first();
|
||||
if (bestPath == noPath) {
|
||||
//no path leads there
|
||||
throw new NodeNotFoundException(g);
|
||||
}
|
||||
return bestPath.fst.head;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1320,6 +1356,33 @@ public class Infer {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* There are two kinds of dependencies between inference variables. The basic
|
||||
* kind of dependency (or bound dependency) arises when a variable mention
|
||||
* another variable in one of its bounds. There's also a more subtle kind
|
||||
* of dependency that arises when a variable 'might' lead to better constraints
|
||||
* on another variable (this is typically the case with variables holding up
|
||||
* stuck expressions).
|
||||
*/
|
||||
enum DependencyKind implements GraphUtils.DependencyKind {
|
||||
|
||||
/** bound dependency */
|
||||
BOUND("dotted"),
|
||||
/** stuck dependency */
|
||||
STUCK("dashed");
|
||||
|
||||
final String dotSyle;
|
||||
|
||||
private DependencyKind(String dotSyle) {
|
||||
this.dotSyle = dotSyle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDotStyle() {
|
||||
return dotSyle;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the graph inference solver - the solver organizes all inference variables in
|
||||
* a given inference context by bound dependencies - in the general case, such dependencies
|
||||
@ -1331,10 +1394,12 @@ public class Infer {
|
||||
class GraphSolver {
|
||||
|
||||
InferenceContext inferenceContext;
|
||||
Map<Type, Set<Type>> stuckDeps;
|
||||
Warner warn;
|
||||
|
||||
GraphSolver(InferenceContext inferenceContext, Warner warn) {
|
||||
GraphSolver(InferenceContext inferenceContext, Map<Type, Set<Type>> stuckDeps, Warner warn) {
|
||||
this.inferenceContext = inferenceContext;
|
||||
this.stuckDeps = stuckDeps;
|
||||
this.warn = warn;
|
||||
}
|
||||
|
||||
@ -1345,7 +1410,7 @@ public class Infer {
|
||||
*/
|
||||
void solve(GraphStrategy sstrategy) {
|
||||
checkWithinBounds(inferenceContext, warn); //initial propagation of bounds
|
||||
InferenceGraph inferenceGraph = new InferenceGraph();
|
||||
InferenceGraph inferenceGraph = new InferenceGraph(stuckDeps);
|
||||
while (!sstrategy.done()) {
|
||||
InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph);
|
||||
List<Type> varsToSolve = List.from(nodeToSolve.data);
|
||||
@ -1390,64 +1455,172 @@ public class Infer {
|
||||
*/
|
||||
class Node extends GraphUtils.TarjanNode<ListBuffer<Type>> {
|
||||
|
||||
Set<Node> deps;
|
||||
/** map listing all dependencies (grouped by kind) */
|
||||
EnumMap<DependencyKind, Set<Node>> deps;
|
||||
|
||||
Node(Type ivar) {
|
||||
super(ListBuffer.of(ivar));
|
||||
this.deps = new HashSet<Node>();
|
||||
this.deps = new EnumMap<DependencyKind, Set<Node>>(DependencyKind.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends Node> getDependencies() {
|
||||
return deps;
|
||||
public GraphUtils.DependencyKind[] getSupportedDependencyKinds() {
|
||||
return DependencyKind.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String printDependency(GraphUtils.Node<ListBuffer<Type>> to) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
String sep = "";
|
||||
for (Type from : data) {
|
||||
UndetVar uv = (UndetVar)inferenceContext.asFree(from);
|
||||
for (Type bound : uv.getBounds(InferenceBound.values())) {
|
||||
if (bound.containsAny(List.from(to.data))) {
|
||||
buf.append(sep);
|
||||
buf.append(bound);
|
||||
sep = ",";
|
||||
public String getDependencyName(GraphUtils.Node<ListBuffer<Type>> to, GraphUtils.DependencyKind dk) {
|
||||
if (dk == DependencyKind.STUCK) return "";
|
||||
else {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
String sep = "";
|
||||
for (Type from : data) {
|
||||
UndetVar uv = (UndetVar)inferenceContext.asFree(from);
|
||||
for (Type bound : uv.getBounds(InferenceBound.values())) {
|
||||
if (bound.containsAny(List.from(to.data))) {
|
||||
buf.append(sep);
|
||||
buf.append(bound);
|
||||
sep = ",";
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
boolean isLeaf(Node n) {
|
||||
@Override
|
||||
public Iterable<? extends Node> getAllDependencies() {
|
||||
return getDependencies(DependencyKind.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<? extends TarjanNode<ListBuffer<Type>>> getDependenciesByKind(GraphUtils.DependencyKind dk) {
|
||||
return getDependencies((DependencyKind)dk);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves all dependencies with given kind(s).
|
||||
*/
|
||||
protected Set<Node> getDependencies(DependencyKind... depKinds) {
|
||||
Set<Node> buf = new LinkedHashSet<Node>();
|
||||
for (DependencyKind dk : depKinds) {
|
||||
Set<Node> depsByKind = deps.get(dk);
|
||||
if (depsByKind != null) {
|
||||
buf.addAll(depsByKind);
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds dependency with given kind.
|
||||
*/
|
||||
protected void addDependency(DependencyKind dk, Node depToAdd) {
|
||||
Set<Node> depsByKind = deps.get(dk);
|
||||
if (depsByKind == null) {
|
||||
depsByKind = new LinkedHashSet<Node>();
|
||||
deps.put(dk, depsByKind);
|
||||
}
|
||||
depsByKind.add(depToAdd);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple dependencies of same given kind.
|
||||
*/
|
||||
protected void addDependencies(DependencyKind dk, Set<Node> depsToAdd) {
|
||||
for (Node n : depsToAdd) {
|
||||
addDependency(dk, n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a dependency, regardless of its kind.
|
||||
*/
|
||||
protected Set<DependencyKind> removeDependency(Node n) {
|
||||
Set<DependencyKind> removedKinds = new HashSet<>();
|
||||
for (DependencyKind dk : DependencyKind.values()) {
|
||||
Set<Node> depsByKind = deps.get(dk);
|
||||
if (depsByKind == null) continue;
|
||||
if (depsByKind.remove(n)) {
|
||||
removedKinds.add(dk);
|
||||
}
|
||||
}
|
||||
return removedKinds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute closure of a give node, by recursively walking
|
||||
* through all its dependencies (of given kinds)
|
||||
*/
|
||||
protected Set<Node> closure(DependencyKind... depKinds) {
|
||||
boolean progress = true;
|
||||
Set<Node> closure = new HashSet<Node>();
|
||||
closure.add(this);
|
||||
while (progress) {
|
||||
progress = false;
|
||||
for (Node n1 : new HashSet<Node>(closure)) {
|
||||
progress = closure.addAll(n1.getDependencies(depKinds));
|
||||
}
|
||||
}
|
||||
return closure;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this node a leaf? This means either the node has no dependencies,
|
||||
* or it just has self-dependencies.
|
||||
*/
|
||||
protected boolean isLeaf() {
|
||||
//no deps, or only one self dep
|
||||
return (n.deps.isEmpty() ||
|
||||
n.deps.size() == 1 && n.deps.contains(n));
|
||||
Set<Node> allDeps = getDependencies(DependencyKind.BOUND, DependencyKind.STUCK);
|
||||
if (allDeps.isEmpty()) return true;
|
||||
for (Node n : allDeps) {
|
||||
if (n != this) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void mergeWith(List<? extends Node> nodes) {
|
||||
/**
|
||||
* Merge this node with another node, acquiring its dependencies.
|
||||
* This routine is used to merge all cyclic node together and
|
||||
* form an acyclic graph.
|
||||
*/
|
||||
protected void mergeWith(List<? extends Node> nodes) {
|
||||
for (Node n : nodes) {
|
||||
Assert.check(n.data.length() == 1, "Attempt to merge a compound node!");
|
||||
data.appendList(n.data);
|
||||
deps.addAll(n.deps);
|
||||
for (DependencyKind dk : DependencyKind.values()) {
|
||||
addDependencies(dk, n.getDependencies(dk));
|
||||
}
|
||||
}
|
||||
//update deps
|
||||
Set<Node> deps2 = new HashSet<Node>();
|
||||
for (Node d : deps) {
|
||||
if (data.contains(d.data.first())) {
|
||||
deps2.add(this);
|
||||
} else {
|
||||
deps2.add(d);
|
||||
EnumMap<DependencyKind, Set<Node>> deps2 = new EnumMap<DependencyKind, Set<Node>>(DependencyKind.class);
|
||||
for (DependencyKind dk : DependencyKind.values()) {
|
||||
for (Node d : getDependencies(dk)) {
|
||||
Set<Node> depsByKind = deps2.get(dk);
|
||||
if (depsByKind == null) {
|
||||
depsByKind = new LinkedHashSet<Node>();
|
||||
deps2.put(dk, depsByKind);
|
||||
}
|
||||
if (data.contains(d.data.first())) {
|
||||
depsByKind.add(this);
|
||||
} else {
|
||||
depsByKind.add(d);
|
||||
}
|
||||
}
|
||||
}
|
||||
deps = deps2;
|
||||
}
|
||||
|
||||
void graphChanged(Node from, Node to) {
|
||||
if (deps.contains(from)) {
|
||||
deps.remove(from);
|
||||
/**
|
||||
* Notify all nodes that something has changed in the graph
|
||||
* topology.
|
||||
*/
|
||||
private void graphChanged(Node from, Node to) {
|
||||
for (DependencyKind dk : removeDependency(from)) {
|
||||
if (to != null) {
|
||||
deps.add(to);
|
||||
addDependency(dk, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1456,8 +1629,21 @@ public class Infer {
|
||||
/** the nodes in the inference graph */
|
||||
ArrayList<Node> nodes;
|
||||
|
||||
InferenceGraph() {
|
||||
initNodes();
|
||||
InferenceGraph(Map<Type, Set<Type>> optDeps) {
|
||||
initNodes(optDeps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic lookup helper for retrieving a graph node given an inference
|
||||
* variable type.
|
||||
*/
|
||||
public Node findNode(Type t) {
|
||||
for (Node n : nodes) {
|
||||
if (n.data.contains(t)) {
|
||||
return n;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1484,24 +1670,32 @@ public class Infer {
|
||||
* Create the graph nodes. First a simple node is created for every inference
|
||||
* variables to be solved. Then Tarjan is used to found all connected components
|
||||
* in the graph. For each component containing more than one node, a super node is
|
||||
* created, effectively replacing the original cyclic nodes.
|
||||
* created, effectively replacing the original cyclic nodes.
|
||||
*/
|
||||
void initNodes() {
|
||||
void initNodes(Map<Type, Set<Type>> stuckDeps) {
|
||||
//add nodes
|
||||
nodes = new ArrayList<Node>();
|
||||
for (Type t : inferenceContext.restvars()) {
|
||||
nodes.add(new Node(t));
|
||||
}
|
||||
//add dependencies
|
||||
for (Node n_i : nodes) {
|
||||
Type i = n_i.data.first();
|
||||
Set<Type> optDepsByNode = stuckDeps.get(i);
|
||||
for (Node n_j : nodes) {
|
||||
Type j = n_j.data.first();
|
||||
UndetVar uv_i = (UndetVar)inferenceContext.asFree(i);
|
||||
if (Type.containsAny(uv_i.getBounds(InferenceBound.values()), List.of(j))) {
|
||||
//update i's deps
|
||||
n_i.deps.add(n_j);
|
||||
//update i's bound dependencies
|
||||
n_i.addDependency(DependencyKind.BOUND, n_j);
|
||||
}
|
||||
if (optDepsByNode != null && optDepsByNode.contains(j)) {
|
||||
//update i's stuck dependencies
|
||||
n_i.addDependency(DependencyKind.STUCK, n_j);
|
||||
}
|
||||
}
|
||||
}
|
||||
//merge cyclic nodes
|
||||
ArrayList<Node> acyclicNodes = new ArrayList<Node>();
|
||||
for (List<? extends Node> conSubGraph : GraphUtils.tarjan(nodes)) {
|
||||
if (conSubGraph.length() > 1) {
|
||||
@ -1631,8 +1825,8 @@ public class Infer {
|
||||
return filterVars(new Filter<UndetVar>() {
|
||||
public boolean accepts(UndetVar uv) {
|
||||
return uv.getBounds(InferenceBound.UPPER)
|
||||
.diff(uv.getDeclaredBounds())
|
||||
.appendList(uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)).nonEmpty();
|
||||
.diff(uv.getDeclaredBounds())
|
||||
.appendList(uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)).nonEmpty();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1822,11 +2016,15 @@ public class Infer {
|
||||
}
|
||||
}
|
||||
|
||||
private void solve(GraphStrategy ss, Warner warn) {
|
||||
solve(ss, new HashMap<Type, Set<Type>>(), warn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Solve with given graph strategy.
|
||||
*/
|
||||
private void solve(GraphStrategy ss, Warner warn) {
|
||||
GraphSolver s = new GraphSolver(this, warn);
|
||||
private void solve(GraphStrategy ss, Map<Type, Set<Type>> stuckDeps, Warner warn) {
|
||||
GraphSolver s = new GraphSolver(this, stuckDeps, warn);
|
||||
s.solve(ss);
|
||||
}
|
||||
|
||||
@ -1855,18 +2053,12 @@ public class Infer {
|
||||
/**
|
||||
* Solve at least one variable in given list.
|
||||
*/
|
||||
public void solveAny(List<Type> varsToSolve, Warner warn) {
|
||||
checkWithinBounds(this, warn); //propagate bounds
|
||||
List<Type> boundedVars = boundedVars().intersect(restvars()).intersect(varsToSolve);
|
||||
if (boundedVars.isEmpty()) {
|
||||
throw inferenceException.setMessage("cyclic.inference",
|
||||
freeVarsIn(varsToSolve));
|
||||
}
|
||||
solve(new BestLeafSolver(boundedVars) {
|
||||
public void solveAny(List<Type> varsToSolve, Map<Type, Set<Type>> optDeps, Warner warn) {
|
||||
solve(new BestLeafSolver(varsToSolve.intersect(restvars())) {
|
||||
public boolean done() {
|
||||
return instvars().intersect(varsToSolve).nonEmpty();
|
||||
}
|
||||
}, warn);
|
||||
}, optDeps, warn);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1745,6 +1745,11 @@ public class LambdaToMethod extends TreeTranslator {
|
||||
// Just erase the type var
|
||||
ret = new VarSymbol(sym.flags(), name,
|
||||
types.erasure(sym.type), sym.owner);
|
||||
|
||||
/* this information should also be kept for LVT generation at Gen
|
||||
* a Symbol with pos < startPos won't be tracked.
|
||||
*/
|
||||
((VarSymbol)ret).pos = ((VarSymbol)sym).pos;
|
||||
break;
|
||||
case CAPTURED_VAR:
|
||||
ret = new VarSymbol(SYNTHETIC | FINAL, name, types.erasure(sym.type), translatedSym) {
|
||||
|
@ -49,7 +49,6 @@ import static com.sun.tools.javac.code.Kinds.*;
|
||||
import static com.sun.tools.javac.code.TypeTag.*;
|
||||
import static com.sun.tools.javac.jvm.ByteCodes.*;
|
||||
import static com.sun.tools.javac.tree.JCTree.Tag.*;
|
||||
import javax.lang.model.type.TypeKind;
|
||||
|
||||
/** This pass translates away some syntactic sugar: inner classes,
|
||||
* class literals, assertions, foreach loops, etc.
|
||||
@ -1480,7 +1479,12 @@ public class Lower extends TreeTranslator {
|
||||
* @param owner The class in which the definitions go.
|
||||
*/
|
||||
List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner) {
|
||||
long flags = FINAL | SYNTHETIC;
|
||||
return freevarDefs(pos, freevars, owner, 0);
|
||||
}
|
||||
|
||||
List<JCVariableDecl> freevarDefs(int pos, List<VarSymbol> freevars, Symbol owner,
|
||||
long additionalFlags) {
|
||||
long flags = FINAL | SYNTHETIC | additionalFlags;
|
||||
if (owner.kind == TYP &&
|
||||
target.usePrivateSyntheticFields())
|
||||
flags |= PRIVATE;
|
||||
@ -1543,7 +1547,7 @@ public class Lower extends TreeTranslator {
|
||||
(owner.isConstructor() && c.isInner() &&
|
||||
!c.isPrivate() && !c.isStatic());
|
||||
long flags =
|
||||
FINAL | (isMandated ? MANDATED : SYNTHETIC);
|
||||
FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER;
|
||||
VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags);
|
||||
owner.extraParams = owner.extraParams.prepend(outerThis);
|
||||
return makeOuterThisVarDecl(pos, outerThis);
|
||||
@ -1627,7 +1631,8 @@ public class Lower extends TreeTranslator {
|
||||
JCTree makeTwrTry(JCTry tree) {
|
||||
make_at(tree.pos());
|
||||
twrVars = twrVars.dup();
|
||||
JCBlock twrBlock = makeTwrBlock(tree.resources, tree.body, 0);
|
||||
JCBlock twrBlock = makeTwrBlock(tree.resources, tree.body,
|
||||
tree.finallyCanCompleteNormally, 0);
|
||||
if (tree.catchers.isEmpty() && tree.finalizer == null)
|
||||
result = translate(twrBlock);
|
||||
else
|
||||
@ -1636,7 +1641,8 @@ public class Lower extends TreeTranslator {
|
||||
return result;
|
||||
}
|
||||
|
||||
private JCBlock makeTwrBlock(List<JCTree> resources, JCBlock block, int depth) {
|
||||
private JCBlock makeTwrBlock(List<JCTree> resources, JCBlock block,
|
||||
boolean finallyCanCompleteNormally, int depth) {
|
||||
if (resources.isEmpty())
|
||||
return block;
|
||||
|
||||
@ -1692,17 +1698,20 @@ public class Lower extends TreeTranslator {
|
||||
make.at(TreeInfo.endPos(block));
|
||||
JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr);
|
||||
make.at(oldPos);
|
||||
JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1),
|
||||
JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block,
|
||||
finallyCanCompleteNormally, depth + 1),
|
||||
List.<JCCatch>of(catchClause),
|
||||
finallyClause);
|
||||
outerTry.finallyCanCompleteNormally = finallyCanCompleteNormally;
|
||||
stats.add(outerTry);
|
||||
return make.Block(0L, stats.toList());
|
||||
JCBlock newBlock = make.Block(0L, stats.toList());
|
||||
return newBlock;
|
||||
}
|
||||
|
||||
private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) {
|
||||
// primaryException.addSuppressed(catchException);
|
||||
VarSymbol catchException =
|
||||
new VarSymbol(0, make.paramName(2),
|
||||
new VarSymbol(SYNTHETIC, make.paramName(2),
|
||||
syms.throwableType,
|
||||
currentMethodSym);
|
||||
JCStatement addSuppressionStatement =
|
||||
@ -1717,6 +1726,7 @@ public class Lower extends TreeTranslator {
|
||||
JCBlock catchBlock = make.Block(0L, List.<JCStatement>of(addSuppressionStatement));
|
||||
List<JCCatch> catchClauses = List.<JCCatch>of(make.Catch(catchExceptionDecl, catchBlock));
|
||||
JCTry tryTree = make.Try(tryBlock, catchClauses, null);
|
||||
tryTree.finallyCanCompleteNormally = true;
|
||||
|
||||
// if (primaryException != null) {try...} else resourceClose;
|
||||
JCIf closeIfStatement = make.If(makeNonNullCheck(make.Ident(primaryException)),
|
||||
@ -2017,7 +2027,7 @@ public class Lower extends TreeTranslator {
|
||||
|
||||
// catchParam := ClassNotFoundException e1
|
||||
VarSymbol catchParam =
|
||||
new VarSymbol(0, make.paramName(1),
|
||||
new VarSymbol(SYNTHETIC, make.paramName(1),
|
||||
syms.classNotFoundExceptionType,
|
||||
classDollarSym);
|
||||
|
||||
@ -2705,7 +2715,7 @@ public class Lower extends TreeTranslator {
|
||||
JCVariableDecl otdef = null;
|
||||
if (currentClass.hasOuterInstance())
|
||||
otdef = outerThisDef(tree.pos, m);
|
||||
List<JCVariableDecl> fvdefs = freevarDefs(tree.pos, fvs, m);
|
||||
List<JCVariableDecl> fvdefs = freevarDefs(tree.pos, fvs, m, PARAMETER);
|
||||
|
||||
// Recursively translate result type, parameters and thrown list.
|
||||
tree.restype = translate(tree.restype);
|
||||
@ -3364,18 +3374,18 @@ public class Lower extends TreeTranslator {
|
||||
*/
|
||||
private void visitArrayForeachLoop(JCEnhancedForLoop tree) {
|
||||
make_at(tree.expr.pos());
|
||||
VarSymbol arraycache = new VarSymbol(0,
|
||||
VarSymbol arraycache = new VarSymbol(SYNTHETIC,
|
||||
names.fromString("arr" + target.syntheticNameChar()),
|
||||
tree.expr.type,
|
||||
currentMethodSym);
|
||||
JCStatement arraycachedef = make.VarDef(arraycache, tree.expr);
|
||||
VarSymbol lencache = new VarSymbol(0,
|
||||
VarSymbol lencache = new VarSymbol(SYNTHETIC,
|
||||
names.fromString("len" + target.syntheticNameChar()),
|
||||
syms.intType,
|
||||
currentMethodSym);
|
||||
JCStatement lencachedef = make.
|
||||
VarDef(lencache, make.Select(make.Ident(arraycache), syms.lengthVar));
|
||||
VarSymbol index = new VarSymbol(0,
|
||||
VarSymbol index = new VarSymbol(SYNTHETIC,
|
||||
names.fromString("i" + target.syntheticNameChar()),
|
||||
syms.intType,
|
||||
currentMethodSym);
|
||||
@ -3457,7 +3467,7 @@ public class Lower extends TreeTranslator {
|
||||
names.iterator,
|
||||
eType,
|
||||
List.<Type>nil());
|
||||
VarSymbol itvar = new VarSymbol(0, names.fromString("i" + target.syntheticNameChar()),
|
||||
VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()),
|
||||
types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)),
|
||||
currentMethodSym);
|
||||
|
||||
@ -3830,19 +3840,32 @@ public class Lower extends TreeTranslator {
|
||||
|
||||
@Override
|
||||
public void visitTry(JCTry tree) {
|
||||
/* special case of try without catchers and with finally emtpy.
|
||||
* Don't give it a try, translate only the body.
|
||||
*/
|
||||
if (tree.resources.isEmpty()) {
|
||||
if (tree.catchers.isEmpty() &&
|
||||
tree.finalizer.getStatements().isEmpty()) {
|
||||
result = translate(tree.body);
|
||||
} else {
|
||||
super.visitTry(tree);
|
||||
}
|
||||
} else {
|
||||
if (tree.resources.nonEmpty()) {
|
||||
result = makeTwrTry(tree);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasBody = tree.body.getStatements().nonEmpty();
|
||||
boolean hasCatchers = tree.catchers.nonEmpty();
|
||||
boolean hasFinally = tree.finalizer != null &&
|
||||
tree.finalizer.getStatements().nonEmpty();
|
||||
|
||||
if (!hasCatchers && !hasFinally) {
|
||||
result = translate(tree.body);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!hasBody) {
|
||||
if (hasFinally) {
|
||||
result = translate(tree.finalizer);
|
||||
} else {
|
||||
result = translate(tree.body);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// no optimizations possible
|
||||
super.visitTry(tree);
|
||||
}
|
||||
|
||||
/**************************************************************************
|
||||
|
@ -84,6 +84,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
private final Source source;
|
||||
private final Target target;
|
||||
private final DeferredLintHandler deferredLintHandler;
|
||||
private final Lint lint;
|
||||
|
||||
public static MemberEnter instance(Context context) {
|
||||
MemberEnter instance = context.get(memberEnterKey);
|
||||
@ -109,6 +110,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
source = Source.instance(context);
|
||||
target = Target.instance(context);
|
||||
deferredLintHandler = DeferredLintHandler.instance(context);
|
||||
lint = Lint.instance(context);
|
||||
allowTypeAnnos = source.allowTypeAnnotations();
|
||||
}
|
||||
|
||||
@ -506,9 +508,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
}
|
||||
|
||||
// process package annotations
|
||||
annotateLater(tree.packageAnnotations, env, tree.packge);
|
||||
annotateLater(tree.packageAnnotations, env, tree.packge, null);
|
||||
|
||||
DeferredLintHandler prevLintHandler = chk.setDeferredLintHandler(DeferredLintHandler.immediateHandler);
|
||||
DiagnosticPosition prevLintPos = deferredLintHandler.immediate();
|
||||
Lint prevLint = chk.setLint(lint);
|
||||
|
||||
try {
|
||||
// Import-on-demand java.lang.
|
||||
@ -517,7 +520,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
// Process all import clauses.
|
||||
memberEnter(tree.defs, env);
|
||||
} finally {
|
||||
chk.setDeferredLintHandler(prevLintHandler);
|
||||
chk.setLint(prevLint);
|
||||
deferredLintHandler.setPos(prevLintPos);
|
||||
}
|
||||
}
|
||||
|
||||
@ -564,8 +568,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
|
||||
Env<AttrContext> localEnv = methodEnv(tree, env);
|
||||
|
||||
DeferredLintHandler prevLintHandler =
|
||||
chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos()));
|
||||
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
|
||||
try {
|
||||
// Compute the method type
|
||||
m.type = signature(m, tree.typarams, tree.params,
|
||||
@ -573,7 +576,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
tree.thrown,
|
||||
localEnv);
|
||||
} finally {
|
||||
chk.setDeferredLintHandler(prevLintHandler);
|
||||
deferredLintHandler.setPos(prevLintPos);
|
||||
}
|
||||
|
||||
if (types.isSignaturePolymorphic(m)) {
|
||||
@ -597,10 +600,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
if (chk.checkUnique(tree.pos(), m, enclScope)) {
|
||||
enclScope.enter(m);
|
||||
}
|
||||
annotateLater(tree.mods.annotations, localEnv, m);
|
||||
annotateLater(tree.mods.annotations, localEnv, m, tree.pos());
|
||||
// Visit the signature of the method. Note that
|
||||
// TypeAnnotate doesn't descend into the body.
|
||||
typeAnnotate(tree, localEnv, m);
|
||||
typeAnnotate(tree, localEnv, m, tree.pos());
|
||||
|
||||
if (tree.defaultValue != null)
|
||||
annotateDefaultValueLater(tree.defaultValue, localEnv, m);
|
||||
@ -630,15 +633,14 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
localEnv = env.dup(tree, env.info.dup());
|
||||
localEnv.info.staticLevel++;
|
||||
}
|
||||
DeferredLintHandler prevLintHandler =
|
||||
chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos()));
|
||||
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
|
||||
try {
|
||||
if (TreeInfo.isEnumInit(tree)) {
|
||||
attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype);
|
||||
} else {
|
||||
// Make sure type annotations are processed.
|
||||
// But we don't have a symbol to attach them to yet - use null.
|
||||
typeAnnotate(tree.vartype, env, null);
|
||||
typeAnnotate(tree.vartype, env, null, tree.pos());
|
||||
attr.attribType(tree.vartype, localEnv);
|
||||
if (tree.nameexpr != null) {
|
||||
attr.attribExpr(tree.nameexpr, localEnv);
|
||||
@ -658,7 +660,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
chk.setDeferredLintHandler(prevLintHandler);
|
||||
deferredLintHandler.setPos(prevLintPos);
|
||||
}
|
||||
|
||||
if ((tree.mods.flags & VARARGS) != 0) {
|
||||
@ -680,15 +682,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
needsLazyConstValue(tree.init)) {
|
||||
Env<AttrContext> initEnv = getInitEnv(tree, env);
|
||||
initEnv.info.enclVar = v;
|
||||
v.setLazyConstValue(initEnv(tree, initEnv), attr, tree.init);
|
||||
v.setLazyConstValue(initEnv(tree, initEnv), attr, tree);
|
||||
}
|
||||
}
|
||||
if (chk.checkUnique(tree.pos(), v, enclScope)) {
|
||||
chk.checkTransparentVar(tree.pos(), v, enclScope);
|
||||
enclScope.enter(v);
|
||||
}
|
||||
annotateLater(tree.mods.annotations, localEnv, v);
|
||||
typeAnnotate(tree.vartype, env, v);
|
||||
annotateLater(tree.mods.annotations, localEnv, v, tree.pos());
|
||||
typeAnnotate(tree.vartype, env, v, tree.pos());
|
||||
annotate.flush();
|
||||
v.pos = tree.pos;
|
||||
}
|
||||
@ -719,6 +721,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
result = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNewArray(JCNewArray that) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLambda(JCLambda that) {
|
||||
result = false;
|
||||
@ -729,6 +736,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
result = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitApply(JCMethodInvocation that) {
|
||||
result = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSelect(JCFieldAccess tree) {
|
||||
tree.selected.accept(this);
|
||||
@ -820,7 +832,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
/** Queue annotations for later processing. */
|
||||
void annotateLater(final List<JCAnnotation> annotations,
|
||||
final Env<AttrContext> localEnv,
|
||||
final Symbol s) {
|
||||
final Symbol s,
|
||||
final DiagnosticPosition deferPos) {
|
||||
if (annotations.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
@ -837,6 +850,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
public void enterAnnotation() {
|
||||
Assert.check(s.kind == PCK || s.annotationsPendingCompletion());
|
||||
JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile);
|
||||
DiagnosticPosition prevLintPos =
|
||||
deferPos != null
|
||||
? deferredLintHandler.setPos(deferPos)
|
||||
: deferredLintHandler.immediate();
|
||||
Lint prevLint = deferPos != null ? null : chk.setLint(lint);
|
||||
try {
|
||||
if (s.hasAnnotations() &&
|
||||
annotations.nonEmpty())
|
||||
@ -845,6 +863,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
kindName(s), s);
|
||||
actualEnterAnnotations(annotations, localEnv, s);
|
||||
} finally {
|
||||
if (prevLint != null)
|
||||
chk.setLint(prevLint);
|
||||
deferredLintHandler.setPos(prevLintPos);
|
||||
log.useSource(prev);
|
||||
}
|
||||
}
|
||||
@ -964,6 +985,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
isFirst = false;
|
||||
|
||||
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
|
||||
DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos());
|
||||
try {
|
||||
// Save class environment for later member enter (2) processing.
|
||||
halfcompleted.append(env);
|
||||
@ -985,9 +1007,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
Env<AttrContext> baseEnv = baseEnv(tree, env);
|
||||
|
||||
if (tree.extending != null)
|
||||
typeAnnotate(tree.extending, baseEnv, sym);
|
||||
typeAnnotate(tree.extending, baseEnv, sym, tree.pos());
|
||||
for (JCExpression impl : tree.implementing)
|
||||
typeAnnotate(impl, baseEnv, sym);
|
||||
typeAnnotate(impl, baseEnv, sym, tree.pos());
|
||||
annotate.flush();
|
||||
|
||||
// Determine supertype.
|
||||
@ -1048,7 +1070,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
attr.attribAnnotationTypes(tree.mods.annotations, baseEnv);
|
||||
if (hasDeprecatedAnnotation(tree.mods.annotations))
|
||||
c.flags_field |= DEPRECATED;
|
||||
annotateLater(tree.mods.annotations, baseEnv, c);
|
||||
annotateLater(tree.mods.annotations, baseEnv, c, tree.pos());
|
||||
// class type parameters use baseEnv but everything uses env
|
||||
|
||||
chk.checkNonCyclicDecl(tree);
|
||||
@ -1056,7 +1078,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
attr.attribTypeVariables(tree.typarams, baseEnv);
|
||||
// Do this here, where we have the symbol.
|
||||
for (JCTypeParameter tp : tree.typarams)
|
||||
typeAnnotate(tp, baseEnv, sym);
|
||||
typeAnnotate(tp, baseEnv, sym, tree.pos());
|
||||
annotate.flush();
|
||||
|
||||
// Add default constructor if needed.
|
||||
@ -1126,6 +1148,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
} catch (CompletionFailure ex) {
|
||||
chk.completionError(tree.pos(), ex);
|
||||
} finally {
|
||||
deferredLintHandler.setPos(prevLintPos);
|
||||
log.useSource(prev);
|
||||
}
|
||||
|
||||
@ -1186,9 +1209,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
}
|
||||
}
|
||||
|
||||
public void typeAnnotate(final JCTree tree, final Env<AttrContext> env, final Symbol sym) {
|
||||
public void typeAnnotate(final JCTree tree, final Env<AttrContext> env, final Symbol sym, DiagnosticPosition deferPos) {
|
||||
if (allowTypeAnnos) {
|
||||
tree.accept(new TypeAnnotate(env, sym));
|
||||
tree.accept(new TypeAnnotate(env, sym, deferPos));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1199,10 +1222,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
private class TypeAnnotate extends TreeScanner {
|
||||
private Env<AttrContext> env;
|
||||
private Symbol sym;
|
||||
private DiagnosticPosition deferPos;
|
||||
|
||||
public TypeAnnotate(final Env<AttrContext> env, final Symbol sym) {
|
||||
public TypeAnnotate(final Env<AttrContext> env, final Symbol sym, DiagnosticPosition deferPos) {
|
||||
this.env = env;
|
||||
this.sym = sym;
|
||||
this.deferPos = deferPos;
|
||||
}
|
||||
|
||||
void annotateTypeLater(final List<JCAnnotation> annotations) {
|
||||
@ -1210,6 +1235,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
return;
|
||||
}
|
||||
|
||||
final DiagnosticPosition deferPos = this.deferPos;
|
||||
|
||||
annotate.normal(new Annotate.Annotator() {
|
||||
@Override
|
||||
public String toString() {
|
||||
@ -1218,9 +1245,16 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
@Override
|
||||
public void enterAnnotation() {
|
||||
JavaFileObject prev = log.useSource(env.toplevel.sourcefile);
|
||||
DiagnosticPosition prevLintPos = null;
|
||||
|
||||
if (deferPos != null) {
|
||||
prevLintPos = deferredLintHandler.setPos(deferPos);
|
||||
}
|
||||
try {
|
||||
actualEnterTypeAnnotations(annotations, env, sym);
|
||||
} finally {
|
||||
if (prevLintPos != null)
|
||||
deferredLintHandler.setPos(prevLintPos);
|
||||
log.useSource(prev);
|
||||
}
|
||||
}
|
||||
@ -1262,13 +1296,19 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
|
||||
@Override
|
||||
public void visitVarDef(final JCVariableDecl tree) {
|
||||
if (sym != null && sym.kind == Kinds.VAR) {
|
||||
// Don't visit a parameter once when the sym is the method
|
||||
// and once when the sym is the parameter.
|
||||
scan(tree.mods);
|
||||
scan(tree.vartype);
|
||||
DiagnosticPosition prevPos = deferPos;
|
||||
deferPos = tree.pos();
|
||||
try {
|
||||
if (sym != null && sym.kind == Kinds.VAR) {
|
||||
// Don't visit a parameter once when the sym is the method
|
||||
// and once when the sym is the parameter.
|
||||
scan(tree.mods);
|
||||
scan(tree.vartype);
|
||||
}
|
||||
scan(tree.init);
|
||||
} finally {
|
||||
deferPos = prevPos;
|
||||
}
|
||||
scan(tree.init);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1532,7 +1572,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
* parameters from baseInit.
|
||||
*/
|
||||
initParams = List.nil();
|
||||
VarSymbol param = new VarSymbol(0, make.paramName(0), argtypes.head, init);
|
||||
VarSymbol param = new VarSymbol(PARAMETER, make.paramName(0), argtypes.head, init);
|
||||
initParams = initParams.append(param);
|
||||
argTypesList = argTypesList.tail;
|
||||
}
|
||||
@ -1541,7 +1581,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
|
||||
initParams = (initParams == null) ? List.<VarSymbol>nil() : initParams;
|
||||
List<VarSymbol> baseInitParams = baseInit.params;
|
||||
while (baseInitParams.nonEmpty() && argTypesList.nonEmpty()) {
|
||||
VarSymbol param = new VarSymbol(baseInitParams.head.flags(),
|
||||
VarSymbol param = new VarSymbol(baseInitParams.head.flags() | PARAMETER,
|
||||
baseInitParams.head.name, argTypesList.head, init);
|
||||
initParams = initParams.append(param);
|
||||
baseInitParams = baseInitParams.tail;
|
||||
|
@ -568,8 +568,10 @@ public class Resolve {
|
||||
currentResolutionContext,
|
||||
warn);
|
||||
|
||||
currentResolutionContext.methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn),
|
||||
DeferredAttr.DeferredAttrContext dc = currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn);
|
||||
currentResolutionContext.methodCheck.argumentsAcceptable(env, dc,
|
||||
argtypes, mt.getParameterTypes(), warn);
|
||||
dc.complete();
|
||||
return mt;
|
||||
}
|
||||
|
||||
@ -1053,7 +1055,8 @@ public class Resolve {
|
||||
DeferredType dt = (DeferredType) actual;
|
||||
DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase);
|
||||
return (e == null || e.speculativeTree == deferredAttr.stuckTree)
|
||||
? false : mostSpecific(found, req, e.speculativeTree, warn);
|
||||
? super.compatible(found, req, warn) :
|
||||
mostSpecific(found, req, e.speculativeTree, warn);
|
||||
default:
|
||||
return standaloneMostSpecific(found, req, actual, warn);
|
||||
}
|
||||
@ -1125,13 +1128,15 @@ public class Resolve {
|
||||
@Override
|
||||
public void visitReference(JCMemberReference tree) {
|
||||
if (types.isFunctionalInterface(t.tsym) &&
|
||||
types.isFunctionalInterface(s.tsym) &&
|
||||
types.asSuper(t, s.tsym) == null &&
|
||||
types.asSuper(s, t.tsym) == null) {
|
||||
types.isFunctionalInterface(s.tsym)) {
|
||||
Type desc_t = types.findDescriptorType(t);
|
||||
Type desc_s = types.findDescriptorType(s);
|
||||
if (types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
|
||||
if (!desc_s.getReturnType().hasTag(VOID)) {
|
||||
if (types.isSameTypes(desc_t.getParameterTypes(),
|
||||
inferenceContext().asFree(desc_s.getParameterTypes()))) {
|
||||
if (types.asSuper(t, s.tsym) != null ||
|
||||
types.asSuper(s, t.tsym) != null) {
|
||||
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
|
||||
} else if (!desc_s.getReturnType().hasTag(VOID)) {
|
||||
//perform structural comparison
|
||||
Type ret_t = desc_t.getReturnType();
|
||||
Type ret_s = desc_s.getReturnType();
|
||||
@ -1141,25 +1146,24 @@ public class Resolve {
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
result &= false;
|
||||
}
|
||||
} else {
|
||||
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
|
||||
result &= false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitLambda(JCLambda tree) {
|
||||
if (types.isFunctionalInterface(t.tsym) &&
|
||||
types.isFunctionalInterface(s.tsym) &&
|
||||
types.asSuper(t, s.tsym) == null &&
|
||||
types.asSuper(s, t.tsym) == null) {
|
||||
types.isFunctionalInterface(s.tsym)) {
|
||||
Type desc_t = types.findDescriptorType(t);
|
||||
Type desc_s = types.findDescriptorType(s);
|
||||
if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT
|
||||
|| types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) {
|
||||
if (!desc_s.getReturnType().hasTag(VOID)) {
|
||||
if (types.isSameTypes(desc_t.getParameterTypes(),
|
||||
inferenceContext().asFree(desc_s.getParameterTypes()))) {
|
||||
if (types.asSuper(t, s.tsym) != null ||
|
||||
types.asSuper(s, t.tsym) != null) {
|
||||
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
|
||||
} else if (!desc_s.getReturnType().hasTag(VOID)) {
|
||||
//perform structural comparison
|
||||
Type ret_t = desc_t.getReturnType();
|
||||
Type ret_s = desc_s.getReturnType();
|
||||
@ -1167,11 +1171,9 @@ public class Resolve {
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
result &= false;
|
||||
}
|
||||
} else {
|
||||
result &= MostSpecificCheckContext.super.compatible(t, s, warn);
|
||||
result &= false;
|
||||
}
|
||||
}
|
||||
//where
|
||||
@ -1521,7 +1523,8 @@ public class Resolve {
|
||||
currentResolutionContext = prevResolutionContext;
|
||||
}
|
||||
}
|
||||
private List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) {
|
||||
|
||||
List<Type> adjustArgs(List<Type> args, Symbol msym, int length, boolean allowVarargs) {
|
||||
if ((msym.flags() & VARARGS) != 0 && allowVarargs) {
|
||||
Type varargsElem = types.elemtype(args.last());
|
||||
if (varargsElem == null) {
|
||||
@ -2241,33 +2244,33 @@ public class Resolve {
|
||||
public List<Type> getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List<Type> argtypes) {
|
||||
return (syms.operatorNames.contains(name)) ?
|
||||
argtypes :
|
||||
Type.map(argtypes, new ResolveDeferredRecoveryMap(accessedSym));
|
||||
}
|
||||
|
||||
class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap {
|
||||
|
||||
public ResolveDeferredRecoveryMap(Symbol msym) {
|
||||
deferredAttr.super(AttrMode.SPECULATIVE, msym, currentResolutionContext.step);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Type typeOf(DeferredType dt) {
|
||||
Type res = super.typeOf(dt);
|
||||
if (!res.isErroneous()) {
|
||||
switch (TreeInfo.skipParens(dt.tree).getTag()) {
|
||||
case LAMBDA:
|
||||
case REFERENCE:
|
||||
return dt;
|
||||
case CONDEXPR:
|
||||
return res == Type.recoveryType ?
|
||||
dt : res;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step));
|
||||
}
|
||||
};
|
||||
|
||||
class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap {
|
||||
|
||||
public ResolveDeferredRecoveryMap(AttrMode mode, Symbol msym, MethodResolutionPhase step) {
|
||||
deferredAttr.super(mode, msym, step);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Type typeOf(DeferredType dt) {
|
||||
Type res = super.typeOf(dt);
|
||||
if (!res.isErroneous()) {
|
||||
switch (TreeInfo.skipParens(dt.tree).getTag()) {
|
||||
case LAMBDA:
|
||||
case REFERENCE:
|
||||
return dt;
|
||||
case CONDEXPR:
|
||||
return res == Type.recoveryType ?
|
||||
dt : res;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/** Check that sym is not an abstract method.
|
||||
*/
|
||||
void checkNonAbstract(DiagnosticPosition pos, Symbol sym) {
|
||||
@ -2543,22 +2546,26 @@ public class Resolve {
|
||||
@Override
|
||||
Symbol access(Env<AttrContext> env, DiagnosticPosition pos, Symbol location, Symbol sym) {
|
||||
if (sym.kind >= AMBIGUOUS) {
|
||||
final JCDiagnostic details = sym.kind == WRONG_MTH ?
|
||||
((InapplicableSymbolError)sym).errCandidate().snd :
|
||||
null;
|
||||
sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) {
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
|
||||
Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
|
||||
String key = details == null ?
|
||||
"cant.apply.diamond" :
|
||||
"cant.apply.diamond.1";
|
||||
return diags.create(dkind, log.currentSource(), pos, key,
|
||||
diags.fragment("diamond", site.tsym), details);
|
||||
}
|
||||
};
|
||||
sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes);
|
||||
env.info.pendingResolutionPhase = currentResolutionContext.step;
|
||||
if (sym.kind != WRONG_MTH && sym.kind != WRONG_MTHS) {
|
||||
sym = super.access(env, pos, location, sym);
|
||||
} else {
|
||||
final JCDiagnostic details = sym.kind == WRONG_MTH ?
|
||||
((InapplicableSymbolError)sym).errCandidate().snd :
|
||||
null;
|
||||
sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) {
|
||||
@Override
|
||||
JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos,
|
||||
Symbol location, Type site, Name name, List<Type> argtypes, List<Type> typeargtypes) {
|
||||
String key = details == null ?
|
||||
"cant.apply.diamond" :
|
||||
"cant.apply.diamond.1";
|
||||
return diags.create(dkind, log.currentSource(), pos, key,
|
||||
diags.fragment("diamond", site.tsym), details);
|
||||
}
|
||||
};
|
||||
sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes);
|
||||
env.info.pendingResolutionPhase = currentResolutionContext.step;
|
||||
}
|
||||
}
|
||||
return sym;
|
||||
}});
|
||||
@ -3969,16 +3976,6 @@ public class Resolve {
|
||||
|
||||
static {
|
||||
String argMismatchRegex = MethodCheckDiag.ARG_MISMATCH.regex();
|
||||
rewriters.put(new Template(argMismatchRegex, new Template("(.*)(bad.arg.types.in.lambda)", skip, skip)),
|
||||
new DiagnosticRewriter() {
|
||||
@Override
|
||||
public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags,
|
||||
DiagnosticPosition preferedPos, DiagnosticSource preferredSource,
|
||||
DiagnosticType preferredKind, JCDiagnostic d) {
|
||||
return (JCDiagnostic)((JCDiagnostic)d.getArgs()[0]).getArgs()[1];
|
||||
}
|
||||
});
|
||||
|
||||
rewriters.put(new Template(argMismatchRegex, skip),
|
||||
new DiagnosticRewriter() {
|
||||
@Override
|
||||
|
@ -310,7 +310,7 @@ public class TransTypes extends TreeTranslator {
|
||||
Type.MethodType mType = (Type.MethodType)bridgeType;
|
||||
List<Type> argTypes = mType.argtypes;
|
||||
while (implParams.nonEmpty() && argTypes.nonEmpty()) {
|
||||
VarSymbol param = new VarSymbol(implParams.head.flags() | SYNTHETIC,
|
||||
VarSymbol param = new VarSymbol(implParams.head.flags() | SYNTHETIC | PARAMETER,
|
||||
implParams.head.name, argTypes.head, bridge);
|
||||
param.setAttributes(implParams.head);
|
||||
bridgeParams = bridgeParams.append(param);
|
||||
@ -833,7 +833,7 @@ public class TransTypes extends TreeTranslator {
|
||||
}
|
||||
|
||||
public void visitReference(JCMemberReference tree) {
|
||||
tree.expr = translate(tree.expr, null);
|
||||
tree.expr = translate(tree.expr, erasure(tree.expr.type));
|
||||
tree.type = erasure(tree.type);
|
||||
result = tree;
|
||||
}
|
||||
|
@ -72,7 +72,7 @@ import static com.sun.tools.javac.main.Option.*;
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class ClassReader implements Completer {
|
||||
public class ClassReader {
|
||||
/** The context key for the class reader. */
|
||||
protected static final Context.Key<ClassReader> classReaderKey =
|
||||
new Context.Key<ClassReader>();
|
||||
@ -234,6 +234,17 @@ public class ClassReader implements Completer {
|
||||
*/
|
||||
Set<Name> warnedAttrs = new HashSet<Name>();
|
||||
|
||||
/**
|
||||
* Completer that delegates to the complete-method of this class.
|
||||
*/
|
||||
private final Completer thisCompleter = new Completer() {
|
||||
@Override
|
||||
public void complete(Symbol sym) throws CompletionFailure {
|
||||
ClassReader.this.complete(sym);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Get the ClassReader instance for this invocation. */
|
||||
public static ClassReader instance(Context context) {
|
||||
ClassReader instance = context.get(classReaderKey);
|
||||
@ -264,8 +275,8 @@ public class ClassReader implements Completer {
|
||||
}
|
||||
|
||||
packages.put(names.empty, syms.rootPackage);
|
||||
syms.rootPackage.completer = this;
|
||||
syms.unnamedPackage.completer = this;
|
||||
syms.rootPackage.completer = thisCompleter;
|
||||
syms.unnamedPackage.completer = thisCompleter;
|
||||
}
|
||||
|
||||
/** Construct a new class reader, optionally treated as the
|
||||
@ -727,12 +738,14 @@ public class ClassReader implements Completer {
|
||||
ClassSymbol t = enterClass(names.fromUtf(signatureBuffer,
|
||||
startSbp,
|
||||
sbp - startSbp));
|
||||
if (outer == Type.noType)
|
||||
outer = t.erasure(types);
|
||||
else
|
||||
outer = new ClassType(outer, List.<Type>nil(), t);
|
||||
sbp = startSbp;
|
||||
return outer;
|
||||
|
||||
try {
|
||||
return (outer == Type.noType) ?
|
||||
t.erasure(types) :
|
||||
new ClassType(outer, List.<Type>nil(), t);
|
||||
} finally {
|
||||
sbp = startSbp;
|
||||
}
|
||||
}
|
||||
|
||||
case '<': // generic arguments
|
||||
@ -797,6 +810,13 @@ public class ClassReader implements Completer {
|
||||
continue;
|
||||
|
||||
case '.':
|
||||
//we have seen an enclosing non-generic class
|
||||
if (outer != Type.noType) {
|
||||
t = enterClass(names.fromUtf(signatureBuffer,
|
||||
startSbp,
|
||||
sbp - startSbp));
|
||||
outer = new ClassType(outer, List.<Type>nil(), t);
|
||||
}
|
||||
signatureBuffer[sbp++] = (byte)'$';
|
||||
continue;
|
||||
case '/':
|
||||
@ -2310,7 +2330,7 @@ public class ClassReader implements Completer {
|
||||
ClassSymbol c = new ClassSymbol(0, name, owner);
|
||||
if (owner.kind == PCK)
|
||||
Assert.checkNull(classes.get(c.flatname), c);
|
||||
c.completer = this;
|
||||
c.completer = thisCompleter;
|
||||
return c;
|
||||
}
|
||||
|
||||
@ -2380,7 +2400,7 @@ public class ClassReader implements Completer {
|
||||
/** Completion for classes to be loaded. Before a class is loaded
|
||||
* we make sure its enclosing class (if any) is loaded.
|
||||
*/
|
||||
public void complete(Symbol sym) throws CompletionFailure {
|
||||
private void complete(Symbol sym) throws CompletionFailure {
|
||||
if (sym.kind == TYP) {
|
||||
ClassSymbol c = (ClassSymbol)sym;
|
||||
c.members_field = new Scope.ErrorScope(c); // make sure it's always defined
|
||||
@ -2601,7 +2621,7 @@ public class ClassReader implements Completer {
|
||||
p = new PackageSymbol(
|
||||
Convert.shortName(fullname),
|
||||
enterPackage(Convert.packagePart(fullname)));
|
||||
p.completer = this;
|
||||
p.completer = thisCompleter;
|
||||
packages.put(fullname, p);
|
||||
}
|
||||
return p;
|
||||
|
@ -37,7 +37,6 @@ import javax.tools.JavaFileObject;
|
||||
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Attribute.RetentionPolicy;
|
||||
import com.sun.tools.javac.code.Attribute.TypeCompound;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.Type.*;
|
||||
import com.sun.tools.javac.code.Types.UniqueType;
|
||||
@ -55,7 +54,6 @@ import static com.sun.tools.javac.jvm.UninitializedType.*;
|
||||
import static com.sun.tools.javac.main.Option.*;
|
||||
import static javax.tools.StandardLocation.CLASS_OUTPUT;
|
||||
|
||||
|
||||
/** This class provides operations to map an internal symbol table graph
|
||||
* rooted in a ClassSymbol into a classfile.
|
||||
*
|
||||
@ -1180,25 +1178,26 @@ public class ClassWriter extends ClassFile {
|
||||
|
||||
if (code.varBufferSize > 0) {
|
||||
int alenIdx = writeAttr(names.LocalVariableTable);
|
||||
databuf.appendChar(code.varBufferSize);
|
||||
|
||||
databuf.appendChar(code.getLVTSize());
|
||||
for (int i=0; i<code.varBufferSize; i++) {
|
||||
Code.LocalVar var = code.varBuffer[i];
|
||||
|
||||
// write variable info
|
||||
Assert.check(var.start_pc >= 0
|
||||
&& var.start_pc <= code.cp);
|
||||
databuf.appendChar(var.start_pc);
|
||||
Assert.check(var.length >= 0
|
||||
&& (var.start_pc + var.length) <= code.cp);
|
||||
databuf.appendChar(var.length);
|
||||
VarSymbol sym = var.sym;
|
||||
databuf.appendChar(pool.put(sym.name));
|
||||
Type vartype = sym.erasure(types);
|
||||
if (needsLocalVariableTypeEntry(sym.type))
|
||||
nGenericVars++;
|
||||
databuf.appendChar(pool.put(typeSig(vartype)));
|
||||
databuf.appendChar(var.reg);
|
||||
for (Code.LocalVar.Range r: var.aliveRanges) {
|
||||
// write variable info
|
||||
Assert.check(r.start_pc >= 0
|
||||
&& r.start_pc <= code.cp);
|
||||
databuf.appendChar(r.start_pc);
|
||||
Assert.check(r.length >= 0
|
||||
&& (r.start_pc + r.length) <= code.cp);
|
||||
databuf.appendChar(r.length);
|
||||
VarSymbol sym = var.sym;
|
||||
databuf.appendChar(pool.put(sym.name));
|
||||
Type vartype = sym.erasure(types);
|
||||
databuf.appendChar(pool.put(typeSig(vartype)));
|
||||
databuf.appendChar(var.reg);
|
||||
if (needsLocalVariableTypeEntry(var.sym.type))
|
||||
nGenericVars++;
|
||||
}
|
||||
}
|
||||
endAttr(alenIdx);
|
||||
acount++;
|
||||
@ -1214,13 +1213,15 @@ public class ClassWriter extends ClassFile {
|
||||
VarSymbol sym = var.sym;
|
||||
if (!needsLocalVariableTypeEntry(sym.type))
|
||||
continue;
|
||||
count++;
|
||||
// write variable info
|
||||
databuf.appendChar(var.start_pc);
|
||||
databuf.appendChar(var.length);
|
||||
databuf.appendChar(pool.put(sym.name));
|
||||
databuf.appendChar(pool.put(typeSig(sym.type)));
|
||||
databuf.appendChar(var.reg);
|
||||
for (Code.LocalVar.Range r : var.aliveRanges) {
|
||||
// write variable info
|
||||
databuf.appendChar(r.start_pc);
|
||||
databuf.appendChar(r.length);
|
||||
databuf.appendChar(pool.put(sym.name));
|
||||
databuf.appendChar(pool.put(typeSig(sym.type)));
|
||||
databuf.appendChar(var.reg);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
Assert.check(count == nGenericVars);
|
||||
endAttr(alenIdx);
|
||||
|
@ -28,6 +28,7 @@ package com.sun.tools.javac.jvm;
|
||||
import com.sun.tools.javac.code.*;
|
||||
import com.sun.tools.javac.code.Symbol.*;
|
||||
import com.sun.tools.javac.code.Types.UniqueType;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.util.*;
|
||||
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
|
||||
|
||||
@ -181,6 +182,8 @@ public class Code {
|
||||
|
||||
final MethodSymbol meth;
|
||||
|
||||
final LVTRanges lvtRanges;
|
||||
|
||||
/** Construct a code object, given the settings of the fatcode,
|
||||
* debugging info switches and the CharacterRangeTable.
|
||||
*/
|
||||
@ -193,7 +196,8 @@ public class Code {
|
||||
CRTable crt,
|
||||
Symtab syms,
|
||||
Types types,
|
||||
Pool pool) {
|
||||
Pool pool,
|
||||
LVTRanges lvtRanges) {
|
||||
this.meth = meth;
|
||||
this.fatcode = fatcode;
|
||||
this.lineMap = lineMap;
|
||||
@ -215,6 +219,7 @@ public class Code {
|
||||
state = new State();
|
||||
lvar = new LocalVar[20];
|
||||
this.pool = pool;
|
||||
this.lvtRanges = lvtRanges;
|
||||
}
|
||||
|
||||
|
||||
@ -305,9 +310,19 @@ public class Code {
|
||||
|
||||
/** The current output code pointer.
|
||||
*/
|
||||
public int curPc() {
|
||||
if (pendingJumps != null) resolvePending();
|
||||
if (pendingStatPos != Position.NOPOS) markStatBegin();
|
||||
public int curCP() {
|
||||
/*
|
||||
* This method has side-effects because calling it can indirectly provoke
|
||||
* extra code generation, like goto instructions, depending on the context
|
||||
* where it's called.
|
||||
* Use with care or even better avoid using it.
|
||||
*/
|
||||
if (pendingJumps != null) {
|
||||
resolvePending();
|
||||
}
|
||||
if (pendingStatPos != Position.NOPOS) {
|
||||
markStatBegin();
|
||||
}
|
||||
fixedPc = true;
|
||||
return cp;
|
||||
}
|
||||
@ -1175,7 +1190,7 @@ public class Code {
|
||||
/** Declare an entry point; return current code pointer
|
||||
*/
|
||||
public int entryPoint() {
|
||||
int pc = curPc();
|
||||
int pc = curCP();
|
||||
alive = true;
|
||||
pendingStackMap = needStackMap;
|
||||
return pc;
|
||||
@ -1185,7 +1200,7 @@ public class Code {
|
||||
* return current code pointer
|
||||
*/
|
||||
public int entryPoint(State state) {
|
||||
int pc = curPc();
|
||||
int pc = curCP();
|
||||
alive = true;
|
||||
this.state = state.dup();
|
||||
Assert.check(state.stacksize <= max_stack);
|
||||
@ -1198,7 +1213,7 @@ public class Code {
|
||||
* return current code pointer
|
||||
*/
|
||||
public int entryPoint(State state, Type pushed) {
|
||||
int pc = curPc();
|
||||
int pc = curCP();
|
||||
alive = true;
|
||||
this.state = state.dup();
|
||||
Assert.check(state.stacksize <= max_stack);
|
||||
@ -1238,7 +1253,7 @@ public class Code {
|
||||
|
||||
/** Emit a stack map entry. */
|
||||
public void emitStackMap() {
|
||||
int pc = curPc();
|
||||
int pc = curCP();
|
||||
if (!needStackMap) return;
|
||||
|
||||
|
||||
@ -1482,6 +1497,9 @@ public class Code {
|
||||
chain.pc + 3 == target && target == cp && !fixedPc) {
|
||||
// If goto the next instruction, the jump is not needed:
|
||||
// compact the code.
|
||||
if (varDebugInfo) {
|
||||
adjustAliveRanges(cp, -3);
|
||||
}
|
||||
cp = cp - 3;
|
||||
target = target - 3;
|
||||
if (chain.next == null) {
|
||||
@ -1781,8 +1799,7 @@ public class Code {
|
||||
sym = sym.clone(sym.owner);
|
||||
sym.type = newtype;
|
||||
LocalVar newlv = lvar[i] = new LocalVar(sym);
|
||||
// should the following be initialized to cp?
|
||||
newlv.start_pc = lv.start_pc;
|
||||
newlv.aliveRanges = lv.aliveRanges;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1870,8 +1887,36 @@ public class Code {
|
||||
static class LocalVar {
|
||||
final VarSymbol sym;
|
||||
final char reg;
|
||||
char start_pc = Character.MAX_VALUE;
|
||||
char length = Character.MAX_VALUE;
|
||||
|
||||
class Range {
|
||||
char start_pc = Character.MAX_VALUE;
|
||||
char length = Character.MAX_VALUE;
|
||||
|
||||
Range() {}
|
||||
|
||||
Range(char start) {
|
||||
this.start_pc = start;
|
||||
}
|
||||
|
||||
Range(char start, char length) {
|
||||
this.start_pc = start;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
boolean closed() {
|
||||
return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
int currentStartPC = start_pc;
|
||||
int currentLength = length;
|
||||
return "startpc = " + currentStartPC + " length " + currentLength;
|
||||
}
|
||||
}
|
||||
|
||||
java.util.List<Range> aliveRanges = new java.util.ArrayList<>();
|
||||
|
||||
LocalVar(VarSymbol v) {
|
||||
this.sym = v;
|
||||
this.reg = (char)v.adr;
|
||||
@ -1879,9 +1924,78 @@ public class Code {
|
||||
public LocalVar dup() {
|
||||
return new LocalVar(sym);
|
||||
}
|
||||
public String toString() {
|
||||
return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length);
|
||||
|
||||
Range firstRange() {
|
||||
return aliveRanges.isEmpty() ? null : aliveRanges.get(0);
|
||||
}
|
||||
|
||||
Range lastRange() {
|
||||
return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (aliveRanges == null) {
|
||||
return "empty local var";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder().append(sym)
|
||||
.append(" in register ").append((int)reg).append(" \n");
|
||||
for (Range r : aliveRanges) {
|
||||
sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc)))
|
||||
.append(" length=").append(Integer.toString(((int)r.length)))
|
||||
.append("\n");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public void openRange(char start) {
|
||||
if (!hasOpenRange()) {
|
||||
aliveRanges.add(new Range(start));
|
||||
}
|
||||
}
|
||||
|
||||
public void closeRange(char end) {
|
||||
if (isLastRangeInitialized()) {
|
||||
Range range = lastRange();
|
||||
if (range != null) {
|
||||
if (range.length == Character.MAX_VALUE) {
|
||||
range.length = end;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!aliveRanges.isEmpty()) {
|
||||
aliveRanges.remove(aliveRanges.size() - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasOpenRange() {
|
||||
if (aliveRanges.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Range range = lastRange();
|
||||
return range.length == Character.MAX_VALUE;
|
||||
}
|
||||
|
||||
public boolean isLastRangeInitialized() {
|
||||
if (aliveRanges.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
Range range = lastRange();
|
||||
return range.start_pc != Character.MAX_VALUE;
|
||||
}
|
||||
|
||||
public Range getWidestRange() {
|
||||
if (aliveRanges.isEmpty()) {
|
||||
return new Range();
|
||||
} else {
|
||||
Range firstRange = firstRange();
|
||||
Range lastRange = lastRange();
|
||||
char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc));
|
||||
return new Range(firstRange.start_pc, length);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/** Local variables, indexed by register. */
|
||||
@ -1892,11 +2006,60 @@ public class Code {
|
||||
int adr = v.adr;
|
||||
lvar = ArrayUtils.ensureCapacity(lvar, adr+1);
|
||||
Assert.checkNull(lvar[adr]);
|
||||
if (pendingJumps != null) resolvePending();
|
||||
if (pendingJumps != null) {
|
||||
resolvePending();
|
||||
}
|
||||
lvar[adr] = new LocalVar(v);
|
||||
state.defined.excl(adr);
|
||||
}
|
||||
|
||||
|
||||
public void closeAliveRanges(JCTree tree) {
|
||||
closeAliveRanges(tree, cp);
|
||||
}
|
||||
|
||||
public void closeAliveRanges(JCTree tree, int closingCP) {
|
||||
List<VarSymbol> locals = lvtRanges.getVars(meth, tree);
|
||||
for (LocalVar localVar: lvar) {
|
||||
for (VarSymbol aliveLocal : locals) {
|
||||
if (localVar == null) {
|
||||
return;
|
||||
}
|
||||
if (localVar.sym == aliveLocal && localVar.lastRange() != null) {
|
||||
char length = (char)(closingCP - localVar.lastRange().start_pc);
|
||||
if (length > 0 && length < Character.MAX_VALUE) {
|
||||
localVar.closeRange(length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void adjustAliveRanges(int oldCP, int delta) {
|
||||
for (LocalVar localVar: lvar) {
|
||||
if (localVar == null) {
|
||||
return;
|
||||
}
|
||||
for (LocalVar.Range range: localVar.aliveRanges) {
|
||||
if (range.closed() && range.start_pc + range.length >= oldCP) {
|
||||
range.length += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the size of the LocalVariableTable.
|
||||
*/
|
||||
public int getLVTSize() {
|
||||
int result = varBufferSize;
|
||||
for (int i = 0; i < varBufferSize; i++) {
|
||||
LocalVar var = varBuffer[i];
|
||||
result += var.aliveRanges.size() - 1;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Set the current variable defined state. */
|
||||
public void setDefined(Bits newDefined) {
|
||||
if (alive && newDefined != state.defined) {
|
||||
@ -1922,8 +2085,7 @@ public class Code {
|
||||
} else {
|
||||
state.defined.incl(adr);
|
||||
if (cp < Character.MAX_VALUE) {
|
||||
if (v.start_pc == Character.MAX_VALUE)
|
||||
v.start_pc = (char)cp;
|
||||
v.openRange((char)cp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1933,15 +2095,15 @@ public class Code {
|
||||
state.defined.excl(adr);
|
||||
if (adr < lvar.length &&
|
||||
lvar[adr] != null &&
|
||||
lvar[adr].start_pc != Character.MAX_VALUE) {
|
||||
lvar[adr].isLastRangeInitialized()) {
|
||||
LocalVar v = lvar[adr];
|
||||
char length = (char)(curPc() - v.start_pc);
|
||||
char length = (char)(curCP() - v.lastRange().start_pc);
|
||||
if (length > 0 && length < Character.MAX_VALUE) {
|
||||
lvar[adr] = v.dup();
|
||||
v.length = length;
|
||||
v.closeRange(length);
|
||||
putVar(v);
|
||||
} else {
|
||||
v.start_pc = Character.MAX_VALUE;
|
||||
v.lastRange().start_pc = Character.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1951,10 +2113,10 @@ public class Code {
|
||||
LocalVar v = lvar[adr];
|
||||
if (v != null) {
|
||||
lvar[adr] = null;
|
||||
if (v.start_pc != Character.MAX_VALUE) {
|
||||
char length = (char)(curPc() - v.start_pc);
|
||||
if (v.isLastRangeInitialized()) {
|
||||
char length = (char)(curCP() - v.lastRange().start_pc);
|
||||
if (length < Character.MAX_VALUE) {
|
||||
v.length = length;
|
||||
v.closeRange(length);
|
||||
putVar(v);
|
||||
fillLocalVarPosition(v);
|
||||
}
|
||||
@ -1968,8 +2130,9 @@ public class Code {
|
||||
return;
|
||||
for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) {
|
||||
TypeAnnotationPosition p = ta.position;
|
||||
p.lvarOffset = new int[] { (int)lv.start_pc };
|
||||
p.lvarLength = new int[] { (int)lv.length };
|
||||
LocalVar.Range widestRange = lv.getWidestRange();
|
||||
p.lvarOffset = new int[] { (int)widestRange.start_pc };
|
||||
p.lvarLength = new int[] { (int)widestRange.length };
|
||||
p.lvarIndex = new int[] { (int)lv.reg };
|
||||
p.isValidOffset = true;
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
*/
|
||||
|
||||
package com.sun.tools.javac.jvm;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import com.sun.tools.javac.util.*;
|
||||
@ -95,10 +96,14 @@ public class Gen extends JCTree.Visitor {
|
||||
return instance;
|
||||
}
|
||||
|
||||
/* Constant pool, reset by genClass.
|
||||
/** Constant pool, reset by genClass.
|
||||
*/
|
||||
private Pool pool;
|
||||
|
||||
/** LVTRanges info.
|
||||
*/
|
||||
private LVTRanges lvtRanges;
|
||||
|
||||
protected Gen(Context context) {
|
||||
context.put(genKey, this);
|
||||
|
||||
@ -128,6 +133,9 @@ public class Gen extends JCTree.Visitor {
|
||||
options.isUnset(G_CUSTOM)
|
||||
? options.isSet(G)
|
||||
: options.isSet(G_CUSTOM, "vars");
|
||||
if (varDebugInfo) {
|
||||
lvtRanges = LVTRanges.instance(context);
|
||||
}
|
||||
genCrt = options.isSet(XJCOV);
|
||||
debugCode = options.isSet("debugcode");
|
||||
allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic");
|
||||
@ -423,7 +431,7 @@ public class Gen extends JCTree.Visitor {
|
||||
*/
|
||||
void endFinalizerGap(Env<GenContext> env) {
|
||||
if (env.info.gaps != null && env.info.gaps.length() % 2 == 1)
|
||||
env.info.gaps.append(code.curPc());
|
||||
env.info.gaps.append(code.curCP());
|
||||
}
|
||||
|
||||
/** Mark end of all gaps in catch-all ranges for finalizers of environments
|
||||
@ -743,10 +751,10 @@ public class Gen extends JCTree.Visitor {
|
||||
genStat(tree, env);
|
||||
return;
|
||||
}
|
||||
int startpc = code.curPc();
|
||||
int startpc = code.curCP();
|
||||
genStat(tree, env);
|
||||
if (tree.hasTag(Tag.BLOCK)) crtFlags |= CRT_BLOCK;
|
||||
code.crt.put(tree, crtFlags, startpc, code.curPc());
|
||||
code.crt.put(tree, crtFlags, startpc, code.curCP());
|
||||
}
|
||||
|
||||
/** Derived visitor method: generate code for a statement.
|
||||
@ -781,9 +789,9 @@ public class Gen extends JCTree.Visitor {
|
||||
if (trees.length() == 1) { // mark one statement with the flags
|
||||
genStat(trees.head, env, crtFlags | CRT_STATEMENT);
|
||||
} else {
|
||||
int startpc = code.curPc();
|
||||
int startpc = code.curCP();
|
||||
genStats(trees, env);
|
||||
code.crt.put(trees, crtFlags, startpc, code.curPc());
|
||||
code.crt.put(trees, crtFlags, startpc, code.curCP());
|
||||
}
|
||||
}
|
||||
|
||||
@ -806,9 +814,9 @@ public class Gen extends JCTree.Visitor {
|
||||
*/
|
||||
public CondItem genCond(JCTree tree, int crtFlags) {
|
||||
if (!genCrt) return genCond(tree, false);
|
||||
int startpc = code.curPc();
|
||||
int startpc = code.curCP();
|
||||
CondItem item = genCond(tree, (crtFlags & CRT_FLOW_CONTROLLER) != 0);
|
||||
code.crt.put(tree, crtFlags, startpc, code.curPc());
|
||||
code.crt.put(tree, crtFlags, startpc, code.curCP());
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -971,7 +979,6 @@ public class Gen extends JCTree.Visitor {
|
||||
// definition.
|
||||
Env<GenContext> localEnv = env.dup(tree);
|
||||
localEnv.enclMethod = tree;
|
||||
|
||||
// The expected type of every return statement in this method
|
||||
// is the method's return type.
|
||||
this.pt = tree.sym.erasure(types).getReturnType();
|
||||
@ -1045,7 +1052,7 @@ public class Gen extends JCTree.Visitor {
|
||||
code.crt.put(tree.body,
|
||||
CRT_BLOCK,
|
||||
startpcCrt,
|
||||
code.curPc());
|
||||
code.curCP());
|
||||
|
||||
code.endScopes(0);
|
||||
|
||||
@ -1087,10 +1094,12 @@ public class Gen extends JCTree.Visitor {
|
||||
: null,
|
||||
syms,
|
||||
types,
|
||||
pool);
|
||||
pool,
|
||||
varDebugInfo ? lvtRanges : null);
|
||||
items = new Items(pool, code, syms, types);
|
||||
if (code.debugCode)
|
||||
if (code.debugCode) {
|
||||
System.err.println(meth + " for body " + tree);
|
||||
}
|
||||
|
||||
// If method is not static, create a new local variable address
|
||||
// for `this'.
|
||||
@ -1111,7 +1120,7 @@ public class Gen extends JCTree.Visitor {
|
||||
}
|
||||
|
||||
// Get ready to generate code for method body.
|
||||
int startpcCrt = genCrt ? code.curPc() : 0;
|
||||
int startpcCrt = genCrt ? code.curCP() : 0;
|
||||
code.entryPoint();
|
||||
|
||||
// Suppress initial stackmap
|
||||
@ -1189,14 +1198,30 @@ public class Gen extends JCTree.Visitor {
|
||||
Chain loopDone = c.jumpFalse();
|
||||
code.resolve(c.trueJumps);
|
||||
genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
|
||||
if (varDebugInfo) {
|
||||
checkLoopLocalVarRangeEnding(loop, body,
|
||||
LoopLocalVarRangeEndingPoint.BEFORE_STEPS);
|
||||
}
|
||||
code.resolve(loopEnv.info.cont);
|
||||
genStats(step, loopEnv);
|
||||
if (varDebugInfo) {
|
||||
checkLoopLocalVarRangeEnding(loop, body,
|
||||
LoopLocalVarRangeEndingPoint.AFTER_STEPS);
|
||||
}
|
||||
code.resolve(code.branch(goto_), startpc);
|
||||
code.resolve(loopDone);
|
||||
} else {
|
||||
genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET);
|
||||
if (varDebugInfo) {
|
||||
checkLoopLocalVarRangeEnding(loop, body,
|
||||
LoopLocalVarRangeEndingPoint.BEFORE_STEPS);
|
||||
}
|
||||
code.resolve(loopEnv.info.cont);
|
||||
genStats(step, loopEnv);
|
||||
if (varDebugInfo) {
|
||||
checkLoopLocalVarRangeEnding(loop, body,
|
||||
LoopLocalVarRangeEndingPoint.AFTER_STEPS);
|
||||
}
|
||||
CondItem c;
|
||||
if (cond != null) {
|
||||
code.statBegin(cond.pos);
|
||||
@ -1210,6 +1235,44 @@ public class Gen extends JCTree.Visitor {
|
||||
code.resolve(loopEnv.info.exit);
|
||||
}
|
||||
|
||||
private enum LoopLocalVarRangeEndingPoint {
|
||||
BEFORE_STEPS,
|
||||
AFTER_STEPS,
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether we have reached an alive range ending point for local
|
||||
* variables after a loop.
|
||||
*
|
||||
* Local variables alive range ending point for loops varies depending
|
||||
* on the loop type. The range can be closed before or after the code
|
||||
* for the steps sentences has been generated.
|
||||
*
|
||||
* - While loops has no steps so in that case the range is closed just
|
||||
* after the body of the loop.
|
||||
*
|
||||
* - For-like loops may have steps so as long as the steps sentences
|
||||
* can possibly contain non-synthetic local variables, the alive range
|
||||
* for local variables must be closed after the steps in this case.
|
||||
*/
|
||||
private void checkLoopLocalVarRangeEnding(JCTree loop, JCTree body,
|
||||
LoopLocalVarRangeEndingPoint endingPoint) {
|
||||
if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) {
|
||||
switch (endingPoint) {
|
||||
case BEFORE_STEPS:
|
||||
if (!loop.hasTag(FORLOOP)) {
|
||||
code.closeAliveRanges(body);
|
||||
}
|
||||
break;
|
||||
case AFTER_STEPS:
|
||||
if (loop.hasTag(FORLOOP)) {
|
||||
code.closeAliveRanges(body);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void visitForeachLoop(JCEnhancedForLoop tree) {
|
||||
throw new AssertionError(); // should have been removed by Lower.
|
||||
}
|
||||
@ -1223,7 +1286,7 @@ public class Gen extends JCTree.Visitor {
|
||||
public void visitSwitch(JCSwitch tree) {
|
||||
int limit = code.nextreg;
|
||||
Assert.check(!tree.selector.type.hasTag(CLASS));
|
||||
int startpcCrt = genCrt ? code.curPc() : 0;
|
||||
int startpcCrt = genCrt ? code.curCP() : 0;
|
||||
Item sel = genExpr(tree.selector, syms.intType);
|
||||
List<JCCase> cases = tree.cases;
|
||||
if (cases.isEmpty()) {
|
||||
@ -1231,13 +1294,13 @@ public class Gen extends JCTree.Visitor {
|
||||
sel.load().drop();
|
||||
if (genCrt)
|
||||
code.crt.put(TreeInfo.skipParens(tree.selector),
|
||||
CRT_FLOW_CONTROLLER, startpcCrt, code.curPc());
|
||||
CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
|
||||
} else {
|
||||
// We are seeing a nonempty switch.
|
||||
sel.load();
|
||||
if (genCrt)
|
||||
code.crt.put(TreeInfo.skipParens(tree.selector),
|
||||
CRT_FLOW_CONTROLLER, startpcCrt, code.curPc());
|
||||
CRT_FLOW_CONTROLLER, startpcCrt, code.curCP());
|
||||
Env<GenContext> switchEnv = env.dup(tree, new GenContext());
|
||||
switchEnv.info.isSwitch = true;
|
||||
|
||||
@ -1278,10 +1341,10 @@ public class Gen extends JCTree.Visitor {
|
||||
?
|
||||
tableswitch : lookupswitch;
|
||||
|
||||
int startpc = code.curPc(); // the position of the selector operation
|
||||
int startpc = code.curCP(); // the position of the selector operation
|
||||
code.emitop0(opcode);
|
||||
code.align(4);
|
||||
int tableBase = code.curPc(); // the start of the jump table
|
||||
int tableBase = code.curCP(); // the start of the jump table
|
||||
int[] offsets = null; // a table of offsets for a lookupswitch
|
||||
code.emit4(-1); // leave space for default offset
|
||||
if (opcode == tableswitch) {
|
||||
@ -1323,6 +1386,9 @@ public class Gen extends JCTree.Visitor {
|
||||
|
||||
// Generate code for the statements in this case.
|
||||
genStats(c.stats, switchEnv, CRT_FLOW_TARGET);
|
||||
if (varDebugInfo && lvtRanges.containsKey(code.meth, c.stats.last())) {
|
||||
code.closeAliveRanges(c.stats.last());
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve all breaks.
|
||||
@ -1402,7 +1468,7 @@ public class Gen extends JCTree.Visitor {
|
||||
void gen() {
|
||||
genLast();
|
||||
Assert.check(syncEnv.info.gaps.length() % 2 == 0);
|
||||
syncEnv.info.gaps.append(code.curPc());
|
||||
syncEnv.info.gaps.append(code.curCP());
|
||||
}
|
||||
void genLast() {
|
||||
if (code.isAlive()) {
|
||||
@ -1441,10 +1507,10 @@ public class Gen extends JCTree.Visitor {
|
||||
jsrState);
|
||||
}
|
||||
Assert.check(tryEnv.info.gaps.length() % 2 == 0);
|
||||
tryEnv.info.gaps.append(code.curPc());
|
||||
tryEnv.info.gaps.append(code.curCP());
|
||||
} else {
|
||||
Assert.check(tryEnv.info.gaps.length() % 2 == 0);
|
||||
tryEnv.info.gaps.append(code.curPc());
|
||||
tryEnv.info.gaps.append(code.curCP());
|
||||
genLast();
|
||||
}
|
||||
}
|
||||
@ -1467,10 +1533,10 @@ public class Gen extends JCTree.Visitor {
|
||||
*/
|
||||
void genTry(JCTree body, List<JCCatch> catchers, Env<GenContext> env) {
|
||||
int limit = code.nextreg;
|
||||
int startpc = code.curPc();
|
||||
int startpc = code.curCP();
|
||||
Code.State stateTry = code.state.dup();
|
||||
genStat(body, env, CRT_BLOCK);
|
||||
int endpc = code.curPc();
|
||||
int endpc = code.curCP();
|
||||
boolean hasFinalizer =
|
||||
env.info.finalize != null &&
|
||||
env.info.finalize.hasFinalizer();
|
||||
@ -1478,82 +1544,77 @@ public class Gen extends JCTree.Visitor {
|
||||
code.statBegin(TreeInfo.endPos(body));
|
||||
genFinalizer(env);
|
||||
code.statBegin(TreeInfo.endPos(env.tree));
|
||||
Chain exitChain;
|
||||
if (startpc != endpc) {
|
||||
exitChain = code.branch(goto_);
|
||||
} else {
|
||||
exitChain = code.branch(dontgoto);
|
||||
Chain exitChain = code.branch(goto_);
|
||||
if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) {
|
||||
code.closeAliveRanges(body);
|
||||
}
|
||||
endFinalizerGap(env);
|
||||
if (startpc != endpc) {
|
||||
for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {
|
||||
// start off with exception on stack
|
||||
code.entryPoint(stateTry, l.head.param.sym.type);
|
||||
genCatch(l.head, env, startpc, endpc, gaps);
|
||||
genFinalizer(env);
|
||||
if (hasFinalizer || l.tail.nonEmpty()) {
|
||||
code.statBegin(TreeInfo.endPos(env.tree));
|
||||
exitChain = Code.mergeChains(exitChain,
|
||||
code.branch(goto_));
|
||||
}
|
||||
endFinalizerGap(env);
|
||||
if (startpc != endpc) for (List<JCCatch> l = catchers; l.nonEmpty(); l = l.tail) {
|
||||
// start off with exception on stack
|
||||
code.entryPoint(stateTry, l.head.param.sym.type);
|
||||
genCatch(l.head, env, startpc, endpc, gaps);
|
||||
genFinalizer(env);
|
||||
if (hasFinalizer || l.tail.nonEmpty()) {
|
||||
code.statBegin(TreeInfo.endPos(env.tree));
|
||||
exitChain = Code.mergeChains(exitChain,
|
||||
code.branch(goto_));
|
||||
}
|
||||
endFinalizerGap(env);
|
||||
}
|
||||
if (hasFinalizer) {
|
||||
// Create a new register segement to avoid allocating
|
||||
// the same variables in finalizers and other statements.
|
||||
code.newRegSegment();
|
||||
|
||||
if (hasFinalizer) {
|
||||
// Create a new register segement to avoid allocating
|
||||
// the same variables in finalizers and other statements.
|
||||
code.newRegSegment();
|
||||
// Add a catch-all clause.
|
||||
|
||||
// Add a catch-all clause.
|
||||
// start off with exception on stack
|
||||
int catchallpc = code.entryPoint(stateTry, syms.throwableType);
|
||||
|
||||
// start off with exception on stack
|
||||
int catchallpc = code.entryPoint(stateTry, syms.throwableType);
|
||||
// Register all exception ranges for catch all clause.
|
||||
// The range of the catch all clause is from the beginning
|
||||
// of the try or synchronized block until the present
|
||||
// code pointer excluding all gaps in the current
|
||||
// environment's GenContext.
|
||||
int startseg = startpc;
|
||||
while (env.info.gaps.nonEmpty()) {
|
||||
int endseg = env.info.gaps.next().intValue();
|
||||
registerCatch(body.pos(), startseg, endseg,
|
||||
catchallpc, 0);
|
||||
startseg = env.info.gaps.next().intValue();
|
||||
}
|
||||
code.statBegin(TreeInfo.finalizerPos(env.tree));
|
||||
code.markStatBegin();
|
||||
|
||||
// Register all exception ranges for catch all clause.
|
||||
// The range of the catch all clause is from the beginning
|
||||
// of the try or synchronized block until the present
|
||||
// code pointer excluding all gaps in the current
|
||||
// environment's GenContext.
|
||||
int startseg = startpc;
|
||||
while (env.info.gaps.nonEmpty()) {
|
||||
int endseg = env.info.gaps.next().intValue();
|
||||
registerCatch(body.pos(), startseg, endseg,
|
||||
catchallpc, 0);
|
||||
startseg = env.info.gaps.next().intValue();
|
||||
}
|
||||
Item excVar = makeTemp(syms.throwableType);
|
||||
excVar.store();
|
||||
genFinalizer(env);
|
||||
excVar.load();
|
||||
registerCatch(body.pos(), startseg,
|
||||
env.info.gaps.next().intValue(),
|
||||
catchallpc, 0);
|
||||
code.emitop0(athrow);
|
||||
code.markDead();
|
||||
|
||||
// If there are jsr's to this finalizer, ...
|
||||
if (env.info.cont != null) {
|
||||
// Resolve all jsr's.
|
||||
code.resolve(env.info.cont);
|
||||
|
||||
// Mark statement line number
|
||||
code.statBegin(TreeInfo.finalizerPos(env.tree));
|
||||
code.markStatBegin();
|
||||
|
||||
Item excVar = makeTemp(syms.throwableType);
|
||||
excVar.store();
|
||||
genFinalizer(env);
|
||||
excVar.load();
|
||||
registerCatch(body.pos(), startseg,
|
||||
env.info.gaps.next().intValue(),
|
||||
catchallpc, 0);
|
||||
code.emitop0(athrow);
|
||||
// Save return address.
|
||||
LocalItem retVar = makeTemp(syms.throwableType);
|
||||
retVar.store();
|
||||
|
||||
// Generate finalizer code.
|
||||
env.info.finalize.genLast();
|
||||
|
||||
// Return.
|
||||
code.emitop1w(ret, retVar.reg);
|
||||
code.markDead();
|
||||
|
||||
// If there are jsr's to this finalizer, ...
|
||||
if (env.info.cont != null) {
|
||||
// Resolve all jsr's.
|
||||
code.resolve(env.info.cont);
|
||||
|
||||
// Mark statement line number
|
||||
code.statBegin(TreeInfo.finalizerPos(env.tree));
|
||||
code.markStatBegin();
|
||||
|
||||
// Save return address.
|
||||
LocalItem retVar = makeTemp(syms.throwableType);
|
||||
retVar.store();
|
||||
|
||||
// Generate finalizer code.
|
||||
env.info.finalize.genLast();
|
||||
|
||||
// Return.
|
||||
code.emitop1w(ret, retVar.reg);
|
||||
code.markDead();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Resolve all breaks.
|
||||
@ -1581,7 +1642,7 @@ public class Gen extends JCTree.Visitor {
|
||||
int catchType = makeRef(tree.pos(), subCatch.type);
|
||||
int end = gaps.head.intValue();
|
||||
registerCatch(tree.pos(),
|
||||
startpc, end, code.curPc(),
|
||||
startpc, end, code.curCP(),
|
||||
catchType);
|
||||
if (subCatch.type.isAnnotated()) {
|
||||
// All compounds share the same position, simply update the
|
||||
@ -1597,7 +1658,7 @@ public class Gen extends JCTree.Visitor {
|
||||
for (JCExpression subCatch : subClauses) {
|
||||
int catchType = makeRef(tree.pos(), subCatch.type);
|
||||
registerCatch(tree.pos(),
|
||||
startpc, endpc, code.curPc(),
|
||||
startpc, endpc, code.curCP(),
|
||||
catchType);
|
||||
if (subCatch.type.isAnnotated()) {
|
||||
// All compounds share the same position, simply update the
|
||||
@ -1740,11 +1801,19 @@ public class Gen extends JCTree.Visitor {
|
||||
code.resolve(c.trueJumps);
|
||||
genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET);
|
||||
thenExit = code.branch(goto_);
|
||||
if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.thenpart)) {
|
||||
code.closeAliveRanges(tree.thenpart,
|
||||
thenExit != null && tree.elsepart == null ? thenExit.pc : code.cp);
|
||||
}
|
||||
}
|
||||
if (elseChain != null) {
|
||||
code.resolve(elseChain);
|
||||
if (tree.elsepart != null)
|
||||
if (tree.elsepart != null) {
|
||||
genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET);
|
||||
if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.elsepart)) {
|
||||
code.closeAliveRanges(tree.elsepart);
|
||||
}
|
||||
}
|
||||
}
|
||||
code.resolve(thenExit);
|
||||
code.endScopes(limit);
|
||||
@ -1838,20 +1907,20 @@ public class Gen extends JCTree.Visitor {
|
||||
Chain elseChain = c.jumpFalse();
|
||||
if (!c.isFalse()) {
|
||||
code.resolve(c.trueJumps);
|
||||
int startpc = genCrt ? code.curPc() : 0;
|
||||
int startpc = genCrt ? code.curCP() : 0;
|
||||
genExpr(tree.truepart, pt).load();
|
||||
code.state.forceStackTop(tree.type);
|
||||
if (genCrt) code.crt.put(tree.truepart, CRT_FLOW_TARGET,
|
||||
startpc, code.curPc());
|
||||
startpc, code.curCP());
|
||||
thenExit = code.branch(goto_);
|
||||
}
|
||||
if (elseChain != null) {
|
||||
code.resolve(elseChain);
|
||||
int startpc = genCrt ? code.curPc() : 0;
|
||||
int startpc = genCrt ? code.curCP() : 0;
|
||||
genExpr(tree.falsepart, pt).load();
|
||||
code.state.forceStackTop(tree.type);
|
||||
if (genCrt) code.crt.put(tree.falsepart, CRT_FLOW_TARGET,
|
||||
startpc, code.curPc());
|
||||
startpc, code.curCP());
|
||||
}
|
||||
code.resolve(thenExit);
|
||||
result = items.makeStackItem(pt);
|
||||
@ -2431,6 +2500,19 @@ public class Gen extends JCTree.Visitor {
|
||||
new Env<GenContext>(cdef, new GenContext());
|
||||
localEnv.toplevel = env.toplevel;
|
||||
localEnv.enclClass = cdef;
|
||||
|
||||
/* We must not analyze synthetic methods
|
||||
*/
|
||||
if (varDebugInfo && (cdef.sym.flags() & SYNTHETIC) == 0) {
|
||||
try {
|
||||
LVTAssignAnalyzer lvtAssignAnalyzer = LVTAssignAnalyzer.make(
|
||||
lvtRanges, syms, names);
|
||||
lvtAssignAnalyzer.analyzeTree(localEnv);
|
||||
} catch (Throwable e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
for (List<JCTree> l = cdef.defs; l.nonEmpty(); l = l.tail) {
|
||||
genDef(l.head, localEnv);
|
||||
}
|
||||
@ -2515,4 +2597,311 @@ public class Gen extends JCTree.Visitor {
|
||||
cont = Code.mergeChains(c, cont);
|
||||
}
|
||||
}
|
||||
|
||||
static class LVTAssignAnalyzer
|
||||
extends Flow.AbstractAssignAnalyzer<LVTAssignAnalyzer.LVTAssignPendingExit> {
|
||||
|
||||
final LVTBits lvtInits;
|
||||
final LVTRanges lvtRanges;
|
||||
|
||||
/* This class is anchored to a context dependent tree. The tree can
|
||||
* vary inside the same instruction for example in the switch instruction
|
||||
* the same FlowBits instance can be anchored to the whole tree, or
|
||||
* to a given case. The aim is to always anchor the bits to the tree
|
||||
* capable of closing a DA range.
|
||||
*/
|
||||
static class LVTBits extends Bits {
|
||||
|
||||
enum BitsOpKind {
|
||||
INIT,
|
||||
CLEAR,
|
||||
INCL_BIT,
|
||||
EXCL_BIT,
|
||||
ASSIGN,
|
||||
AND_SET,
|
||||
OR_SET,
|
||||
DIFF_SET,
|
||||
XOR_SET,
|
||||
INCL_RANGE,
|
||||
EXCL_RANGE,
|
||||
}
|
||||
|
||||
JCTree currentTree;
|
||||
LVTAssignAnalyzer analyzer;
|
||||
private int[] oldBits = null;
|
||||
BitsState stateBeforeOp;
|
||||
|
||||
LVTBits() {
|
||||
super(false);
|
||||
}
|
||||
|
||||
LVTBits(int[] bits, BitsState initState) {
|
||||
super(bits, initState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
generalOp(null, -1, BitsOpKind.CLEAR);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void internalReset() {
|
||||
super.internalReset();
|
||||
oldBits = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bits assign(Bits someBits) {
|
||||
// bits can be null
|
||||
oldBits = bits;
|
||||
stateBeforeOp = currentState;
|
||||
super.assign(someBits);
|
||||
changed();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void excludeFrom(int start) {
|
||||
generalOp(null, start, BitsOpKind.EXCL_RANGE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void excl(int x) {
|
||||
Assert.check(x >= 0);
|
||||
generalOp(null, x, BitsOpKind.EXCL_BIT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bits andSet(Bits xs) {
|
||||
return generalOp(xs, -1, BitsOpKind.AND_SET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bits orSet(Bits xs) {
|
||||
return generalOp(xs, -1, BitsOpKind.OR_SET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bits diffSet(Bits xs) {
|
||||
return generalOp(xs, -1, BitsOpKind.DIFF_SET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bits xorSet(Bits xs) {
|
||||
return generalOp(xs, -1, BitsOpKind.XOR_SET);
|
||||
}
|
||||
|
||||
private Bits generalOp(Bits xs, int i, BitsOpKind opKind) {
|
||||
Assert.check(currentState != BitsState.UNKNOWN);
|
||||
oldBits = dupBits();
|
||||
stateBeforeOp = currentState;
|
||||
switch (opKind) {
|
||||
case AND_SET:
|
||||
super.andSet(xs);
|
||||
break;
|
||||
case OR_SET:
|
||||
super.orSet(xs);
|
||||
break;
|
||||
case XOR_SET:
|
||||
super.xorSet(xs);
|
||||
break;
|
||||
case DIFF_SET:
|
||||
super.diffSet(xs);
|
||||
break;
|
||||
case CLEAR:
|
||||
super.clear();
|
||||
break;
|
||||
case EXCL_BIT:
|
||||
super.excl(i);
|
||||
break;
|
||||
case EXCL_RANGE:
|
||||
super.excludeFrom(i);
|
||||
break;
|
||||
}
|
||||
changed();
|
||||
return this;
|
||||
}
|
||||
|
||||
/* The tree we need to anchor the bits instance to.
|
||||
*/
|
||||
LVTBits at(JCTree tree) {
|
||||
this.currentTree = tree;
|
||||
return this;
|
||||
}
|
||||
|
||||
/* If the instance should be changed but the tree is not a closing
|
||||
* tree then a reset is needed or the former tree can mistakingly be
|
||||
* used.
|
||||
*/
|
||||
LVTBits resetTree() {
|
||||
this.currentTree = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/** 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 void changed() {
|
||||
if (currentTree != null &&
|
||||
stateBeforeOp != BitsState.UNKNOWN &&
|
||||
trackTree(currentTree)) {
|
||||
List<VarSymbol> locals =
|
||||
analyzer.lvtRanges
|
||||
.getVars(analyzer.currentMethod, currentTree);
|
||||
locals = locals != null ?
|
||||
locals : List.<VarSymbol>nil();
|
||||
for (JCVariableDecl vardecl : analyzer.vardecls) {
|
||||
//once the first is null, the rest will be so.
|
||||
if (vardecl == null) {
|
||||
break;
|
||||
}
|
||||
if (trackVar(vardecl.sym) && bitChanged(vardecl.sym.adr)) {
|
||||
locals = locals.prepend(vardecl.sym);
|
||||
}
|
||||
}
|
||||
if (!locals.isEmpty()) {
|
||||
analyzer.lvtRanges.setEntry(analyzer.currentMethod,
|
||||
currentTree, locals);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean bitChanged(int x) {
|
||||
boolean isMemberOfBits = isMember(x);
|
||||
int[] tmp = bits;
|
||||
bits = oldBits;
|
||||
boolean isMemberOfOldBits = isMember(x);
|
||||
bits = tmp;
|
||||
return (!isMemberOfBits && isMemberOfOldBits);
|
||||
}
|
||||
|
||||
boolean trackVar(VarSymbol var) {
|
||||
return (var.owner.kind == MTH &&
|
||||
(var.flags() & (PARAMETER | HASINIT)) == 0 &&
|
||||
analyzer.trackable(var));
|
||||
}
|
||||
|
||||
boolean trackTree(JCTree tree) {
|
||||
switch (tree.getTag()) {
|
||||
// of course a method closes the alive range of a local variable.
|
||||
case METHODDEF:
|
||||
// for while loops we want only the body
|
||||
case WHILELOOP:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class LVTAssignPendingExit extends Flow.AssignAnalyzer.AssignPendingExit {
|
||||
|
||||
LVTAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) {
|
||||
super(tree, inits, uninits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolveJump(JCTree tree) {
|
||||
lvtInits.at(tree);
|
||||
super.resolveJump(tree);
|
||||
}
|
||||
}
|
||||
|
||||
private LVTAssignAnalyzer(LVTRanges lvtRanges, Symtab syms, Names names) {
|
||||
super(new LVTBits(), syms, names);
|
||||
lvtInits = (LVTBits)inits;
|
||||
this.lvtRanges = lvtRanges;
|
||||
}
|
||||
|
||||
public static LVTAssignAnalyzer make(LVTRanges lvtRanges, Symtab syms, Names names) {
|
||||
LVTAssignAnalyzer result = new LVTAssignAnalyzer(lvtRanges, syms, names);
|
||||
result.lvtInits.analyzer = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void markDead(JCTree tree) {
|
||||
lvtInits.at(tree).inclRange(returnadr, nextadr);
|
||||
super.markDead(tree);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void merge(JCTree tree) {
|
||||
lvtInits.at(tree);
|
||||
super.merge(tree);
|
||||
}
|
||||
|
||||
boolean isSyntheticOrMandated(Symbol sym) {
|
||||
return (sym.flags() & (SYNTHETIC | MANDATED)) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean trackable(VarSymbol sym) {
|
||||
if (isSyntheticOrMandated(sym)) {
|
||||
//fast check to avoid tracking synthetic or mandated variables
|
||||
return false;
|
||||
}
|
||||
return super.trackable(sym);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initParam(JCVariableDecl def) {
|
||||
if (!isSyntheticOrMandated(def.sym)) {
|
||||
super.initParam(def);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void assignToInits(JCTree tree, Bits bits) {
|
||||
lvtInits.at(tree);
|
||||
lvtInits.assign(bits);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void andSetInits(JCTree tree, Bits bits) {
|
||||
lvtInits.at(tree);
|
||||
lvtInits.andSet(bits);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void orSetInits(JCTree tree, Bits bits) {
|
||||
lvtInits.at(tree);
|
||||
lvtInits.orSet(bits);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exclVarFromInits(JCTree tree, int adr) {
|
||||
lvtInits.at(tree);
|
||||
lvtInits.excl(adr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LVTAssignPendingExit createNewPendingExit(JCTree tree, Bits inits, Bits uninits) {
|
||||
return new LVTAssignPendingExit(tree, inits, uninits);
|
||||
}
|
||||
|
||||
MethodSymbol currentMethod;
|
||||
|
||||
@Override
|
||||
public void visitMethodDef(JCMethodDecl tree) {
|
||||
if ((tree.sym.flags() & (SYNTHETIC | GENERATEDCONSTR)) != 0) {
|
||||
return;
|
||||
}
|
||||
if (tree.name.equals(names.clinit)) {
|
||||
return;
|
||||
}
|
||||
boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0;
|
||||
if (enumClass &&
|
||||
(tree.name.equals(names.valueOf) ||
|
||||
tree.name.equals(names.values) ||
|
||||
tree.name.equals(names.init))) {
|
||||
return;
|
||||
}
|
||||
currentMethod = tree.sym;
|
||||
super.visitMethodDef(tree);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -789,18 +789,18 @@ public class Items {
|
||||
Chain jumpTrue() {
|
||||
if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode));
|
||||
// we should proceed further in -Xjcov mode only
|
||||
int startpc = code.curPc();
|
||||
int startpc = code.curCP();
|
||||
Chain c = Code.mergeChains(trueJumps, code.branch(opcode));
|
||||
code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc());
|
||||
code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curCP());
|
||||
return c;
|
||||
}
|
||||
|
||||
Chain jumpFalse() {
|
||||
if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
|
||||
// we should proceed further in -Xjcov mode only
|
||||
int startpc = code.curPc();
|
||||
int startpc = code.curCP();
|
||||
Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode)));
|
||||
code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc());
|
||||
code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curCP());
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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.javac.jvm;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
import com.sun.tools.javac.code.Symbol.MethodSymbol;
|
||||
import com.sun.tools.javac.code.Symbol.VarSymbol;
|
||||
import com.sun.tools.javac.tree.JCTree;
|
||||
import com.sun.tools.javac.util.Context;
|
||||
import com.sun.tools.javac.util.List;
|
||||
|
||||
/** This class contains a one to many relation between a tree and a set of variables.
|
||||
* The relation implies that the given tree closes the DA (definite assignment)
|
||||
* range for the set of variables.
|
||||
*
|
||||
* <p><b>This is NOT part of any supported API.
|
||||
* If you write code that depends on this, you do so at your own risk.
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class LVTRanges {
|
||||
/** The context key for the LVT ranges. */
|
||||
protected static final Context.Key<LVTRanges> lvtRangesKey = new Context.Key<>();
|
||||
|
||||
/** Get the LVTRanges instance for this context. */
|
||||
public static LVTRanges instance(Context context) {
|
||||
LVTRanges instance = context.get(lvtRangesKey);
|
||||
if (instance == null) {
|
||||
instance = new LVTRanges(context);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 1812267524140424433L;
|
||||
|
||||
protected Context context;
|
||||
|
||||
protected Map<MethodSymbol, Map<JCTree, List<VarSymbol>>>
|
||||
aliveRangeClosingTrees = new WeakHashMap<>();
|
||||
|
||||
public LVTRanges(Context context) {
|
||||
this.context = context;
|
||||
context.put(lvtRangesKey, this);
|
||||
}
|
||||
|
||||
public List<VarSymbol> getVars(MethodSymbol method, JCTree tree) {
|
||||
Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method);
|
||||
return (varMap != null) ? varMap.get(tree) : null;
|
||||
}
|
||||
|
||||
public boolean containsKey(MethodSymbol method, JCTree tree) {
|
||||
Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method);
|
||||
if (varMap == null) {
|
||||
return false;
|
||||
}
|
||||
return varMap.containsKey(tree);
|
||||
}
|
||||
|
||||
public void setEntry(MethodSymbol method, JCTree tree, List<VarSymbol> vars) {
|
||||
Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method);
|
||||
if (varMap != null) {
|
||||
varMap.put(tree, vars);
|
||||
} else {
|
||||
varMap = new WeakHashMap<>();
|
||||
varMap.put(tree, vars);
|
||||
aliveRangeClosingTrees.put(method, varMap);
|
||||
}
|
||||
}
|
||||
|
||||
public List<VarSymbol> removeEntry(MethodSymbol method, JCTree tree) {
|
||||
Map<JCTree, List<VarSymbol>> varMap = aliveRangeClosingTrees.get(method);
|
||||
if (varMap != null) {
|
||||
List<VarSymbol> result = varMap.remove(tree);
|
||||
if (varMap.isEmpty()) {
|
||||
aliveRangeClosingTrees.remove(method);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/* This method should be used for debugging LVT related issues.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
String result = "";
|
||||
for (Entry<MethodSymbol, Map<JCTree, List<VarSymbol>>> mainEntry: aliveRangeClosingTrees.entrySet()) {
|
||||
result += "Method: \n" + mainEntry.getKey().flatName() + "\n";
|
||||
int i = 1;
|
||||
for (Entry<JCTree, List<VarSymbol>> treeEntry: mainEntry.getValue().entrySet()) {
|
||||
result += " Tree " + i + ": \n" + treeEntry.getKey().toString() + "\n";
|
||||
result += " Variables closed:\n";
|
||||
for (VarSymbol var: treeEntry.getValue()) {
|
||||
result += " " + var.toString();
|
||||
}
|
||||
result += "\n";
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
@ -80,7 +80,7 @@ import static com.sun.tools.javac.util.ListBuffer.lb;
|
||||
* This code and its internal interfaces are subject to change or
|
||||
* deletion without notice.</b>
|
||||
*/
|
||||
public class JavaCompiler implements ClassReader.SourceCompleter {
|
||||
public class JavaCompiler {
|
||||
/** The context key for the compiler. */
|
||||
protected static final Context.Key<JavaCompiler> compilerKey =
|
||||
new Context.Key<JavaCompiler>();
|
||||
@ -310,6 +310,17 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
|
||||
*/
|
||||
protected JavaCompiler delegateCompiler;
|
||||
|
||||
/**
|
||||
* SourceCompleter that delegates to the complete-method of this class.
|
||||
*/
|
||||
protected final ClassReader.SourceCompleter thisCompleter =
|
||||
new ClassReader.SourceCompleter() {
|
||||
@Override
|
||||
public void complete(ClassSymbol sym) throws CompletionFailure {
|
||||
JavaCompiler.this.complete(sym);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Command line options.
|
||||
*/
|
||||
@ -374,7 +385,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter {
|
||||
types = Types.instance(context);
|
||||
taskListener = MultiTaskListener.instance(context);
|
||||
|
||||
reader.sourceCompleter = this;
|
||||
reader.sourceCompleter = thisCompleter;
|
||||
|
||||
options = Options.instance(context);
|
||||
|
||||
|
@ -742,11 +742,6 @@ compiler.misc.incompatible.arg.types.in.lambda=\
|
||||
compiler.misc.incompatible.arg.types.in.mref=\
|
||||
incompatible parameter types in method reference
|
||||
|
||||
# 0: list of type, 1: message segment
|
||||
compiler.misc.bad.arg.types.in.lambda=\
|
||||
cannot type-check lambda expression with inferred parameter types\n\
|
||||
inferred types: {0}
|
||||
|
||||
compiler.err.new.not.allowed.in.annotation=\
|
||||
''new'' not allowed in an annotation
|
||||
|
||||
@ -1397,6 +1392,10 @@ compiler.warn.long.SVUID=\
|
||||
compiler.warn.missing.SVUID=\
|
||||
serializable class {0} has no definition of serialVersionUID
|
||||
|
||||
# 0: symbol, 1: symbol, 2: symbol, 3: symbol
|
||||
compiler.warn.potentially.ambiguous.overload=\
|
||||
{0} in {1} is potentially ambiguous with {2} in {3}
|
||||
|
||||
# 0: message segment
|
||||
compiler.warn.override.varargs.missing=\
|
||||
{0}; overridden method has no ''...''
|
||||
@ -1916,10 +1915,6 @@ compiler.misc.inferred.do.not.conform.to.eq.bounds=\
|
||||
inferred: {0}\n\
|
||||
equality constraints(s): {1}
|
||||
|
||||
# 0: list of type
|
||||
compiler.misc.cyclic.inference=\
|
||||
Cannot instantiate inference variables {0} because of an inference loop
|
||||
|
||||
# 0: symbol
|
||||
compiler.misc.diamond=\
|
||||
{0}<>
|
||||
@ -1932,6 +1927,10 @@ compiler.misc.diamond.non.generic=\
|
||||
compiler.misc.diamond.and.explicit.params=\
|
||||
cannot use ''<>'' with explicit type parameters for constructor
|
||||
|
||||
# 0: unused
|
||||
compiler.misc.mref.infer.and.explicit.params=\
|
||||
cannot use raw constructor reference with explicit type parameters for constructor
|
||||
|
||||
# 0: type, 1: list of type
|
||||
compiler.misc.explicit.param.do.not.conform.to.bounds=\
|
||||
explicit type argument {0} does not conform to declared bound(s) {1}
|
||||
|
@ -1596,7 +1596,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
public List<JCVariableDecl> params;
|
||||
public JCTree body;
|
||||
public boolean canCompleteNormally = true;
|
||||
public List<Type> inferredThrownTypes;
|
||||
public ParameterKind paramKind;
|
||||
|
||||
public JCLambda(List<JCVariableDecl> params,
|
||||
@ -1908,6 +1907,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
* Selects a member expression.
|
||||
*/
|
||||
public static class JCMemberReference extends JCFunctionalExpression implements MemberReferenceTree {
|
||||
|
||||
public ReferenceMode mode;
|
||||
public ReferenceKind kind;
|
||||
public Name name;
|
||||
@ -1917,6 +1917,12 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
public Type varargsElement;
|
||||
public PolyKind refPolyKind;
|
||||
public boolean ownerAccessible;
|
||||
public OverloadKind overloadKind;
|
||||
|
||||
public enum OverloadKind {
|
||||
OVERLOADED,
|
||||
UNOVERLOADED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Javac-dependent classification for member references, based
|
||||
|
@ -890,7 +890,7 @@ public class TreeMaker implements JCTree.Factory {
|
||||
/** Create a value parameter tree from its name, type, and owner.
|
||||
*/
|
||||
public JCVariableDecl Param(Name name, Type argtype, Symbol owner) {
|
||||
return VarDef(new VarSymbol(0, name, argtype, owner), null);
|
||||
return VarDef(new VarSymbol(PARAMETER, name, argtype, owner), null);
|
||||
}
|
||||
|
||||
/** Create a a list of value parameter trees x0, ..., xn from a list of
|
||||
|
@ -27,8 +27,6 @@ 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.
|
||||
@ -38,20 +36,6 @@ import static com.sun.tools.javac.util.Bits.BitsOpKind.*;
|
||||
*/
|
||||
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 \
|
||||
// \____________/ | \_________/
|
||||
@ -64,11 +48,14 @@ public class Bits {
|
||||
// | |
|
||||
// -----------
|
||||
// any
|
||||
private enum BitsState {
|
||||
protected 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.
|
||||
*
|
||||
* Bits instances are final fields in Flow so the UNKNOWN state models
|
||||
* the null assignment.
|
||||
*/
|
||||
UNKNOWN,
|
||||
/* A Bits instance is in UNINIT when it is created with the default
|
||||
@ -103,13 +90,9 @@ public class 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;
|
||||
protected BitsState currentState;
|
||||
|
||||
/** Construct an initially empty set.
|
||||
*/
|
||||
@ -127,27 +110,20 @@ public class Bits {
|
||||
|
||||
/** Construct a set consisting initially of given bit vector.
|
||||
*/
|
||||
private Bits(int[] bits, BitsState initState) {
|
||||
protected Bits(int[] bits, BitsState initState) {
|
||||
this.bits = bits;
|
||||
this.currentState = initState;
|
||||
switch (initState) {
|
||||
case UNKNOWN:
|
||||
reset(); //this will also set current state;
|
||||
this.bits = null;
|
||||
break;
|
||||
case NORMAL:
|
||||
Assert.check(bits != unassignedBits);
|
||||
lastOperation = INIT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** 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 void changed() {}
|
||||
|
||||
private void sizeTo(int len) {
|
||||
protected void sizeTo(int len) {
|
||||
if (bits.length < len) {
|
||||
bits = Arrays.copyOf(bits, len);
|
||||
}
|
||||
@ -157,16 +133,18 @@ public class Bits {
|
||||
*/
|
||||
public void clear() {
|
||||
Assert.check(currentState != BitsState.UNKNOWN);
|
||||
oldBits = bits;
|
||||
lastOperation = CLEAR;
|
||||
for (int i = 0; i < bits.length; i++) bits[i] = 0;
|
||||
changed();
|
||||
for (int i = 0; i < bits.length; i++) {
|
||||
bits[i] = 0;
|
||||
}
|
||||
currentState = BitsState.NORMAL;
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
internalReset();
|
||||
}
|
||||
|
||||
protected void internalReset() {
|
||||
bits = null;
|
||||
oldBits = null;
|
||||
currentState = BitsState.UNKNOWN;
|
||||
}
|
||||
|
||||
@ -175,40 +153,40 @@ public class Bits {
|
||||
}
|
||||
|
||||
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.
|
||||
*/
|
||||
private Bits dup() {
|
||||
public 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);
|
||||
}
|
||||
tmp.bits = dupBits();
|
||||
currentState = BitsState.NORMAL;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
protected int[] dupBits() {
|
||||
int [] result;
|
||||
if (currentState != BitsState.NORMAL) {
|
||||
result = bits;
|
||||
} else {
|
||||
result = new int[bits.length];
|
||||
System.arraycopy(bits, 0, result, 0, bits.length);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Include x in this set.
|
||||
*/
|
||||
public void incl(int x) {
|
||||
Assert.check(currentState != BitsState.UNKNOWN);
|
||||
Assert.check(x >= 0);
|
||||
oldBits = bits;
|
||||
lastOperation = INCL_BIT;
|
||||
Assert.check(x >= 0, "Value of x " + x);
|
||||
sizeTo((x >>> wordshift) + 1);
|
||||
bits[x >>> wordshift] = bits[x >>> wordshift] |
|
||||
(1 << (x & wordmask));
|
||||
changed();
|
||||
currentState = BitsState.NORMAL;
|
||||
}
|
||||
|
||||
@ -217,14 +195,11 @@ public class Bits {
|
||||
*/
|
||||
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++) {
|
||||
bits[x >>> wordshift] = bits[x >>> wordshift] |
|
||||
(1 << (x & wordmask));
|
||||
}
|
||||
changed();
|
||||
currentState = BitsState.NORMAL;
|
||||
}
|
||||
|
||||
@ -232,13 +207,10 @@ public class Bits {
|
||||
*/
|
||||
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);
|
||||
internalAndSet(temp);
|
||||
changed();
|
||||
currentState = BitsState.NORMAL;
|
||||
}
|
||||
|
||||
@ -247,12 +219,9 @@ public class Bits {
|
||||
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;
|
||||
}
|
||||
|
||||
@ -269,15 +238,12 @@ public class Bits {
|
||||
*/
|
||||
public Bits andSet(Bits xs) {
|
||||
Assert.check(currentState != BitsState.UNKNOWN);
|
||||
oldBits = bits;
|
||||
lastOperation = AND_SET;
|
||||
internalAndSet(xs);
|
||||
changed();
|
||||
currentState = BitsState.NORMAL;
|
||||
return this;
|
||||
}
|
||||
|
||||
private void internalAndSet(Bits xs) {
|
||||
protected void internalAndSet(Bits xs) {
|
||||
Assert.check(currentState != BitsState.UNKNOWN);
|
||||
sizeTo(xs.bits.length);
|
||||
for (int i = 0; i < xs.bits.length; i++) {
|
||||
@ -289,13 +255,10 @@ public class Bits {
|
||||
*/
|
||||
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++) {
|
||||
bits[i] = bits[i] | xs.bits[i];
|
||||
}
|
||||
changed();
|
||||
currentState = BitsState.NORMAL;
|
||||
return this;
|
||||
}
|
||||
@ -304,14 +267,11 @@ public class Bits {
|
||||
*/
|
||||
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;
|
||||
}
|
||||
@ -320,13 +280,10 @@ public class Bits {
|
||||
*/
|
||||
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++) {
|
||||
bits[i] = bits[i] ^ xs.bits[i];
|
||||
}
|
||||
changed();
|
||||
currentState = BitsState.NORMAL;
|
||||
return this;
|
||||
}
|
||||
@ -336,7 +293,9 @@ public class Bits {
|
||||
*/
|
||||
private static int trailingZeroBits(int x) {
|
||||
Assert.check(wordlen == 32);
|
||||
if (x == 0) return 32;
|
||||
if (x == 0) {
|
||||
return 32;
|
||||
}
|
||||
int n = 1;
|
||||
if ((x & 0xffff) == 0) { n += 16; x >>>= 16; }
|
||||
if ((x & 0x00ff) == 0) { n += 8; x >>>= 8; }
|
||||
@ -355,24 +314,31 @@ public class Bits {
|
||||
public int nextBit(int x) {
|
||||
Assert.check(currentState != BitsState.UNKNOWN);
|
||||
int windex = x >>> wordshift;
|
||||
if (windex >= bits.length) return -1;
|
||||
if (windex >= bits.length) {
|
||||
return -1;
|
||||
}
|
||||
int word = bits[windex] & ~((1 << (x & wordmask))-1);
|
||||
while (true) {
|
||||
if (word != 0)
|
||||
if (word != 0) {
|
||||
return (windex << wordshift) + trailingZeroBits(word);
|
||||
}
|
||||
windex++;
|
||||
if (windex >= bits.length) return -1;
|
||||
if (windex >= bits.length) {
|
||||
return -1;
|
||||
}
|
||||
word = bits[windex];
|
||||
}
|
||||
}
|
||||
|
||||
/** a string representation of this set.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
if (bits.length > 0) {
|
||||
if (bits != null && bits.length > 0) {
|
||||
char[] digits = new char[bits.length * wordlen];
|
||||
for (int i = 0; i < bits.length * wordlen; i++)
|
||||
for (int i = 0; i < bits.length * wordlen; i++) {
|
||||
digits[i] = isMember(i) ? '1' : '0';
|
||||
}
|
||||
return new String(digits);
|
||||
} else {
|
||||
return "[]";
|
||||
@ -396,6 +362,8 @@ public class Bits {
|
||||
System.out.println("found " + i);
|
||||
count ++;
|
||||
}
|
||||
if (count != 125) throw new Error();
|
||||
if (count != 125) {
|
||||
throw new Error();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,18 @@ package com.sun.tools.javac.util;
|
||||
*/
|
||||
public class GraphUtils {
|
||||
|
||||
/**
|
||||
* Basic interface for defining various dependency kinds. All dependency kinds
|
||||
* must at least support basic capabilities to tell the DOT engine how to render them.
|
||||
*/
|
||||
public interface DependencyKind {
|
||||
/**
|
||||
* Returns the DOT representation (to be used in a {@code style} attribute
|
||||
* that's most suited for this dependency kind.
|
||||
*/
|
||||
String getDotStyle();
|
||||
}
|
||||
|
||||
/**
|
||||
* This class is a basic abstract class for representing a node.
|
||||
* A node is associated with a given data.
|
||||
@ -43,9 +55,20 @@ public class GraphUtils {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public abstract Iterable<? extends Node<D>> getDependencies();
|
||||
/**
|
||||
* Get an array of the dependency kinds supported by this node.
|
||||
*/
|
||||
public abstract DependencyKind[] getSupportedDependencyKinds();
|
||||
|
||||
public abstract String printDependency(Node<D> to);
|
||||
/**
|
||||
* Get all dependencies, regardless of their kind.
|
||||
*/
|
||||
public abstract Iterable<? extends Node<D>> getAllDependencies();
|
||||
|
||||
/**
|
||||
* Get a name for the dependency (of given kind) linking this node to a given node
|
||||
*/
|
||||
public abstract String getDependencyName(Node<D> to, DependencyKind dk);
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
@ -66,7 +89,9 @@ public class GraphUtils {
|
||||
super(data);
|
||||
}
|
||||
|
||||
public abstract Iterable<? extends TarjanNode<D>> getDependencies();
|
||||
public abstract Iterable<? extends TarjanNode<D>> getAllDependencies();
|
||||
|
||||
public abstract Iterable<? extends TarjanNode<D>> getDependenciesByKind(DependencyKind dk);
|
||||
|
||||
public int compareTo(TarjanNode<D> o) {
|
||||
return (index < o.index) ? -1 : (index == o.index) ? 0 : 1;
|
||||
@ -95,7 +120,7 @@ public class GraphUtils {
|
||||
index++;
|
||||
stack.prepend(v);
|
||||
v.active = true;
|
||||
for (TarjanNode<D> nd: v.getDependencies()) {
|
||||
for (TarjanNode<D> nd: v.getAllDependencies()) {
|
||||
@SuppressWarnings("unchecked")
|
||||
N n = (N)nd;
|
||||
if (n.index == -1) {
|
||||
@ -134,9 +159,11 @@ public class GraphUtils {
|
||||
}
|
||||
//dump arcs
|
||||
for (TarjanNode<D> from : nodes) {
|
||||
for (TarjanNode<D> to : from.getDependencies()) {
|
||||
buf.append(String.format("%s -> %s [label = \" %s \"];\n",
|
||||
from.hashCode(), to.hashCode(), from.printDependency(to)));
|
||||
for (DependencyKind dk : from.getSupportedDependencyKinds()) {
|
||||
for (TarjanNode<D> to : from.getDependenciesByKind(dk)) {
|
||||
buf.append(String.format("%s -> %s [label = \" %s \" style = %s ];\n",
|
||||
from.hashCode(), to.hashCode(), from.getDependencyName(to, dk), dk.getDotStyle()));
|
||||
}
|
||||
}
|
||||
}
|
||||
buf.append("}\n");
|
||||
|
@ -116,6 +116,19 @@ public class List<A> extends AbstractCollection<A> implements java.util.List<A>
|
||||
return buf.toList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new list from the first {@code n} elements of this list
|
||||
*/
|
||||
public List<A> take(int n) {
|
||||
ListBuffer<A> buf = ListBuffer.lb();
|
||||
int count = 0;
|
||||
for (A el : this) {
|
||||
if (count++ == n) break;
|
||||
buf.append(el);
|
||||
}
|
||||
return buf.toList();
|
||||
}
|
||||
|
||||
/** Construct a list consisting of given element.
|
||||
*/
|
||||
public static <A> List<A> of(A x1) {
|
||||
|
@ -40,7 +40,7 @@ import com.sun.tools.javac.util.List;
|
||||
public class AnnotatedTypeImpl
|
||||
extends AbstractTypeImpl implements AnnotatedType {
|
||||
|
||||
AnnotatedTypeImpl(DocEnv env, com.sun.tools.javac.code.Type.AnnotatedType type) {
|
||||
AnnotatedTypeImpl(DocEnv env, com.sun.tools.javac.code.Type type) {
|
||||
super(env, type);
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ public class AnnotatedTypeImpl
|
||||
*/
|
||||
@Override
|
||||
public AnnotationDesc[] annotations() {
|
||||
List<TypeCompound> tas = ((com.sun.tools.javac.code.Type.AnnotatedType)type).typeAnnotations;
|
||||
List<? extends TypeCompound> tas = type.getAnnotationMirrors();
|
||||
if (tas == null ||
|
||||
tas.isEmpty()) {
|
||||
return new AnnotationDesc[0];
|
||||
@ -65,7 +65,7 @@ public class AnnotatedTypeImpl
|
||||
|
||||
@Override
|
||||
public com.sun.javadoc.Type underlyingType() {
|
||||
return TypeMaker.getType(env, ((com.sun.tools.javac.code.Type.AnnotatedType)type).underlyingType, true, false);
|
||||
return TypeMaker.getType(env, type.unannotatedType(), true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -289,7 +289,7 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc {
|
||||
}
|
||||
|
||||
public boolean isFunctionalInterface() {
|
||||
return env.types.isFunctionalInterface(tsym);
|
||||
return env.types.isFunctionalInterface(tsym) && env.source.allowLambda();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,6 +123,11 @@ public class DocEnv {
|
||||
*/
|
||||
private boolean silent = false;
|
||||
|
||||
/**
|
||||
* The source language version.
|
||||
*/
|
||||
protected Source source;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
@ -144,6 +149,7 @@ public class DocEnv {
|
||||
|
||||
// Default. Should normally be reset with setLocale.
|
||||
this.doclocale = new DocLocale(this, "", breakiterator);
|
||||
source = Source.instance(context);
|
||||
}
|
||||
|
||||
public void setSilent(boolean silent) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -134,7 +134,7 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler {
|
||||
docenv.setEncoding(encoding);
|
||||
docenv.docClasses = docClasses;
|
||||
docenv.legacyDoclet = legacyDoclet;
|
||||
javadocReader.sourceCompleter = docClasses ? null : this;
|
||||
javadocReader.sourceCompleter = docClasses ? null : thisCompleter;
|
||||
|
||||
ListBuffer<String> names = new ListBuffer<String>();
|
||||
ListBuffer<JCCompilationUnit> classTrees = new ListBuffer<JCCompilationUnit>();
|
||||
|
@ -63,10 +63,8 @@ public class TypeMaker {
|
||||
t = env.types.erasure(t);
|
||||
}
|
||||
|
||||
if (considerAnnotations &&
|
||||
t.isAnnotated()) {
|
||||
Type.AnnotatedType at = (Type.AnnotatedType) t;
|
||||
return new AnnotatedTypeImpl(env, at);
|
||||
if (considerAnnotations && t.isAnnotated()) {
|
||||
return new AnnotatedTypeImpl(env, t);
|
||||
}
|
||||
|
||||
switch (t.getTag()) {
|
||||
@ -143,8 +141,7 @@ public class TypeMaker {
|
||||
static String getTypeString(DocEnv env, Type t, boolean full) {
|
||||
// TODO: should annotations be included here?
|
||||
if (t.isAnnotated()) {
|
||||
Type.AnnotatedType at = (Type.AnnotatedType)t;
|
||||
t = at.underlyingType;
|
||||
t = t.unannotatedType();
|
||||
}
|
||||
switch (t.getTag()) {
|
||||
case ARRAY:
|
||||
|
@ -140,7 +140,7 @@ public class TypeVariableImpl extends AbstractTypeImpl implements TypeVariable {
|
||||
if (!type.isAnnotated()) {
|
||||
return new AnnotationDesc[0];
|
||||
}
|
||||
List<TypeCompound> tas = ((com.sun.tools.javac.code.Type.AnnotatedType) type).typeAnnotations;
|
||||
List<? extends TypeCompound> tas = type.getAnnotationMirrors();
|
||||
AnnotationDesc res[] = new AnnotationDesc[tas.length()];
|
||||
int i = 0;
|
||||
for (Attribute.Compound a : tas) {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4638136
|
||||
* @bug 4638136 7198273
|
||||
* @summary Add ability to skip over nav bar for accessibility
|
||||
* @author dkramer
|
||||
* @run main AccessSkipNav
|
||||
@ -42,7 +42,7 @@ import java.io.*;
|
||||
*/
|
||||
public class AccessSkipNav {
|
||||
|
||||
private static final String BUGID = "4638136";
|
||||
private static final String BUGID = "4638136 - 7198273";
|
||||
private static final String BUGNAME = "AccessSkipNav";
|
||||
private static final String FS = System.getProperty("file.separator");
|
||||
private static final String PS = System.getProperty("path.separator");
|
||||
@ -86,7 +86,7 @@ public class AccessSkipNav {
|
||||
// Testing only for the presence of the <a href> and <a name>
|
||||
|
||||
// Top navbar <a href>
|
||||
{ "<a href=\"#skip-navbar_top\" title=\"Skip navigation links\"></a>",
|
||||
{ "<a href=\"#skip-navbar_top\" title=\"Skip navigation links\">Skip navigation links</a>",
|
||||
TMPDEST_DIR1 + "p1" + FS + "C1.html" },
|
||||
|
||||
// Top navbar <a name>
|
||||
@ -95,7 +95,7 @@ public class AccessSkipNav {
|
||||
TMPDEST_DIR1 + "p1" + FS + "C1.html" },
|
||||
|
||||
// Bottom navbar <a href>
|
||||
{ "<a href=\"#skip-navbar_bottom\" title=\"Skip navigation links\"></a>",
|
||||
{ "<a href=\"#skip-navbar_bottom\" title=\"Skip navigation links\">Skip navigation links</a>",
|
||||
TMPDEST_DIR1 + "p1" + FS + "C1.html" },
|
||||
|
||||
// Bottom navbar <a name>
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8000418
|
||||
* @bug 8000418 8024288
|
||||
* @summary Verify that files use a common Generated By string
|
||||
* @library ../lib/
|
||||
* @build JavadocTester TestGeneratedBy
|
||||
@ -50,32 +50,44 @@ public class TestGeneratedBy extends JavadocTester {
|
||||
"index.html"
|
||||
};
|
||||
|
||||
private static final String[] ARGS =
|
||||
private static final String[] STD_ARGS =
|
||||
new String[] {
|
||||
"-d", OUTPUT_DIR,
|
||||
"-sourcepath", SRC_DIR,
|
||||
"pkg"
|
||||
};
|
||||
private static final String BUG_ID = "8000418";
|
||||
|
||||
private static String[][] getTests() {
|
||||
private static final String[] NO_TIMESTAMP_ARGS =
|
||||
new String[] {
|
||||
"-notimestamp",
|
||||
"-d", OUTPUT_DIR,
|
||||
"-sourcepath", SRC_DIR,
|
||||
"pkg"
|
||||
};
|
||||
|
||||
private static final String BUG_ID = "8000418-8024288";
|
||||
|
||||
private static String[][] getTests(boolean timestamp) {
|
||||
String version = System.getProperty("java.version");
|
||||
String[][] tests = new String[FILES.length][];
|
||||
for (int i = 0; i < FILES.length; i++) {
|
||||
String genBy = "Generated by javadoc";
|
||||
if (timestamp) genBy += " (" + version + ") on ";
|
||||
tests[i] = new String[] {
|
||||
OUTPUT_DIR + FS + FILES[i],
|
||||
"Generated by javadoc (" + version + ") on "
|
||||
OUTPUT_DIR + FS + FILES[i], genBy
|
||||
};
|
||||
}
|
||||
return tests;
|
||||
}
|
||||
|
||||
private static String[][] getNegatedTests() {
|
||||
private static String[][] getNegatedTests(boolean timestamp) {
|
||||
String[][] tests = new String[FILES.length][];
|
||||
for (int i = 0; i < FILES.length; i++) {
|
||||
tests[i] = new String[] {
|
||||
OUTPUT_DIR + FS + FILES[i],
|
||||
"Generated by javadoc (version",
|
||||
(timestamp
|
||||
? "Generated by javadoc (version"
|
||||
: "Generated by javadoc ("),
|
||||
"Generated by javadoc on"
|
||||
};
|
||||
}
|
||||
@ -88,9 +100,10 @@ public class TestGeneratedBy extends JavadocTester {
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
TestGeneratedBy tester = new TestGeneratedBy();
|
||||
int exitCode = run(tester, ARGS, getTests(), getNegatedTests());
|
||||
int ec1 = run(tester, STD_ARGS, getTests(true), getNegatedTests(true));
|
||||
int ec2 = run(tester, NO_TIMESTAMP_ARGS, getTests(false), getNegatedTests(false));
|
||||
tester.printSummary();
|
||||
if (exitCode != 0) {
|
||||
if (ec1 != 0 || ec2 != 0) {
|
||||
throw new Error("Error found while executing Javadoc");
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8004893
|
||||
* @bug 8004893 8022738
|
||||
* @summary Make sure that the lambda feature changes work fine in
|
||||
* javadoc.
|
||||
* @author bpatel
|
||||
@ -35,11 +35,15 @@
|
||||
public class TestLambdaFeature extends JavadocTester {
|
||||
|
||||
//Test information.
|
||||
private static final String BUG_ID = "8004893";
|
||||
private static final String BUG_ID = "8004893-8022738";
|
||||
|
||||
//Javadoc arguments.
|
||||
private static final String[] ARGS = new String[] {
|
||||
"-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg"
|
||||
"-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg", "pkg1"
|
||||
};
|
||||
|
||||
private static final String[] ARGS_1 = new String[] {
|
||||
"-d", BUG_ID + "-2", "-sourcepath", SRC_DIR, "-source", "1.5", "pkg1"
|
||||
};
|
||||
|
||||
//Input for string search tests.
|
||||
@ -60,6 +64,11 @@ public class TestLambdaFeature extends JavadocTester {
|
||||
"<a href=\"javascript:show(16);\">Default Methods</a></span>" +
|
||||
"<span class=\"tabEnd\"> </span></span></caption>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "A.html",
|
||||
"<dl>" + NL + "<dt>Functional Interface:</dt>" + NL +
|
||||
"<dd>This is a functional interface and can therefore be used as " +
|
||||
"the assignment target for a lambda expression or method " +
|
||||
"reference.</dd>" + NL + "</dl>"},
|
||||
{BUG_ID + FS + "pkg1" + FS + "FuncInf.html",
|
||||
"<dl>" + NL + "<dt>Functional Interface:</dt>" + NL +
|
||||
"<dd>This is a functional interface and can therefore be used as " +
|
||||
"the assignment target for a lambda expression or method " +
|
||||
@ -75,6 +84,10 @@ public class TestLambdaFeature extends JavadocTester {
|
||||
{BUG_ID + FS + "pkg" + FS + "B.html",
|
||||
"<dl>" + NL + "<dt>Functional Interface:</dt>"}
|
||||
};
|
||||
private static final String[][] NEGATED_TEST_1 = {
|
||||
{BUG_ID + "-2" + FS + "pkg1" + FS + "FuncInf.html",
|
||||
"<dl>" + NL + "<dt>Functional Interface:</dt>"}
|
||||
};
|
||||
|
||||
/**
|
||||
* The entry point of the test.
|
||||
@ -83,6 +96,7 @@ public class TestLambdaFeature extends JavadocTester {
|
||||
public static void main(String[] args) {
|
||||
TestLambdaFeature tester = new TestLambdaFeature();
|
||||
run(tester, ARGS, TEST, NEGATED_TEST);
|
||||
run(tester, ARGS_1, NO_TEST, NEGATED_TEST_1);
|
||||
tester.printSummary();
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 pkg1;
|
||||
|
||||
public interface FuncInf<V> {
|
||||
|
||||
V call() throws Exception;
|
||||
}
|
@ -25,5 +25,13 @@
|
||||
/**
|
||||
* This is an {@underline underline}.
|
||||
* @todo Finish this class.
|
||||
* @check Check this.
|
||||
*/
|
||||
public class C {}
|
||||
public class C {
|
||||
|
||||
/**
|
||||
* @todo Tag in Method.
|
||||
*/
|
||||
public void mtd() {
|
||||
}
|
||||
}
|
||||
|
143
langtools/test/com/sun/javadoc/testLegacyTaglet/Check.java
Normal file
143
langtools/test/com/sun/javadoc/testLegacyTaglet/Check.java
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
import com.sun.tools.doclets.Taglet;
|
||||
import com.sun.javadoc.*;
|
||||
import java.util.Map;
|
||||
|
||||
public class Check implements Taglet {
|
||||
|
||||
private static final String TAG_NAME = "check";
|
||||
private static final String TAG_HEADER = "Check:";
|
||||
|
||||
/**
|
||||
* Return true since the tag can be used in package documentation.
|
||||
*
|
||||
* @return true since the tag can be used in package documentation.
|
||||
*/
|
||||
public boolean inPackage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true since the tag can be used in overview documentation.
|
||||
*
|
||||
* @return true since the tag can be used in overview documentation.
|
||||
*/
|
||||
public boolean inOverview() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true since the tag can be used in type (class/interface)
|
||||
* documentation.
|
||||
*
|
||||
* @return true since the tag can be used in type (class/interface)
|
||||
* documentation.
|
||||
*/
|
||||
public boolean inType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true since the tag can be used in constructor documentation.
|
||||
*
|
||||
* @return true since the tag can be used in constructor documentation.
|
||||
*/
|
||||
public boolean inConstructor() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true since the tag can be used in field documentation.
|
||||
*
|
||||
* @return true since the tag can be used in field documentation.
|
||||
*/
|
||||
public boolean inField() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true since the tag can be used in method documentation.
|
||||
*
|
||||
* @return true since the tag can be used in method documentation.
|
||||
*/
|
||||
public boolean inMethod() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return false since the tag is not an inline tag.
|
||||
*
|
||||
* @return false since the tag is not an inline tag.
|
||||
*/
|
||||
public boolean isInlineTag() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register this taglet.
|
||||
*
|
||||
* @param tagletMap the map to register this tag to.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static void register(Map tagletMap) {
|
||||
Check tag = new Check();
|
||||
Taglet t = (Taglet) tagletMap.get(tag.getName());
|
||||
if (t != null) {
|
||||
tagletMap.remove(tag.getName());
|
||||
}
|
||||
tagletMap.put(tag.getName(), tag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the name of this custom tag.
|
||||
*
|
||||
* @return the name of this tag.
|
||||
*/
|
||||
public String getName() {
|
||||
return TAG_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the tag representation of this custom tag, return its string
|
||||
* representation.
|
||||
*
|
||||
* @param tag the tag representation of this custom tag.
|
||||
*/
|
||||
public String toString(Tag tag) {
|
||||
return "<dt><span class=\"strong\">" + TAG_HEADER + ":</span></dt><dd>" + tag.text() +
|
||||
"</dd>\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array of tags representing this custom tag, return its string
|
||||
* representation.
|
||||
*
|
||||
* @param tags the array of tags representing of this custom tag.
|
||||
* @return null to test if the javadoc throws an exception or not.
|
||||
*/
|
||||
public String toString(Tag[] tags) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,32 +23,33 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4638723
|
||||
* @bug 4638723 8015882
|
||||
* @summary Test to ensure that the refactored version of the standard
|
||||
* doclet still works with Taglets that implement the 1.4.0 interface.
|
||||
* @author jamieh
|
||||
* @library ../lib/
|
||||
* @compile ../lib/JavadocTester.java
|
||||
* @compile TestLegacyTaglet.java
|
||||
* @compile ToDoTaglet.java
|
||||
* @compile UnderlineTaglet.java
|
||||
* @compile ../lib/JavadocTester.java TestLegacyTaglet.java ToDoTaglet.java UnderlineTaglet.java Check.java
|
||||
* @run main TestLegacyTaglet
|
||||
*/
|
||||
|
||||
public class TestLegacyTaglet extends JavadocTester {
|
||||
|
||||
private static final String BUG_ID = "4638723";
|
||||
private static final String BUG_ID = "4638723-8015882";
|
||||
|
||||
private static final String[] ARGS =
|
||||
new String[] {"-d", BUG_ID, "-sourcepath", SRC_DIR,
|
||||
"-tagletpath", SRC_DIR, "-taglet", "ToDoTaglet",
|
||||
"-tagletpath", SRC_DIR, "-taglet", "ToDoTaglet", "-taglet", "Check",
|
||||
"-taglet", "UnderlineTaglet", SRC_DIR + FS + "C.java"};
|
||||
|
||||
private static final String[][] TEST = new String[][] {
|
||||
{BUG_ID + FS + "C.html", "This is an <u>underline</u>"},
|
||||
{BUG_ID + FS + "C.html",
|
||||
"<DT><B>To Do:</B><DD><table cellpadding=2 cellspacing=0><tr>" +
|
||||
"<td bgcolor=\"yellow\">Finish this class.</td></tr></table></DD>"}};
|
||||
"<td bgcolor=\"yellow\">Finish this class.</td></tr></table></DD>"},
|
||||
{BUG_ID + FS + "C.html",
|
||||
"<DT><B>To Do:</B><DD><table cellpadding=2 cellspacing=0><tr>" +
|
||||
"<td bgcolor=\"yellow\">Tag in Method.</td></tr></table></DD>"}
|
||||
};
|
||||
|
||||
private static final String[][] NEGATED_TEST = NO_TEST;
|
||||
|
||||
@ -59,6 +60,9 @@ public class TestLegacyTaglet extends JavadocTester {
|
||||
public static void main(String[] args) {
|
||||
TestLegacyTaglet tester = new TestLegacyTaglet();
|
||||
run(tester, ARGS, TEST, NEGATED_TEST);
|
||||
if (tester.getErrorOutput().contains("NullPointerException")) {
|
||||
throw new AssertionError("javadoc threw NullPointerException");
|
||||
}
|
||||
tester.printSummary();
|
||||
}
|
||||
|
||||
|
@ -23,13 +23,12 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4131628 4664607 7025314
|
||||
* @bug 4131628 4664607 7025314 8023700 7198273
|
||||
* @summary Make sure the Next/Prev Class links iterate through all types.
|
||||
* Make sure the navagation is 2 columns, not 3.
|
||||
* @author jamieh
|
||||
* @library ../lib/
|
||||
* @build JavadocTester
|
||||
* @build TestNavigation
|
||||
* @build JavadocTester TestNavigation
|
||||
* @run main TestNavigation
|
||||
*/
|
||||
|
||||
@ -45,23 +44,23 @@ public class TestNavigation extends JavadocTester {
|
||||
|
||||
//Input for string search tests.
|
||||
private static final String[][] TEST = {
|
||||
{BUG_ID + FS + "pkg" + FS + "A.html", "<li>Prev Class</li>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "A.html", "<li>Prev Class</li>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "A.html",
|
||||
"<a href=\"../pkg/C.html\" title=\"class in pkg\"><span class=\"strong\">Next Class</span></a>"},
|
||||
"<a href=\"../pkg/C.html\" title=\"class in pkg\"><span class=\"strong\">Next Class</span></a>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "C.html",
|
||||
"<a href=\"../pkg/A.html\" title=\"annotation in pkg\"><span class=\"strong\">Prev Class</span></a>"},
|
||||
"<a href=\"../pkg/A.html\" title=\"annotation in pkg\"><span class=\"strong\">Prev Class</span></a>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "C.html",
|
||||
"<a href=\"../pkg/E.html\" title=\"enum in pkg\"><span class=\"strong\">Next Class</span></a>"},
|
||||
"<a href=\"../pkg/E.html\" title=\"enum in pkg\"><span class=\"strong\">Next Class</span></a>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "E.html",
|
||||
"<a href=\"../pkg/C.html\" title=\"class in pkg\"><span class=\"strong\">Prev Class</span></a>"},
|
||||
"<a href=\"../pkg/C.html\" title=\"class in pkg\"><span class=\"strong\">Prev Class</span></a>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "E.html",
|
||||
"<a href=\"../pkg/I.html\" title=\"interface in pkg\"><span class=\"strong\">Next Class</span></a>"},
|
||||
"<a href=\"../pkg/I.html\" title=\"interface in pkg\"><span class=\"strong\">Next Class</span></a>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "I.html",
|
||||
"<a href=\"../pkg/E.html\" title=\"enum in pkg\"><span class=\"strong\">Prev Class</span></a>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "I.html", "<li>Next Class</li>"},
|
||||
"<a href=\"../pkg/E.html\" title=\"enum in pkg\"><span class=\"strong\">Prev Class</span></a>"},
|
||||
{BUG_ID + FS + "pkg" + FS + "I.html", "<li>Next Class</li>"},
|
||||
// Test for 4664607
|
||||
{BUG_ID + FS + "pkg" + FS + "I.html",
|
||||
"<a href=\"#skip-navbar_top\" title=\"Skip navigation links\"></a><a name=\"navbar_top_firstrow\">" + NL +
|
||||
"<div class=\"skipNav\"><a href=\"#skip-navbar_top\" title=\"Skip navigation links\">Skip navigation links</a></div>" + NL + "<a name=\"navbar_top_firstrow\">" + NL +
|
||||
"<!-- -->" + NL + "</a>"}
|
||||
};
|
||||
private static final String[][] NEGATED_TEST = NO_TEST;
|
||||
|
@ -23,9 +23,9 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8006124 8009684 8016921
|
||||
* @bug 8006124 8009684 8016921 8023700
|
||||
* @summary Test javadoc support for profiles.
|
||||
* @author Bhavesh Patel
|
||||
* @author Bhavesh Patel, Evgeniya Stepanova
|
||||
* @library ../lib/
|
||||
* @build JavadocTester TestProfiles
|
||||
* @run main TestProfiles
|
||||
@ -38,8 +38,9 @@ public class TestProfiles extends JavadocTester {
|
||||
private static final String PACKAGE_BUG_ID = BUG_ID + "-2";
|
||||
//Javadoc arguments.
|
||||
private static final String[] ARGS1 = new String[]{
|
||||
"-d", PROFILE_BUG_ID, "-sourcepath", SRC_DIR, "-Xprofilespath", SRC_DIR + FS
|
||||
+ "profile-rtjar-includes.txt", "pkg1", "pkg2", "pkg3", "pkg4", "pkg5"
|
||||
"-d", PROFILE_BUG_ID, "-sourcepath", SRC_DIR, "-Xprofilespath",
|
||||
SRC_DIR + FS + "profile-rtjar-includes.txt", "pkg1", "pkg2",
|
||||
"pkg3", "pkg4", "pkg5", "pkgDeprecated"
|
||||
};
|
||||
private static final String[] ARGS2 = new String[]{
|
||||
"-d", PACKAGE_BUG_ID, "-sourcepath", SRC_DIR, "pkg1", "pkg2", "pkg3", "pkg4", "pkg5"
|
||||
@ -49,7 +50,7 @@ public class TestProfiles extends JavadocTester {
|
||||
// Tests for profile-overview-frame.html listing all profiles.
|
||||
{PROFILE_BUG_ID + FS + "profile-overview-frame.html",
|
||||
"<span><a href=\"overview-frame.html\" "
|
||||
+ "target=\"packageListFrame\">All Packages</a></span>"
|
||||
+ "target=\"packageListFrame\">All Packages</a></span>"
|
||||
},
|
||||
{PROFILE_BUG_ID + FS + "profile-overview-frame.html",
|
||||
"<li><a href=\"compact1-frame.html\" target=\"packageListFrame\">"
|
||||
@ -58,8 +59,8 @@ public class TestProfiles extends JavadocTester {
|
||||
// Tests for profileName-frame.html listing all packages in a profile.
|
||||
{PROFILE_BUG_ID + FS + "compact2-frame.html",
|
||||
"<span><a href=\"overview-frame.html\" target=\"packageListFrame\">"
|
||||
+ "All Packages</a></span><span><a href=\"profile-overview-frame.html\" "
|
||||
+ "target=\"packageListFrame\">All Profiles</a></span>"
|
||||
+ "All Packages</a></span><span><a href=\"profile-overview-frame.html\" "
|
||||
+ "target=\"packageListFrame\">All Profiles</a></span>"
|
||||
},
|
||||
{PROFILE_BUG_ID + FS + "compact2-frame.html",
|
||||
"<li><a href=\"pkg4/compact2-package-frame.html\" "
|
||||
@ -74,8 +75,8 @@ public class TestProfiles extends JavadocTester {
|
||||
},
|
||||
// Tests for profileName-summary.html listing the summary for a profile.
|
||||
{PROFILE_BUG_ID + FS + "compact2-summary.html",
|
||||
"<li><a href=\"compact1-summary.html\">Prev Profile</a></li>" + NL
|
||||
+ "<li><a href=\"compact3-summary.html\">Next Profile</a></li>"
|
||||
"<li><a href=\"compact1-summary.html\">Prev Profile</a></li>" + NL
|
||||
+ "<li><a href=\"compact3-summary.html\">Next Profile</a></li>"
|
||||
},
|
||||
{PROFILE_BUG_ID + FS + "compact2-summary.html",
|
||||
"<h1 title=\"Profile\" class=\"title\">Profile compact2</h1>"
|
||||
@ -87,7 +88,7 @@ public class TestProfiles extends JavadocTester {
|
||||
// Tests for profileName-package-summary.html listing the summary for a
|
||||
// package in a profile.
|
||||
{PROFILE_BUG_ID + FS + "pkg5" + FS + "compact3-package-summary.html",
|
||||
"<li><a href=\"../pkg4/compact3-package-summary.html\">Prev Package"
|
||||
"<li><a href=\"../pkg4/compact3-package-summary.html\">Prev Package"
|
||||
+ "</a></li>"
|
||||
},
|
||||
{PROFILE_BUG_ID + FS + "pkg5" + FS + "compact3-package-summary.html",
|
||||
@ -96,7 +97,7 @@ public class TestProfiles extends JavadocTester {
|
||||
//Test for "overview-frame.html" showing the "All Profiles" link.
|
||||
{PROFILE_BUG_ID + FS + "overview-frame.html",
|
||||
"<span><a href=\"profile-overview-frame.html\" "
|
||||
+ "target=\"packageListFrame\">All Profiles</a></span>"
|
||||
+ "target=\"packageListFrame\">All Profiles</a></span>"
|
||||
},
|
||||
//Test for "className.html" showing the profile information for the type.
|
||||
{PROFILE_BUG_ID + FS + "pkg2" + FS + "Class1Pkg2.html",
|
||||
@ -113,6 +114,49 @@ public class TestProfiles extends JavadocTester {
|
||||
"target=\"classFrame\">compact2</a></li>" + NL + "<li><a href=\"" +
|
||||
"compact3-summary.html\" target=\"classFrame\">compact3</a></li>" + NL +
|
||||
"</ul>"
|
||||
},
|
||||
//Test deprecated class in profiles
|
||||
{PROFILE_BUG_ID + FS + "compact1-summary.html","<td class=\"colFirst\">"
|
||||
+ "<a href=\"pkg2/Class1Pkg2.html\" title=\"class in pkg2\">Class1Pkg2</a></td>"
|
||||
+ NL + "<td class=\"colLast\">Deprecated"
|
||||
},
|
||||
{PROFILE_BUG_ID + FS + "deprecated-list.html","<td class=\"colOne\">"
|
||||
+ "<a href=\"pkg2/Class1Pkg2.html\" title=\"class in pkg2\">pkg2.Class1Pkg2</a>"
|
||||
+ NL +"<div class=\"block\"><span class=\"italic\">Class1Pkg2. This class is deprecated</span></div>"
|
||||
},
|
||||
//Test deprecated package in profile
|
||||
{PROFILE_BUG_ID + FS + "deprecated-list.html","<td class=\"colOne\">"
|
||||
+ "<a href=\"pkgDeprecated/package-summary.html\">pkgDeprecated</a>"
|
||||
+ NL +"<div class=\"block\"><span class=\"italic\">This package is <b>Deprecated</b>."
|
||||
+ " Use pkg1.</span></div>"
|
||||
},
|
||||
{PROFILE_BUG_ID + FS + "pkgDeprecated" + FS + "package-summary.html",
|
||||
"<div class=\"deprecatedContent\"><span class=\"strong\">Deprecated.</span>"
|
||||
+ NL + "<div class=\"block\"><span class=\"italic\">This package is <b>Deprecated</b>."
|
||||
+ " Use pkg1.</span></div>"
|
||||
},
|
||||
// need to add teststring when JDK-8015496 will be fixed
|
||||
//Test exception in profiles
|
||||
{PROFILE_BUG_ID + FS + "compact1-summary.html","<table class=\"packageSummary\" "
|
||||
+ "border=\"0\" cellpadding=\"3\" cellspacing=\"0\" "
|
||||
+ "summary=\"Exception Summary table, listing exceptions, and an explanation\">"
|
||||
+ NL + "<caption><span>Exception Summary</span><span class=\"tabEnd\">"
|
||||
+ " </span></caption>" + NL + "<tr>" + NL + "<th class=\"colFirst\" "
|
||||
+ "scope=\"col\">Exception</th>" + NL + "<th class=\"colLast\" scope=\"col\">"
|
||||
+ "Description</th>" + NL + "</tr>" + NL + "<tbody>" + NL + "<tr class=\"altColor\">"
|
||||
+ NL + "<td class=\"colFirst\"><a href=\"pkg2/ClassException.html\""
|
||||
+ " title=\"class in pkg2\">ClassException</a></td>"
|
||||
},
|
||||
//Test errors in profiles
|
||||
{PROFILE_BUG_ID + FS + "compact1-summary.html",
|
||||
"<table class=\"packageSummary\" border=\"0\" cellpadding=\"3\" cellspacing=\"0\" "
|
||||
+ "summary=\"Error Summary table, listing errors, and an explanation\">"
|
||||
+ NL + "<caption><span>Error Summary</span><span class=\"tabEnd\"> "
|
||||
+ "</span></caption>" + NL + "<tr>" + NL + "<th class=\"colFirst\""
|
||||
+ " scope=\"col\">Error</th>" + NL + "<th class=\"colLast\" "
|
||||
+ "scope=\"col\">Description</th>" + NL + "</tr>" + NL + "<tbody>"
|
||||
+ NL + "<tr class=\"altColor\">" + NL + "<td class=\"colFirst\">"
|
||||
+ "<a href=\"pkg2/ClassError.html\" title=\"class in pkg2\">ClassError</a></td>"
|
||||
}
|
||||
};
|
||||
private static final String[][] PROFILES_NEGATED_TEST = {
|
||||
@ -125,6 +169,8 @@ public class TestProfiles extends JavadocTester {
|
||||
{PROFILE_BUG_ID + FS + "pkg4" + FS + "compact2-package-frame.html",
|
||||
"<li><a href=\"Anno1Pkg4.html\" title=\"annotation in pkg4\" "
|
||||
+ "target=\"classFrame\">Anno1Pkg4</a></li>"
|
||||
},
|
||||
{PROFILE_BUG_ID + FS + "compact1-summary.html","<li>Use</li>"
|
||||
}
|
||||
};
|
||||
private static final String[][] PACKAGES_TEST = {
|
||||
@ -143,12 +189,12 @@ public class TestProfiles extends JavadocTester {
|
||||
private static final String[][] PACKAGES_NEGATED_TEST = {
|
||||
{PACKAGE_BUG_ID + FS + "profile-overview-frame.html",
|
||||
"<span><a href=\"overview-frame.html\" "
|
||||
+ "target=\"packageListFrame\">All Packages</a></span>"
|
||||
+ "target=\"packageListFrame\">All Packages</a></span>"
|
||||
},
|
||||
{PACKAGE_BUG_ID + FS + "compact2-frame.html",
|
||||
"<span><a href=\"overview-frame.html\" target=\"packageListFrame\">"
|
||||
+ "All Packages</a></span><span><a href=\"profile-overview-frame.html\" "
|
||||
+ "target=\"packageListFrame\">All Profiles</a></span>"
|
||||
+ "All Packages</a></span><span><a href=\"profile-overview-frame.html\" "
|
||||
+ "target=\"packageListFrame\">All Profiles</a></span>"
|
||||
},
|
||||
{PACKAGE_BUG_ID + FS + "pkg2" + FS + "compact2-package-frame.html",
|
||||
"<a href=\"../compact2-summary.html\" target=\"classFrame\">"
|
||||
@ -163,7 +209,7 @@ public class TestProfiles extends JavadocTester {
|
||||
},
|
||||
{PACKAGE_BUG_ID + FS + "overview-frame.html",
|
||||
"<span><a href=\"profile-overview-frame.html\" "
|
||||
+ "target=\"packageListFrame\">All Profiles</a></span>"
|
||||
+ "target=\"packageListFrame\">All Profiles</a></span>"
|
||||
},
|
||||
{PACKAGE_BUG_ID + FS + "pkg2" + FS + "Class1Pkg2.html",
|
||||
"<div class=\"subTitle\">compact1, compact2, compact3</div>"
|
||||
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* 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 8006124 8009684 8015663 8015496
|
||||
* @summary Test javadoc options support for profiles.
|
||||
* @author Evgeniya Stepanova
|
||||
* @library ../lib/
|
||||
* @build JavadocTester TestProfilesConfiguration
|
||||
* @run main TestProfilesConfiguration
|
||||
*/
|
||||
public class TestProfilesConfiguration extends JavadocTester {
|
||||
|
||||
//Test information.
|
||||
private static final String BUG_ID = "8006124-8009684";
|
||||
private static final String PROFILE_CONFIGURATION_BUG_ID = BUG_ID + "-3";
|
||||
private static final String NODEPR_NOPKGS_BUG_ID = BUG_ID + "-4";
|
||||
//Javadoc arguments.
|
||||
private static final String[] ARGS3 = new String[]{
|
||||
"-d", PROFILE_CONFIGURATION_BUG_ID, "-sourcepath", SRC_DIR, "-nocomment",
|
||||
"-keywords", "-Xprofilespath", SRC_DIR + FS + "profile-rtjar-includes.txt",
|
||||
"-doctitle", "Simple doctitle", "-use", "pkg3", "pkg1", "pkg2", "pkg4",
|
||||
"pkg5", "-packagesheader", "Simple packages header","pkgDeprecated"
|
||||
};
|
||||
private static final String[] ARGS4 = new String[]{
|
||||
"-d", NODEPR_NOPKGS_BUG_ID, "-sourcepath", SRC_DIR, "-nocomment", "-nodeprecated",
|
||||
"-keywords", "-Xprofilespath", SRC_DIR + FS + "profile-rtjar-includes-nopkgs.txt",
|
||||
"-doctitle", "Simple doctitle", "-use", "-packagesheader", "Simple packages header",
|
||||
"pkg1", "pkg2", "pkg3", "pkg4", "pkg5", "pkgDeprecated"
|
||||
};
|
||||
private static final String[][] NODEPR_NOPKGS_TEST = {
|
||||
{NODEPR_NOPKGS_BUG_ID + FS + "overview-summary.html",
|
||||
"<ul>" + NL + "<li><a href=\"compact2-summary.html\" target=\"classFrame\">" +
|
||||
"compact2</a></li>" + NL + "<li><a href=\"compact3-summary.html\" target=\"" +
|
||||
"classFrame\">compact3</a></li>" + NL + "</ul>"
|
||||
},
|
||||
{NODEPR_NOPKGS_BUG_ID + FS + "profile-overview-frame.html",
|
||||
"<ul title=\"Profiles\">" + NL + "<li><a href=\"compact2-frame.html\" target=\"packageListFrame\">" +
|
||||
"compact2</a></li>" + NL + "<li><a href=\"compact3-frame.html\" target=\"" +
|
||||
"packageListFrame\">compact3</a></li>" + NL + "</ul>"
|
||||
}
|
||||
};
|
||||
private static final String[][] NODEPR_NOPKGS_NEGATED_TEST = {
|
||||
{NODEPR_NOPKGS_BUG_ID + FS + "overview-summary.html",
|
||||
"compact1"
|
||||
}
|
||||
};
|
||||
|
||||
private static final String[][] PROFILES_CONFIGURATION_TEST = {
|
||||
//-use option test string fo profile view page
|
||||
{PROFILE_CONFIGURATION_BUG_ID + FS + "compact1-summary.html","<li>Use</li>"
|
||||
},
|
||||
//-doctitle option test string
|
||||
{PROFILE_CONFIGURATION_BUG_ID + FS + "overview-summary.html",
|
||||
"<div class=\"header\">" + NL + "<h1 class=\"title\">Simple doctitle</h1>"
|
||||
},
|
||||
//-packagesheader option test string fo profiles
|
||||
{PROFILE_CONFIGURATION_BUG_ID + FS + "profile-overview-frame.html",
|
||||
"<h1 title=\"Simple packages header\" class=\"bar\">Simple packages header</h1>"
|
||||
},
|
||||
//-keywords option test string for profiles
|
||||
{PROFILE_CONFIGURATION_BUG_ID + FS + "compact1-summary.html",
|
||||
"<meta name=\"keywords\" content=\"compact1 profile\">"
|
||||
},
|
||||
//Deprecated information on a package
|
||||
{PROFILE_CONFIGURATION_BUG_ID + FS + "compact1-summary.html",
|
||||
"<h3><a href=\"pkgDeprecated/compact1-package-summary.html\" target=\"" +
|
||||
"classFrame\">pkgDeprecated</a></h3>" + NL + "<div class=\"deprecatedContent\">" +
|
||||
"<span class=\"strong\">Deprecated.</span></div>"
|
||||
}
|
||||
};
|
||||
private static final String[][] PROFILES_CONFIGURATION_NEGATED_TEST = {
|
||||
//-nocomments option test string
|
||||
{PROFILE_CONFIGURATION_BUG_ID + FS + "compact1-summary.html",
|
||||
"<div class=\"block\"><i>Class1Pkg2.</i></div>"
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* The entry point of the test.
|
||||
*
|
||||
* @param args the array of command line arguments.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
TestProfilesConfiguration tester = new TestProfilesConfiguration();
|
||||
run(tester, ARGS3, PROFILES_CONFIGURATION_TEST,
|
||||
PROFILES_CONFIGURATION_NEGATED_TEST);
|
||||
run(tester, ARGS4, NODEPR_NOPKGS_TEST,
|
||||
NODEPR_NOPKGS_NEGATED_TEST);
|
||||
tester.printSummary();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getBugId() {
|
||||
return BUG_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String getBugName() {
|
||||
return getClass().getName();
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@
|
||||
package pkg2;
|
||||
|
||||
/**
|
||||
* Another test class.
|
||||
* @deprecated Class1Pkg2. This class is deprecated
|
||||
*
|
||||
* @author Bhavesh Patel
|
||||
*/
|
||||
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 pkg2;
|
||||
|
||||
/**
|
||||
* Simple error class.
|
||||
*
|
||||
* @author Evgeniya Stepanova
|
||||
*/
|
||||
public class ClassError extends Error {}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 pkg2;
|
||||
|
||||
/**
|
||||
* Simple exception class.
|
||||
*
|
||||
* @author Evgeniya Stepanova
|
||||
*/
|
||||
public class ClassException extends Exception {}
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -21,17 +21,16 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.prob.found.req
|
||||
// key: compiler.misc.cyclic.inference
|
||||
package pkgDeprecated;
|
||||
|
||||
class CyclicInference {
|
||||
interface SAM<X> {
|
||||
void m(X x);
|
||||
}
|
||||
/**
|
||||
* Simple deprecated class of deprecated package.
|
||||
*
|
||||
* @author Evgeniya Stepanova
|
||||
*/
|
||||
public class Class1PkgDeprecated {
|
||||
|
||||
<Z> void g(SAM<Z> sz) { }
|
||||
|
||||
void test() {
|
||||
g(x-> {});
|
||||
public void method(int t) {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deprecated package.
|
||||
*
|
||||
* @deprecated This package is <b>Deprecated</b>. Use pkg1.
|
||||
*/
|
||||
package pkgDeprecated;
|
@ -0,0 +1,41 @@
|
||||
PROFILE_1_RTJAR_INCLUDE_PACKAGES :=
|
||||
|
||||
PROFILE_1_RTJAR_INCLUDE_TYPES :=
|
||||
|
||||
PROFILE_1_RTJAR_EXCLUDE_TYPES :=
|
||||
|
||||
PROFILE_1_INCLUDE_METAINF_SERVICES :=
|
||||
|
||||
|
||||
PROFILE_2_RTJAR_INCLUDE_PACKAGES := \
|
||||
pkg4 \
|
||||
pkgDeprecated
|
||||
|
||||
PROFILE_2_RTJAR_INCLUDE_TYPES :=
|
||||
|
||||
PROFILE_2_RTJAR_EXCLUDE_TYPES := \
|
||||
pkg4/Anno1Pkg4.class
|
||||
|
||||
PROFILE_2_INCLUDE_METAINF_SERVICES :=
|
||||
|
||||
|
||||
PROFILE_3_RTJAR_INCLUDE_PACKAGES := \
|
||||
pkg5
|
||||
|
||||
PROFILE_3_RTJAR_INCLUDE_TYPES :=
|
||||
|
||||
PROFILE_3_RTJAR_EXCLUDE_TYPES :=
|
||||
|
||||
PROFILE_3_INCLUDE_METAINF_SERVICES :=
|
||||
|
||||
|
||||
PROFILE_4_RTJAR_INCLUDE_PACKAGES := \
|
||||
pkg1
|
||||
|
||||
PROFILE_4_RTJAR_INCLUDE_TYPES :=
|
||||
|
||||
PROFILE_4_RTJAR_EXCLUDE_TYPES :=
|
||||
|
||||
PROFILE_4_INCLUDE_METAINF_SERVICES :=
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
PROFILE_1_RTJAR_INCLUDE_PACKAGES := \
|
||||
pkg2
|
||||
pkg2 \
|
||||
pkgDeprecated
|
||||
|
||||
PROFILE_1_RTJAR_INCLUDE_TYPES := \
|
||||
pkg3/Class1Pkg3.class
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4494033 7028815 7052425 8007338
|
||||
* @bug 4494033 7028815 7052425 8007338 8023608
|
||||
* @summary Run tests on doclet stylesheet.
|
||||
* @author jamieh
|
||||
* @library ../lib/
|
||||
@ -72,7 +72,46 @@ public class TestStylesheet extends JavadocTester {
|
||||
" overflow:hidden;" + NL +
|
||||
" padding:0px;" + NL +
|
||||
" margin:0px;" + NL +
|
||||
" white-space:pre;" + NL +
|
||||
"}"},
|
||||
{BUG_ID + FS + "stylesheet.css",
|
||||
".overviewSummary caption span, .packageSummary caption span, " +
|
||||
".contentContainer ul.blockList li.blockList caption span, " +
|
||||
".summary caption span, .classUseContainer caption span, " +
|
||||
".constantValuesContainer caption span {" + NL +
|
||||
" white-space:nowrap;" + NL +
|
||||
" padding-top:8px;" + NL +
|
||||
" padding-left:8px;" + NL +
|
||||
" display:inline-block;" + NL +
|
||||
" float:left;" + NL +
|
||||
" background-image:url(resources/titlebar.gif);" + NL +
|
||||
"}"},
|
||||
{BUG_ID + FS + "stylesheet.css",
|
||||
".contentContainer ul.blockList li.blockList caption " +
|
||||
"span.activeTableTab span {" + NL +
|
||||
" white-space:nowrap;" + NL +
|
||||
" padding-top:8px;" + NL +
|
||||
" padding-left:8px;" + NL +
|
||||
" display:inline-block;" + NL +
|
||||
" float:left;" + NL +
|
||||
" background-image:url(resources/activetitlebar.gif);" + NL +
|
||||
"}"},
|
||||
{BUG_ID + FS + "stylesheet.css",
|
||||
".contentContainer ul.blockList li.blockList caption span.tableTab span {" + NL +
|
||||
" white-space:nowrap;" + NL +
|
||||
" padding-top:8px;" + NL +
|
||||
" padding-left:8px;" + NL +
|
||||
" display:inline-block;" + NL +
|
||||
" float:left;" + NL +
|
||||
" background-image:url(resources/titlebar.gif);" + NL +
|
||||
"}"},
|
||||
{BUG_ID + FS + "stylesheet.css",
|
||||
".contentContainer ul.blockList li.blockList caption span.tableTab, " +
|
||||
".contentContainer ul.blockList li.blockList caption span.activeTableTab {" + NL +
|
||||
" padding-top:0px;" + NL +
|
||||
" padding-left:0px;" + NL +
|
||||
" background-image:none;" + NL +
|
||||
" float:none;" + NL +
|
||||
" display:inline-block;" + NL +
|
||||
"}"},
|
||||
// Test whether a link to the stylesheet file is inserted properly
|
||||
// in the class documentation.
|
||||
|
4
langtools/test/lib/combo/TEST.properties
Normal file
4
langtools/test/lib/combo/TEST.properties
Normal file
@ -0,0 +1,4 @@
|
||||
# This file identifies root(s) of the test-ng hierarchy.
|
||||
|
||||
|
||||
TestNG.dirs = .
|
82
langtools/test/lib/combo/tools/javac/combo/Diagnostics.java
Normal file
82
langtools/test/lib/combo/tools/javac/combo/Diagnostics.java
Normal 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.
|
||||
*
|
||||
* 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 tools.javac.combo;
|
||||
|
||||
import javax.tools.Diagnostic;
|
||||
import javax.tools.JavaFileObject;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* A container for compiler diagnostics, separated into errors and warnings,
|
||||
* used by JavacTemplateTestBase.
|
||||
*
|
||||
* @author Brian Goetz
|
||||
*/
|
||||
public class Diagnostics implements javax.tools.DiagnosticListener<JavaFileObject> {
|
||||
|
||||
protected List<Diagnostic<? extends JavaFileObject>> diags = new ArrayList<>();
|
||||
protected boolean foundErrors = false;
|
||||
|
||||
public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
|
||||
diags.add(diagnostic);
|
||||
foundErrors = foundErrors || diagnostic.getKind() == Diagnostic.Kind.ERROR;
|
||||
}
|
||||
|
||||
/** Were there any errors found? */
|
||||
public boolean errorsFound() {
|
||||
return foundErrors;
|
||||
}
|
||||
|
||||
/** Get all diagnostic keys */
|
||||
public List<String> keys() {
|
||||
return diags.stream()
|
||||
.map(Diagnostic::getCode)
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
/** Do the diagnostics contain the specified error key? */
|
||||
public boolean containsErrorKey(String key) {
|
||||
return diags.stream()
|
||||
.filter(d -> d.getKind() == Diagnostic.Kind.ERROR)
|
||||
.anyMatch(d -> d.getCode().equals(key));
|
||||
}
|
||||
|
||||
/** Get the error keys */
|
||||
public List<String> errorKeys() {
|
||||
return diags.stream()
|
||||
.filter(d -> d.getKind() == Diagnostic.Kind.ERROR)
|
||||
.map(Diagnostic::getCode)
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
public String toString() { return keys().toString(); }
|
||||
|
||||
/** Clear all diagnostic state */
|
||||
public void reset() {
|
||||
diags.clear();
|
||||
foundErrors = false;
|
||||
}
|
||||
}
|
@ -0,0 +1,362 @@
|
||||
/*
|
||||
* 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 tools.javac.combo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.JavaFileObject;
|
||||
import javax.tools.SimpleJavaFileObject;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.StandardLocation;
|
||||
import javax.tools.ToolProvider;
|
||||
|
||||
import com.sun.source.util.JavacTask;
|
||||
import com.sun.tools.javac.util.Pair;
|
||||
import org.testng.ITestResult;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.AfterSuite;
|
||||
import org.testng.annotations.BeforeMethod;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.fail;
|
||||
|
||||
/**
|
||||
* Base class for template-driven TestNG javac tests that support on-the-fly
|
||||
* source file generation, compilation, classloading, execution, and separate
|
||||
* compilation.
|
||||
*
|
||||
* <p>Manages a set of templates (which have embedded tags of the form
|
||||
* {@code #\{NAME\}}), source files (which are also templates), and compile
|
||||
* options. Test cases can register templates and source files, cause them to
|
||||
* be compiled, validate whether the set of diagnostic messages output by the
|
||||
* compiler is correct, and optionally load and run the compiled classes.
|
||||
*
|
||||
* @author Brian Goetz
|
||||
*/
|
||||
@Test
|
||||
public abstract class JavacTemplateTestBase {
|
||||
private static final Set<String> suiteErrors = Collections.synchronizedSet(new HashSet<>());
|
||||
private static final AtomicInteger counter = new AtomicInteger();
|
||||
private static final File root = new File("gen");
|
||||
private static final File nullDir = new File("empty");
|
||||
|
||||
protected final Map<String, Template> templates = new HashMap<>();
|
||||
protected final Diagnostics diags = new Diagnostics();
|
||||
protected final List<Pair<String, Template>> sourceFiles = new ArrayList<>();
|
||||
protected final List<String> compileOptions = new ArrayList<>();
|
||||
protected final List<File> classpaths = new ArrayList<>();
|
||||
protected final Template.Resolver defaultResolver = new MapResolver(templates);
|
||||
|
||||
private Template.Resolver currentResolver = defaultResolver;
|
||||
|
||||
/** Add a template with a specified name */
|
||||
protected void addTemplate(String name, Template t) {
|
||||
templates.put(name, t);
|
||||
}
|
||||
|
||||
/** Add a template with a specified name */
|
||||
protected void addTemplate(String name, String s) {
|
||||
templates.put(name, new StringTemplate(s));
|
||||
}
|
||||
|
||||
/** Add a source file */
|
||||
protected void addSourceFile(String name, Template t) {
|
||||
sourceFiles.add(new Pair<>(name, t));
|
||||
}
|
||||
|
||||
/** Add a File to the class path to be used when loading classes; File values
|
||||
* will generally be the result of a previous call to {@link #compile()}.
|
||||
* This enables testing of separate compilation scenarios if the class path
|
||||
* is set up properly.
|
||||
*/
|
||||
protected void addClassPath(File path) {
|
||||
classpaths.add(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a set of compilation command-line options
|
||||
*/
|
||||
protected void addCompileOptions(String... opts) {
|
||||
Collections.addAll(compileOptions, opts);
|
||||
}
|
||||
|
||||
/** Reset the compile options to the default (empty) value */
|
||||
protected void resetCompileOptions() { compileOptions.clear(); }
|
||||
|
||||
/** Remove all templates */
|
||||
protected void resetTemplates() { templates.clear(); }
|
||||
|
||||
/** Remove accumulated diagnostics */
|
||||
protected void resetDiagnostics() { diags.reset(); }
|
||||
|
||||
/** Remove all source files */
|
||||
protected void resetSourceFiles() { sourceFiles.clear(); }
|
||||
|
||||
/** Remove registered class paths */
|
||||
protected void resetClassPaths() { classpaths.clear(); }
|
||||
|
||||
// Before each test method, reset everything
|
||||
@BeforeMethod
|
||||
public void reset() {
|
||||
resetCompileOptions();
|
||||
resetDiagnostics();
|
||||
resetSourceFiles();
|
||||
resetTemplates();
|
||||
resetClassPaths();
|
||||
}
|
||||
|
||||
// After each test method, if the test failed, capture source files and diagnostics and put them in the log
|
||||
@AfterMethod
|
||||
public void copyErrors(ITestResult result) {
|
||||
if (!result.isSuccess()) {
|
||||
suiteErrors.addAll(diags.errorKeys());
|
||||
|
||||
List<Object> list = new ArrayList<>();
|
||||
Collections.addAll(list, result.getParameters());
|
||||
list.add("Test case: " + getTestCaseDescription());
|
||||
for (Pair<String, Template> e : sourceFiles)
|
||||
list.add("Source file " + e.fst + ": " + e.snd);
|
||||
if (diags.errorsFound())
|
||||
list.add("Compile diagnostics: " + diags.toString());
|
||||
result.setParameters(list.toArray(new Object[list.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
@AfterSuite
|
||||
// After the suite is done, dump any errors to output
|
||||
public void dumpErrors() {
|
||||
if (!suiteErrors.isEmpty())
|
||||
System.err.println("Errors found in test suite: " + suiteErrors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a description of this test case; since test cases may be combinatorially
|
||||
* generated, this should include all information needed to describe the test case
|
||||
*/
|
||||
protected String getTestCaseDescription() {
|
||||
return this.toString();
|
||||
}
|
||||
|
||||
/** Assert that all previous calls to compile() succeeded */
|
||||
protected void assertCompileSucceeded() {
|
||||
if (diags.errorsFound())
|
||||
fail("Expected successful compilation");
|
||||
}
|
||||
|
||||
/**
|
||||
* If the provided boolean is true, assert all previous compiles succeeded,
|
||||
* otherwise assert that a compile failed.
|
||||
* */
|
||||
protected void assertCompileSucceededIff(boolean b) {
|
||||
if (b)
|
||||
assertCompileSucceeded();
|
||||
else
|
||||
assertCompileFailed();
|
||||
}
|
||||
|
||||
/** Assert that a previous call to compile() failed */
|
||||
protected void assertCompileFailed() {
|
||||
if (!diags.errorsFound())
|
||||
fail("Expected failed compilation");
|
||||
}
|
||||
|
||||
/** Assert that a previous call to compile() failed with a specific error key */
|
||||
protected void assertCompileFailed(String message) {
|
||||
if (!diags.errorsFound())
|
||||
fail("Expected failed compilation: " + message);
|
||||
}
|
||||
|
||||
/** Assert that a previous call to compile() failed with all of the specified error keys */
|
||||
protected void assertCompileErrors(String... keys) {
|
||||
if (!diags.errorsFound())
|
||||
fail("Expected failed compilation");
|
||||
for (String k : keys)
|
||||
if (!diags.containsErrorKey(k))
|
||||
fail("Expected compilation error " + k);
|
||||
}
|
||||
|
||||
/** Convert an object, which may be a Template or a String, into a Template */
|
||||
protected Template asTemplate(Object o) {
|
||||
if (o instanceof Template)
|
||||
return (Template) o;
|
||||
else if (o instanceof String)
|
||||
return new StringTemplate((String) o);
|
||||
else
|
||||
return new StringTemplate(o.toString());
|
||||
}
|
||||
|
||||
/** Compile all registered source files */
|
||||
protected void compile() throws IOException {
|
||||
compile(false);
|
||||
}
|
||||
|
||||
/** Compile all registered source files, optionally generating class files
|
||||
* and returning a File describing the directory to which they were written */
|
||||
protected File compile(boolean generate) throws IOException {
|
||||
List<JavaFileObject> files = new ArrayList<>();
|
||||
for (Pair<String, Template> e : sourceFiles)
|
||||
files.add(new FileAdapter(e.fst, asTemplate(e.snd)));
|
||||
return compile(classpaths, files, generate);
|
||||
}
|
||||
|
||||
/** Compile all registered source files, using the provided list of class paths
|
||||
* for finding required classfiles, optionally generating class files
|
||||
* and returning a File describing the directory to which they were written */
|
||||
protected File compile(List<File> classpaths, boolean generate) throws IOException {
|
||||
List<JavaFileObject> files = new ArrayList<>();
|
||||
for (Pair<String, Template> e : sourceFiles)
|
||||
files.add(new FileAdapter(e.fst, asTemplate(e.snd)));
|
||||
return compile(classpaths, files, generate);
|
||||
}
|
||||
|
||||
private File compile(List<File> classpaths, List<JavaFileObject> files, boolean generate) throws IOException {
|
||||
JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler();
|
||||
StandardJavaFileManager fm = systemJavaCompiler.getStandardFileManager(null, null, null);
|
||||
if (classpaths.size() > 0)
|
||||
fm.setLocation(StandardLocation.CLASS_PATH, classpaths);
|
||||
JavacTask ct = (JavacTask) systemJavaCompiler.getTask(null, fm, diags, compileOptions, null, files);
|
||||
if (generate) {
|
||||
File destDir = new File(root, Integer.toString(counter.incrementAndGet()));
|
||||
// @@@ Assert that this directory didn't exist, or start counter at max+1
|
||||
destDir.mkdirs();
|
||||
fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir));
|
||||
ct.generate();
|
||||
return destDir;
|
||||
}
|
||||
else {
|
||||
ct.analyze();
|
||||
return nullDir;
|
||||
}
|
||||
}
|
||||
|
||||
/** Load the given class using the provided list of class paths */
|
||||
protected Class<?> loadClass(String className, File... destDirs) {
|
||||
try {
|
||||
List<URL> list = new ArrayList<>();
|
||||
for (File f : destDirs)
|
||||
list.add(new URL("file:" + f.toString().replace("\\", "/") + "/"));
|
||||
return Class.forName(className, true, new URLClassLoader(list.toArray(new URL[list.size()])));
|
||||
} catch (ClassNotFoundException | MalformedURLException e) {
|
||||
throw new RuntimeException("Error loading class " + className, e);
|
||||
}
|
||||
}
|
||||
|
||||
/** An implementation of Template which is backed by a String */
|
||||
protected class StringTemplate implements Template {
|
||||
protected final String template;
|
||||
|
||||
public StringTemplate(String template) {
|
||||
this.template = template;
|
||||
}
|
||||
|
||||
public String expand(String selector) {
|
||||
return Behavior.expandTemplate(template, currentResolver);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return expand("");
|
||||
}
|
||||
|
||||
public StringTemplate with(final String key, final String value) {
|
||||
return new StringTemplateWithResolver(template, new KeyResolver(key, value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** An implementation of Template which is backed by a String and which
|
||||
* encapsulates a Resolver for resolving embedded tags. */
|
||||
protected class StringTemplateWithResolver extends StringTemplate {
|
||||
private final Resolver localResolver;
|
||||
|
||||
public StringTemplateWithResolver(String template, Resolver localResolver) {
|
||||
super(template);
|
||||
this.localResolver = localResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String expand(String selector) {
|
||||
Resolver saved = currentResolver;
|
||||
currentResolver = new ChainedResolver(currentResolver, localResolver);
|
||||
try {
|
||||
return super.expand(selector);
|
||||
}
|
||||
finally {
|
||||
currentResolver = saved;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringTemplate with(String key, String value) {
|
||||
return new StringTemplateWithResolver(template, new ChainedResolver(localResolver, new KeyResolver(key, value)));
|
||||
}
|
||||
}
|
||||
|
||||
/** A Resolver which uses a Map to resolve tags */
|
||||
private class KeyResolver implements Template.Resolver {
|
||||
private final String key;
|
||||
private final String value;
|
||||
|
||||
public KeyResolver(String key, String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Template lookup(String k) {
|
||||
return key.equals(k) ? new StringTemplate(value) : null;
|
||||
}
|
||||
}
|
||||
|
||||
private class FileAdapter extends SimpleJavaFileObject {
|
||||
private final String filename;
|
||||
private final Template template;
|
||||
|
||||
public FileAdapter(String filename, Template template) {
|
||||
super(URI.create("myfo:/" + filename), Kind.SOURCE);
|
||||
this.template = template;
|
||||
this.filename = filename;
|
||||
}
|
||||
|
||||
public CharSequence getCharContent(boolean ignoreEncodingErrors) {
|
||||
return toString();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Template.Behavior.expandTemplate(template.expand(filename), defaultResolver);
|
||||
}
|
||||
}
|
||||
}
|
123
langtools/test/lib/combo/tools/javac/combo/Template.java
Normal file
123
langtools/test/lib/combo/tools/javac/combo/Template.java
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 tools.javac.combo;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A template into which tags of the form {@code #\{KEY\}} or
|
||||
* {@code #\{KEY.SUBKEY\}} can be expanded.
|
||||
*/
|
||||
public interface Template {
|
||||
String expand(String selector);
|
||||
|
||||
interface Resolver {
|
||||
public Template lookup(String key);
|
||||
}
|
||||
|
||||
public static class Behavior {
|
||||
/* Looks for expandable keys. An expandable key can take the form:
|
||||
* #{MAJOR}
|
||||
* #{MAJOR.}
|
||||
* #{MAJOR.MINOR}
|
||||
* where MAJOR can be IDENTIFIER or IDENTIFIER[NUMERIC_INDEX]
|
||||
* and MINOR can be an identifier.
|
||||
*
|
||||
* The ability to have an empty minor is provided on the
|
||||
* assumption that some tests that can be written with this
|
||||
* will find it useful to make a distinction akin to
|
||||
* distinguishing F from F(), where F is a function pointer,
|
||||
* and also cases of #{FOO.#{BAR}}, where BAR expands to an
|
||||
* empty string.
|
||||
*
|
||||
* However, this being a general-purpose framework, the exact
|
||||
* use is left up to the test writers.
|
||||
*/
|
||||
private static final Pattern pattern = Pattern.compile("#\\{([A-Z_][A-Z0-9_]*(?:\\[\\d+\\])?)(?:\\.([A-Z0-9_]*))?\\}");
|
||||
|
||||
public static String expandTemplate(String template, final Map<String, Template> vars) {
|
||||
return expandTemplate(template, new MapResolver(vars));
|
||||
}
|
||||
|
||||
public static String expandTemplate(String template, Resolver res) {
|
||||
CharSequence in = template;
|
||||
StringBuffer out = new StringBuffer();
|
||||
while (true) {
|
||||
boolean more = false;
|
||||
Matcher m = pattern.matcher(in);
|
||||
while (m.find()) {
|
||||
String major = m.group(1);
|
||||
String minor = m.group(2);
|
||||
Template key = res.lookup(major);
|
||||
if (key == null)
|
||||
throw new IllegalStateException("Unknown major key " + major);
|
||||
|
||||
String replacement = key.expand(minor == null ? "" : minor);
|
||||
more |= pattern.matcher(replacement).find();
|
||||
m.appendReplacement(out, replacement);
|
||||
}
|
||||
m.appendTail(out);
|
||||
if (!more)
|
||||
return out.toString();
|
||||
else {
|
||||
in = out;
|
||||
out = new StringBuffer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class MapResolver implements Template.Resolver {
|
||||
private final Map<String, Template> vars;
|
||||
|
||||
public MapResolver(Map<String, Template> vars) {this.vars = vars;}
|
||||
|
||||
public Template lookup(String key) {
|
||||
return vars.get(key);
|
||||
}
|
||||
}
|
||||
|
||||
class ChainedResolver implements Template.Resolver {
|
||||
private final Template.Resolver upstreamResolver, thisResolver;
|
||||
|
||||
public ChainedResolver(Template.Resolver upstreamResolver, Template.Resolver thisResolver) {
|
||||
this.upstreamResolver = upstreamResolver;
|
||||
this.thisResolver = thisResolver;
|
||||
}
|
||||
|
||||
public Template.Resolver getUpstreamResolver() {
|
||||
return upstreamResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Template lookup(String key) {
|
||||
Template result = thisResolver.lookup(key);
|
||||
if (result == null)
|
||||
result = upstreamResolver.lookup(key);
|
||||
return result;
|
||||
}
|
||||
}
|
94
langtools/test/lib/combo/tools/javac/combo/TemplateTest.java
Normal file
94
langtools/test/lib/combo/tools/javac/combo/TemplateTest.java
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 tools.javac.combo;
|
||||
|
||||
import org.testng.annotations.BeforeTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* TemplateTest
|
||||
*/
|
||||
@Test
|
||||
public class TemplateTest {
|
||||
Map<String, Template> vars = new HashMap<>();
|
||||
|
||||
@BeforeTest
|
||||
void before() { vars.clear(); }
|
||||
|
||||
private void assertTemplate(String expected, String template) {
|
||||
String result = Template.Behavior.expandTemplate(template, vars);
|
||||
assertEquals(result, expected, "for " + template);
|
||||
}
|
||||
|
||||
private String dotIf(String s) {
|
||||
return s == null || s.isEmpty() ? "" : "." + s;
|
||||
}
|
||||
|
||||
public void testTemplateExpansion() {
|
||||
vars.put("A", s -> "a" + dotIf(s));
|
||||
vars.put("B", s -> "b" + dotIf(s));
|
||||
vars.put("C", s -> "#{A}#{B}");
|
||||
vars.put("D", s -> "#{A" + dotIf(s) + "}#{B" + dotIf(s) + "}");
|
||||
vars.put("_D", s -> "d");
|
||||
|
||||
assertTemplate("", "");
|
||||
assertTemplate("foo", "foo");
|
||||
assertTemplate("a", "#{A}");
|
||||
assertTemplate("a", "#{A.}");
|
||||
assertTemplate("a.FOO", "#{A.FOO}");
|
||||
assertTemplate("aa", "#{A}#{A}");
|
||||
assertTemplate("ab", "#{C}");
|
||||
assertTemplate("ab", "#{C.FOO}");
|
||||
assertTemplate("ab", "#{C.}");
|
||||
assertTemplate("a.FOOb.FOO", "#{D.FOO}");
|
||||
assertTemplate("ab", "#{D}");
|
||||
assertTemplate("d", "#{_D}");
|
||||
assertTemplate("#{A", "#{A");
|
||||
}
|
||||
|
||||
public void testIndexedTemplate() {
|
||||
vars.put("A[0]", s -> "a" );
|
||||
vars.put("A[1]", s -> "b" );
|
||||
vars.put("A[2]", s -> "c" );
|
||||
vars.put("X", s -> "0");
|
||||
assertTemplate("a", "#{A[0]}");
|
||||
assertTemplate("b", "#{A[1]}");
|
||||
assertTemplate("c", "#{A[2]}");
|
||||
}
|
||||
|
||||
public void testAngleBrackets() {
|
||||
vars.put("X", s -> "xyz");
|
||||
assertTemplate("List<String> ls = xyz;", "List<String> ls = #{X};");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = IllegalStateException.class )
|
||||
public void testUnknownKey() {
|
||||
assertTemplate("#{Q}", "#{Q}");
|
||||
}
|
||||
}
|
@ -1,3 +1,2 @@
|
||||
T8012003c.java:18:15: compiler.err.report.access: m(), private, P
|
||||
- compiler.note.compressed.diags
|
||||
1 error
|
||||
|
@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 8022162
|
||||
* @summary Incorrect signature determination for certain inner class generics
|
||||
* @library /tools/javac/lib
|
||||
* @build ToolBox
|
||||
* @run main IncorrectSignatureDeterminationForInnerClassesTest
|
||||
*/
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class IncorrectSignatureDeterminationForInnerClassesTest {
|
||||
|
||||
private static final String DSrc =
|
||||
"package p1;\n" +
|
||||
|
||||
"public class D<T> {\n" +
|
||||
"}\n" +
|
||||
|
||||
"abstract class Q<T> {\n" +
|
||||
" protected void m(M.E e) {}\n" +
|
||||
|
||||
" public class M extends D<T> {\n" +
|
||||
" public class E {}\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
private static final String HSrc =
|
||||
"package p1;\n" +
|
||||
|
||||
"public class H {\n" +
|
||||
" static class EQ extends Q<Object> {\n" +
|
||||
" private void m2(M.E item) {\n" +
|
||||
" m(item);\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
new IncorrectSignatureDeterminationForInnerClassesTest().run();
|
||||
}
|
||||
|
||||
void run() throws Exception {
|
||||
compile();
|
||||
}
|
||||
|
||||
void compile() throws Exception {
|
||||
Files.createDirectory(Paths.get("classes"));
|
||||
|
||||
ToolBox.JavaToolArgs javacParams =
|
||||
new ToolBox.JavaToolArgs()
|
||||
.appendArgs("-d", "classes")
|
||||
.setSources(DSrc);
|
||||
|
||||
ToolBox.javac(javacParams);
|
||||
|
||||
// compile class H against the class files for classes D and Q
|
||||
javacParams =
|
||||
new ToolBox.JavaToolArgs()
|
||||
.appendArgs("-d", "classes", "-cp", "classes")
|
||||
.setSources(HSrc);
|
||||
ToolBox.javac(javacParams);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8023545
|
||||
* @summary Misleading error message when using diamond operator with private constructor
|
||||
* @compile/fail/ref=MisleadingErrorMsgDiamondPlusPrivateCtorTest.out -XDrawDiagnostics MisleadingErrorMsgDiamondPlusPrivateCtorTest.java
|
||||
*/
|
||||
|
||||
public class MisleadingErrorMsgDiamondPlusPrivateCtorTest {
|
||||
public void foo() {
|
||||
MyClass<Object> foo = new MyClass<>();
|
||||
}
|
||||
}
|
||||
|
||||
class MyClass<E> {
|
||||
private MyClass() {}
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
MisleadingErrorMsgDiamondPlusPrivateCtorTest.java:10:31: compiler.err.report.access: <E>MyClass(), private, MyClass
|
||||
1 error
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* 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 8024039
|
||||
* @summary javac, previous solution for JDK-8022186 was incorrect
|
||||
* @library /tools/javac/lib
|
||||
* @build ToolBox
|
||||
* @run main NoDeadCodeGenerationOnTrySmtTest
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.Code_attribute;
|
||||
import com.sun.tools.classfile.Code_attribute.Exception_data;
|
||||
import com.sun.tools.classfile.Method;
|
||||
import com.sun.tools.javac.util.Assert;
|
||||
|
||||
public class NoDeadCodeGenerationOnTrySmtTest {
|
||||
|
||||
static final String testSource =
|
||||
"public class Test {\n" +
|
||||
" void m1(int arg) {\n" +
|
||||
" synchronized (new Integer(arg)) {\n" +
|
||||
" {\n" +
|
||||
" label0:\n" +
|
||||
" do {\n" +
|
||||
" break label0;\n" +
|
||||
" } while (arg != 0);\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
|
||||
" void m2(int arg) {\n" +
|
||||
" synchronized (new Integer(arg)) {\n" +
|
||||
" {\n" +
|
||||
" label0:\n" +
|
||||
" {\n" +
|
||||
" break label0;\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
static final int[][] expectedExceptionTable = {
|
||||
// {from, to, target, type},
|
||||
{11, 13, 16, 0},
|
||||
{16, 19, 16, 0}
|
||||
};
|
||||
|
||||
static final String[] methodsToLookFor = {"m1", "m2"};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
new NoDeadCodeGenerationOnTrySmtTest().run();
|
||||
}
|
||||
|
||||
void run() throws Exception {
|
||||
compileTestClass();
|
||||
checkClassFile(new File(Paths.get(System.getProperty("user.dir"),
|
||||
"Test.class").toUri()), methodsToLookFor);
|
||||
}
|
||||
|
||||
void compileTestClass() throws Exception {
|
||||
ToolBox.JavaToolArgs javacSuccessArgs =
|
||||
new ToolBox.JavaToolArgs().setSources(testSource);
|
||||
ToolBox.javac(javacSuccessArgs);
|
||||
}
|
||||
|
||||
void checkClassFile(final File cfile, String[] methodsToFind) throws Exception {
|
||||
ClassFile classFile = ClassFile.read(cfile);
|
||||
int numberOfmethodsFound = 0;
|
||||
for (String methodToFind : methodsToFind) {
|
||||
for (Method method : classFile.methods) {
|
||||
if (method.getName(classFile.constant_pool).equals(methodToFind)) {
|
||||
numberOfmethodsFound++;
|
||||
Code_attribute code = (Code_attribute) method.attributes.get("Code");
|
||||
Assert.check(code.exception_table_langth == expectedExceptionTable.length,
|
||||
"The ExceptionTable found has a length different to the expected one");
|
||||
int i = 0;
|
||||
for (Exception_data entry: code.exception_table) {
|
||||
Assert.check(entry.start_pc == expectedExceptionTable[i][0] &&
|
||||
entry.end_pc == expectedExceptionTable[i][1] &&
|
||||
entry.handler_pc == expectedExceptionTable[i][2] &&
|
||||
entry.catch_type == expectedExceptionTable[i][3],
|
||||
"Exception table entry at pos " + i + " differ from expected.");
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert.check(numberOfmethodsFound == 2, "Some seek methods were not found");
|
||||
}
|
||||
|
||||
void error(String msg) {
|
||||
throw new AssertionError(msg);
|
||||
}
|
||||
|
||||
}
|
23
langtools/test/tools/javac/T8024207/FlowCrashTest.java
Normal file
23
langtools/test/tools/javac/T8024207/FlowCrashTest.java
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8024207
|
||||
* @summary javac crash in Flow$AssignAnalyzer.visitIdent
|
||||
* @compile/fail/ref=FlowCrashTest.out -XDrawDiagnostics FlowCrashTest.java
|
||||
*/
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.*;
|
||||
|
||||
public class FlowCrashTest {
|
||||
static class ViewId { }
|
||||
|
||||
public void crash() {
|
||||
|
||||
Map<ViewId,String> viewToProfile = null;
|
||||
new TreeMap<>(viewToProfile.entrySet().stream()
|
||||
.collect(Collectors.toMap((vid, prn) -> prn,
|
||||
(vid, prn) -> Arrays.asList(vid),
|
||||
(a, b) -> { a.addAll(b); return a; })));
|
||||
|
||||
}
|
||||
}
|
2
langtools/test/tools/javac/T8024207/FlowCrashTest.out
Normal file
2
langtools/test/tools/javac/T8024207/FlowCrashTest.out
Normal file
@ -0,0 +1,2 @@
|
||||
FlowCrashTest.java:18:42: compiler.err.cant.apply.symbols: kindname.method, toMap, @475,@542,@624,{(compiler.misc.inapplicable.method: kindname.method, java.util.stream.Collectors, <T,K,U>toMap(java.util.function.Function<? super T,? extends K>,java.util.function.Function<? super T,? extends U>), (compiler.misc.infer.arg.length.mismatch: T,K,U)),(compiler.misc.inapplicable.method: kindname.method, java.util.stream.Collectors, <T,K,U>toMap(java.util.function.Function<? super T,? extends K>,java.util.function.Function<? super T,? extends U>,java.util.function.BinaryOperator<U>), (compiler.misc.infer.no.conforming.assignment.exists: T,K,U, (compiler.misc.incompatible.arg.types.in.lambda))),(compiler.misc.inapplicable.method: kindname.method, java.util.stream.Collectors, <T,K,U,M>toMap(java.util.function.Function<? super T,? extends K>,java.util.function.Function<? super T,? extends U>,java.util.function.BinaryOperator<U>,java.util.function.Supplier<M>), (compiler.misc.infer.arg.length.mismatch: T,K,U,M))}
|
||||
1 error
|
49
langtools/test/tools/javac/T8024398/NPETryTest.java
Normal file
49
langtools/test/tools/javac/T8024398/NPETryTest.java
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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 8024398
|
||||
* @summary javac, compiler crashes with try with empty body
|
||||
* @compile NPETryTest.java
|
||||
*/
|
||||
|
||||
public class NPETryTest {
|
||||
void m()
|
||||
{
|
||||
/* This is the statement provoking the error the rest are provided as
|
||||
* additional tests
|
||||
*/
|
||||
try {}
|
||||
catch (Exception e) {}
|
||||
|
||||
try {}
|
||||
catch (Exception e) {}
|
||||
finally {}
|
||||
|
||||
try {}
|
||||
finally {}
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8022322
|
||||
* @summary Default methods are not allowed in an annotation.
|
||||
* @compile/fail/ref=NoDefault.out -XDrawDiagnostics NoDefault.java
|
||||
*/
|
||||
@interface NoDefault {
|
||||
default int m() {return 0;}
|
||||
}
|
3
langtools/test/tools/javac/annotations/neg/NoDefault.out
Normal file
3
langtools/test/tools/javac/annotations/neg/NoDefault.out
Normal file
@ -0,0 +1,3 @@
|
||||
NoDefault.java:8:17: compiler.err.mod.not.allowed.here: default
|
||||
NoDefault.java:8:21: compiler.err.intf.meth.cant.have.body
|
||||
2 errors
|
@ -0,0 +1,9 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8022322
|
||||
* @summary Default methods are not allowed in an annotation.
|
||||
* @compile/fail/ref=NoDefaultAbstract.out -XDrawDiagnostics NoDefaultAbstract.java
|
||||
*/
|
||||
@interface NoDefaultAbstract {
|
||||
default int m();
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
NoDefaultAbstract.java:8:17: compiler.err.mod.not.allowed.here: default
|
||||
1 error
|
10
langtools/test/tools/javac/annotations/neg/NoStatic.java
Normal file
10
langtools/test/tools/javac/annotations/neg/NoStatic.java
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8022322
|
||||
* @summary Static methods are not allowed in an annotation.
|
||||
* @compile/fail/ref=NoStatic.out -XDrawDiagnostics NoStatic.java
|
||||
*/
|
||||
|
||||
@interface NoStatic {
|
||||
static int m() {return 0;}
|
||||
}
|
3
langtools/test/tools/javac/annotations/neg/NoStatic.out
Normal file
3
langtools/test/tools/javac/annotations/neg/NoStatic.out
Normal file
@ -0,0 +1,3 @@
|
||||
NoStatic.java:9:16: compiler.err.mod.not.allowed.here: static
|
||||
NoStatic.java:9:20: compiler.err.intf.meth.cant.have.body
|
||||
2 errors
|
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 8022322
|
||||
* @summary Static methods are not allowed in an annotation.
|
||||
* @compile/fail/ref=NoStaticAbstract.out -XDrawDiagnostics NoStaticAbstract.java
|
||||
*/
|
||||
|
||||
@interface NoStaticAbstract {
|
||||
static int m();
|
||||
}
|
@ -0,0 +1,2 @@
|
||||
NoStaticAbstract.java:9:16: compiler.err.mod.not.allowed.here: static
|
||||
1 error
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -23,6 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 7192246
|
||||
* @summary check that default methods don't cause ClassReader to complete classes recursively
|
||||
* @author Maurizio Cimadamore
|
||||
* @compile pkg/Foo.java
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
/* @test /nodynamiccopyright/
|
||||
* @bug 7192246
|
||||
* @summary negative test for ambiguous defaults
|
||||
* @compile/fail/ref=Neg01.out -XDrawDiagnostics Neg01.java
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
/* @test /nodynamiccopyright/
|
||||
* @bug 7192246
|
||||
* @summary check that ill-formed MI hierarchies do not compile
|
||||
* @compile/fail/ref=Neg02.out -XDrawDiagnostics Neg02.java
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
/* @test /nodynamiccopyright/
|
||||
* @bug 7192246
|
||||
* @summary check that re-abstraction works properly
|
||||
* @compile/fail/ref=Neg03.out -XDrawDiagnostics Neg03.java
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
/* @test /nodynamiccopyright/
|
||||
* @bug 7192246
|
||||
* @summary check that default method must have most specific return type
|
||||
* @compile/fail/ref=Neg04.out -XDrawDiagnostics Neg04.java
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
/* @test /nodynamiccopyright/
|
||||
* @bug 7192246
|
||||
* @summary check that abstract methods are compatible with inherited defaults
|
||||
* @compile/fail/ref=Neg05.out -XDrawDiagnostics Neg05.java
|
||||
*/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
/* @test /nodynamiccopyright/
|
||||
* @bug 7192246
|
||||
* @summary flow analysis is not run on inlined default bodies
|
||||
* @compile/fail/ref=Neg06.out -XDrawDiagnostics Neg06.java
|
||||
*/
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user