Preparing for experiments with enhancing the Java Hints SPI: adding a copy of spi.java.hints and making it usable outside NB proper
1.1 --- a/hudson/trunk Wed May 01 21:53:41 2013 +0200
1.2 +++ b/hudson/trunk Wed May 08 21:47:42 2013 +0200
1.3 @@ -41,7 +41,7 @@
1.4
1.5 ant -Dnbplatform.active.dir=$PLATFORM -f lib/download.xml download copy-from-platform
1.6
1.7 -SUBPROJECTS="remoting duplicates language cmdline";
1.8 +SUBPROJECTS="remoting duplicates language java.hints cmdline";
1.9
1.10 for subproject in $SUBPROJECTS; do
1.11 (cd $subproject; ./build.sh -Dnbplatform.default.harness.dir=$PLATFORM/harness -Dnbplatform.default.netbeans.dest.dir=$PLATFORM -Dnbplatform.active.dir=$PLATFORM) || exit 1
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/java.hints/build.sh Wed May 08 21:47:42 2013 +0200
2.3 @@ -0,0 +1,3 @@
2.4 +#!/bin/bash
2.5 +ant "$@" clean && ant "$@" nbms && ant "$@" test || exit 1
2.6 +
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/java.hints/build.xml Wed May 08 21:47:42 2013 +0200
3.3 @@ -0,0 +1,8 @@
3.4 +<?xml version="1.0" encoding="UTF-8"?>
3.5 +<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
3.6 +<!-- for some information on what you could do (e.g. targets to override). -->
3.7 +<!-- If you delete this file and reopen the project it will be recreated. -->
3.8 +<project name="java.hints" basedir=".">
3.9 + <description>Builds the module suite java.hints.</description>
3.10 + <import file="nbproject/build-impl.xml"/>
3.11 +</project>
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/java.hints/nbproject/build-impl.xml Wed May 08 21:47:42 2013 +0200
4.3 @@ -0,0 +1,50 @@
4.4 +<?xml version="1.0" encoding="UTF-8"?>
4.5 +<!--
4.6 +*** GENERATED FROM project.xml - DO NOT EDIT ***
4.7 +*** EDIT ../build.xml INSTEAD ***
4.8 +-->
4.9 +<project name="java.hints-impl" basedir=".." xmlns:sproject="http://www.netbeans.org/ns/nb-module-suite-project/1">
4.10 + <fail message="Please build using Ant 1.7.1 or higher.">
4.11 + <condition>
4.12 + <not>
4.13 + <antversion atleast="1.7.1"/>
4.14 + </not>
4.15 + </condition>
4.16 + </fail>
4.17 + <property file="nbproject/private/platform-private.properties"/>
4.18 + <property file="nbproject/platform.properties"/>
4.19 + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
4.20 + <attribute name="name"/>
4.21 + <attribute name="value"/>
4.22 + <sequential>
4.23 + <property name="@{name}" value="${@{value}}"/>
4.24 + </sequential>
4.25 + </macrodef>
4.26 + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-suite-project/1">
4.27 + <attribute name="property"/>
4.28 + <attribute name="value"/>
4.29 + <sequential>
4.30 + <property name="@{property}" value="@{value}"/>
4.31 + </sequential>
4.32 + </macrodef>
4.33 + <property file="${user.properties.file}"/>
4.34 + <sproject:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir"/>
4.35 + <sproject:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir"/>
4.36 + <sproject:evalprops property="cluster.path.evaluated" value="${cluster.path}"/>
4.37 + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
4.38 + <condition>
4.39 + <not>
4.40 + <contains string="${cluster.path.evaluated}" substring="platform"/>
4.41 + </not>
4.42 + </condition>
4.43 + </fail>
4.44 + <ant antfile="nbproject/platform.xml"/>
4.45 + <fail message="Cannot find NetBeans build harness. ${line.separator}Check that nbplatform.${nbplatform.active}.netbeans.dest.dir and nbplatform.${nbplatform.active}.harness.dir are defined. ${line.separator}On a developer machine these are normally defined in ${user.properties.file}=${netbeans.user}/build.properties ${line.separator}but for automated builds you should pass these properties to Ant explicitly. ${line.separator}You may instead download the harness and platform: -Dbootstrap.url=.../tasks.jar -Dautoupdate.catalog.url=.../updates.xml">
4.46 + <condition>
4.47 + <not>
4.48 + <available file="${harness.dir}/suite.xml"/>
4.49 + </not>
4.50 + </condition>
4.51 + </fail>
4.52 + <import file="${harness.dir}/suite.xml"/>
4.53 +</project>
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/java.hints/nbproject/genfiles.properties Wed May 08 21:47:42 2013 +0200
5.3 @@ -0,0 +1,11 @@
5.4 +build.xml.data.CRC32=85cca5f7
5.5 +build.xml.script.CRC32=25a1521a
5.6 +build.xml.stylesheet.CRC32=eaf9f76a@2.58
5.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
5.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
5.9 +nbproject/build-impl.xml.data.CRC32=85cca5f7
5.10 +nbproject/build-impl.xml.script.CRC32=82e0fe0b
5.11 +nbproject/build-impl.xml.stylesheet.CRC32=0f381476@2.58
5.12 +nbproject/platform.xml.data.CRC32=85cca5f7
5.13 +nbproject/platform.xml.script.CRC32=db9e1f43
5.14 +nbproject/platform.xml.stylesheet.CRC32=df8ac4dd@2.58
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/java.hints/nbproject/platform.properties Wed May 08 21:47:42 2013 +0200
6.3 @@ -0,0 +1,18 @@
6.4 +cluster.path=\
6.5 + ${nbplatform.active.dir}/apisupport:\
6.6 + ${nbplatform.active.dir}/cnd:\
6.7 + ${nbplatform.active.dir}/dlight:\
6.8 + ${nbplatform.active.dir}/enterprise:\
6.9 + ${nbplatform.active.dir}/extide:\
6.10 + ${nbplatform.active.dir}/harness:\
6.11 + ${nbplatform.active.dir}/ide:\
6.12 + ${nbplatform.active.dir}/java:\
6.13 + ${nbplatform.active.dir}/nb:\
6.14 + ${nbplatform.active.dir}/platform:\
6.15 + ${nbplatform.active.dir}/profiler:\
6.16 + ${nbplatform.active.dir}/webcommon:\
6.17 + ${nbplatform.active.dir}/websvccommon:\
6.18 + ../remoting/common/build/cluster
6.19 +extcluster.../remoting/common/build/cluster.javadoc=
6.20 +extcluster.../remoting/common/build/cluster.sources=
6.21 +nbplatform.active=default
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/java.hints/nbproject/platform.xml Wed May 08 21:47:42 2013 +0200
7.3 @@ -0,0 +1,34 @@
7.4 +<?xml version="1.0" encoding="UTF-8"?>
7.5 +<project name="platform" default="download" basedir="..">
7.6 + <condition property="download.required">
7.7 + <and>
7.8 + <not>
7.9 + <available file="${harness.dir}/suite.xml"/>
7.10 + </not>
7.11 + <isset property="bootstrap.url"/>
7.12 + <isset property="autoupdate.catalog.url"/>
7.13 + </and>
7.14 + </condition>
7.15 + <target name="download" if="download.required">
7.16 + <mkdir dir="${harness.dir}"/>
7.17 + <pathconvert pathsep="|" property="download.clusters">
7.18 + <mapper type="flatten"/>
7.19 + <path path="${cluster.path}"/>
7.20 + </pathconvert>
7.21 + <property name="disabled.modules" value=""/>
7.22 + <pathconvert property="module.includes" pathsep="">
7.23 + <mapper type="glob" from="${basedir}${file.separator}*" to="(?!\Q*\E)"/>
7.24 + <path>
7.25 + <filelist files="${disabled.modules}" dir="."/>
7.26 + </path>
7.27 + </pathconvert>
7.28 + <echo message="Downloading clusters ${download.clusters}"/>
7.29 + <property name="tasks.jar" location="${java.io.tmpdir}/tasks.jar"/>
7.30 + <get src="${bootstrap.url}" dest="${tasks.jar}" usetimestamp="true" verbose="true"/>
7.31 + <taskdef name="autoupdate" classname="org.netbeans.nbbuild.AutoUpdate" classpath="${tasks.jar}"/>
7.32 + <autoupdate installdir="${nbplatform.active.dir}" updatecenter="${autoupdate.catalog.url}">
7.33 + <modules includes="${module.includes}.*" clusters="${download.clusters}"/>
7.34 + <modules includes="org[.]netbeans[.]modules[.]apisupport[.]harness" clusters="harness"/>
7.35 + </autoupdate>
7.36 + </target>
7.37 +</project>
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/java.hints/nbproject/project.properties Wed May 08 21:47:42 2013 +0200
8.3 @@ -0,0 +1,3 @@
8.4 +modules=\
8.5 + ${project.org.netbeans.spi.java.hints}
8.6 +project.org.netbeans.spi.java.hints=spi.java.hints
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/java.hints/nbproject/project.xml Wed May 08 21:47:42 2013 +0200
9.3 @@ -0,0 +1,9 @@
9.4 +<?xml version="1.0" encoding="UTF-8"?>
9.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
9.6 + <type>org.netbeans.modules.apisupport.project.suite</type>
9.7 + <configuration>
9.8 + <data xmlns="http://www.netbeans.org/ns/nb-module-suite-project/1">
9.9 + <name>java.hints</name>
9.10 + </data>
9.11 + </configuration>
9.12 +</project>
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/java.hints/spi.java.hints/apichanges.xml Wed May 08 21:47:42 2013 +0200
10.3 @@ -0,0 +1,139 @@
10.4 +<?xml version="1.0" encoding="UTF-8"?>
10.5 +<!--
10.6 +DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
10.7 +
10.8 +Copyright 2012 Oracle and/or its affiliates. All rights reserved.
10.9 +
10.10 +Oracle and Java are registered trademarks of Oracle and/or its affiliates.
10.11 +Other names may be trademarks of their respective owners.
10.12 +
10.13 +The contents of this file are subject to the terms of either the GNU
10.14 +General Public License Version 2 only ("GPL") or the Common
10.15 +Development and Distribution License("CDDL") (collectively, the
10.16 +"License"). You may not use this file except in compliance with the
10.17 +License. You can obtain a copy of the License at
10.18 +http://www.netbeans.org/cddl-gplv2.html
10.19 +or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
10.20 +specific language governing permissions and limitations under the
10.21 +License. When distributing the software, include this License Header
10.22 +Notice in each file and include the License file at
10.23 +nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
10.24 +particular file as subject to the "Classpath" exception as provided
10.25 +by Oracle in the GPL Version 2 section of the License file that
10.26 +accompanied this code. If applicable, add the following below the
10.27 +License Header, with the fields enclosed by brackets [] replaced by
10.28 +your own identifying information:
10.29 +"Portions Copyrighted [year] [name of copyright owner]"
10.30 +
10.31 +If you wish your version of this file to be governed by only the CDDL
10.32 +or only the GPL Version 2, indicate your decision by adding
10.33 +"[Contributor] elects to include this software in this distribution
10.34 +under the [CDDL or GPL Version 2] license." If you do not indicate a
10.35 +single choice of license, a recipient has the option to distribute
10.36 +your version of this file under either the CDDL, the GPL Version 2 or
10.37 +to extend the choice of license to its licensees as provided above.
10.38 +However, if you add GPL Version 2 code and therefore, elected the GPL
10.39 +Version 2 license, then the option applies only if the new code is
10.40 +made subject to such option by the copyright holder.
10.41 +
10.42 +Contributor(s):
10.43 +
10.44 +Portions Copyrighted 2012 Sun Microsystems, Inc.
10.45 +-->
10.46 +<!DOCTYPE apichanges PUBLIC "-//NetBeans//DTD API changes list 1.0//EN" "../nbbuild/javadoctools/apichanges.dtd">
10.47 +<apichanges>
10.48 + <apidefs>
10.49 + <apidef name="JavaHintsSPI">Java Hints SPI</apidef>
10.50 + </apidefs>
10.51 + <changes>
10.52 + <change id="ProjectHintsJava">
10.53 + <api name="JavaHintsSPI"/>
10.54 + <summary>Defining system filesystem folder for per-project Java hints customizers</summary>
10.55 + <version major="1" minor="16"/>
10.56 + <date day="24" month="4" year="2013"/>
10.57 + <author login="jlahoda"/>
10.58 + <compatibility addition="yes"/>
10.59 + <description>
10.60 + <p>
10.61 + Defining <code>Project/hints/java-based</code> folder, where provider for
10.62 + hints customizers for Java-based projects should be stored.
10.63 + </p>
10.64 + </description>
10.65 +<!-- <issue number="227959"/>-->
10.66 + </change>
10.67 + <change id="IntegerOption">
10.68 + <api name="JavaHintsSPI"/>
10.69 + <summary>Added support for integer options. Hints can be declared to appear only in inspect & transform</summary>
10.70 + <version major="1" minor="14"/>
10.71 + <date day="3" month="4" year="2013"/>
10.72 + <author login="sdedic"/>
10.73 + <compatibility addition="yes"/>
10.74 + <description>
10.75 + <p>
10.76 + Added declarative support for integer options. <code>@IntegerOption</code> can
10.77 + be used with option name field, similar to <code>@BooleanOption</code>.
10.78 + </p>
10.79 + <p>
10.80 + An option was added to <code>Hint.Options</code>, so that hint can declare
10.81 + to be only shown in Inspect & transform dialog. Useful for computation-intensive
10.82 + hints, which should only run on demand.
10.83 + </p>
10.84 + </description>
10.85 + <class package="org.netbeans.spi.java.hints" name="IntegerOption"/>
10.86 + <class package="org.netbeans.spi.java.hints" name="Hint"/>
10.87 + <issue number="227822"/>
10.88 + <issue number="227959"/>
10.89 + </change>
10.90 + <change id="ErrorDescriptionFactory.forSpan">
10.91 + <api name="JavaHintsSPI"/>
10.92 + <summary>Introducing ErrorDescriptionFactory.forSpan.</summary>
10.93 + <version major="1" minor="9"/>
10.94 + <date day="19" month="12" year="2012"/>
10.95 + <author login="jlahoda"/>
10.96 + <compatibility addition="yes"/>
10.97 + <description>
10.98 + <p>
10.99 + Added ErrorDescriptionFactory.forSpan to create the correct
10.100 + Java-enhanced ErrorDescription from a span.
10.101 + </p>
10.102 + </description>
10.103 + <class package="org.netbeans.spi.java.hints" name="ErrorDescriptionFactory"/>
10.104 + <issue number="223723"/>
10.105 + </change>
10.106 + <change id="TransformationSupport">
10.107 + <api name="JavaHintsSPI"/>
10.108 + <summary>Added support for using jackpot patterns from other modules (e.g. refactoring).</summary>
10.109 + <version major="1" minor="1"/>
10.110 + <date day="29" month="3" year="2012"/>
10.111 + <author login="jbecicka"/>
10.112 + <compatibility addition="yes"/>
10.113 + <description>
10.114 + <p>
10.115 + Added support for using jackpot patterns from other modules (e.g. refactoring).
10.116 + </p>
10.117 + </description>
10.118 + <class package="org.netbeans.spi.java.hints.support" name="TransformationSupport"/>
10.119 + <issue number="210262"/>
10.120 + </change>
10.121 + </changes>
10.122 + <htmlcontents>
10.123 + <head>
10.124 + <title>Change History for the Java Hints SPI</title>
10.125 + <link rel="stylesheet" href="prose.css" type="text/css"/>
10.126 + </head>
10.127 + <body>
10.128 + <p class="overviewlink">
10.129 + <a href="overview-summary.html">Overview</a>
10.130 + </p>
10.131 + <h1>Introduction</h1>
10.132 + <p>This document lists changes made to the Java Hints SPI.</p>
10.133 +
10.134 + <!-- The actual lists of changes, as summaries and details: -->
10.135 + <hr/>
10.136 + <standard-changelists module-code-name="$codebase"/>
10.137 +
10.138 + <hr/>
10.139 + <p>@FOOTER@</p>
10.140 + </body>
10.141 + </htmlcontents>
10.142 +</apichanges>
11.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
11.2 +++ b/java.hints/spi.java.hints/arch.xml Wed May 08 21:47:42 2013 +0200
11.3 @@ -0,0 +1,1115 @@
11.4 +<?xml version="1.0" encoding="UTF-8"?>
11.5 +<!DOCTYPE api-answers PUBLIC "-//NetBeans//DTD Arch Answers//EN" "../nbbuild/antsrc/org/netbeans/nbbuild/Arch.dtd" [
11.6 + <!ENTITY api-questions SYSTEM "../nbbuild/antsrc/org/netbeans/nbbuild/Arch-api-questions.xml">
11.7 +]>
11.8 +
11.9 +<api-answers
11.10 + question-version="1.29"
11.11 + author="jlahoda@netbeans.org"
11.12 +>
11.13 +
11.14 + &api-questions;
11.15 +
11.16 +
11.17 +<!--
11.18 + <question id="arch-overall" when="init">
11.19 + Describe the overall architecture.
11.20 + <hint>
11.21 + What will be API for
11.22 + <a href="http://openide.netbeans.org/tutorial/api-design.html#design.apiandspi">
11.23 + clients and what support API</a>?
11.24 + What parts will be pluggable?
11.25 + How will plug-ins be registered? Please use <code><api type="export"/></code>
11.26 + to describe your general APIs and specify their
11.27 + <a href="http://openide.netbeans.org/tutorial/api-design.html#category-private">
11.28 + stability categories</a>.
11.29 + If possible please provide simple diagrams.
11.30 + </hint>
11.31 + </question>
11.32 +-->
11.33 + <answer id="arch-overall">
11.34 + <p>
11.35 + <api type="export" category="devel" group="java" name="spi.java.hints">
11.36 + SPI to create custom Java hints, including code smell warnings, productivity tips, etc.
11.37 + Please see the Use Cases section for a guide on how to use this SPI.
11.38 + </api>
11.39 + </p>
11.40 + </answer>
11.41 +
11.42 +
11.43 +
11.44 +<!--
11.45 + <question id="arch-quality" when="init">
11.46 + How will the <a href="http://www.netbeans.org/community/guidelines/q-evangelism.html">quality</a>
11.47 + of your code be tested and
11.48 + how are future regressions going to be prevented?
11.49 + <hint>
11.50 + What kind of testing do
11.51 + you want to use? How much functionality, in which areas,
11.52 + should be covered by the tests? How you find out that your
11.53 + project was successful?
11.54 + </hint>
11.55 + </question>
11.56 +-->
11.57 + <answer id="arch-quality">
11.58 + <p>
11.59 + XXX no answer for arch-quality
11.60 + </p>
11.61 + </answer>
11.62 +
11.63 +
11.64 +
11.65 +<!--
11.66 + <question id="arch-time" when="init">
11.67 + What are the time estimates of the work?
11.68 + <hint>
11.69 + Please express your estimates of how long the design, implementation,
11.70 + stabilization are likely to last. How many people will be needed to
11.71 + implement this and what is the expected milestone by which the work should be
11.72 + ready?
11.73 + </hint>
11.74 + </question>
11.75 +-->
11.76 + <answer id="arch-time">
11.77 + <p>
11.78 + XXX no answer for arch-time
11.79 + </p>
11.80 + </answer>
11.81 +
11.82 +
11.83 +
11.84 +<!--
11.85 + <question id="arch-usecases" when="init">
11.86 + <hint>
11.87 + Content of this answer will be displayed as part of page at
11.88 + http://www.netbeans.org/download/dev/javadoc/usecases.html
11.89 + You can use tags <usecase name="name> regular html description </usecase>
11.90 + and if you want to use an URL you can prefix if with @TOP@ to begin
11.91 + at the root of your javadoc
11.92 + </hint>
11.93 +
11.94 + Describe the main <a href="http://openide.netbeans.org/tutorial/api-design.html#usecase">
11.95 + use cases</a> of the new API. Who will use it under
11.96 + what circumstances? What kind of code would typically need to be written
11.97 + to use the module?
11.98 + </question>
11.99 +-->
11.100 + <answer id="arch-usecases">
11.101 + <p>
11.102 + <usecase id="creating" name="Creating a new Java Hint">
11.103 + Simple way to create a new Java hint is as follows:
11.104 + <ul>
11.105 + <li>Create a new class, annotate it with the <a href="@TOP@/org/netbeans/spi/java/hints/Hint.html">@Hint</a>
11.106 + annotation to it.</li>
11.107 + <li>Create a <code>public static ErrorDescription hint(HintContext ctx) {}</code> method in the
11.108 + class. Annotate the method either with the <a href="@TOP@/org/netbeans/spi/java/hints/TriggerPattern.html">@TriggerPattern</a>
11.109 + annotation (strongly recommended), or with the <a href="@TOP@/org/netbeans/spi/java/hints/TriggerTreeKind.html">@TriggerTreeKind</a>.
11.110 + This method will be called when for parts of the code that match the given pattern, of for trees of the specified kinds.</li>
11.111 + <li>Perform whatever checks necessary to find out whether a warning should be produced at the given place, and produce the ErrorDescription if needed.</li>
11.112 + </ul>
11.113 + <br/>
11.114 + Tips:
11.115 + <ul>
11.116 + <li>Always use the java.hints' <a href="@TOP@/org/netbeans/spi/java/hints/ErrorDescriptionFactory.html">ErrorDescriptionFactory</a> to produce the resulting ErrorDescription.</li>
11.117 + <li>Never try to produce a custom suppress warnings "fix". Specify suppress warnings keys in the @Hint annotation.</li>
11.118 + <li>If an automated transformation is to be prodived from your hint, subclass <a href="@TOP@/org/netbeans/spi/java/hints/JavaFix.html">JavaFix</a> and
11.119 + use its <code>toEditorFix()</code> method to get the <code>Fix</code>, if the transformation is going to be used inside Inspect&Transform.
11.120 + </li>
11.121 + <li>The name of the method is arbitrary, one hint can consist of more that one "triggered" method.</li>
11.122 + </ul>
11.123 + </usecase>
11.124 + <usecase id="no-class" name="Creating a new Java Hint Without a Class">
11.125 + For simple hints, it is possible to annotate the hint method with the <a href="@TOP@/org/netbeans/spi/java/hints/Hint.html">@Hint</a> annotation.
11.126 + The hint then consists of this sole method. Any number of such hints may be created in a single class.
11.127 + </usecase>
11.128 + <usecase id="testing" name="Creating a Tests for the Newly Created Java Hint">
11.129 + Creating automated tests for the hints is simple: create a test class, and use
11.130 + <a href="@TOP@/../org-netbeans-modules-java-hints-test/org/netbeans/modules/java/hints/test/api/HintTest.html">HintTest</a>
11.131 + to setup the test, run the hint and verify that its outcomes are correct.
11.132 + The tests automatically run with <code>test</code> branding, so create <code>Bundle_test.properties</code>, and add
11.133 + bundle keys into it for ErrorDescription and Fix display names, to isolate the test from changes in the production
11.134 + <code>Bundle.properties</code>.
11.135 + </usecase>
11.136 + <usecase id="adding-options" name="Adding options to a Java Hint">
11.137 + To add a simple boolean option to your hint, use <a href="@TOP@/org/netbeans/spi/java/hints/BooleanOption.html">@BooleanOption</a>.
11.138 + </usecase>
11.139 + </p>
11.140 + </answer>
11.141 +
11.142 +
11.143 +
11.144 +<!--
11.145 + <question id="arch-what" when="init">
11.146 + What is this project good for?
11.147 + <hint>
11.148 + Please provide here a few lines describing the project,
11.149 + what problem it should solve, provide links to documentation,
11.150 + specifications, etc.
11.151 + </hint>
11.152 + </question>
11.153 +-->
11.154 + <answer id="arch-what">
11.155 + <p>
11.156 + XXX no answer for arch-what
11.157 + </p>
11.158 + </answer>
11.159 +
11.160 +
11.161 +
11.162 +<!--
11.163 + <question id="arch-where" when="impl">
11.164 + Where one can find sources for your module?
11.165 + <hint>
11.166 + Please provide link to the Hg web client at
11.167 + http://hg.netbeans.org/
11.168 + or just use tag defaultanswer generate='here'
11.169 + </hint>
11.170 + </question>
11.171 +-->
11.172 + <answer id="arch-where">
11.173 + <defaultanswer generate='here' />
11.174 + </answer>
11.175 +
11.176 +
11.177 +
11.178 +<!--
11.179 + <question id="compat-deprecation" when="init">
11.180 + How the introduction of your project influences functionality
11.181 + provided by previous version of the product?
11.182 + <hint>
11.183 + If you are planning to deprecate/remove/change any existing APIs,
11.184 + list them here accompanied with the reason explaining why you
11.185 + are doing so.
11.186 + </hint>
11.187 + </question>
11.188 +-->
11.189 + <answer id="compat-deprecation">
11.190 + <p>
11.191 + XXX no answer for compat-deprecation
11.192 + </p>
11.193 + </answer>
11.194 +
11.195 +
11.196 +
11.197 +<!--
11.198 + <question id="compat-i18n" when="impl">
11.199 + Is your module correctly internationalized?
11.200 + <hint>
11.201 + Correct internationalization means that it obeys instructions
11.202 + at <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/i18n-branding.html">
11.203 + NetBeans I18N pages</a>.
11.204 + </hint>
11.205 + </question>
11.206 +-->
11.207 + <answer id="compat-i18n">
11.208 + <p>
11.209 + XXX no answer for compat-i18n
11.210 + </p>
11.211 + </answer>
11.212 +
11.213 +
11.214 +
11.215 +<!--
11.216 + <question id="compat-standards" when="init">
11.217 + Does the module implement or define any standards? Is the
11.218 + implementation exact or does it deviate somehow?
11.219 + </question>
11.220 +-->
11.221 + <answer id="compat-standards">
11.222 + <p>
11.223 + XXX no answer for compat-standards
11.224 + </p>
11.225 + </answer>
11.226 +
11.227 +
11.228 +
11.229 +<!--
11.230 + <question id="compat-version" when="impl">
11.231 + Can your module coexist with earlier and future
11.232 + versions of itself? Can you correctly read all old settings? Will future
11.233 + versions be able to read your current settings? Can you read
11.234 + or politely ignore settings stored by a future version?
11.235 +
11.236 + <hint>
11.237 + Very helpful for reading settings is to store version number
11.238 + there, so future versions can decide whether how to read/convert
11.239 + the settings and older versions can ignore the new ones.
11.240 + </hint>
11.241 + </question>
11.242 +-->
11.243 + <answer id="compat-version">
11.244 + <p>
11.245 + XXX no answer for compat-version
11.246 + </p>
11.247 + </answer>
11.248 +
11.249 +
11.250 +
11.251 +<!--
11.252 + <question id="dep-jre" when="final">
11.253 + Which version of JRE do you need (1.2, 1.3, 1.4, etc.)?
11.254 + <hint>
11.255 + It is expected that if your module runs on 1.x that it will run
11.256 + on 1.x+1 if no, state that please. Also describe here cases where
11.257 + you run different code on different versions of JRE and why.
11.258 + </hint>
11.259 + </question>
11.260 +-->
11.261 + <answer id="dep-jre">
11.262 + <p>
11.263 + XXX no answer for dep-jre
11.264 + </p>
11.265 + </answer>
11.266 +
11.267 +
11.268 +
11.269 +<!--
11.270 + <question id="dep-jrejdk" when="final">
11.271 + Do you require the JDK or is the JRE enough?
11.272 + </question>
11.273 +-->
11.274 + <answer id="dep-jrejdk">
11.275 + <p>
11.276 + XXX no answer for dep-jrejdk
11.277 + </p>
11.278 + </answer>
11.279 +
11.280 +
11.281 +
11.282 +<!--
11.283 + <question id="dep-nb" when="init">
11.284 + What other NetBeans projects and modules does this one depend on?
11.285 + <hint>
11.286 + Depending on other NetBeans projects influnces the ability of
11.287 + users of your work to customize their own branded version of
11.288 + NetBeans by enabling and disabling some modules. Too
11.289 + much dependencies restrict this kind of customization. If that
11.290 + is your case, then you may want to split your functionality into
11.291 + pieces of autoload, eager and regular modules which can be
11.292 + enabled independently. Usually the answer to this question
11.293 + is generated from your <code>project.xml</code> file, but
11.294 + if it is not guessed correctly, you can suppress it by
11.295 + specifying <defaultanswer generate="none"/> and
11.296 + write here your own. Please describe such projects as imported APIs using
11.297 + the <code><api name="identification" type="import or export" category="stable" url="where is the description" /></code>.
11.298 + By doing this information gets listed in the summary page of your
11.299 + javadoc.
11.300 + </hint>
11.301 + </question>
11.302 +-->
11.303 + <answer id="dep-nb">
11.304 + <defaultanswer generate='here' />
11.305 + </answer>
11.306 +
11.307 +
11.308 +
11.309 +<!--
11.310 + <question id="dep-non-nb" when="init">
11.311 + What other projects outside NetBeans does this one depend on?
11.312 +
11.313 + <hint>
11.314 + Depending on 3rd party libraries is always problematic,
11.315 + especially if they are not open source, as that complicates
11.316 + the licensing scheme of NetBeans. Please enumerate your
11.317 + external dependencies here, so it is correctly understood since
11.318 + the begining what are the legal implications of your project.
11.319 + Also please note that
11.320 + some non-NetBeans projects are packaged as NetBeans modules
11.321 + (see <a href="http://libs.netbeans.org/">libraries</a>) and
11.322 + it is preferred to use this approach when more modules may
11.323 + depend and share such third-party libraries.
11.324 + </hint>
11.325 + </question>
11.326 +-->
11.327 + <answer id="dep-non-nb">
11.328 + <p>
11.329 + XXX no answer for dep-non-nb
11.330 + </p>
11.331 + </answer>
11.332 +
11.333 +
11.334 +
11.335 +<!--
11.336 + <question id="dep-platform" when="init">
11.337 + On which platforms does your module run? Does it run in the same
11.338 + way on each?
11.339 + <hint>
11.340 + If you plan any dependency on OS or any usage of native code,
11.341 + please describe why you are doing so and describe how you envision
11.342 + to enforce the portability of your code.
11.343 + Please note that there is a support for <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-modules/org/openide/modules/doc-files/api.html#how-os-specific">OS conditionally
11.344 + enabled modules</a> which together with autoload/eager modules
11.345 + can allow you to enable to provide the best OS aware support
11.346 + on certain OSes while providing compatibility bridge on the not
11.347 + supported ones.
11.348 + Also please list the supported
11.349 + OSes/HW platforms and mentioned the lovest version of JDK required
11.350 + for your project to run on. Also state whether JRE is enough or
11.351 + you really need JDK.
11.352 + </hint>
11.353 + </question>
11.354 +-->
11.355 + <answer id="dep-platform">
11.356 + <p>
11.357 + XXX no answer for dep-platform
11.358 + </p>
11.359 + </answer>
11.360 +
11.361 +
11.362 +
11.363 +<!--
11.364 + <question id="deploy-dependencies" when="final">
11.365 + What do other modules need to do to declare a dependency on this one,
11.366 + in addition to or instead of the normal module dependency declaration
11.367 + (e.g. tokens to require)?
11.368 + <hint>
11.369 + Provide a sample of the actual lines you would add to a module manifest
11.370 + to declare a dependency, for example OpenIDE-Module-Requires: some.token.
11.371 + If other modules should not depend on this module, or should just use a
11.372 + simple regular module dependency, you can just answer "nothing". If you
11.373 + intentionally expose a semistable API to clients using implementation
11.374 + dependencies, you should mention that here (but there is no need to give
11.375 + an example of usage).
11.376 + </hint>
11.377 + </question>
11.378 +-->
11.379 + <answer id="deploy-dependencies">
11.380 + <p>
11.381 + XXX no answer for deploy-dependencies
11.382 + </p>
11.383 + </answer>
11.384 +
11.385 +
11.386 +
11.387 +<!--
11.388 + <question id="deploy-jar" when="impl">
11.389 + Do you deploy just module JAR file(s) or other files as well?
11.390 + <hint>
11.391 + Usually a module consist of one JAR file (perhaps with Class-Path
11.392 + extensions) and also a configuration file that enables it. If you
11.393 + have any other files, use
11.394 + <api group="java.io.File" name="yourname" type="export" category="friend">...</api>
11.395 + to define the location, name and stability of your files (of course
11.396 + changing "yourname" and "friend" to suit your needs).
11.397 +
11.398 + If it uses more than one JAR, describe where they are located, how
11.399 + they refer to each other.
11.400 + If it consist of module JAR(s) and other files, please describe
11.401 + what is their purpose, why other files are necessary. Please
11.402 + make sure that installation/uninstallation leaves the system
11.403 + in state as it was before installation.
11.404 + </hint>
11.405 + </question>
11.406 +-->
11.407 + <answer id="deploy-jar">
11.408 + <p>
11.409 + XXX no answer for deploy-jar
11.410 + </p>
11.411 + </answer>
11.412 +
11.413 +
11.414 +
11.415 +<!--
11.416 + <question id="deploy-nbm" when="impl">
11.417 + Can you deploy an NBM via the Update Center?
11.418 + <hint>
11.419 + If not why?
11.420 + </hint>
11.421 + </question>
11.422 +-->
11.423 + <answer id="deploy-nbm">
11.424 + <p>
11.425 + XXX no answer for deploy-nbm
11.426 + </p>
11.427 + </answer>
11.428 +
11.429 +
11.430 +
11.431 +<!--
11.432 + <question id="deploy-packages" when="init">
11.433 + Are packages of your module made inaccessible by not declaring them
11.434 + public?
11.435 +
11.436 + <hint>
11.437 + By default NetBeans build harness treats all packages are private.
11.438 + If you export some of them - either as public or friend packages,
11.439 + you should have a reason. If the reason is described elsewhere
11.440 + in this document, you can ignore this question.
11.441 + </hint>
11.442 + </question>
11.443 +-->
11.444 + <answer id="deploy-packages">
11.445 + <p>
11.446 + XXX no answer for deploy-packages
11.447 + </p>
11.448 + </answer>
11.449 +
11.450 +
11.451 +
11.452 +<!--
11.453 + <question id="deploy-shared" when="final">
11.454 + Do you need to be installed in the shared location only, or in the user directory only,
11.455 + or can your module be installed anywhere?
11.456 + <hint>
11.457 + Installation location shall not matter, if it does explain why.
11.458 + Consider also whether <code>InstalledFileLocator</code> can help.
11.459 + </hint>
11.460 + </question>
11.461 +-->
11.462 + <answer id="deploy-shared">
11.463 + <p>
11.464 + XXX no answer for deploy-shared
11.465 + </p>
11.466 + </answer>
11.467 +
11.468 +
11.469 +
11.470 +<!--
11.471 + <question id="exec-ant-tasks" when="impl">
11.472 + Do you define or register any ant tasks that other can use?
11.473 +
11.474 + <hint>
11.475 + If you provide an ant task that users can use, you need to be very
11.476 + careful about its syntax and behaviour, as it most likely forms an
11.477 + API for end users and as there is a lot of end users, their reaction
11.478 + when such API gets broken can be pretty strong.
11.479 + </hint>
11.480 + </question>
11.481 +-->
11.482 + <answer id="exec-ant-tasks">
11.483 + <p>
11.484 + XXX no answer for exec-ant-tasks
11.485 + </p>
11.486 + </answer>
11.487 +
11.488 +
11.489 +
11.490 +<!--
11.491 + <question id="exec-classloader" when="impl">
11.492 + Does your code create its own class loader(s)?
11.493 + <hint>
11.494 + A bit unusual. Please explain why and what for.
11.495 + </hint>
11.496 + </question>
11.497 +-->
11.498 + <answer id="exec-classloader">
11.499 + <p>
11.500 + XXX no answer for exec-classloader
11.501 + </p>
11.502 + </answer>
11.503 +
11.504 +
11.505 +
11.506 +<!--
11.507 + <question id="exec-component" when="impl">
11.508 + Is execution of your code influenced by any (string) property
11.509 + of any of your components?
11.510 +
11.511 + <hint>
11.512 + Often <code>JComponent.getClientProperty</code>, <code>Action.getValue</code>
11.513 + or <code>PropertyDescriptor.getValue</code>, etc. are used to influence
11.514 + a behavior of some code. This of course forms an interface that should
11.515 + be documented. Also if one depends on some interface that an object
11.516 + implements (<code>component instanceof Runnable</code>) that forms an
11.517 + API as well.
11.518 + </hint>
11.519 + </question>
11.520 +-->
11.521 + <answer id="exec-component">
11.522 + <p>
11.523 + XXX no answer for exec-component
11.524 + </p>
11.525 + </answer>
11.526 +
11.527 +
11.528 +
11.529 +<!--
11.530 + <question id="exec-introspection" when="impl">
11.531 + Does your module use any kind of runtime type information (<code>instanceof</code>,
11.532 + work with <code>java.lang.Class</code>, etc.)?
11.533 + <hint>
11.534 + Check for cases when you have an object of type A and you also
11.535 + expect it to (possibly) be of type B and do some special action. That
11.536 + should be documented. The same applies on operations in meta-level
11.537 + (Class.isInstance(...), Class.isAssignableFrom(...), etc.).
11.538 + </hint>
11.539 + </question>
11.540 +-->
11.541 + <answer id="exec-introspection">
11.542 + <p>
11.543 + XXX no answer for exec-introspection
11.544 + </p>
11.545 + </answer>
11.546 +
11.547 +
11.548 +
11.549 +<!--
11.550 + <question id="exec-privateaccess" when="final">
11.551 + Are you aware of any other parts of the system calling some of
11.552 + your methods by reflection?
11.553 + <hint>
11.554 + If so, describe the "contract" as an API. Likely private or friend one, but
11.555 + still API and consider rewrite of it.
11.556 + </hint>
11.557 + </question>
11.558 +-->
11.559 + <answer id="exec-privateaccess">
11.560 + <p>
11.561 + XXX no answer for exec-privateaccess
11.562 + </p>
11.563 + </answer>
11.564 +
11.565 +
11.566 +
11.567 +<!--
11.568 + <question id="exec-process" when="impl">
11.569 + Do you execute an external process from your module? How do you ensure
11.570 + that the result is the same on different platforms? Do you parse output?
11.571 + Do you depend on result code?
11.572 + <hint>
11.573 + If you feed an input, parse the output please declare that as an API.
11.574 + </hint>
11.575 + </question>
11.576 +-->
11.577 + <answer id="exec-process">
11.578 + <p>
11.579 + XXX no answer for exec-process
11.580 + </p>
11.581 + </answer>
11.582 +
11.583 +
11.584 +
11.585 +<!--
11.586 + <question id="exec-property" when="impl">
11.587 + Is execution of your code influenced by any environment or
11.588 + Java system (<code>System.getProperty</code>) property?
11.589 + On a similar note, is there something interesting that you
11.590 + pass to <code>java.util.logging.Logger</code>? Or do you observe
11.591 + what others log?
11.592 + <hint>
11.593 + If there is a property that can change the behavior of your
11.594 + code, somebody will likely use it. You should describe what it does
11.595 + and the <a href="http://openide.netbeans.org/tutorial/api-design.html#life">stability category</a>
11.596 + of this API. You may use
11.597 + <pre>
11.598 + <api type="export" group="property" name="id" category="private" url="http://...">
11.599 + description of the property, where it is used, what it influence, etc.
11.600 + </api>
11.601 + </pre>
11.602 + </hint>
11.603 + </question>
11.604 +-->
11.605 + <answer id="exec-property">
11.606 + <p>
11.607 + XXX no answer for exec-property
11.608 + </p>
11.609 + </answer>
11.610 +
11.611 +
11.612 +
11.613 +<!--
11.614 + <question id="exec-reflection" when="impl">
11.615 + Does your code use Java Reflection to execute other code?
11.616 + <hint>
11.617 + This usually indicates a missing or insufficient API in the other
11.618 + part of the system. If the other side is not aware of your dependency
11.619 + this contract can be easily broken.
11.620 + </hint>
11.621 + </question>
11.622 +-->
11.623 + <answer id="exec-reflection">
11.624 + <p>
11.625 + XXX no answer for exec-reflection
11.626 + </p>
11.627 + </answer>
11.628 +
11.629 +
11.630 +
11.631 +<!--
11.632 + <question id="exec-threading" when="init">
11.633 + What threading models, if any, does your module adhere to? How the
11.634 + project behaves with respect to threading?
11.635 + <hint>
11.636 + Is your API threadsafe? Can it be accessed from any threads or
11.637 + just from some dedicated ones? Any special relation to AWT and
11.638 + its Event Dispatch thread? Also
11.639 + if your module calls foreign APIs which have a specific threading model,
11.640 + indicate how you comply with the requirements for multithreaded access
11.641 + (synchronization, mutexes, etc.) applicable to those APIs.
11.642 + If your module defines any APIs, or has complex internal structures
11.643 + that might be used from multiple threads, declare how you protect
11.644 + data against concurrent access, race conditions, deadlocks, etc.,
11.645 + and whether such rules are enforced by runtime warnings, errors, assertions, etc.
11.646 + Examples: a class might be non-thread-safe (like Java Collections); might
11.647 + be fully thread-safe (internal locking); might require access through a mutex
11.648 + (and may or may not automatically acquire that mutex on behalf of a client method);
11.649 + might be able to run only in the event queue; etc.
11.650 + Also describe when any events are fired: synchronously, asynchronously, etc.
11.651 + Ideas: <a href="http://core.netbeans.org/proposals/threading/index.html#recommendations">Threading Recommendations</a> (in progress)
11.652 + </hint>
11.653 + </question>
11.654 +-->
11.655 + <answer id="exec-threading">
11.656 + <p>
11.657 + XXX no answer for exec-threading
11.658 + </p>
11.659 + </answer>
11.660 +
11.661 +
11.662 +
11.663 +<!--
11.664 + <question id="format-clipboard" when="impl">
11.665 + Which data flavors (if any) does your code read from or insert to
11.666 + the clipboard (by access to clipboard on means calling methods on <code>java.awt.datatransfer.Transferable</code>?
11.667 +
11.668 + <hint>
11.669 + Often Node's deal with clipboard by usage of <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
11.670 + Check your code for overriding these methods.
11.671 + </hint>
11.672 + </question>
11.673 +-->
11.674 + <answer id="format-clipboard">
11.675 + <p>
11.676 + XXX no answer for format-clipboard
11.677 + </p>
11.678 + </answer>
11.679 +
11.680 +
11.681 +
11.682 +<!--
11.683 + <question id="format-dnd" when="impl">
11.684 + Which protocols (if any) does your code understand during Drag & Drop?
11.685 + <hint>
11.686 + Often Node's deal with clipboard by usage of <code>Node.drag, Node.getDropType</code>.
11.687 + Check your code for overriding these methods. Btw. if they are not overridden, they
11.688 + by default delegate to <code>Node.clipboardCopy, Node.clipboardCut and Node.pasteTypes</code>.
11.689 + </hint>
11.690 + </question>
11.691 +-->
11.692 + <answer id="format-dnd">
11.693 + <p>
11.694 + XXX no answer for format-dnd
11.695 + </p>
11.696 + </answer>
11.697 +
11.698 +
11.699 +
11.700 +<!--
11.701 + <question id="format-types" when="impl">
11.702 + Which protocols and file formats (if any) does your module read or write on disk,
11.703 + or transmit or receive over the network? Do you generate an ant build script?
11.704 + Can it be edited and modified?
11.705 +
11.706 + <hint>
11.707 + <p>
11.708 + Files can be read and written by other programs, modules and users. If they influence
11.709 + your behaviour, make sure you either document the format or claim that it is a private
11.710 + api (using the <api> tag).
11.711 + </p>
11.712 +
11.713 + <p>
11.714 + If you generate an ant build file, this is very likely going to be seen by end users and
11.715 + they will be attempted to edit it. You should be ready for that and provide here a link
11.716 + to documentation that you have for such purposes and also describe how you are going to
11.717 + understand such files during next release, when you (very likely) slightly change the
11.718 + format.
11.719 + </p>
11.720 + </hint>
11.721 + </question>
11.722 +-->
11.723 + <answer id="format-types">
11.724 + <p>
11.725 + XXX no answer for format-types
11.726 + </p>
11.727 + </answer>
11.728 +
11.729 +
11.730 +
11.731 +<!--
11.732 + <question id="lookup-lookup" when="init">
11.733 + Does your module use <code>org.openide.util.Lookup</code>
11.734 + or any similar technology to find any components to communicate with? Which ones?
11.735 +
11.736 + <hint>
11.737 + NetBeans is build around a generic registry of services called
11.738 + lookup. It is preferable to use it for registration and discovery
11.739 + if possible. See
11.740 + <a href="http://www.netbeans.org/download/dev/javadoc/org-openide-util/org/openide/util/lookup/doc-files/index.html">
11.741 + The Solution to Comunication Between Components
11.742 + </a>. If you do not plan to use lookup and insist usage
11.743 + of other solution, then please describe why it is not working for
11.744 + you.
11.745 + <br/>
11.746 + When filling the final version of your arch document, please
11.747 + describe the interfaces you are searching for, where
11.748 + are defined, whether you are searching for just one or more of them,
11.749 + if the order is important, etc. Also classify the stability of such
11.750 + API contract. Use <api group=&lookup& /> tag, so
11.751 + your information gets listed in the summary page of your javadoc.
11.752 + </hint>
11.753 + </question>
11.754 +-->
11.755 + <answer id="lookup-lookup">
11.756 + <p>
11.757 + XXX no answer for lookup-lookup
11.758 + </p>
11.759 + </answer>
11.760 +
11.761 +
11.762 +
11.763 +<!--
11.764 + <question id="lookup-register" when="final">
11.765 + Do you register anything into lookup for other code to find?
11.766 + <hint>
11.767 + Do you register using layer file or using a declarative annotation such as <code>@ServiceProvider</code>?
11.768 + Who is supposed to find your component?
11.769 + </hint>
11.770 + </question>
11.771 +-->
11.772 + <answer id="lookup-register">
11.773 + <p>
11.774 + XXX no answer for lookup-register
11.775 + </p>
11.776 + </answer>
11.777 +
11.778 +
11.779 +
11.780 +<!--
11.781 + <question id="lookup-remove" when="final">
11.782 + Do you remove entries of other modules from lookup?
11.783 + <hint>
11.784 + Why? Of course, that is possible, but it can be dangerous. Is the module
11.785 + your are masking resource from aware of what you are doing?
11.786 + </hint>
11.787 + </question>
11.788 +-->
11.789 + <answer id="lookup-remove">
11.790 + <p>
11.791 + XXX no answer for lookup-remove
11.792 + </p>
11.793 + </answer>
11.794 +
11.795 +
11.796 +
11.797 +<!--
11.798 + <question id="perf-exit" when="final">
11.799 + Does your module run any code on exit?
11.800 + </question>
11.801 +-->
11.802 + <answer id="perf-exit">
11.803 + <p>
11.804 + XXX no answer for perf-exit
11.805 + </p>
11.806 + </answer>
11.807 +
11.808 +
11.809 +
11.810 +<!--
11.811 + <question id="perf-huge_dialogs" when="final">
11.812 + Does your module contain any dialogs or wizards with a large number of
11.813 + GUI controls such as combo boxes, lists, trees, or text areas?
11.814 + </question>
11.815 +-->
11.816 + <answer id="perf-huge_dialogs">
11.817 + <p>
11.818 + XXX no answer for perf-huge_dialogs
11.819 + </p>
11.820 + </answer>
11.821 +
11.822 +
11.823 +
11.824 +<!--
11.825 + <question id="perf-limit" when="init">
11.826 + Are there any hard-coded or practical limits in the number or size of
11.827 + elements your code can handle?
11.828 + <hint>
11.829 + Most of algorithms have increasing memory and speed complexity
11.830 + with respect to size of data they operate on. What is the critical
11.831 + part of your project that can be seen as a bottleneck with
11.832 + respect to speed or required memory? What are the practical
11.833 + sizes of data you tested your project with? What is your estimate
11.834 + of potential size of data that would cause visible performance
11.835 + problems? Is there some kind of check to detect such situation
11.836 + and prevent "hard" crashes - for example the CloneableEditorSupport
11.837 + checks for size of a file to be opened in editor
11.838 + and if it is larger than 1Mb it shows a dialog giving the
11.839 + user the right to decide - e.g. to cancel or commit suicide.
11.840 + </hint>
11.841 + </question>
11.842 +-->
11.843 + <answer id="perf-limit">
11.844 + <p>
11.845 + XXX no answer for perf-limit
11.846 + </p>
11.847 + </answer>
11.848 +
11.849 +
11.850 +
11.851 +<!--
11.852 + <question id="perf-mem" when="final">
11.853 + How much memory does your component consume? Estimate
11.854 + with a relation to the number of windows, etc.
11.855 + </question>
11.856 +-->
11.857 + <answer id="perf-mem">
11.858 + <p>
11.859 + XXX no answer for perf-mem
11.860 + </p>
11.861 + </answer>
11.862 +
11.863 +
11.864 +
11.865 +<!--
11.866 + <question id="perf-menus" when="final">
11.867 + Does your module use dynamically updated context menus, or
11.868 + context-sensitive actions with complicated and slow enablement logic?
11.869 + <hint>
11.870 + If you do a lot of tricks when adding actions to regular or context menus, you can significantly
11.871 + slow down display of the menu, even when the user is not using your action. Pay attention to
11.872 + actions you add to the main menu bar, and to context menus of foreign nodes or components. If
11.873 + the action is conditionally enabled, or changes its display dynamically, you need to check the
11.874 + impact on performance. In some cases it may be more appropriate to make a simple action that is
11.875 + always enabled but does more detailed checks in a dialog if it is actually run.
11.876 + </hint>
11.877 + </question>
11.878 +-->
11.879 + <answer id="perf-menus">
11.880 + <p>
11.881 + XXX no answer for perf-menus
11.882 + </p>
11.883 + </answer>
11.884 +
11.885 +
11.886 +
11.887 +<!--
11.888 + <question id="perf-progress" when="final">
11.889 + Does your module execute any long-running tasks?
11.890 +
11.891 + <hint>Long running tasks should never block
11.892 + AWT thread as it badly hurts the UI
11.893 + <a href="http://performance.netbeans.org/responsiveness/issues.html">
11.894 + responsiveness</a>.
11.895 + Tasks like connecting over
11.896 + network, computing huge amount of data, compilation
11.897 + be done asynchronously (for example
11.898 + using <code>RequestProcessor</code>), definitively it should
11.899 + not block AWT thread.
11.900 + </hint>
11.901 + </question>
11.902 +-->
11.903 + <answer id="perf-progress">
11.904 + <p>
11.905 + XXX no answer for perf-progress
11.906 + </p>
11.907 + </answer>
11.908 +
11.909 +
11.910 +
11.911 +<!--
11.912 + <question id="perf-scale" when="init">
11.913 + Which external criteria influence the performance of your
11.914 + program (size of file in editor, number of files in menu,
11.915 + in source directory, etc.) and how well your code scales?
11.916 + <hint>
11.917 + Please include some estimates, there are other more detailed
11.918 + questions to answer in later phases of implementation.
11.919 + </hint>
11.920 + </question>
11.921 +-->
11.922 + <answer id="perf-scale">
11.923 + <p>
11.924 + XXX no answer for perf-scale
11.925 + </p>
11.926 + </answer>
11.927 +
11.928 +
11.929 +
11.930 +<!--
11.931 + <question id="perf-spi" when="init">
11.932 + How the performance of the plugged in code will be enforced?
11.933 + <hint>
11.934 + If you allow foreign code to be plugged into your own module, how
11.935 + do you enforce that it will behave correctly and quickly and will not
11.936 + negatively influence the performance of your own module?
11.937 + </hint>
11.938 + </question>
11.939 +-->
11.940 + <answer id="perf-spi">
11.941 + <p>
11.942 + XXX no answer for perf-spi
11.943 + </p>
11.944 + </answer>
11.945 +
11.946 +
11.947 +
11.948 +<!--
11.949 + <question id="perf-startup" when="final">
11.950 + Does your module run any code on startup?
11.951 + </question>
11.952 +-->
11.953 + <answer id="perf-startup">
11.954 + <p>
11.955 + XXX no answer for perf-startup
11.956 + </p>
11.957 + </answer>
11.958 +
11.959 +
11.960 +
11.961 +<!--
11.962 + <question id="perf-wakeup" when="final">
11.963 + Does any piece of your code wake up periodically and do something
11.964 + even when the system is otherwise idle (no user interaction)?
11.965 + </question>
11.966 +-->
11.967 + <answer id="perf-wakeup">
11.968 + <p>
11.969 + XXX no answer for perf-wakeup
11.970 + </p>
11.971 + </answer>
11.972 +
11.973 +
11.974 +
11.975 +<!--
11.976 + <question id="resources-file" when="final">
11.977 + Does your module use <code>java.io.File</code> directly?
11.978 +
11.979 + <hint>
11.980 + NetBeans provide a logical wrapper over plain files called
11.981 + <code>org.openide.filesystems.FileObject</code> that
11.982 + provides uniform access to such resources and is the preferred
11.983 + way that should be used. But of course there can be situations when
11.984 + this is not suitable.
11.985 + </hint>
11.986 + </question>
11.987 +-->
11.988 + <answer id="resources-file">
11.989 + <p>
11.990 + XXX no answer for resources-file
11.991 + </p>
11.992 + </answer>
11.993 +
11.994 +
11.995 +
11.996 +<!--
11.997 + <question id="resources-layer" when="final">
11.998 + Does your module provide own layer? Does it create any files or
11.999 + folders in it? What it is trying to communicate by that and with which
11.1000 + components?
11.1001 +
11.1002 + <hint>
11.1003 + NetBeans allows automatic and declarative installation of resources
11.1004 + by module layers. Module register files into appropriate places
11.1005 + and other components use that information to perform their task
11.1006 + (build menu, toolbar, window layout, list of templates, set of
11.1007 + options, etc.).
11.1008 + </hint>
11.1009 + </question>
11.1010 +-->
11.1011 + <answer id="resources-layer">
11.1012 + <p>
11.1013 + XXX no answer for resources-layer
11.1014 + </p>
11.1015 + </answer>
11.1016 +
11.1017 +
11.1018 +
11.1019 +<!--
11.1020 + <question id="resources-mask" when="final">
11.1021 + Does your module mask/hide/override any resources provided by other modules in
11.1022 + their layers?
11.1023 +
11.1024 + <hint>
11.1025 + If you mask a file provided by another module, you probably depend
11.1026 + on that and do not want the other module to (for example) change
11.1027 + the file's name. That module shall thus make that file available as an API
11.1028 + of some stability category.
11.1029 + </hint>
11.1030 + </question>
11.1031 +-->
11.1032 + <answer id="resources-mask">
11.1033 + <p>
11.1034 + XXX no answer for resources-mask
11.1035 + </p>
11.1036 + </answer>
11.1037 +
11.1038 +
11.1039 +
11.1040 +<!--
11.1041 + <question id="resources-preferences" when="final">
11.1042 + Does your module uses preferences via Preferences API? Does your module use NbPreferences or
11.1043 + or regular JDK Preferences ? Does it read, write or both ?
11.1044 + Does it share preferences with other modules ? If so, then why ?
11.1045 + <hint>
11.1046 + You may use
11.1047 + <api type="export" group="preferences"
11.1048 + name="preference node name" category="private">
11.1049 + description of individual keys, where it is used, what it
11.1050 + influences, whether the module reads/write it, etc.
11.1051 + </api>
11.1052 + Due to XML ID restrictions, rather than /org/netbeans/modules/foo give the "name" as org.netbeans.modules.foo.
11.1053 + Note that if you use NbPreferences this name will then be the same as the code name base of the module.
11.1054 + </hint>
11.1055 + </question>
11.1056 +-->
11.1057 + <answer id="resources-preferences">
11.1058 + <p>
11.1059 + XXX no answer for resources-preferences
11.1060 + </p>
11.1061 + </answer>
11.1062 +
11.1063 +
11.1064 +
11.1065 +<!--
11.1066 + <question id="resources-read" when="final">
11.1067 + Does your module read any resources from layers? For what purpose?
11.1068 +
11.1069 + <hint>
11.1070 + As this is some kind of intermodule dependency, it is a kind of API.
11.1071 + Please describe it and classify according to
11.1072 + <a href="http://openide.netbeans.org/tutorial/api-design.html#categories">
11.1073 + common stability categories</a>.
11.1074 + </hint>
11.1075 + </question>
11.1076 +-->
11.1077 + <answer id="resources-read">
11.1078 + <p>
11.1079 + XXX no answer for resources-read
11.1080 + </p>
11.1081 + </answer>
11.1082 +
11.1083 +
11.1084 +
11.1085 +<!--
11.1086 + <question id="security-grant" when="final">
11.1087 + Does your code grant additional rights to some other code?
11.1088 + <hint>Avoid using a class loader that adds extra
11.1089 + permissions to loaded code unless really necessary.
11.1090 + Also note that your API implementation
11.1091 + can also expose unneeded permissions to enemy code by
11.1092 + calling AccessController.doPrivileged().</hint>
11.1093 + </question>
11.1094 +-->
11.1095 + <answer id="security-grant">
11.1096 + <p>
11.1097 + XXX no answer for security-grant
11.1098 + </p>
11.1099 + </answer>
11.1100 +
11.1101 +
11.1102 +
11.1103 +<!--
11.1104 + <question id="security-policy" when="final">
11.1105 + Does your functionality require modifications to the standard policy file?
11.1106 + <hint>Your code might pass control to third-party code not
11.1107 + coming from trusted domains. This could be code downloaded over the
11.1108 + network or code coming from libraries that are not bundled
11.1109 + with NetBeans. Which permissions need to be granted to which domains?</hint>
11.1110 + </question>
11.1111 +-->
11.1112 + <answer id="security-policy">
11.1113 + <p>
11.1114 + XXX no answer for security-policy
11.1115 + </p>
11.1116 + </answer>
11.1117 +
11.1118 +</api-answers>
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/java.hints/spi.java.hints/build.xml Wed May 08 21:47:42 2013 +0200
12.3 @@ -0,0 +1,8 @@
12.4 +<?xml version="1.0" encoding="UTF-8"?>
12.5 +<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
12.6 +<!-- for some information on what you could do (e.g. targets to override). -->
12.7 +<!-- If you delete this file and reopen the project it will be recreated. -->
12.8 +<project name="org.netbeans.spi.java.hints" default="netbeans" basedir=".">
12.9 + <description>Builds, tests, and runs the project org.netbeans.spi.java.hints.</description>
12.10 + <import file="nbproject/build-impl.xml"/>
12.11 +</project>
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/java.hints/spi.java.hints/manifest.mf Wed May 08 21:47:42 2013 +0200
13.3 @@ -0,0 +1,5 @@
13.4 +Manifest-Version: 1.0
13.5 +OpenIDE-Module: org.netbeans.spi.java.hints
13.6 +OpenIDE-Module-Implementation-Version: 11
13.7 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/java/hints/spiimpl/Bundle.properties
13.8 +
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/java.hints/spi.java.hints/nbproject/build-impl.xml Wed May 08 21:47:42 2013 +0200
14.3 @@ -0,0 +1,45 @@
14.4 +<?xml version="1.0" encoding="UTF-8"?>
14.5 +<!--
14.6 +*** GENERATED FROM project.xml - DO NOT EDIT ***
14.7 +*** EDIT ../build.xml INSTEAD ***
14.8 +-->
14.9 +<project name="org.netbeans.spi.java.hints-impl" basedir="..">
14.10 + <fail message="Please build using Ant 1.7.1 or higher.">
14.11 + <condition>
14.12 + <not>
14.13 + <antversion atleast="1.7.1"/>
14.14 + </not>
14.15 + </condition>
14.16 + </fail>
14.17 + <property file="nbproject/private/suite-private.properties"/>
14.18 + <property file="nbproject/suite.properties"/>
14.19 + <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
14.20 + <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
14.21 + <property file="${suite.dir}/nbproject/platform.properties"/>
14.22 + <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
14.23 + <attribute name="name"/>
14.24 + <attribute name="value"/>
14.25 + <sequential>
14.26 + <property name="@{name}" value="${@{value}}"/>
14.27 + </sequential>
14.28 + </macrodef>
14.29 + <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
14.30 + <attribute name="property"/>
14.31 + <attribute name="value"/>
14.32 + <sequential>
14.33 + <property name="@{property}" value="@{value}"/>
14.34 + </sequential>
14.35 + </macrodef>
14.36 + <property file="${user.properties.file}"/>
14.37 + <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
14.38 + <nbmproject2:property name="nbplatform.active.dir" value="nbplatform.${nbplatform.active}.netbeans.dest.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
14.39 + <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
14.40 + <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
14.41 + <condition>
14.42 + <not>
14.43 + <contains string="${cluster.path.evaluated}" substring="platform"/>
14.44 + </not>
14.45 + </condition>
14.46 + </fail>
14.47 + <import file="${harness.dir}/build.xml"/>
14.48 +</project>
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/java.hints/spi.java.hints/nbproject/genfiles.properties Wed May 08 21:47:42 2013 +0200
15.3 @@ -0,0 +1,8 @@
15.4 +build.xml.data.CRC32=81a58345
15.5 +build.xml.script.CRC32=caab83d9
15.6 +build.xml.stylesheet.CRC32=a56c6a5b@2.58
15.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
15.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
15.9 +nbproject/build-impl.xml.data.CRC32=81a58345
15.10 +nbproject/build-impl.xml.script.CRC32=7438bc77
15.11 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.58
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/java.hints/spi.java.hints/nbproject/org-netbeans-spi-java-hints.sig Wed May 08 21:47:42 2013 +0200
16.3 @@ -0,0 +1,276 @@
16.4 +#Signature file v4.1
16.5 +#Version 1.10.1
16.6 +
16.7 +CLSS public abstract interface java.io.Serializable
16.8 +
16.9 +CLSS public abstract interface java.lang.Comparable<%0 extends java.lang.Object>
16.10 +meth public abstract int compareTo({java.lang.Comparable%0})
16.11 +
16.12 +CLSS public abstract java.lang.Enum<%0 extends java.lang.Enum<{java.lang.Enum%0}>>
16.13 +cons protected init(java.lang.String,int)
16.14 +intf java.io.Serializable
16.15 +intf java.lang.Comparable<{java.lang.Enum%0}>
16.16 +meth protected final java.lang.Object clone() throws java.lang.CloneNotSupportedException
16.17 +meth protected final void finalize()
16.18 +meth public final boolean equals(java.lang.Object)
16.19 +meth public final int compareTo({java.lang.Enum%0})
16.20 +meth public final int hashCode()
16.21 +meth public final int ordinal()
16.22 +meth public final java.lang.Class<{java.lang.Enum%0}> getDeclaringClass()
16.23 +meth public final java.lang.String name()
16.24 +meth public java.lang.String toString()
16.25 +meth public static <%0 extends java.lang.Enum<{%%0}>> {%%0} valueOf(java.lang.Class<{%%0}>,java.lang.String)
16.26 +supr java.lang.Object
16.27 +hfds name,ordinal
16.28 +
16.29 +CLSS public java.lang.Object
16.30 +cons public init()
16.31 +meth protected java.lang.Object clone() throws java.lang.CloneNotSupportedException
16.32 +meth protected void finalize() throws java.lang.Throwable
16.33 +meth public boolean equals(java.lang.Object)
16.34 +meth public final java.lang.Class<?> getClass()
16.35 +meth public final void notify()
16.36 +meth public final void notifyAll()
16.37 +meth public final void wait() throws java.lang.InterruptedException
16.38 +meth public final void wait(long) throws java.lang.InterruptedException
16.39 +meth public final void wait(long,int) throws java.lang.InterruptedException
16.40 +meth public int hashCode()
16.41 +meth public java.lang.String toString()
16.42 +
16.43 +CLSS public abstract interface java.lang.annotation.Annotation
16.44 +meth public abstract boolean equals(java.lang.Object)
16.45 +meth public abstract int hashCode()
16.46 +meth public abstract java.lang.Class<? extends java.lang.annotation.Annotation> annotationType()
16.47 +meth public abstract java.lang.String toString()
16.48 +
16.49 +CLSS public abstract interface !annotation java.lang.annotation.Documented
16.50 + anno 0 java.lang.annotation.Documented()
16.51 + anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
16.52 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
16.53 +intf java.lang.annotation.Annotation
16.54 +
16.55 +CLSS public abstract interface !annotation java.lang.annotation.Retention
16.56 + anno 0 java.lang.annotation.Documented()
16.57 + anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
16.58 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
16.59 +intf java.lang.annotation.Annotation
16.60 +meth public abstract java.lang.annotation.RetentionPolicy value()
16.61 +
16.62 +CLSS public abstract interface !annotation java.lang.annotation.Target
16.63 + anno 0 java.lang.annotation.Documented()
16.64 + anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=RUNTIME)
16.65 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[ANNOTATION_TYPE])
16.66 +intf java.lang.annotation.Annotation
16.67 +meth public abstract java.lang.annotation.ElementType[] value()
16.68 +
16.69 +CLSS public abstract interface !annotation org.netbeans.spi.java.hints.BooleanOption
16.70 + anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=SOURCE)
16.71 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[FIELD])
16.72 +intf java.lang.annotation.Annotation
16.73 +meth public abstract boolean defaultValue()
16.74 +meth public abstract java.lang.String displayName()
16.75 +meth public abstract java.lang.String tooltip()
16.76 +
16.77 +CLSS public abstract interface !annotation org.netbeans.spi.java.hints.ConstraintVariableType
16.78 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[])
16.79 +intf java.lang.annotation.Annotation
16.80 +meth public abstract java.lang.String type()
16.81 +meth public abstract java.lang.String variable()
16.82 +
16.83 +CLSS public abstract interface org.netbeans.spi.java.hints.CustomizerProvider
16.84 +meth public abstract javax.swing.JComponent getCustomizer(java.util.prefs.Preferences)
16.85 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.86 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.87 +
16.88 +CLSS public org.netbeans.spi.java.hints.ErrorDescriptionFactory
16.89 +meth public !varargs static org.netbeans.spi.editor.hints.ErrorDescription forName(org.netbeans.spi.java.hints.HintContext,com.sun.source.tree.Tree,java.lang.String,org.netbeans.spi.editor.hints.Fix[])
16.90 +meth public !varargs static org.netbeans.spi.editor.hints.ErrorDescription forName(org.netbeans.spi.java.hints.HintContext,com.sun.source.util.TreePath,java.lang.String,org.netbeans.spi.editor.hints.Fix[])
16.91 +meth public !varargs static org.netbeans.spi.editor.hints.ErrorDescription forSpan(org.netbeans.spi.java.hints.HintContext,int,int,java.lang.String,org.netbeans.spi.editor.hints.Fix[])
16.92 +meth public !varargs static org.netbeans.spi.editor.hints.ErrorDescription forTree(org.netbeans.spi.java.hints.HintContext,com.sun.source.tree.Tree,java.lang.String,org.netbeans.spi.editor.hints.Fix[])
16.93 +meth public !varargs static org.netbeans.spi.editor.hints.ErrorDescription forTree(org.netbeans.spi.java.hints.HintContext,com.sun.source.util.TreePath,java.lang.String,org.netbeans.spi.editor.hints.Fix[])
16.94 +supr java.lang.Object
16.95 +hfds DECLARATION
16.96 +hcls DisableConfigure,FixImpl,InspectFix,TopLevelConfigureFix
16.97 +
16.98 +CLSS public abstract interface !annotation org.netbeans.spi.java.hints.Hint
16.99 + anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=SOURCE)
16.100 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[TYPE, METHOD])
16.101 +innr public final static !enum Kind
16.102 +innr public final static !enum Options
16.103 +intf java.lang.annotation.Annotation
16.104 +meth public abstract !hasdefault boolean enabled()
16.105 +meth public abstract !hasdefault java.lang.Class<? extends org.netbeans.spi.java.hints.CustomizerProvider> customizerProvider()
16.106 +meth public abstract !hasdefault java.lang.String id()
16.107 +meth public abstract !hasdefault java.lang.String[] suppressWarnings()
16.108 +meth public abstract !hasdefault org.netbeans.spi.editor.hints.Severity severity()
16.109 +meth public abstract !hasdefault org.netbeans.spi.java.hints.Hint$Kind hintKind()
16.110 +meth public abstract !hasdefault org.netbeans.spi.java.hints.Hint$Options[] options()
16.111 +meth public abstract java.lang.String category()
16.112 +meth public abstract java.lang.String description()
16.113 +meth public abstract java.lang.String displayName()
16.114 +
16.115 +CLSS public final static !enum org.netbeans.spi.java.hints.Hint$Kind
16.116 + outer org.netbeans.spi.java.hints.Hint
16.117 +fld public final static org.netbeans.spi.java.hints.Hint$Kind ACTION
16.118 +fld public final static org.netbeans.spi.java.hints.Hint$Kind INSPECTION
16.119 +meth public static org.netbeans.spi.java.hints.Hint$Kind valueOf(java.lang.String)
16.120 +meth public static org.netbeans.spi.java.hints.Hint$Kind[] values()
16.121 +supr java.lang.Enum<org.netbeans.spi.java.hints.Hint$Kind>
16.122 +
16.123 +CLSS public final static !enum org.netbeans.spi.java.hints.Hint$Options
16.124 + outer org.netbeans.spi.java.hints.Hint
16.125 +fld public final static org.netbeans.spi.java.hints.Hint$Options NO_BATCH
16.126 +fld public final static org.netbeans.spi.java.hints.Hint$Options QUERY
16.127 +meth public static org.netbeans.spi.java.hints.Hint$Options valueOf(java.lang.String)
16.128 +meth public static org.netbeans.spi.java.hints.Hint$Options[] values()
16.129 +supr java.lang.Enum<org.netbeans.spi.java.hints.Hint$Options>
16.130 +
16.131 +CLSS public org.netbeans.spi.java.hints.HintContext
16.132 +innr public final static !enum MessageKind
16.133 +meth public boolean isBulkMode()
16.134 +meth public boolean isCanceled()
16.135 +meth public com.sun.source.util.TreePath getPath()
16.136 +meth public int getCaretLocation()
16.137 +meth public java.util.Map<java.lang.String,com.sun.source.util.TreePath> getVariables()
16.138 +meth public java.util.Map<java.lang.String,java.lang.String> getVariableNames()
16.139 +meth public java.util.Map<java.lang.String,java.util.Collection<? extends com.sun.source.util.TreePath>> getMultiVariables()
16.140 +meth public java.util.Map<java.lang.String,javax.lang.model.type.TypeMirror> getConstraints()
16.141 +meth public java.util.prefs.Preferences getPreferences()
16.142 +meth public org.netbeans.api.java.source.CompilationInfo getInfo()
16.143 +meth public org.netbeans.spi.editor.hints.Severity getSeverity()
16.144 +meth public void reportMessage(org.netbeans.spi.java.hints.HintContext$MessageKind,java.lang.String)
16.145 +supr java.lang.Object
16.146 +hfds bulkMode,cancel,caret,constraints,info,messages,metadata,multiVariables,path,preferences,severity,variableNames,variables
16.147 +
16.148 +CLSS public final static !enum org.netbeans.spi.java.hints.HintContext$MessageKind
16.149 + outer org.netbeans.spi.java.hints.HintContext
16.150 +fld public final static org.netbeans.spi.java.hints.HintContext$MessageKind ERROR
16.151 +fld public final static org.netbeans.spi.java.hints.HintContext$MessageKind WARNING
16.152 +meth public static org.netbeans.spi.java.hints.HintContext$MessageKind valueOf(java.lang.String)
16.153 +meth public static org.netbeans.spi.java.hints.HintContext$MessageKind[] values()
16.154 +supr java.lang.Enum<org.netbeans.spi.java.hints.HintContext$MessageKind>
16.155 +
16.156 +CLSS public final !enum org.netbeans.spi.java.hints.HintSeverity
16.157 +fld public final static org.netbeans.spi.java.hints.HintSeverity CURRENT_LINE_WARNING
16.158 +fld public final static org.netbeans.spi.java.hints.HintSeverity ERROR
16.159 +fld public final static org.netbeans.spi.java.hints.HintSeverity WARNING
16.160 +meth public org.netbeans.spi.editor.hints.Severity toEditorSeverity()
16.161 +meth public static org.netbeans.spi.java.hints.HintSeverity valueOf(java.lang.String)
16.162 +meth public static org.netbeans.spi.java.hints.HintSeverity[] values()
16.163 +supr java.lang.Enum<org.netbeans.spi.java.hints.HintSeverity>
16.164 +
16.165 +CLSS public abstract org.netbeans.spi.java.hints.JavaFix
16.166 +cons protected init(org.netbeans.api.java.source.CompilationInfo,com.sun.source.util.TreePath)
16.167 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.168 + anno 2 org.netbeans.api.annotations.common.NonNull()
16.169 +cons protected init(org.netbeans.api.java.source.TreePathHandle)
16.170 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.171 +innr public final static TransformationContext
16.172 +meth protected abstract java.lang.String getText()
16.173 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.174 +meth protected abstract void performRewrite(org.netbeans.spi.java.hints.JavaFix$TransformationContext) throws java.lang.Exception
16.175 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.176 +meth public final org.netbeans.spi.editor.hints.Fix toEditorFix()
16.177 +supr java.lang.Object
16.178 +hfds LOG,handle,options
16.179 +
16.180 +CLSS public final static org.netbeans.spi.java.hints.JavaFix$TransformationContext
16.181 + outer org.netbeans.spi.java.hints.JavaFix
16.182 +meth public com.sun.source.util.TreePath getPath()
16.183 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.184 +meth public java.io.InputStream getResourceContent(org.openide.filesystems.FileObject) throws java.io.IOException
16.185 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.186 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.187 +meth public java.io.OutputStream getResourceOutput(org.openide.filesystems.FileObject) throws java.io.IOException
16.188 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.189 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.190 +meth public org.netbeans.api.java.source.WorkingCopy getWorkingCopy()
16.191 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.192 +supr java.lang.Object
16.193 +hfds canShowUI,fileChanges,path,resourceContentChanges,workingCopy
16.194 +
16.195 +CLSS public org.netbeans.spi.java.hints.JavaFixUtilities
16.196 +cons public init()
16.197 +meth public static boolean requiresParenthesis(com.sun.source.tree.Tree,com.sun.source.tree.Tree,com.sun.source.tree.Tree)
16.198 +meth public static org.netbeans.spi.editor.hints.Fix removeFromParent(org.netbeans.spi.java.hints.HintContext,java.lang.String,com.sun.source.util.TreePath)
16.199 +meth public static org.netbeans.spi.editor.hints.Fix rewriteFix(org.netbeans.spi.java.hints.HintContext,java.lang.String,com.sun.source.util.TreePath,java.lang.String)
16.200 +supr java.lang.Object
16.201 +hfds NUMBER_LITERAL_KINDS,OPERATOR_PRIORITIES,SPEC_VERSION
16.202 +hcls JavaFixRealImpl,MoveFile,RemoveFromParent,ReplaceParameters
16.203 +
16.204 +CLSS public org.netbeans.spi.java.hints.MatcherUtilities
16.205 +cons public init()
16.206 +meth public static boolean matches(org.netbeans.spi.java.hints.HintContext,com.sun.source.util.TreePath,java.lang.String)
16.207 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.208 + anno 2 org.netbeans.api.annotations.common.NonNull()
16.209 + anno 3 org.netbeans.api.annotations.common.NonNull()
16.210 +meth public static boolean matches(org.netbeans.spi.java.hints.HintContext,com.sun.source.util.TreePath,java.lang.String,boolean)
16.211 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.212 + anno 2 org.netbeans.api.annotations.common.NonNull()
16.213 + anno 3 org.netbeans.api.annotations.common.NonNull()
16.214 +meth public static boolean matches(org.netbeans.spi.java.hints.HintContext,com.sun.source.util.TreePath,java.lang.String,java.util.Map<java.lang.String,com.sun.source.util.TreePath>,java.util.Map<java.lang.String,java.util.Collection<? extends com.sun.source.util.TreePath>>,java.util.Map<java.lang.String,java.lang.String>)
16.215 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.216 + anno 2 org.netbeans.api.annotations.common.NonNull()
16.217 + anno 3 org.netbeans.api.annotations.common.NonNull()
16.218 +meth public static boolean matches(org.netbeans.spi.java.hints.HintContext,java.util.Collection<? extends com.sun.source.util.TreePath>,java.lang.String,java.util.Map<java.lang.String,com.sun.source.util.TreePath>,java.util.Map<java.lang.String,java.util.Collection<? extends com.sun.source.util.TreePath>>,java.util.Map<java.lang.String,java.lang.String>)
16.219 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.220 + anno 2 org.netbeans.api.annotations.common.NonNull()
16.221 + anno 3 org.netbeans.api.annotations.common.NonNull()
16.222 +supr java.lang.Object
16.223 +
16.224 +CLSS public abstract interface !annotation org.netbeans.spi.java.hints.TriggerPattern
16.225 + anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=SOURCE)
16.226 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[METHOD])
16.227 +intf java.lang.annotation.Annotation
16.228 +meth public abstract !hasdefault org.netbeans.spi.java.hints.ConstraintVariableType[] constraints()
16.229 +meth public abstract java.lang.String value()
16.230 +
16.231 +CLSS public abstract interface !annotation org.netbeans.spi.java.hints.TriggerPatterns
16.232 + anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=SOURCE)
16.233 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[METHOD])
16.234 +intf java.lang.annotation.Annotation
16.235 +meth public abstract org.netbeans.spi.java.hints.TriggerPattern[] value()
16.236 +
16.237 +CLSS public abstract interface !annotation org.netbeans.spi.java.hints.TriggerTreeKind
16.238 + anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=SOURCE)
16.239 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[METHOD])
16.240 +intf java.lang.annotation.Annotation
16.241 +meth public abstract com.sun.source.tree.Tree$Kind[] value()
16.242 +
16.243 +CLSS public abstract interface !annotation org.netbeans.spi.java.hints.UseOptions
16.244 + anno 0 java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy value=SOURCE)
16.245 + anno 0 java.lang.annotation.Target(java.lang.annotation.ElementType[] value=[METHOD])
16.246 +intf java.lang.annotation.Annotation
16.247 +meth public abstract java.lang.String[] value()
16.248 +
16.249 +CLSS public final org.netbeans.spi.java.hints.support.FixFactory
16.250 +meth public final static org.netbeans.spi.editor.hints.Fix addModifiersFix(org.netbeans.api.java.source.CompilationInfo,com.sun.source.util.TreePath,java.util.Set<javax.lang.model.element.Modifier>,java.lang.String)
16.251 +meth public final static org.netbeans.spi.editor.hints.Fix changeModifiersFix(org.netbeans.api.java.source.CompilationInfo,com.sun.source.util.TreePath,java.util.Set<javax.lang.model.element.Modifier>,java.util.Set<javax.lang.model.element.Modifier>,java.lang.String)
16.252 +meth public final static org.netbeans.spi.editor.hints.Fix removeModifiersFix(org.netbeans.api.java.source.CompilationInfo,com.sun.source.util.TreePath,java.util.Set<javax.lang.model.element.Modifier>,java.lang.String)
16.253 +supr java.lang.Object
16.254 +hcls ChangeModifiersFixImpl
16.255 +
16.256 +CLSS public final org.netbeans.spi.java.hints.support.TransformationSupport
16.257 +innr public abstract interface static Transformer
16.258 +meth public java.util.Collection<? extends org.netbeans.api.java.source.ModificationResult> processAllProjects()
16.259 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.260 +meth public org.netbeans.spi.java.hints.support.TransformationSupport setCancel(java.util.concurrent.atomic.AtomicBoolean)
16.261 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.262 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.263 +meth public static org.netbeans.spi.java.hints.support.TransformationSupport create(java.lang.String)
16.264 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.265 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.266 +meth public static org.netbeans.spi.java.hints.support.TransformationSupport create(java.lang.String,org.netbeans.spi.java.hints.support.TransformationSupport$Transformer)
16.267 + anno 0 org.netbeans.api.annotations.common.NonNull()
16.268 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.269 + anno 2 org.netbeans.api.annotations.common.NonNull()
16.270 +meth public void transformTreePath(org.netbeans.api.java.source.WorkingCopy,com.sun.source.util.TreePath)
16.271 + anno 1 org.netbeans.api.annotations.common.NonNull()
16.272 + anno 2 org.netbeans.api.annotations.common.NonNull()
16.273 +supr java.lang.Object
16.274 +hfds cancel,jackpotPattern,transformer
16.275 +
16.276 +CLSS public abstract interface static org.netbeans.spi.java.hints.support.TransformationSupport$Transformer
16.277 + outer org.netbeans.spi.java.hints.support.TransformationSupport
16.278 +meth public abstract void transform(org.netbeans.api.java.source.WorkingCopy,org.netbeans.api.java.source.matching.Occurrence)
16.279 +
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/java.hints/spi.java.hints/nbproject/project.properties Wed May 08 21:47:42 2013 +0200
17.3 @@ -0,0 +1,7 @@
17.4 +is.autoload=true
17.5 +javac.source=1.7
17.6 +javac.compilerargs=-Xlint -Xlint:-serial
17.7 +spec.version.base=2.0.0
17.8 +requires.nb.javac=true
17.9 +javadoc.arch=${basedir}/arch.xml
17.10 +javadoc.apichanges=${basedir}/apichanges.xml
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/java.hints/spi.java.hints/nbproject/project.xml Wed May 08 21:47:42 2013 +0200
18.3 @@ -0,0 +1,456 @@
18.4 +<?xml version="1.0" encoding="UTF-8"?>
18.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
18.6 + <type>org.netbeans.modules.apisupport.project</type>
18.7 + <configuration>
18.8 + <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
18.9 + <code-name-base>org.netbeans.spi.java.hints</code-name-base>
18.10 + <suite-component/>
18.11 + <module-dependencies>
18.12 + <dependency>
18.13 + <code-name-base>org.netbeans.api.annotations.common</code-name-base>
18.14 + <build-prerequisite/>
18.15 + <compile-dependency/>
18.16 + <run-dependency>
18.17 + <release-version>1</release-version>
18.18 + <specification-version>1.4</specification-version>
18.19 + </run-dependency>
18.20 + </dependency>
18.21 + <dependency>
18.22 + <code-name-base>org.netbeans.api.java</code-name-base>
18.23 + <build-prerequisite/>
18.24 + <compile-dependency/>
18.25 + <run-dependency>
18.26 + <release-version>1</release-version>
18.27 + <specification-version>1.18</specification-version>
18.28 + </run-dependency>
18.29 + </dependency>
18.30 + <dependency>
18.31 + <code-name-base>org.netbeans.api.java.classpath</code-name-base>
18.32 + <build-prerequisite/>
18.33 + <compile-dependency/>
18.34 + <run-dependency>
18.35 + <release-version>1</release-version>
18.36 + <specification-version>1.24</specification-version>
18.37 + </run-dependency>
18.38 + </dependency>
18.39 + <dependency>
18.40 + <code-name-base>org.netbeans.api.progress</code-name-base>
18.41 + <build-prerequisite/>
18.42 + <compile-dependency/>
18.43 + <run-dependency>
18.44 + <release-version>1</release-version>
18.45 + <specification-version>1.16</specification-version>
18.46 + </run-dependency>
18.47 + </dependency>
18.48 + <dependency>
18.49 + <code-name-base>org.netbeans.lib.nbjavac</code-name-base>
18.50 + <build-prerequisite/>
18.51 + <compile-dependency/>
18.52 + <run-dependency>
18.53 + <implementation-version/>
18.54 + </run-dependency>
18.55 + </dependency>
18.56 + <dependency>
18.57 + <code-name-base>org.netbeans.libs.javacapi</code-name-base>
18.58 + <build-prerequisite/>
18.59 + <compile-dependency/>
18.60 + <run-dependency>
18.61 + <specification-version>8.0</specification-version>
18.62 + </run-dependency>
18.63 + </dependency>
18.64 + <dependency>
18.65 + <code-name-base>org.netbeans.libs.javacimpl</code-name-base>
18.66 + <build-prerequisite/>
18.67 + <compile-dependency/>
18.68 + <run-dependency>
18.69 + <release-version>1</release-version>
18.70 + <implementation-version/>
18.71 + </run-dependency>
18.72 + </dependency>
18.73 + <dependency>
18.74 + <code-name-base>org.netbeans.libs.lucene</code-name-base>
18.75 + <build-prerequisite/>
18.76 + <compile-dependency/>
18.77 + <run-dependency>
18.78 + <release-version>3</release-version>
18.79 + <specification-version>3.0</specification-version>
18.80 + </run-dependency>
18.81 + </dependency>
18.82 + <dependency>
18.83 + <code-name-base>org.netbeans.modules.code.analysis</code-name-base>
18.84 + <build-prerequisite/>
18.85 + <compile-dependency/>
18.86 + <run-dependency>
18.87 + <release-version>0</release-version>
18.88 + <specification-version>1.8</specification-version>
18.89 + </run-dependency>
18.90 + </dependency>
18.91 + <dependency>
18.92 + <code-name-base>org.netbeans.modules.editor</code-name-base>
18.93 + <build-prerequisite/>
18.94 + <compile-dependency/>
18.95 + <run-dependency>
18.96 + <release-version>3</release-version>
18.97 + <specification-version>1.53</specification-version>
18.98 + </run-dependency>
18.99 + </dependency>
18.100 + <dependency>
18.101 + <code-name-base>org.netbeans.modules.editor.errorstripe.api</code-name-base>
18.102 + <build-prerequisite/>
18.103 + <compile-dependency/>
18.104 + <run-dependency>
18.105 + <release-version>1</release-version>
18.106 + <specification-version>2.3</specification-version>
18.107 + </run-dependency>
18.108 + </dependency>
18.109 + <dependency>
18.110 + <code-name-base>org.netbeans.modules.editor.lib</code-name-base>
18.111 + <build-prerequisite/>
18.112 + <compile-dependency/>
18.113 + <run-dependency>
18.114 + <release-version>3</release-version>
18.115 + <specification-version>3.1</specification-version>
18.116 + </run-dependency>
18.117 + </dependency>
18.118 + <dependency>
18.119 + <code-name-base>org.netbeans.modules.editor.lib2</code-name-base>
18.120 + <build-prerequisite/>
18.121 + <compile-dependency/>
18.122 + <run-dependency>
18.123 + <release-version>1</release-version>
18.124 + <specification-version>1.8</specification-version>
18.125 + </run-dependency>
18.126 + </dependency>
18.127 + <dependency>
18.128 + <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
18.129 + <build-prerequisite/>
18.130 + <compile-dependency/>
18.131 + <run-dependency>
18.132 + <release-version>1</release-version>
18.133 + <specification-version>1.15</specification-version>
18.134 + </run-dependency>
18.135 + </dependency>
18.136 + <dependency>
18.137 + <code-name-base>org.netbeans.modules.editor.settings</code-name-base>
18.138 + <build-prerequisite/>
18.139 + <compile-dependency/>
18.140 + <run-dependency>
18.141 + <release-version>1</release-version>
18.142 + <specification-version>1.28</specification-version>
18.143 + </run-dependency>
18.144 + </dependency>
18.145 + <dependency>
18.146 + <code-name-base>org.netbeans.modules.editor.util</code-name-base>
18.147 + <build-prerequisite/>
18.148 + <compile-dependency/>
18.149 + <run-dependency>
18.150 + <release-version>1</release-version>
18.151 + <specification-version>1.33</specification-version>
18.152 + </run-dependency>
18.153 + </dependency>
18.154 + <dependency>
18.155 + <code-name-base>org.netbeans.modules.java.lexer</code-name-base>
18.156 + <build-prerequisite/>
18.157 + <compile-dependency/>
18.158 + <run-dependency>
18.159 + <release-version>1</release-version>
18.160 + <specification-version>1.0</specification-version>
18.161 + </run-dependency>
18.162 + </dependency>
18.163 + <dependency>
18.164 + <code-name-base>org.netbeans.modules.java.platform</code-name-base>
18.165 + <build-prerequisite/>
18.166 + <compile-dependency/>
18.167 + <run-dependency>
18.168 + <release-version>1</release-version>
18.169 + <specification-version>1.16</specification-version>
18.170 + </run-dependency>
18.171 + </dependency>
18.172 + <dependency>
18.173 + <code-name-base>org.netbeans.modules.java.project</code-name-base>
18.174 + <build-prerequisite/>
18.175 + <compile-dependency/>
18.176 + <run-dependency>
18.177 + <release-version>1</release-version>
18.178 + <specification-version>1.41</specification-version>
18.179 + </run-dependency>
18.180 + </dependency>
18.181 + <dependency>
18.182 + <code-name-base>org.netbeans.modules.java.source</code-name-base>
18.183 + <build-prerequisite/>
18.184 + <compile-dependency/>
18.185 + <run-dependency>
18.186 + <implementation-version/>
18.187 + </run-dependency>
18.188 + </dependency>
18.189 + <dependency>
18.190 + <code-name-base>org.netbeans.modules.lexer</code-name-base>
18.191 + <build-prerequisite/>
18.192 + <compile-dependency/>
18.193 + <run-dependency>
18.194 + <release-version>2</release-version>
18.195 + <specification-version>1.25</specification-version>
18.196 + </run-dependency>
18.197 + </dependency>
18.198 + <dependency>
18.199 + <code-name-base>org.netbeans.modules.options.api</code-name-base>
18.200 + <build-prerequisite/>
18.201 + <compile-dependency/>
18.202 + <run-dependency>
18.203 + <release-version>1</release-version>
18.204 + <specification-version>1.5</specification-version>
18.205 + </run-dependency>
18.206 + </dependency>
18.207 + <dependency>
18.208 + <code-name-base>org.netbeans.modules.options.editor</code-name-base>
18.209 + <build-prerequisite/>
18.210 + <compile-dependency/>
18.211 + <run-dependency>
18.212 + <release-version>1</release-version>
18.213 + <specification-version>1.28</specification-version>
18.214 + </run-dependency>
18.215 + </dependency>
18.216 + <dependency>
18.217 + <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
18.218 + <build-prerequisite/>
18.219 + <compile-dependency/>
18.220 + <run-dependency>
18.221 + <release-version>1</release-version>
18.222 + <implementation-version/>
18.223 + </run-dependency>
18.224 + </dependency>
18.225 + <dependency>
18.226 + <code-name-base>org.netbeans.modules.projectapi</code-name-base>
18.227 + <build-prerequisite/>
18.228 + <compile-dependency/>
18.229 + <run-dependency>
18.230 + <release-version>1</release-version>
18.231 + <specification-version>1.42</specification-version>
18.232 + </run-dependency>
18.233 + </dependency>
18.234 + <dependency>
18.235 + <code-name-base>org.netbeans.modules.queries</code-name-base>
18.236 + <build-prerequisite/>
18.237 + <compile-dependency/>
18.238 + <run-dependency>
18.239 + <release-version>1</release-version>
18.240 + <specification-version>1.18</specification-version>
18.241 + </run-dependency>
18.242 + </dependency>
18.243 + <dependency>
18.244 + <code-name-base>org.netbeans.modules.refactoring.api</code-name-base>
18.245 + <build-prerequisite/>
18.246 + <compile-dependency/>
18.247 + <run-dependency>
18.248 + <specification-version>1.23</specification-version>
18.249 + </run-dependency>
18.250 + </dependency>
18.251 + <dependency>
18.252 + <code-name-base>org.netbeans.spi.editor.hints</code-name-base>
18.253 + <build-prerequisite/>
18.254 + <compile-dependency/>
18.255 + <run-dependency>
18.256 + <release-version>0-1</release-version>
18.257 + <specification-version>1.22</specification-version>
18.258 + </run-dependency>
18.259 + </dependency>
18.260 + <dependency>
18.261 + <code-name-base>org.openide.actions</code-name-base>
18.262 + <build-prerequisite/>
18.263 + <compile-dependency/>
18.264 + <run-dependency>
18.265 + <specification-version>6.15</specification-version>
18.266 + </run-dependency>
18.267 + </dependency>
18.268 + <dependency>
18.269 + <code-name-base>org.openide.awt</code-name-base>
18.270 + <build-prerequisite/>
18.271 + <compile-dependency/>
18.272 + <run-dependency>
18.273 + <specification-version>6.10</specification-version>
18.274 + </run-dependency>
18.275 + </dependency>
18.276 + <dependency>
18.277 + <code-name-base>org.openide.dialogs</code-name-base>
18.278 + <build-prerequisite/>
18.279 + <compile-dependency/>
18.280 + <run-dependency>
18.281 + <specification-version>7.0</specification-version>
18.282 + </run-dependency>
18.283 + </dependency>
18.284 + <dependency>
18.285 + <code-name-base>org.openide.explorer</code-name-base>
18.286 + <build-prerequisite/>
18.287 + <compile-dependency/>
18.288 + <run-dependency>
18.289 + <specification-version>6.22</specification-version>
18.290 + </run-dependency>
18.291 + </dependency>
18.292 + <dependency>
18.293 + <code-name-base>org.openide.filesystems</code-name-base>
18.294 + <build-prerequisite/>
18.295 + <compile-dependency/>
18.296 + <run-dependency>
18.297 + <specification-version>7.19</specification-version>
18.298 + </run-dependency>
18.299 + </dependency>
18.300 + <dependency>
18.301 + <code-name-base>org.openide.loaders</code-name-base>
18.302 + <build-prerequisite/>
18.303 + <compile-dependency/>
18.304 + <run-dependency/>
18.305 + </dependency>
18.306 + <dependency>
18.307 + <code-name-base>org.openide.modules</code-name-base>
18.308 + <build-prerequisite/>
18.309 + <compile-dependency/>
18.310 + <run-dependency>
18.311 + <specification-version>7.3</specification-version>
18.312 + </run-dependency>
18.313 + </dependency>
18.314 + <dependency>
18.315 + <code-name-base>org.openide.nodes</code-name-base>
18.316 + <build-prerequisite/>
18.317 + <compile-dependency/>
18.318 + <run-dependency>
18.319 + <specification-version>6.2</specification-version>
18.320 + </run-dependency>
18.321 + </dependency>
18.322 + <dependency>
18.323 + <code-name-base>org.openide.text</code-name-base>
18.324 + <build-prerequisite/>
18.325 + <compile-dependency/>
18.326 + <run-dependency>
18.327 + <specification-version>6.16</specification-version>
18.328 + </run-dependency>
18.329 + </dependency>
18.330 + <dependency>
18.331 + <code-name-base>org.openide.util</code-name-base>
18.332 + <build-prerequisite/>
18.333 + <compile-dependency/>
18.334 + <run-dependency>
18.335 + <specification-version>8.32</specification-version>
18.336 + </run-dependency>
18.337 + </dependency>
18.338 + <dependency>
18.339 + <code-name-base>org.openide.util.lookup</code-name-base>
18.340 + <build-prerequisite/>
18.341 + <compile-dependency/>
18.342 + <run-dependency>
18.343 + <specification-version>8.0</specification-version>
18.344 + </run-dependency>
18.345 + </dependency>
18.346 + <dependency>
18.347 + <code-name-base>org.openide.windows</code-name-base>
18.348 + <build-prerequisite/>
18.349 + <compile-dependency/>
18.350 + <run-dependency>
18.351 + <specification-version>6.16</specification-version>
18.352 + </run-dependency>
18.353 + </dependency>
18.354 + </module-dependencies>
18.355 + <test-dependencies>
18.356 + <test-type>
18.357 + <name>unit</name>
18.358 + <test-dependency>
18.359 + <code-name-base>org.netbeans.core</code-name-base>
18.360 + <compile-dependency/>
18.361 + </test-dependency>
18.362 + <test-dependency>
18.363 + <code-name-base>org.netbeans.insane</code-name-base>
18.364 + <compile-dependency/>
18.365 + </test-dependency>
18.366 + <test-dependency>
18.367 + <code-name-base>org.netbeans.libs.freemarker</code-name-base>
18.368 + <recursive/>
18.369 + <compile-dependency/>
18.370 + </test-dependency>
18.371 + <test-dependency>
18.372 + <code-name-base>org.netbeans.libs.junit4</code-name-base>
18.373 + <compile-dependency/>
18.374 + </test-dependency>
18.375 + <test-dependency>
18.376 + <code-name-base>org.netbeans.modules.classfile</code-name-base>
18.377 + </test-dependency>
18.378 + <test-dependency>
18.379 + <code-name-base>org.netbeans.modules.defaults</code-name-base>
18.380 + </test-dependency>
18.381 + <test-dependency>
18.382 + <code-name-base>org.netbeans.modules.editor</code-name-base>
18.383 + <test/>
18.384 + </test-dependency>
18.385 + <test-dependency>
18.386 + <code-name-base>org.netbeans.modules.editor.mimelookup</code-name-base>
18.387 + <compile-dependency/>
18.388 + <test/>
18.389 + </test-dependency>
18.390 + <test-dependency>
18.391 + <code-name-base>org.netbeans.modules.editor.settings</code-name-base>
18.392 + </test-dependency>
18.393 + <test-dependency>
18.394 + <code-name-base>org.netbeans.modules.editor.settings.storage</code-name-base>
18.395 + </test-dependency>
18.396 + <test-dependency>
18.397 + <code-name-base>org.netbeans.modules.editor.util</code-name-base>
18.398 + </test-dependency>
18.399 + <test-dependency>
18.400 + <code-name-base>org.netbeans.modules.jackpot30.test.borrowed</code-name-base>
18.401 + <compile-dependency/>
18.402 + </test-dependency>
18.403 + <test-dependency>
18.404 + <code-name-base>org.netbeans.modules.java.editor</code-name-base>
18.405 + <recursive/>
18.406 + <compile-dependency/>
18.407 + </test-dependency>
18.408 + <test-dependency>
18.409 + <code-name-base>org.netbeans.modules.java.hints</code-name-base>
18.410 + <compile-dependency/>
18.411 + </test-dependency>
18.412 + <test-dependency>
18.413 + <code-name-base>org.netbeans.modules.java.hints.declarative</code-name-base>
18.414 + <compile-dependency/>
18.415 + </test-dependency>
18.416 + <test-dependency>
18.417 + <code-name-base>org.netbeans.modules.java.source</code-name-base>
18.418 + <compile-dependency/>
18.419 + <test/>
18.420 + </test-dependency>
18.421 + <test-dependency>
18.422 + <code-name-base>org.netbeans.modules.masterfs</code-name-base>
18.423 + </test-dependency>
18.424 + <test-dependency>
18.425 + <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
18.426 + <compile-dependency/>
18.427 + </test-dependency>
18.428 + <test-dependency>
18.429 + <code-name-base>org.netbeans.modules.parsing.api</code-name-base>
18.430 + <compile-dependency/>
18.431 + <test/>
18.432 + </test-dependency>
18.433 + <test-dependency>
18.434 + <code-name-base>org.netbeans.modules.progress.ui</code-name-base>
18.435 + </test-dependency>
18.436 + <test-dependency>
18.437 + <code-name-base>org.netbeans.modules.projectui</code-name-base>
18.438 + </test-dependency>
18.439 + <test-dependency>
18.440 + <code-name-base>org.openide.util</code-name-base>
18.441 + <compile-dependency/>
18.442 + <test/>
18.443 + </test-dependency>
18.444 + <test-dependency>
18.445 + <code-name-base>org.openide.util.lookup</code-name-base>
18.446 + <compile-dependency/>
18.447 + <test/>
18.448 + </test-dependency>
18.449 + </test-type>
18.450 + </test-dependencies>
18.451 + <public-packages>
18.452 + <package>org.netbeans.spi.java.hints</package>
18.453 + <package>org.netbeans.spi.java.hints.annotations</package>
18.454 + <package>org.netbeans.spi.java.hints.matching</package>
18.455 + <package>org.netbeans.spi.java.hints.support</package>
18.456 + </public-packages>
18.457 + </data>
18.458 + </configuration>
18.459 +</project>
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/java.hints/spi.java.hints/nbproject/suite.properties Wed May 08 21:47:42 2013 +0200
19.3 @@ -0,0 +1,1 @@
19.4 +suite.dir=${basedir}/..
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/jackpot/spi/Bundle.properties Wed May 08 21:47:42 2013 +0200
20.3 @@ -0,0 +1,42 @@
20.4 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
20.5 +#
20.6 +# Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
20.7 +#
20.8 +# Oracle and Java are registered trademarks of Oracle and/or its affiliates.
20.9 +# Other names may be trademarks of their respective owners.
20.10 +#
20.11 +# The contents of this file are subject to the terms of either the GNU
20.12 +# General Public License Version 2 only ("GPL") or the Common
20.13 +# Development and Distribution License("CDDL") (collectively, the
20.14 +# "License"). You may not use this file except in compliance with the
20.15 +# License. You can obtain a copy of the License at
20.16 +# http://www.netbeans.org/cddl-gplv2.html
20.17 +# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
20.18 +# specific language governing permissions and limitations under the
20.19 +# License. When distributing the software, include this License Header
20.20 +# Notice in each file and include the License file at
20.21 +# nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
20.22 +# particular file as subject to the "Classpath" exception as provided
20.23 +# by Oracle in the GPL Version 2 section of the License file that
20.24 +# accompanied this code. If applicable, add the following below the
20.25 +# License Header, with the fields enclosed by brackets [] replaced by
20.26 +# your own identifying information:
20.27 +# "Portions Copyrighted [year] [name of copyright owner]"
20.28 +#
20.29 +# Contributor(s):
20.30 +#
20.31 +# The Original Software is NetBeans. The Initial Developer of the Original
20.32 +# Software is Sun Microsystems, Inc. Portions Copyright 2008-2009 Sun
20.33 +# Microsystems, Inc. All Rights Reserved.
20.34 +#
20.35 +# If you wish your version of this file to be governed by only the CDDL
20.36 +# or only the GPL Version 2, indicate your decision by adding
20.37 +# "[Contributor] elects to include this software in this distribution
20.38 +# under the [CDDL or GPL Version 2] license." If you do not indicate a
20.39 +# single choice of license, a recipient has the option to distribute
20.40 +# your version of this file under either the CDDL, the GPL Version 2 or
20.41 +# to extend the choice of license to its licensees as provided above.
20.42 +# However, if you add GPL Version 2 code and therefore, elected the GPL
20.43 +# Version 2 license, then the option applies only if the new code is
20.44 +# made subject to such option by the copyright holder.
20.45 +LBL_UpdateDependencyQuestion=Update dependency on module {0} to specification version {1}?
20.46 \ No newline at end of file
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/jackpot/spi/HintsRunner.java Wed May 08 21:47:42 2013 +0200
21.3 @@ -0,0 +1,69 @@
21.4 +/*
21.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
21.6 + *
21.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
21.8 + *
21.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
21.10 + * Other names may be trademarks of their respective owners.
21.11 + *
21.12 + * The contents of this file are subject to the terms of either the GNU
21.13 + * General Public License Version 2 only ("GPL") or the Common
21.14 + * Development and Distribution License("CDDL") (collectively, the
21.15 + * "License"). You may not use this file except in compliance with the
21.16 + * License. You can obtain a copy of the License at
21.17 + * http://www.netbeans.org/cddl-gplv2.html
21.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
21.19 + * specific language governing permissions and limitations under the
21.20 + * License. When distributing the software, include this License Header
21.21 + * Notice in each file and include the License file at
21.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
21.23 + * particular file as subject to the "Classpath" exception as provided
21.24 + * by Oracle in the GPL Version 2 section of the License file that
21.25 + * accompanied this code. If applicable, add the following below the
21.26 + * License Header, with the fields enclosed by brackets [] replaced by
21.27 + * your own identifying information:
21.28 + * "Portions Copyrighted [year] [name of copyright owner]"
21.29 + *
21.30 + * If you wish your version of this file to be governed by only the CDDL
21.31 + * or only the GPL Version 2, indicate your decision by adding
21.32 + * "[Contributor] elects to include this software in this distribution
21.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
21.34 + * single choice of license, a recipient has the option to distribute
21.35 + * your version of this file under either the CDDL, the GPL Version 2 or
21.36 + * to extend the choice of license to its licensees as provided above.
21.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
21.38 + * Version 2 license, then the option applies only if the new code is
21.39 + * made subject to such option by the copyright holder.
21.40 + *
21.41 + * Contributor(s):
21.42 + *
21.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
21.44 + */
21.45 +
21.46 +package org.netbeans.modules.java.hints.jackpot.spi;
21.47 +
21.48 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
21.49 +import com.sun.source.util.TreePath;
21.50 +import java.util.LinkedList;
21.51 +import java.util.List;
21.52 +import java.util.Map;
21.53 +import java.util.concurrent.atomic.AtomicBoolean;
21.54 +import org.netbeans.api.annotations.common.CheckForNull;
21.55 +import org.netbeans.api.java.source.CompilationInfo;
21.56 +import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
21.57 +import org.netbeans.modules.java.hints.spiimpl.hints.HintsInvoker;
21.58 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
21.59 +import org.netbeans.spi.editor.hints.ErrorDescription;
21.60 +
21.61 +/**XXX: probably unused
21.62 + *
21.63 + * @author lahvac
21.64 + */
21.65 +public class HintsRunner {
21.66 +
21.67 + @CheckForNull
21.68 + public static Map<HintDescription, List<ErrorDescription>> computeErrors(CompilationInfo info, Iterable<? extends HintDescription> hints, AtomicBoolean cancel) {
21.69 + return new HintsInvoker(HintsSettings.getSettingsFor(info.getFileObject()), cancel).computeHints(info, new TreePath(info.getCompilationUnit()), hints, new LinkedList<MessageImpl>());
21.70 + }
21.71 +
21.72 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/jackpot/spi/PatternConvertor.java Wed May 08 21:47:42 2013 +0200
22.3 @@ -0,0 +1,113 @@
22.4 +/*
22.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
22.6 + *
22.7 + * Copyright 2009-2011 Sun Microsystems, Inc. All rights reserved.
22.8 + *
22.9 + * The contents of this file are subject to the terms of either the GNU
22.10 + * General Public License Version 2 only ("GPL") or the Common
22.11 + * Development and Distribution License("CDDL") (collectively, the
22.12 + * "License"). You may not use this file except in compliance with the
22.13 + * License. You can obtain a copy of the License at
22.14 + * http://www.netbeans.org/cddl-gplv2.html
22.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
22.16 + * specific language governing permissions and limitations under the
22.17 + * License. When distributing the software, include this License Header
22.18 + * Notice in each file and include the License file at
22.19 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
22.20 + * particular file as subject to the "Classpath" exception as provided
22.21 + * by Sun in the GPL Version 2 section of the License file that
22.22 + * accompanied this code. If applicable, add the following below the
22.23 + * License Header, with the fields enclosed by brackets [] replaced by
22.24 + * your own identifying information:
22.25 + * "Portions Copyrighted [year] [name of copyright owner]"
22.26 + *
22.27 + * If you wish your version of this file to be governed by only the CDDL
22.28 + * or only the GPL Version 2, indicate your decision by adding
22.29 + * "[Contributor] elects to include this software in this distribution
22.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
22.31 + * single choice of license, a recipient has the option to distribute
22.32 + * your version of this file under either the CDDL, the GPL Version 2 or
22.33 + * to extend the choice of license to its licensees as provided above.
22.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
22.35 + * Version 2 license, then the option applies only if the new code is
22.36 + * made subject to such option by the copyright holder.
22.37 + *
22.38 + * Contributor(s):
22.39 + *
22.40 + * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
22.41 + */
22.42 +
22.43 +package org.netbeans.modules.java.hints.jackpot.spi;
22.44 +
22.45 +import org.netbeans.modules.java.hints.providers.spi.HintDescriptionFactory;
22.46 +import org.netbeans.spi.java.hints.HintContext;
22.47 +import java.util.ArrayList;
22.48 +import java.util.Collection;
22.49 +import java.util.Collections;
22.50 +import org.netbeans.api.annotations.common.CheckForNull;
22.51 +import org.netbeans.api.annotations.common.NonNull;
22.52 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.Worker;
22.53 +import org.netbeans.modules.java.hints.providers.spi.Trigger.PatternDescription;
22.54 +import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
22.55 +import org.netbeans.spi.editor.hints.ErrorDescription;
22.56 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
22.57 +import org.openide.util.Lookup;
22.58 +
22.59 +/**XXX: big hack?
22.60 + *
22.61 + * @author lahvac
22.62 + */
22.63 +public abstract class PatternConvertor {
22.64 +
22.65 + protected abstract @CheckForNull Iterable<? extends HintDescription> parseString(@NonNull String code);
22.66 +
22.67 + public static @CheckForNull Iterable<? extends HintDescription> create(@NonNull String code) {
22.68 + Collection<String> patterns = new ArrayList<String>();
22.69 +
22.70 + //XXX:
22.71 + if (code.contains(";;")) {
22.72 + PatternConvertor c = Lookup.getDefault().lookup(PatternConvertor.class);
22.73 +
22.74 + if (c != null) {
22.75 + return c.parseString(code);
22.76 + }
22.77 +
22.78 + for (String s : code.split(";;")) {
22.79 + s = s.trim();
22.80 + if (s.isEmpty()) {
22.81 + continue;
22.82 + }
22.83 +
22.84 + patterns.add(s);
22.85 + }
22.86 + } else {
22.87 + patterns.add(code);
22.88 + }
22.89 +
22.90 + Collection<HintDescription> result = new ArrayList<HintDescription>(patterns.size());
22.91 +
22.92 + for (String pattern : patterns) {
22.93 + PatternDescription pd = PatternDescription.create(pattern, Collections.<String, String>emptyMap());
22.94 +
22.95 + HintDescription desc = HintDescriptionFactory.create()
22.96 + // .setDisplayName("Pattern Matches")
22.97 + .setTrigger(pd)
22.98 + .setWorker(new WorkerImpl())
22.99 + .produce();
22.100 +
22.101 + result.add(desc);
22.102 + }
22.103 +
22.104 + return result;
22.105 + }
22.106 +
22.107 + private static final class WorkerImpl implements Worker {
22.108 +
22.109 + public Collection<? extends ErrorDescription> createErrors(HintContext ctx) {
22.110 + ErrorDescription ed = ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), "Found pattern occurrence");
22.111 +
22.112 + return Collections.singleton(ed);
22.113 + }
22.114 +
22.115 + }
22.116 +}
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/jackpot/spi/ProjectDependencyUpgrader.java Wed May 08 21:47:42 2013 +0200
23.3 @@ -0,0 +1,64 @@
23.4 +/*
23.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
23.6 + *
23.7 + * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23.8 + *
23.9 + * The contents of this file are subject to the terms of either the GNU
23.10 + * General Public License Version 2 only ("GPL") or the Common
23.11 + * Development and Distribution License("CDDL") (collectively, the
23.12 + * "License"). You may not use this file except in compliance with the
23.13 + * License. You can obtain a copy of the License at
23.14 + * http://www.netbeans.org/cddl-gplv2.html
23.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
23.16 + * specific language governing permissions and limitations under the
23.17 + * License. When distributing the software, include this License Header
23.18 + * Notice in each file and include the License file at
23.19 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
23.20 + * particular file as subject to the "Classpath" exception as provided
23.21 + * by Sun in the GPL Version 2 section of the License file that
23.22 + * accompanied this code. If applicable, add the following below the
23.23 + * License Header, with the fields enclosed by brackets [] replaced by
23.24 + * your own identifying information:
23.25 + * "Portions Copyrighted [year] [name of copyright owner]"
23.26 + *
23.27 + * If you wish your version of this file to be governed by only the CDDL
23.28 + * or only the GPL Version 2, indicate your decision by adding
23.29 + * "[Contributor] elects to include this software in this distribution
23.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
23.31 + * single choice of license, a recipient has the option to distribute
23.32 + * your version of this file under either the CDDL, the GPL Version 2 or
23.33 + * to extend the choice of license to its licensees as provided above.
23.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
23.35 + * Version 2 license, then the option applies only if the new code is
23.36 + * made subject to such option by the copyright holder.
23.37 + *
23.38 + * Contributor(s):
23.39 + *
23.40 + * Portions Copyrighted 2010 Sun Microsystems, Inc.
23.41 + */
23.42 +package org.netbeans.modules.java.hints.jackpot.spi;
23.43 +
23.44 +import org.netbeans.api.project.Project;
23.45 +import org.openide.DialogDisplayer;
23.46 +import org.openide.NotifyDescriptor;
23.47 +import org.openide.filesystems.FileObject;
23.48 +import org.openide.modules.SpecificationVersion;
23.49 +
23.50 +/**
23.51 + *
23.52 + * @author lahvac
23.53 + */
23.54 +public abstract class ProjectDependencyUpgrader {
23.55 +
23.56 + public abstract boolean ensureDependency(Project p, FileObject dep, SpecificationVersion spec, boolean canShowUI);
23.57 + public abstract boolean ensureDependency(Project p, String specification, boolean b);
23.58 +
23.59 + protected final boolean showDependencyUpgradeDialog(Project p, String dep, SpecificationVersion currentDependency, SpecificationVersion spec, boolean newDepenency, boolean canShowUI) {
23.60 + if (!canShowUI) return true;
23.61 +
23.62 + NotifyDescriptor nd = new NotifyDescriptor.Confirmation("New version: " + spec, "Update spec version.", NotifyDescriptor.YES_NO_OPTION);
23.63 +
23.64 + return DialogDisplayer.getDefault().notify(nd) == NotifyDescriptor.YES_OPTION;
23.65 + }
23.66 +
23.67 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/code/CodeHintProviderImpl.java Wed May 08 21:47:42 2013 +0200
24.3 @@ -0,0 +1,456 @@
24.4 +/*
24.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
24.6 + *
24.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
24.8 + *
24.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
24.10 + * Other names may be trademarks of their respective owners.
24.11 + *
24.12 + * The contents of this file are subject to the terms of either the GNU
24.13 + * General Public License Version 2 only ("GPL") or the Common
24.14 + * Development and Distribution License("CDDL") (collectively, the
24.15 + * "License"). You may not use this file except in compliance with the
24.16 + * License. You can obtain a copy of the License at
24.17 + * http://www.netbeans.org/cddl-gplv2.html
24.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
24.19 + * specific language governing permissions and limitations under the
24.20 + * License. When distributing the software, include this License Header
24.21 + * Notice in each file and include the License file at
24.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
24.23 + * particular file as subject to the "Classpath" exception as provided
24.24 + * by Oracle in the GPL Version 2 section of the License file that
24.25 + * accompanied this code. If applicable, add the following below the
24.26 + * License Header, with the fields enclosed by brackets [] replaced by
24.27 + * your own identifying information:
24.28 + * "Portions Copyrighted [year] [name of copyright owner]"
24.29 + *
24.30 + * If you wish your version of this file to be governed by only the CDDL
24.31 + * or only the GPL Version 2, indicate your decision by adding
24.32 + * "[Contributor] elects to include this software in this distribution
24.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
24.34 + * single choice of license, a recipient has the option to distribute
24.35 + * your version of this file under either the CDDL, the GPL Version 2 or
24.36 + * to extend the choice of license to its licensees as provided above.
24.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
24.38 + * Version 2 license, then the option applies only if the new code is
24.39 + * made subject to such option by the copyright holder.
24.40 + *
24.41 + * Contributor(s):
24.42 + *
24.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
24.44 + */
24.45 +
24.46 +package org.netbeans.modules.java.hints.providers.code;
24.47 +
24.48 +import com.sun.source.tree.Tree.Kind;
24.49 +import java.lang.annotation.Annotation;
24.50 +import java.lang.reflect.InvocationTargetException;
24.51 +import java.lang.reflect.Method;
24.52 +import java.util.ArrayList;
24.53 +import java.util.Arrays;
24.54 +import java.util.Collection;
24.55 +import java.util.Collections;
24.56 +import java.util.EnumSet;
24.57 +import java.util.HashMap;
24.58 +import java.util.HashSet;
24.59 +import java.util.LinkedList;
24.60 +import java.util.List;
24.61 +import java.util.Map;
24.62 +import java.util.Set;
24.63 +import java.util.concurrent.atomic.AtomicReference;
24.64 +import java.util.logging.Level;
24.65 +import java.util.logging.Logger;
24.66 +import java.util.prefs.Preferences;
24.67 +import javax.swing.JComponent;
24.68 +import javax.swing.JPanel;
24.69 +import org.netbeans.modules.java.hints.providers.code.FSWrapper.ClassWrapper;
24.70 +import org.netbeans.modules.java.hints.providers.code.FSWrapper.FieldWrapper;
24.71 +import org.netbeans.modules.java.hints.providers.code.FSWrapper.MethodWrapper;
24.72 +import org.netbeans.modules.java.hints.providers.code.ReflectiveCustomizerProvider.OptionDescriptor;
24.73 +import org.netbeans.spi.java.hints.CustomizerProvider;
24.74 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
24.75 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.Worker;
24.76 +import org.netbeans.modules.java.hints.providers.spi.HintDescriptionFactory;
24.77 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
24.78 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata.Options;
24.79 +import org.netbeans.modules.java.hints.providers.spi.HintProvider;
24.80 +import org.netbeans.modules.java.hints.providers.spi.Trigger.Kinds;
24.81 +import org.netbeans.modules.java.hints.providers.spi.Trigger.PatternDescription;
24.82 +import org.netbeans.spi.editor.hints.ErrorDescription;
24.83 +import org.netbeans.spi.editor.hints.Severity;
24.84 +import org.netbeans.spi.java.hints.BooleanOption;
24.85 +import org.netbeans.spi.java.hints.ConstraintVariableType;
24.86 +import org.netbeans.spi.java.hints.Hint;
24.87 +import org.netbeans.spi.java.hints.IntegerOption;
24.88 +import org.netbeans.spi.java.hints.TriggerPattern;
24.89 +import org.netbeans.spi.java.hints.TriggerPatterns;
24.90 +import org.netbeans.spi.java.hints.TriggerTreeKind;
24.91 +import org.netbeans.spi.java.hints.UseOptions;
24.92 +import org.openide.util.Exceptions;
24.93 +import org.openide.util.Lookup;
24.94 +import org.openide.util.NbCollections;
24.95 +import org.openide.util.lookup.ServiceProvider;
24.96 +
24.97 +/**
24.98 + *
24.99 + * @author lahvac
24.100 + */
24.101 +@ServiceProvider(service=HintProvider.class)
24.102 +public class CodeHintProviderImpl implements HintProvider {
24.103 +
24.104 + private static final Logger LOG = Logger.getLogger(WorkerImpl.class.getName());
24.105 +
24.106 + public Map<HintMetadata, ? extends Collection<? extends HintDescription>> computeHints() {
24.107 + return computeHints(findLoader(), "META-INF/nb-hints/hints");
24.108 + }
24.109 +
24.110 + private Map<HintMetadata, ? extends Collection<? extends HintDescription>> computeHints(ClassLoader l, String path) {
24.111 + Map<HintMetadata, Collection<HintDescription>> result = new HashMap<HintMetadata, Collection<HintDescription>>();
24.112 +
24.113 + for (ClassWrapper c : FSWrapper.listClasses()) {
24.114 + try {
24.115 + processClass(c, result);
24.116 + } catch (ThreadDeath td) {
24.117 + throw td;
24.118 + } catch (Throwable t) {
24.119 + Exceptions.printStackTrace(t);
24.120 + }
24.121 + }
24.122 +
24.123 + return result;
24.124 + }
24.125 +
24.126 + static ClassLoader findLoader() {
24.127 + ClassLoader l = Lookup.getDefault().lookup(ClassLoader.class);
24.128 +
24.129 + if (l == null) {
24.130 + return CodeHintProviderImpl.class.getClassLoader();
24.131 + }
24.132 +
24.133 + return l;
24.134 + }
24.135 +
24.136 + public static void processClass(ClassWrapper clazz, Map<HintMetadata, Collection<HintDescription>> result) throws SecurityException {
24.137 + Hint metadata = clazz.getAnnotation(Hint.class);
24.138 + HintMetadata hm;
24.139 +
24.140 + if (metadata != null) {
24.141 + String id = metadata.id();
24.142 +
24.143 + if (id == null || id.length() == 0) {
24.144 + id = clazz.getName();
24.145 + }
24.146 + hm = fromAnnotation(id, clazz, null, metadata);
24.147 + } else {
24.148 + hm = null;
24.149 + }
24.150 +
24.151 + for (MethodWrapper m : clazz.getMethods()) {
24.152 + Hint localMetadataAnnotation = m.getAnnotation(Hint.class);
24.153 + HintMetadata localMetadata;
24.154 +
24.155 + if (localMetadataAnnotation != null) {
24.156 + String localID = localMetadataAnnotation.id();
24.157 +
24.158 + if (localID == null || localID.length() == 0) {
24.159 + localID = clazz.getName() + "." + m.getName();
24.160 + }
24.161 +
24.162 + localMetadata = fromAnnotation(localID, clazz, m, localMetadataAnnotation);
24.163 + } else {
24.164 + localMetadata = hm;
24.165 + }
24.166 +
24.167 + if (localMetadata != null) {
24.168 + processMethod(result, m, localMetadata);
24.169 + }
24.170 + }
24.171 + }
24.172 +
24.173 + private static HintMetadata fromAnnotation(String id, ClassWrapper clazz, MethodWrapper method, Hint metadata) {
24.174 + HintMetadata hm = HintMetadata.Builder.create(id)
24.175 + .setDescription(metadata.displayName(), metadata.description())
24.176 + .setCategory(metadata.category())
24.177 + .setEnabled(metadata.enabled())
24.178 + .setSeverity(metadata.severity())
24.179 + .setKind(metadata.hintKind())
24.180 + .setCustomizerProvider(createCustomizerProvider(clazz, method, id, metadata))
24.181 + .addSuppressWarnings(metadata.suppressWarnings())
24.182 + .addOptions(Options.fromHintOptions(metadata.options()).toArray(new Options[0]))
24.183 + .build();
24.184 + return hm;
24.185 + }
24.186 +
24.187 + private static CustomizerProvider createCustomizerProvider(ClassWrapper clazz, MethodWrapper method, String id, Hint hint) {
24.188 + Class<? extends CustomizerProvider> customizerClass = hint.customizerProvider();
24.189 +
24.190 + if (customizerClass != CustomizerProvider.class) {
24.191 + return new DelegatingCustomizerProvider(customizerClass);
24.192 + }
24.193 +
24.194 + Set<String> allowedOptions = null;
24.195 +
24.196 + if (method != null) {
24.197 + UseOptions useOptions = method.getAnnotation(UseOptions.class);
24.198 +
24.199 + if (useOptions == null) return null;
24.200 +
24.201 + allowedOptions = new HashSet<String>(Arrays.asList(useOptions.value()));
24.202 + }
24.203 +
24.204 + List<OptionDescriptor> declarativeOptions = new ArrayList<OptionDescriptor>();
24.205 +
24.206 + for (FieldWrapper fw : clazz.getFields()) {
24.207 + BooleanOption option = fw.getAnnotation(BooleanOption.class);
24.208 + IntegerOption iOption = fw.getAnnotation(IntegerOption.class);
24.209 +
24.210 + String key = fw.getConstantValue();
24.211 +
24.212 + if (key == null) continue;
24.213 + if (allowedOptions != null && !allowedOptions.contains(key)) continue;
24.214 +
24.215 + Object defValue;
24.216 + String displayName;
24.217 + String tooltip;
24.218 + if (option != null) {
24.219 + defValue = option.defaultValue();
24.220 + displayName = option.displayName();
24.221 + tooltip = option.tooltip();
24.222 + } else if (iOption != null) {
24.223 + defValue = iOption.defaultValue();
24.224 + displayName = iOption.displayName();
24.225 + tooltip = iOption.tooltip();
24.226 + } else {
24.227 + return null;
24.228 + }
24.229 +
24.230 + declarativeOptions.add(
24.231 + new OptionDescriptor(
24.232 + key,
24.233 + defValue,
24.234 + displayName,
24.235 + tooltip,
24.236 + option != null ? option : iOption)
24.237 + );
24.238 + }
24.239 +
24.240 + return !declarativeOptions.isEmpty() ? new ReflectiveCustomizerProvider(clazz.getName(), id, declarativeOptions) : null;
24.241 + }
24.242 +
24.243 + static void processMethod(Map<HintMetadata, Collection<HintDescription>> hints, MethodWrapper m, HintMetadata metadata) {
24.244 + //XXX: combinations of TriggerTreeKind and TriggerPattern?
24.245 + processTreeKindHint(hints, m, metadata);
24.246 + processPatternHint(hints, m, metadata);
24.247 + }
24.248 +
24.249 + private static void processTreeKindHint(Map<HintMetadata, Collection<HintDescription>> hints, MethodWrapper m, HintMetadata metadata) {
24.250 + TriggerTreeKind kindTrigger = m.getAnnotation(TriggerTreeKind.class);
24.251 +
24.252 + if (kindTrigger == null) {
24.253 + return ;
24.254 + }
24.255 +
24.256 + Worker w = new WorkerImpl(m.getClazz().getName(), m.getName());
24.257 +
24.258 + Set<Kind> kinds = EnumSet.noneOf(Kind.class);
24.259 +
24.260 + kinds.addAll(Arrays.asList(kindTrigger.value()));
24.261 +
24.262 + addHint(hints, metadata, HintDescriptionFactory.create()
24.263 + .setTrigger(new Kinds(kinds))
24.264 + .setWorker(w)
24.265 + .setMetadata(metadata)
24.266 + .produce());
24.267 + }
24.268 +
24.269 + private static void processPatternHint(Map<HintMetadata, Collection<HintDescription>> hints, MethodWrapper m, HintMetadata metadata) {
24.270 + TriggerPattern patternTrigger = m.getAnnotation(TriggerPattern.class);
24.271 +
24.272 + if (patternTrigger != null) {
24.273 + processPatternHint(hints, patternTrigger, m, metadata);
24.274 + return ;
24.275 + }
24.276 +
24.277 + TriggerPatterns patternTriggers = m.getAnnotation(TriggerPatterns.class);
24.278 +
24.279 + if (patternTriggers != null) {
24.280 + for (TriggerPattern pattern : patternTriggers.value()) {
24.281 + processPatternHint(hints, pattern, m, metadata);
24.282 + }
24.283 + return ;
24.284 + }
24.285 + }
24.286 +
24.287 + private static void processPatternHint(Map<HintMetadata, Collection<HintDescription>> hints, TriggerPattern patternTrigger, MethodWrapper m, HintMetadata metadata) {
24.288 + String pattern = patternTrigger.value();
24.289 + Map<String, String> constraints = new HashMap<String, String>();
24.290 +
24.291 + for (ConstraintVariableType c : patternTrigger.constraints()) {
24.292 + constraints.put(c.variable(), c.type());
24.293 + }
24.294 +
24.295 + PatternDescription pd = PatternDescription.create(pattern, constraints);
24.296 +
24.297 + addHint(hints, metadata, HintDescriptionFactory.create()
24.298 + .setTrigger(pd)
24.299 + .setWorker(new WorkerImpl(m.getClazz().getName(), m.getName()))
24.300 + .setMetadata(metadata)
24.301 + .produce());
24.302 + }
24.303 +
24.304 + private static void addHint(Map<HintMetadata, Collection<HintDescription>> hints, HintMetadata metadata, HintDescription hint) {
24.305 + Collection<HintDescription> list = hints.get(metadata);
24.306 +
24.307 + if (list == null) {
24.308 + hints.put(metadata, list = new LinkedList<HintDescription>());
24.309 + }
24.310 +
24.311 + list.add(hint);
24.312 + }
24.313 +
24.314 + //accessed by tests:
24.315 + static final class WorkerImpl implements Worker {
24.316 +
24.317 + private final String className;
24.318 + private final String methodName;
24.319 +
24.320 + public WorkerImpl(String className, String methodName) {
24.321 + this.className = className;
24.322 + this.methodName = methodName;
24.323 + }
24.324 +
24.325 + private final AtomicReference<Method> methodRef = new AtomicReference<Method>();
24.326 +
24.327 + public Collection<? extends ErrorDescription> createErrors(org.netbeans.spi.java.hints.HintContext ctx) {
24.328 + try {
24.329 + Method method = methodRef.get();
24.330 +
24.331 + if (method == null) {
24.332 + methodRef.set(method = getMethod());
24.333 + }
24.334 +
24.335 + Object result = method.invoke(null, ctx);
24.336 +
24.337 + if (result == null) {
24.338 + return null;
24.339 + }
24.340 +
24.341 + if (result instanceof Iterable) {
24.342 + List<ErrorDescription> out = new LinkedList<ErrorDescription>();
24.343 +
24.344 + for (ErrorDescription ed : NbCollections.iterable(NbCollections.checkedIteratorByFilter(((Iterable) result).iterator(), ErrorDescription.class, false))) {
24.345 + out.add(ed);
24.346 + }
24.347 +
24.348 + return out;
24.349 + }
24.350 +
24.351 + if (result instanceof ErrorDescription) {
24.352 + return Collections.singletonList((ErrorDescription) result);
24.353 + }
24.354 +
24.355 + //XXX: log if result was ignored...
24.356 + } catch (IllegalAccessException ex) {
24.357 + Exceptions.printStackTrace(ex);
24.358 + } catch (IllegalArgumentException ex) {
24.359 + Exceptions.printStackTrace(ex);
24.360 + } catch (ClassNotFoundException ex) {
24.361 + Exceptions.printStackTrace(ex);
24.362 + } catch (NoSuchMethodException ex) {
24.363 + Exceptions.printStackTrace(ex);
24.364 + } catch (InvocationTargetException ex) {
24.365 + LOG.log(Level.INFO, className + "." + methodName, ex);
24.366 + //so that the exceptions are categorized better:
24.367 + Exceptions.printStackTrace(ex.getCause());
24.368 + }
24.369 +
24.370 + return null;
24.371 + }
24.372 +
24.373 + //used by tests:
24.374 + Method getMethod() throws NoSuchMethodException, ClassNotFoundException {
24.375 + return FSWrapper.resolveMethod(className, methodName);
24.376 + }
24.377 +
24.378 + }
24.379 +
24.380 + private static final class EmptyHintMetadataDescription implements Hint {
24.381 +
24.382 + public String id() {
24.383 + return "";
24.384 + }
24.385 +
24.386 + public String category() {
24.387 + return "general";
24.388 + }
24.389 +
24.390 + public boolean enabled() {
24.391 + return true;
24.392 + }
24.393 +
24.394 + public Severity severity() {
24.395 + return Severity.VERIFIER;
24.396 + }
24.397 +
24.398 + private static final String[] EMPTY_SW = new String[0];
24.399 +
24.400 + public String[] suppressWarnings() {
24.401 + return EMPTY_SW;
24.402 + }
24.403 +
24.404 + public Class<? extends Annotation> annotationType() {
24.405 + return Hint.class;
24.406 + }
24.407 +
24.408 + public Class<? extends CustomizerProvider> customizerProvider() {
24.409 + return CustomizerProvider.class;
24.410 + }
24.411 +
24.412 + public Kind hintKind() {
24.413 + return Kind.INSPECTION;
24.414 + }
24.415 +
24.416 + private static final Options[] EMPTY_OPTIONS = new Options[0];
24.417 +
24.418 + public Options[] options() {
24.419 + return EMPTY_OPTIONS;
24.420 + }
24.421 +
24.422 + @Override public String displayName() {
24.423 + return "";
24.424 + }
24.425 +
24.426 + @Override public String description() {
24.427 + return "";
24.428 + }
24.429 +
24.430 + }
24.431 +
24.432 + private static final class DelegatingCustomizerProvider implements CustomizerProvider {
24.433 +
24.434 + private final Class<? extends CustomizerProvider> component;
24.435 +
24.436 + public DelegatingCustomizerProvider(Class<? extends CustomizerProvider> component) {
24.437 + this.component = component;
24.438 + }
24.439 +
24.440 + @Override
24.441 + public JComponent getCustomizer(Preferences prefs) {
24.442 + try {
24.443 + return component.newInstance().getCustomizer(prefs);
24.444 + } catch (SecurityException ex) {
24.445 + Exceptions.printStackTrace(ex);
24.446 + } catch (InstantiationException ex) {
24.447 + Exceptions.printStackTrace(ex);
24.448 + } catch (IllegalAccessException ex) {
24.449 + Exceptions.printStackTrace(ex);
24.450 + } catch (IllegalArgumentException ex) {
24.451 + Exceptions.printStackTrace(ex);
24.452 + }
24.453 +
24.454 + return new JPanel();
24.455 + }
24.456 +
24.457 + }
24.458 +
24.459 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/code/FSWrapper.java Wed May 08 21:47:42 2013 +0200
25.3 @@ -0,0 +1,319 @@
25.4 +/*
25.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
25.6 + *
25.7 + * Copyright 2010-2011 Oracle and/or its affiliates. All rights reserved.
25.8 + *
25.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
25.10 + * Other names may be trademarks of their respective owners.
25.11 + *
25.12 + * The contents of this file are subject to the terms of either the GNU
25.13 + * General Public License Version 2 only ("GPL") or the Common
25.14 + * Development and Distribution License("CDDL") (collectively, the
25.15 + * "License"). You may not use this file except in compliance with the
25.16 + * License. You can obtain a copy of the License at
25.17 + * http://www.netbeans.org/cddl-gplv2.html
25.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
25.19 + * specific language governing permissions and limitations under the
25.20 + * License. When distributing the software, include this License Header
25.21 + * Notice in each file and include the License file at
25.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
25.23 + * particular file as subject to the "Classpath" exception as provided
25.24 + * by Oracle in the GPL Version 2 section of the License file that
25.25 + * accompanied this code. If applicable, add the following below the
25.26 + * License Header, with the fields enclosed by brackets [] replaced by
25.27 + * your own identifying information:
25.28 + * "Portions Copyrighted [year] [name of copyright owner]"
25.29 + *
25.30 + * If you wish your version of this file to be governed by only the CDDL
25.31 + * or only the GPL Version 2, indicate your decision by adding
25.32 + * "[Contributor] elects to include this software in this distribution
25.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
25.34 + * single choice of license, a recipient has the option to distribute
25.35 + * your version of this file under either the CDDL, the GPL Version 2 or
25.36 + * to extend the choice of license to its licensees as provided above.
25.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
25.38 + * Version 2 license, then the option applies only if the new code is
25.39 + * made subject to such option by the copyright holder.
25.40 + *
25.41 + * Contributor(s):
25.42 + *
25.43 + * Portions Copyrighted 2010-2011 Sun Microsystems, Inc.
25.44 + */
25.45 +
25.46 +package org.netbeans.modules.java.hints.providers.code;
25.47 +
25.48 +import java.lang.annotation.Annotation;
25.49 +import java.lang.reflect.Array;
25.50 +import java.lang.reflect.InvocationHandler;
25.51 +import java.lang.reflect.Method;
25.52 +import java.lang.reflect.Proxy;
25.53 +import java.util.HashMap;
25.54 +import java.util.LinkedList;
25.55 +import java.util.List;
25.56 +import java.util.Map;
25.57 +import java.util.logging.Level;
25.58 +import java.util.logging.Logger;
25.59 +import org.netbeans.spi.java.hints.HintContext;
25.60 +import org.openide.filesystems.FileObject;
25.61 +import org.openide.filesystems.FileUtil;
25.62 +import org.openide.util.Exceptions;
25.63 +
25.64 +/**
25.65 + *
25.66 + * @author lahvac
25.67 + */
25.68 +public class FSWrapper {
25.69 +
25.70 + public static Iterable<? extends ClassWrapper> listClasses() {
25.71 + ClassLoader loader = FSWrapper.class.getClassLoader();
25.72 +
25.73 + if (loader == null) {
25.74 + loader = ClassLoader.getSystemClassLoader();
25.75 + }
25.76 +
25.77 + List<ClassWrapper> result = new LinkedList<ClassWrapper>();
25.78 + FileObject main = FileUtil.getConfigFile("org-netbeans-modules-java-hints/code-hints/");
25.79 +
25.80 + if (main != null) {
25.81 + for (FileObject c : main.getChildren()) {
25.82 + result.add(new ClassWrapper(loader, c));
25.83 + }
25.84 + }
25.85 +
25.86 + return result;
25.87 + }
25.88 +
25.89 + public static Method resolveMethod(String className, String methodName) throws NoSuchMethodException, ClassNotFoundException {
25.90 + Class<?> clazz = CodeHintProviderImpl.findLoader().loadClass(className);
25.91 +
25.92 + return clazz.getDeclaredMethod(methodName, HintContext.class);
25.93 + }
25.94 +
25.95 + public static class AnnotatableWrapper {
25.96 + protected final ClassLoader loader;
25.97 + protected final FileObject folder;
25.98 + protected AnnotatableWrapper(ClassLoader loader, FileObject folder) {
25.99 + this.loader = loader;
25.100 + this.folder = folder;
25.101 + }
25.102 +
25.103 + private final Map<Class<? extends Annotation>, Annotation> annotations = new HashMap<Class<? extends Annotation>, Annotation>();
25.104 +
25.105 + public synchronized <T extends Annotation> T getAnnotation(Class<T> annotationClass) {
25.106 + if (!this.annotations.containsKey(annotationClass)) {
25.107 + FileObject f = folder.getFileObject(annotationClass.getName().replace('.', '-') + ".annotation");
25.108 + T result = null;
25.109 +
25.110 + if (f != null) {
25.111 + try {
25.112 + Annotation a = loadAnnotation(loader, f);
25.113 +
25.114 + result = annotationClass.cast(a);
25.115 + } catch (ClassNotFoundException ex) {
25.116 + Exceptions.printStackTrace(ex);
25.117 + }
25.118 + }
25.119 +
25.120 + this.annotations.put(annotationClass, result);
25.121 + }
25.122 +
25.123 + return annotationClass.cast(this.annotations.get(annotationClass));
25.124 + }
25.125 + }
25.126 +
25.127 + public static class ClassWrapper extends AnnotatableWrapper {
25.128 + private final String className;
25.129 + public ClassWrapper(ClassLoader loader, FileObject folder) {
25.130 + super(loader, folder);
25.131 + className = folder.getName().replace('-', '.');
25.132 + }
25.133 +
25.134 + private Iterable<? extends MethodWrapper> methods;
25.135 +
25.136 + public synchronized Iterable<? extends MethodWrapper> getMethods() {
25.137 + if (this.methods == null) {
25.138 + List<MethodWrapper> methods = new LinkedList<MethodWrapper>();
25.139 +
25.140 + for (FileObject c : folder.getChildren()) {
25.141 + if (c.getExt().equals("method")) {
25.142 + methods.add(new MethodWrapper(loader, c, this));
25.143 + }
25.144 + }
25.145 +
25.146 + this.methods = methods;
25.147 + }
25.148 +
25.149 + return this.methods;
25.150 + }
25.151 +
25.152 + private Iterable<? extends FieldWrapper> fields;
25.153 +
25.154 + public synchronized Iterable<? extends FieldWrapper> getFields() {
25.155 + if (this.fields == null) {
25.156 + List<FieldWrapper> fields = new LinkedList<FieldWrapper>();
25.157 +
25.158 + for (FileObject c : folder.getChildren()) {
25.159 + if (c.getExt().equals("field")) {
25.160 + fields.add(new FieldWrapper(loader, c, this));
25.161 + }
25.162 + }
25.163 +
25.164 + this.fields = fields;
25.165 + }
25.166 +
25.167 + return this.fields;
25.168 + }
25.169 +
25.170 + public String getName() {
25.171 + return className;
25.172 + }
25.173 +
25.174 + private Class<?> clazz;
25.175 + public synchronized Class<?> getDeclaredClass() {
25.176 + if (clazz != null) {
25.177 + return clazz;
25.178 + }
25.179 +
25.180 + try {
25.181 + return this.clazz = loader.loadClass(className);
25.182 + } catch (ClassNotFoundException ex) {
25.183 + Exceptions.printStackTrace(ex);
25.184 + }
25.185 +
25.186 + return null; //XXX
25.187 + }
25.188 + }
25.189 +
25.190 + public static class MethodWrapper extends AnnotatableWrapper {
25.191 + private final ClassWrapper clazz;
25.192 + public MethodWrapper(ClassLoader loader, FileObject folder, ClassWrapper clazz) {
25.193 + super(loader, folder);
25.194 + this.clazz = clazz;
25.195 + }
25.196 +
25.197 + ClassWrapper getClazz() {
25.198 + return clazz;
25.199 + }
25.200 +
25.201 + String getName() {
25.202 + return folder.getName();
25.203 + }
25.204 + }
25.205 +
25.206 + public static class FieldWrapper extends AnnotatableWrapper {
25.207 + private final ClassWrapper clazz;
25.208 + public FieldWrapper(ClassLoader loader, FileObject folder, ClassWrapper clazz) {
25.209 + super(loader, folder);
25.210 + this.clazz = clazz;
25.211 + }
25.212 +
25.213 + ClassWrapper getClazz() {
25.214 + return clazz;
25.215 + }
25.216 +
25.217 + String getName() {
25.218 + return folder.getName();
25.219 + }
25.220 +
25.221 + String getConstantValue() {
25.222 + Object constantValue = folder.getAttribute("constantValue");
25.223 +
25.224 + if (constantValue instanceof String) {
25.225 + return (String) constantValue;
25.226 + }
25.227 +
25.228 + return null;
25.229 + }
25.230 + }
25.231 +
25.232 + private static final Object MARKER = new Object();
25.233 +
25.234 + private static Object computeAttributeValue(ClassLoader loader, FileObject folder, String attributeName, Class<?> returnType, Object defaulValue) throws ClassNotFoundException {
25.235 + Object result = folder.getAttribute(attributeName);
25.236 +
25.237 + if (result == null) {
25.238 + FileObject embedded = folder.getFileObject(attributeName);
25.239 +
25.240 + if (embedded == null) {
25.241 + result = defaulValue;
25.242 + } else {
25.243 + if (returnType.isArray()) {
25.244 + List<Object> items = new LinkedList<Object>();
25.245 + int c = 0;
25.246 +
25.247 + while (true) {
25.248 + Object val = computeAttributeValue(loader, embedded, "item" + c, returnType.getComponentType(), MARKER);
25.249 +
25.250 + if (val == MARKER) {
25.251 + break;
25.252 + }
25.253 +
25.254 + items.add(val);
25.255 + c++;
25.256 + }
25.257 +
25.258 + Object res = Array.newInstance(returnType.getComponentType(), items.size());
25.259 + int ci = 0;
25.260 +
25.261 + for (Object i : items) {
25.262 + Array.set(res, ci++, i);
25.263 + }
25.264 +
25.265 + result = res;
25.266 + } else if (returnType.isAnnotation()) {
25.267 + result = loadAnnotation(loader, embedded.getChildren()[0]);
25.268 + }
25.269 + }
25.270 + } else {
25.271 + if (returnType.isEnum()) {
25.272 + String fqn = (String) result;
25.273 + int lastDot = fqn.lastIndexOf('.');
25.274 + Class<? extends Enum> enumClass = (Class<? extends Enum>) loader.loadClass(fqn.substring(0, lastDot));
25.275 +
25.276 + result = Enum.valueOf(enumClass, fqn.substring(lastDot + 1));
25.277 + } else if (returnType == Class.class) {
25.278 + String fqn = (String) result;
25.279 +
25.280 + try {
25.281 + result = loader.loadClass(fqn);
25.282 + } catch (ClassNotFoundException ex) {
25.283 + Logger.getLogger(FSWrapper.class.getName()).log(Level.FINE, null, ex);
25.284 + result = CodeHintProviderImpl.findLoader().loadClass(fqn);
25.285 + }
25.286 + }
25.287 + }
25.288 +
25.289 + return result;
25.290 + }
25.291 +
25.292 +
25.293 + private static <T extends Annotation> T loadAnnotation(ClassLoader l, FileObject annotationFolder) throws ClassNotFoundException {
25.294 + Class<?> clazz = l.loadClass(annotationFolder.getName().replace('-', '.'));
25.295 +
25.296 + return (T) Proxy.newProxyInstance(l, new Class[] {clazz}, new InvocationHandlerImpl(l, annotationFolder));
25.297 + }
25.298 +
25.299 + private static final class InvocationHandlerImpl implements InvocationHandler {
25.300 +
25.301 + private final ClassLoader loader;
25.302 + private final FileObject folder;
25.303 + private final Map<String, Object> attributes = new HashMap<String, Object>();
25.304 +
25.305 + public InvocationHandlerImpl(ClassLoader loader, FileObject folder) {
25.306 + this.loader = loader;
25.307 + this.folder = folder;
25.308 + }
25.309 +
25.310 + public synchronized Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
25.311 + if (!attributes.containsKey(method.getName())) {
25.312 + Object result = computeAttributeValue(loader, folder, method.getName(), method.getReturnType(), method.getDefaultValue());
25.313 +
25.314 + attributes.put(method.getName(), result);
25.315 + }
25.316 +
25.317 + return attributes.get(method.getName());
25.318 + }
25.319 +
25.320 + }
25.321 +
25.322 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/code/ReflectiveCustomizerProvider.java Wed May 08 21:47:42 2013 +0200
26.3 @@ -0,0 +1,261 @@
26.4 +/*
26.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
26.6 + *
26.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
26.8 + *
26.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
26.10 + * Other names may be trademarks of their respective owners.
26.11 + *
26.12 + * The contents of this file are subject to the terms of either the GNU
26.13 + * General Public License Version 2 only ("GPL") or the Common
26.14 + * Development and Distribution License("CDDL") (collectively, the
26.15 + * "License"). You may not use this file except in compliance with the
26.16 + * License. You can obtain a copy of the License at
26.17 + * http://www.netbeans.org/cddl-gplv2.html
26.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
26.19 + * specific language governing permissions and limitations under the
26.20 + * License. When distributing the software, include this License Header
26.21 + * Notice in each file and include the License file at
26.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
26.23 + * particular file as subject to the "Classpath" exception as provided
26.24 + * by Oracle in the GPL Version 2 section of the License file that
26.25 + * accompanied this code. If applicable, add the following below the
26.26 + * License Header, with the fields enclosed by brackets [] replaced by
26.27 + * your own identifying information:
26.28 + * "Portions Copyrighted [year] [name of copyright owner]"
26.29 + *
26.30 + * If you wish your version of this file to be governed by only the CDDL
26.31 + * or only the GPL Version 2, indicate your decision by adding
26.32 + * "[Contributor] elects to include this software in this distribution
26.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
26.34 + * single choice of license, a recipient has the option to distribute
26.35 + * your version of this file under either the CDDL, the GPL Version 2 or
26.36 + * to extend the choice of license to its licensees as provided above.
26.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
26.38 + * Version 2 license, then the option applies only if the new code is
26.39 + * made subject to such option by the copyright holder.
26.40 + *
26.41 + * Contributor(s):
26.42 + *
26.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
26.44 + */
26.45 +package org.netbeans.modules.java.hints.providers.code;
26.46 +
26.47 +import java.awt.GridBagConstraints;
26.48 +import java.awt.GridBagLayout;
26.49 +import java.awt.Insets;
26.50 +import java.awt.event.ActionEvent;
26.51 +import java.awt.event.ActionListener;
26.52 +import java.util.List;
26.53 +import java.util.prefs.Preferences;
26.54 +import javax.swing.JCheckBox;
26.55 +import javax.swing.JComponent;
26.56 +import javax.swing.JFormattedTextField;
26.57 +import javax.swing.JLabel;
26.58 +import javax.swing.JPanel;
26.59 +import javax.swing.JSpinner;
26.60 +import javax.swing.SpinnerNumberModel;
26.61 +import javax.swing.event.ChangeEvent;
26.62 +import javax.swing.event.ChangeListener;
26.63 +import javax.swing.text.NumberFormatter;
26.64 +import org.netbeans.spi.java.hints.BooleanOption;
26.65 +import org.netbeans.spi.java.hints.CustomizerProvider;
26.66 +import org.netbeans.spi.java.hints.IntegerOption;
26.67 +import org.openide.util.Exceptions;
26.68 +
26.69 +/**
26.70 + *
26.71 + * @author lahvac
26.72 + */
26.73 +public class ReflectiveCustomizerProvider implements CustomizerProvider {
26.74 + private final String hintClassName;
26.75 + private final String hintId;
26.76 + private final List<OptionDescriptor> options;
26.77 +
26.78 + public ReflectiveCustomizerProvider(String hintClassName, String hintId, List<OptionDescriptor> options) {
26.79 + this.hintClassName = hintClassName;
26.80 + this.hintId = hintId;
26.81 + this.options = options;
26.82 + }
26.83 +
26.84 + @Override
26.85 + public JComponent getCustomizer(Preferences prefs) {
26.86 + return new CustomizerImpl(prefs, hintClassName, hintId, options);
26.87 + }
26.88 +
26.89 + private static final class CustomizerImpl extends JPanel {
26.90 + private int row;
26.91 +
26.92 + public CustomizerImpl(Preferences prefs, String hintClassName, String hintId, List<OptionDescriptor> options) {
26.93 + try {
26.94 + setLayout(new GridBagLayout());
26.95 + row = 0;
26.96 +
26.97 + for (OptionDescriptor option : options) {
26.98 + if (option.parameters instanceof IntegerOption) {
26.99 + createIntegerOption(option, prefs);
26.100 + }
26.101 + }
26.102 +
26.103 + for (OptionDescriptor option : options) {
26.104 + if (option.parameters instanceof BooleanOption) {
26.105 + createBooleanOption(option, prefs);
26.106 + }
26.107 + }
26.108 +
26.109 + GridBagConstraints constraints = new GridBagConstraints();
26.110 +
26.111 + constraints.anchor = GridBagConstraints.NORTHWEST;
26.112 + constraints.fill = GridBagConstraints.BOTH;
26.113 + constraints.gridheight = 1;
26.114 + constraints.gridwidth = GridBagConstraints.REMAINDER;
26.115 + constraints.gridx = 0;
26.116 + constraints.gridy = row++;
26.117 + constraints.weightx = 1;
26.118 + constraints.weighty = 1;
26.119 +
26.120 + add(new JPanel(), constraints);
26.121 + } catch (IllegalArgumentException ex) {
26.122 + Exceptions.printStackTrace(ex);
26.123 + } catch (SecurityException ex) {
26.124 + Exceptions.printStackTrace(ex);
26.125 + }
26.126 + }
26.127 +
26.128 + private void createIntegerOption(OptionDescriptor option, Preferences prefs) {
26.129 + IntegerOption iopt = (IntegerOption)option.parameters;
26.130 + JLabel l = new JLabel();
26.131 + org.openide.awt.Mnemonics.setLocalizedText(l, option.displayName + ":");
26.132 +
26.133 + GridBagConstraints constraints = new GridBagConstraints();
26.134 + constraints.anchor = GridBagConstraints.WEST;
26.135 + constraints.fill = GridBagConstraints.NONE;
26.136 + constraints.gridheight = 1;
26.137 + constraints.gridwidth = 1;
26.138 + constraints.gridx = 0;
26.139 + constraints.gridy = row;
26.140 + constraints.weightx = 0;
26.141 + constraints.weighty = 0;
26.142 + constraints.insets = new Insets(0, 0, 0, 8);
26.143 +
26.144 + add(l, constraints);
26.145 +
26.146 + JComponent field;
26.147 + int val = prefs.getInt(option.preferencesKey, ((Integer)option.defaultValue).intValue());
26.148 + if (iopt.step() > 0) {
26.149 + val = Math.min(iopt.maxValue(), Math.max(iopt.minValue(), val));
26.150 + JSpinner spinner = new JSpinner(
26.151 + new SpinnerNumberModel(val, iopt.minValue(), iopt.maxValue(), iopt.step()));
26.152 + spinner.addChangeListener(new ActionListenerImpl(option.preferencesKey, prefs));
26.153 + field = spinner;
26.154 + } else {
26.155 + NumberFormatter nf = new NumberFormatter();
26.156 + nf.setValueClass(Integer.class);
26.157 + nf.setMaximum(iopt.maxValue());
26.158 + nf.setMinimum(iopt.minValue());
26.159 + JFormattedTextField formatted = new JFormattedTextField(nf);
26.160 + field = formatted;
26.161 + }
26.162 + if (option.tooltip != null && !option.tooltip.isEmpty()) {
26.163 + field.setToolTipText(option.tooltip);
26.164 + }
26.165 + constraints = new GridBagConstraints();
26.166 + constraints.anchor = GridBagConstraints.WEST;
26.167 + constraints.fill = GridBagConstraints.HORIZONTAL;
26.168 + constraints.gridheight = 1;
26.169 + constraints.gridwidth = 1;
26.170 + constraints.gridx = 1;
26.171 + constraints.gridy = row;
26.172 + constraints.weightx = 0;
26.173 + constraints.weighty = 0;
26.174 +
26.175 + add(field, constraints);
26.176 +
26.177 + constraints = new GridBagConstraints();
26.178 + constraints.anchor = GridBagConstraints.WEST;
26.179 + constraints.fill = GridBagConstraints.HORIZONTAL;
26.180 + constraints.gridheight = 1;
26.181 + constraints.gridwidth = GridBagConstraints.REMAINDER;
26.182 + constraints.gridx = 2;
26.183 + constraints.gridy = row++;
26.184 + constraints.weightx = 1;
26.185 + constraints.weighty = 0;
26.186 +
26.187 + add(new JPanel(), constraints);
26.188 + }
26.189 +
26.190 + private JComponent createBooleanOption(OptionDescriptor option, Preferences prefs) {
26.191 + JCheckBox checkBox = new JCheckBox();
26.192 +
26.193 + org.openide.awt.Mnemonics.setLocalizedText(checkBox, option.displayName);
26.194 + checkBox.setToolTipText(option.tooltip);
26.195 + checkBox.addActionListener(new ActionListenerImpl(option.preferencesKey, prefs));
26.196 +
26.197 + checkBox.setSelected(prefs.getBoolean(option.preferencesKey,
26.198 + Boolean.TRUE == option.defaultValue));
26.199 + GridBagConstraints constraints = new GridBagConstraints();
26.200 +
26.201 + constraints.anchor = GridBagConstraints.WEST;
26.202 + constraints.fill = GridBagConstraints.NONE;
26.203 + constraints.gridheight = 1;
26.204 + constraints.gridwidth = 2;
26.205 + constraints.gridx = 0;
26.206 + constraints.gridy = row++;
26.207 + constraints.weightx = 0;
26.208 + constraints.weighty = 0;
26.209 +
26.210 + add(checkBox, constraints);
26.211 + return checkBox;
26.212 + }
26.213 +
26.214 +
26.215 + private static final class ActionListenerImpl implements ActionListener, ChangeListener {
26.216 + private final String key;
26.217 + private final Preferences prefs;
26.218 +
26.219 + public ActionListenerImpl(String key, Preferences prefs) {
26.220 + this.key = key;
26.221 + this.prefs = prefs;
26.222 + }
26.223 +
26.224 + @Override
26.225 + public void actionPerformed(ActionEvent e) {
26.226 + JCheckBox checkBox = ((JCheckBox)e.getSource());
26.227 + prefs.putBoolean(key, checkBox.isSelected());
26.228 + }
26.229 +
26.230 + @Override
26.231 + public void stateChanged(ChangeEvent e) {
26.232 + Integer i = (Integer)((JSpinner)e.getSource()).getValue();
26.233 + prefs.putInt(key, i);
26.234 + }
26.235 +
26.236 + }
26.237 +
26.238 + }
26.239 +
26.240 + public static final class OptionDescriptor {
26.241 + public final String preferencesKey;
26.242 + public final Object defaultValue;
26.243 + public final String displayName;
26.244 + public final String tooltip;
26.245 + /**
26.246 + * The original Annotation object, type-specific parameters.
26.247 + */
26.248 + public final Object parameters;
26.249 +
26.250 + public OptionDescriptor(
26.251 + String preferencesKey,
26.252 + Object defaultValue,
26.253 + String displayName, String tooltip,
26.254 + Object parameters) {
26.255 + this.preferencesKey = preferencesKey;
26.256 + this.defaultValue = defaultValue;
26.257 + this.displayName = displayName;
26.258 + this.tooltip = tooltip;
26.259 + this.parameters = parameters;
26.260 + }
26.261 +
26.262 + }
26.263 +
26.264 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/spi/ClassPathBasedHintProvider.java Wed May 08 21:47:42 2013 +0200
27.3 @@ -0,0 +1,57 @@
27.4 +/*
27.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
27.6 + *
27.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
27.8 + *
27.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
27.10 + * Other names may be trademarks of their respective owners.
27.11 + *
27.12 + * The contents of this file are subject to the terms of either the GNU
27.13 + * General Public License Version 2 only ("GPL") or the Common
27.14 + * Development and Distribution License("CDDL") (collectively, the
27.15 + * "License"). You may not use this file except in compliance with the
27.16 + * License. You can obtain a copy of the License at
27.17 + * http://www.netbeans.org/cddl-gplv2.html
27.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
27.19 + * specific language governing permissions and limitations under the
27.20 + * License. When distributing the software, include this License Header
27.21 + * Notice in each file and include the License file at
27.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
27.23 + * particular file as subject to the "Classpath" exception as provided
27.24 + * by Oracle in the GPL Version 2 section of the License file that
27.25 + * accompanied this code. If applicable, add the following below the
27.26 + * License Header, with the fields enclosed by brackets [] replaced by
27.27 + * your own identifying information:
27.28 + * "Portions Copyrighted [year] [name of copyright owner]"
27.29 + *
27.30 + * If you wish your version of this file to be governed by only the CDDL
27.31 + * or only the GPL Version 2, indicate your decision by adding
27.32 + * "[Contributor] elects to include this software in this distribution
27.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
27.34 + * single choice of license, a recipient has the option to distribute
27.35 + * your version of this file under either the CDDL, the GPL Version 2 or
27.36 + * to extend the choice of license to its licensees as provided above.
27.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
27.38 + * Version 2 license, then the option applies only if the new code is
27.39 + * made subject to such option by the copyright holder.
27.40 + *
27.41 + * Contributor(s):
27.42 + *
27.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
27.44 + */
27.45 +
27.46 +package org.netbeans.modules.java.hints.providers.spi;
27.47 +
27.48 +import java.util.Collection;
27.49 +import org.netbeans.api.java.classpath.ClassPath;
27.50 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
27.51 +
27.52 +/**
27.53 + * XXX: this is another ugly hack!
27.54 + * @author lahvac
27.55 + */
27.56 +public interface ClassPathBasedHintProvider {
27.57 +
27.58 + public Collection<? extends HintDescription> computeHints(ClassPath cp);
27.59 +
27.60 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/spi/ElementBasedHintProvider.java Wed May 08 21:47:42 2013 +0200
28.3 @@ -0,0 +1,57 @@
28.4 +/*
28.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
28.6 + *
28.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
28.8 + *
28.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
28.10 + * Other names may be trademarks of their respective owners.
28.11 + *
28.12 + * The contents of this file are subject to the terms of either the GNU
28.13 + * General Public License Version 2 only ("GPL") or the Common
28.14 + * Development and Distribution License("CDDL") (collectively, the
28.15 + * "License"). You may not use this file except in compliance with the
28.16 + * License. You can obtain a copy of the License at
28.17 + * http://www.netbeans.org/cddl-gplv2.html
28.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
28.19 + * specific language governing permissions and limitations under the
28.20 + * License. When distributing the software, include this License Header
28.21 + * Notice in each file and include the License file at
28.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
28.23 + * particular file as subject to the "Classpath" exception as provided
28.24 + * by Oracle in the GPL Version 2 section of the License file that
28.25 + * accompanied this code. If applicable, add the following below the
28.26 + * License Header, with the fields enclosed by brackets [] replaced by
28.27 + * your own identifying information:
28.28 + * "Portions Copyrighted [year] [name of copyright owner]"
28.29 + *
28.30 + * If you wish your version of this file to be governed by only the CDDL
28.31 + * or only the GPL Version 2, indicate your decision by adding
28.32 + * "[Contributor] elects to include this software in this distribution
28.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
28.34 + * single choice of license, a recipient has the option to distribute
28.35 + * your version of this file under either the CDDL, the GPL Version 2 or
28.36 + * to extend the choice of license to its licensees as provided above.
28.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
28.38 + * Version 2 license, then the option applies only if the new code is
28.39 + * made subject to such option by the copyright holder.
28.40 + *
28.41 + * Contributor(s):
28.42 + *
28.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
28.44 + */
28.45 +
28.46 +package org.netbeans.modules.java.hints.providers.spi;
28.47 +
28.48 +import java.util.Collection;
28.49 +import org.netbeans.api.java.source.CompilationInfo;
28.50 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
28.51 +
28.52 +/**
28.53 + * XXX: this is an ugly hack!
28.54 + * @author lahvac
28.55 + */
28.56 +public interface ElementBasedHintProvider {
28.57 +
28.58 + public Collection<? extends HintDescription> computeHints(CompilationInfo info);
28.59 +
28.60 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/spi/HintDescription.java Wed May 08 21:47:42 2013 +0200
29.3 @@ -0,0 +1,127 @@
29.4 +/*
29.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
29.6 + *
29.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
29.8 + *
29.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
29.10 + * Other names may be trademarks of their respective owners.
29.11 + *
29.12 + * The contents of this file are subject to the terms of either the GNU
29.13 + * General Public License Version 2 only ("GPL") or the Common
29.14 + * Development and Distribution License("CDDL") (collectively, the
29.15 + * "License"). You may not use this file except in compliance with the
29.16 + * License. You can obtain a copy of the License at
29.17 + * http://www.netbeans.org/cddl-gplv2.html
29.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
29.19 + * specific language governing permissions and limitations under the
29.20 + * License. When distributing the software, include this License Header
29.21 + * Notice in each file and include the License file at
29.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
29.23 + * particular file as subject to the "Classpath" exception as provided
29.24 + * by Oracle in the GPL Version 2 section of the License file that
29.25 + * accompanied this code. If applicable, add the following below the
29.26 + * License Header, with the fields enclosed by brackets [] replaced by
29.27 + * your own identifying information:
29.28 + * "Portions Copyrighted [year] [name of copyright owner]"
29.29 + *
29.30 + * If you wish your version of this file to be governed by only the CDDL
29.31 + * or only the GPL Version 2, indicate your decision by adding
29.32 + * "[Contributor] elects to include this software in this distribution
29.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
29.34 + * single choice of license, a recipient has the option to distribute
29.35 + * your version of this file under either the CDDL, the GPL Version 2 or
29.36 + * to extend the choice of license to its licensees as provided above.
29.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
29.38 + * Version 2 license, then the option applies only if the new code is
29.39 + * made subject to such option by the copyright holder.
29.40 + *
29.41 + * Contributor(s):
29.42 + *
29.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
29.44 + */
29.45 +
29.46 +package org.netbeans.modules.java.hints.providers.spi;
29.47 +
29.48 +import java.util.Collection;
29.49 +import java.util.Collections;
29.50 +import java.util.HashSet;
29.51 +import java.util.Set;
29.52 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata.Options;
29.53 +import org.netbeans.spi.editor.hints.ErrorDescription;
29.54 +import org.netbeans.spi.java.hints.HintContext;
29.55 +
29.56 +/**
29.57 + *
29.58 + * @author Jan Lahoda
29.59 + */
29.60 +public final class HintDescription {
29.61 +
29.62 + private final HintMetadata metadata;
29.63 + private final Trigger trigger;
29.64 + private final Worker worker;
29.65 + private final AdditionalQueryConstraints additionalConstraints;
29.66 + private final String hintText;
29.67 + private final Set<Options> options;
29.68 +
29.69 + private HintDescription(HintMetadata metadata, Trigger trigger, Worker worker, AdditionalQueryConstraints additionalConstraints, String hintText, Set<Options> options) {
29.70 + this.metadata = metadata;
29.71 + this.trigger = trigger;
29.72 + this.worker = worker;
29.73 + this.additionalConstraints = additionalConstraints;
29.74 + this.hintText = hintText;
29.75 + this.options = options;
29.76 + }
29.77 +
29.78 + static HintDescription create(HintMetadata metadata, Trigger trigger, Worker worker, AdditionalQueryConstraints additionalConstraints, String hintText, Set<Options> options) {
29.79 + return new HintDescription(metadata, trigger, worker, additionalConstraints, hintText, options);
29.80 + }
29.81 +
29.82 + @Override
29.83 + public String toString() {
29.84 + return "[HintDescription:" + trigger + "]";
29.85 + }
29.86 +
29.87 + public AdditionalQueryConstraints getAdditionalConstraints() {
29.88 + return additionalConstraints;
29.89 + }
29.90 +
29.91 + public String getHintText() {
29.92 + return hintText;
29.93 + }
29.94 +
29.95 + public HintMetadata getMetadata() {
29.96 + return metadata;
29.97 + }
29.98 +
29.99 + public Trigger getTrigger() {
29.100 + return trigger;
29.101 + }
29.102 +
29.103 + public Worker getWorker() {
29.104 + return worker;
29.105 + }
29.106 +
29.107 + public Set<Options> getOptions() {
29.108 + return options;
29.109 + }
29.110 +
29.111 + public static interface Worker {
29.112 +
29.113 + public Collection<? extends ErrorDescription> createErrors(HintContext ctx);
29.114 +
29.115 + }
29.116 +
29.117 + public static final class AdditionalQueryConstraints {
29.118 + public final Set<String> requiredErasedTypes;
29.119 +
29.120 + public AdditionalQueryConstraints(Set<String> requiredErasedTypes) {
29.121 + this.requiredErasedTypes = Collections.unmodifiableSet(new HashSet<String>(requiredErasedTypes));
29.122 + }
29.123 +
29.124 + private static final AdditionalQueryConstraints EMPTY = new AdditionalQueryConstraints(Collections.<String>emptySet());
29.125 + public static AdditionalQueryConstraints empty() {
29.126 + return EMPTY;
29.127 + }
29.128 + }
29.129 +
29.130 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/spi/HintDescriptionFactory.java Wed May 08 21:47:42 2013 +0200
30.3 @@ -0,0 +1,127 @@
30.4 +/*
30.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
30.6 + *
30.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
30.8 + *
30.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
30.10 + * Other names may be trademarks of their respective owners.
30.11 + *
30.12 + * The contents of this file are subject to the terms of either the GNU
30.13 + * General Public License Version 2 only ("GPL") or the Common
30.14 + * Development and Distribution License("CDDL") (collectively, the
30.15 + * "License"). You may not use this file except in compliance with the
30.16 + * License. You can obtain a copy of the License at
30.17 + * http://www.netbeans.org/cddl-gplv2.html
30.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
30.19 + * specific language governing permissions and limitations under the
30.20 + * License. When distributing the software, include this License Header
30.21 + * Notice in each file and include the License file at
30.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
30.23 + * particular file as subject to the "Classpath" exception as provided
30.24 + * by Oracle in the GPL Version 2 section of the License file that
30.25 + * accompanied this code. If applicable, add the following below the
30.26 + * License Header, with the fields enclosed by brackets [] replaced by
30.27 + * your own identifying information:
30.28 + * "Portions Copyrighted [year] [name of copyright owner]"
30.29 + *
30.30 + * If you wish your version of this file to be governed by only the CDDL
30.31 + * or only the GPL Version 2, indicate your decision by adding
30.32 + * "[Contributor] elects to include this software in this distribution
30.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
30.34 + * single choice of license, a recipient has the option to distribute
30.35 + * your version of this file under either the CDDL, the GPL Version 2 or
30.36 + * to extend the choice of license to its licensees as provided above.
30.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
30.38 + * Version 2 license, then the option applies only if the new code is
30.39 + * made subject to such option by the copyright holder.
30.40 + *
30.41 + * Contributor(s):
30.42 + *
30.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
30.44 + */
30.45 +
30.46 +package org.netbeans.modules.java.hints.providers.spi;
30.47 +
30.48 +import java.util.Arrays;
30.49 +import java.util.Collections;
30.50 +import java.util.EnumSet;
30.51 +import java.util.Set;
30.52 +import org.netbeans.api.annotations.common.NonNull;
30.53 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.AdditionalQueryConstraints;
30.54 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.Worker;
30.55 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata.Options;
30.56 +
30.57 +/**
30.58 + *
30.59 + * @author lahvac
30.60 + */
30.61 +public class HintDescriptionFactory {
30.62 +
30.63 + private HintMetadata metadata;
30.64 + private Trigger trigger;
30.65 + private Worker worker;
30.66 + private AdditionalQueryConstraints additionalConstraints;
30.67 + private String hintText;
30.68 + private Set<Options> options;
30.69 + private boolean finished;
30.70 +
30.71 + private HintDescriptionFactory() {
30.72 + }
30.73 +
30.74 + public static HintDescriptionFactory create() {
30.75 + return new HintDescriptionFactory();
30.76 + }
30.77 +
30.78 + /**TODO: move to create?
30.79 + *
30.80 + * @param metadata
30.81 + * @return
30.82 + */
30.83 + public HintDescriptionFactory setMetadata(HintMetadata metadata) {
30.84 + this.metadata = metadata;
30.85 + return this;
30.86 + }
30.87 +
30.88 + public HintDescriptionFactory setTrigger(Trigger trigger) {
30.89 + if (this.trigger != null) {
30.90 + throw new IllegalStateException(this.trigger.toString());
30.91 + }
30.92 +
30.93 + this.trigger = trigger;
30.94 + return this;
30.95 + }
30.96 +
30.97 + public HintDescriptionFactory setWorker(Worker worker) {
30.98 + this.worker = worker;
30.99 + return this;
30.100 + }
30.101 +
30.102 + public HintDescriptionFactory setAdditionalConstraints(AdditionalQueryConstraints additionalConstraints) {
30.103 + this.additionalConstraints = additionalConstraints;
30.104 + return this;
30.105 + }
30.106 +
30.107 + public HintDescriptionFactory setHintText(@NonNull String hintText) {
30.108 + this.hintText = hintText;
30.109 + return this;
30.110 + }
30.111 +
30.112 + public HintDescriptionFactory addOptions(Options... options) {
30.113 + if (this.options == null) {
30.114 + this.options = EnumSet.noneOf(Options.class);
30.115 + }
30.116 + this.options.addAll(Arrays.asList(options));
30.117 + return this;
30.118 + }
30.119 +
30.120 + public HintDescription produce() {
30.121 + if (metadata == null) {
30.122 + metadata = HintMetadata.Builder.create("no-id").addOptions(Options.NON_GUI).build();
30.123 + }
30.124 + if (this.additionalConstraints == null) {
30.125 + this.additionalConstraints = AdditionalQueryConstraints.empty();
30.126 + }
30.127 + return HintDescription.create(metadata, trigger, worker, additionalConstraints, hintText, options != null ? options : Collections.<Options>emptySet());
30.128 + }
30.129 +
30.130 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/spi/HintMetadata.java Wed May 08 21:47:42 2013 +0200
31.3 @@ -0,0 +1,224 @@
31.4 +/*
31.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
31.6 + *
31.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
31.8 + *
31.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
31.10 + * Other names may be trademarks of their respective owners.
31.11 + *
31.12 + * The contents of this file are subject to the terms of either the GNU
31.13 + * General Public License Version 2 only ("GPL") or the Common
31.14 + * Development and Distribution License("CDDL") (collectively, the
31.15 + * "License"). You may not use this file except in compliance with the
31.16 + * License. You can obtain a copy of the License at
31.17 + * http://www.netbeans.org/cddl-gplv2.html
31.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
31.19 + * specific language governing permissions and limitations under the
31.20 + * License. When distributing the software, include this License Header
31.21 + * Notice in each file and include the License file at
31.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
31.23 + * particular file as subject to the "Classpath" exception as provided
31.24 + * by Oracle in the GPL Version 2 section of the License file that
31.25 + * accompanied this code. If applicable, add the following below the
31.26 + * License Header, with the fields enclosed by brackets [] replaced by
31.27 + * your own identifying information:
31.28 + * "Portions Copyrighted [year] [name of copyright owner]"
31.29 + *
31.30 + * If you wish your version of this file to be governed by only the CDDL
31.31 + * or only the GPL Version 2, indicate your decision by adding
31.32 + * "[Contributor] elects to include this software in this distribution
31.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
31.34 + * single choice of license, a recipient has the option to distribute
31.35 + * your version of this file under either the CDDL, the GPL Version 2 or
31.36 + * to extend the choice of license to its licensees as provided above.
31.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
31.38 + * Version 2 license, then the option applies only if the new code is
31.39 + * made subject to such option by the copyright holder.
31.40 + *
31.41 + * Contributor(s):
31.42 + *
31.43 + * Portions Copyrighted 2010 Sun Microsystems, Inc.
31.44 + */
31.45 +
31.46 +package org.netbeans.modules.java.hints.providers.spi;
31.47 +
31.48 +import java.util.ArrayList;
31.49 +import java.util.Arrays;
31.50 +import java.util.Collection;
31.51 +import java.util.EnumSet;
31.52 +import java.util.HashSet;
31.53 +import java.util.MissingResourceException;
31.54 +import java.util.ResourceBundle;
31.55 +import java.util.Set;
31.56 +import java.util.logging.Level;
31.57 +import java.util.logging.Logger;
31.58 +import org.netbeans.spi.editor.hints.Severity;
31.59 +import org.netbeans.spi.java.hints.CustomizerProvider;
31.60 +import org.netbeans.spi.java.hints.Hint;
31.61 +import org.openide.util.NbBundle;
31.62 +
31.63 +/**
31.64 + *
31.65 + * @author lahvac
31.66 + */
31.67 +public class HintMetadata {
31.68 +
31.69 + public final String id;
31.70 + public final String displayName;
31.71 + public final String description;
31.72 + public final String category;
31.73 + public final boolean enabled;
31.74 + public final Hint.Kind kind;
31.75 + public final Severity severity;
31.76 + public final Collection<? extends String> suppressWarnings;
31.77 + public final CustomizerProvider customizer;
31.78 + public final boolean showInTaskList = false;
31.79 + public final Set<Options> options;
31.80 +
31.81 + HintMetadata(String id, String displayName, String description, String category, boolean enabled, Hint.Kind kind, Severity severity, Collection<? extends String> suppressWarnings, CustomizerProvider customizer, Set<Options> options) {
31.82 + this.id = id;
31.83 + this.displayName = displayName;
31.84 + this.description = description;
31.85 + this.category = category;
31.86 + this.enabled = enabled;
31.87 + this.kind = kind;
31.88 + this.severity = severity;
31.89 + this.suppressWarnings = suppressWarnings;
31.90 + this.customizer = customizer;
31.91 + this.options = options;
31.92 + }
31.93 +
31.94 + @Override
31.95 + public String toString() {
31.96 + return this.displayName;
31.97 + }
31.98 +
31.99 + private static String lookup(ResourceBundle bundle, String key, String def) {
31.100 + try {
31.101 + return bundle != null ? bundle.getString(key) : def;
31.102 + } catch (MissingResourceException mre) {
31.103 + Logger.getLogger(HintMetadata.class.getName()).log(Level.FINE, null, mre);
31.104 + return def;
31.105 + }
31.106 + }
31.107 +
31.108 + public static final class Builder {
31.109 + private final String id;
31.110 + private String displayName;
31.111 + private String description;
31.112 + private String category;
31.113 + private boolean enabled;
31.114 + private Hint.Kind kind;
31.115 + private Severity severity;
31.116 + private final Collection<String> suppressWarnings = new ArrayList<String>();
31.117 + private CustomizerProvider customizer;
31.118 + private final Set<Options> options = EnumSet.noneOf(Options.class);
31.119 +
31.120 + private Builder(String id) {
31.121 + this.id = id;
31.122 + this.displayName = "";
31.123 + this.description = "";
31.124 + this.category = "";
31.125 + this.enabled = true;
31.126 + this.kind = Hint.Kind.INSPECTION;
31.127 + this.severity = Severity.VERIFIER;
31.128 + }
31.129 +
31.130 + public static Builder create(String id) {
31.131 + return new Builder(id);
31.132 + }
31.133 +
31.134 + public Builder setDescription(String displayName, String description) {
31.135 + this.displayName = displayName;
31.136 + this.description = description;
31.137 + return this;
31.138 + }
31.139 +
31.140 + public Builder setBundle(ResourceBundle bundle) {
31.141 + return setBundle(bundle, null, null);
31.142 + }
31.143 +
31.144 + public Builder setBundle(ResourceBundle bundle, String fallbackDisplayName, String fallbackDescription) {
31.145 + if (fallbackDisplayName == null) fallbackDisplayName = "No Display Name";
31.146 + if (fallbackDescription == null) fallbackDescription = "No Description";
31.147 +
31.148 + this.displayName = lookup(bundle, "DN_" + id.replace('$', '.'), fallbackDisplayName);
31.149 + this.description = lookup(bundle, "DESC_" + id.replace('$', '.'), fallbackDescription);
31.150 + return this;
31.151 + }
31.152 +
31.153 + public Builder setBundle(String bundleForFQN) {
31.154 + ResourceBundle bundle;
31.155 +
31.156 + try {
31.157 + int lastDot = bundleForFQN.lastIndexOf('.');
31.158 +
31.159 + assert lastDot >= 0;
31.160 +
31.161 + bundle = NbBundle.getBundle(bundleForFQN.substring(0, lastDot + 1) + "Bundle");
31.162 + } catch (MissingResourceException mre) {
31.163 + Logger.getLogger(HintMetadata.class.getName()).log(Level.FINE, null, mre);
31.164 + bundle = null;
31.165 + }
31.166 + return setBundle(bundle);
31.167 + }
31.168 +
31.169 + public Builder setCategory(String category) {
31.170 + this.category = category;
31.171 + return this;
31.172 + }
31.173 +
31.174 + public Builder setEnabled(boolean enabled) {
31.175 + this.enabled = enabled;
31.176 + return this;
31.177 + }
31.178 +
31.179 + public Builder setKind(Hint.Kind kind) {
31.180 + this.kind = kind;
31.181 + return this;
31.182 + }
31.183 +
31.184 + public Builder setSeverity(Severity severity) {
31.185 + this.severity = severity;
31.186 + return this;
31.187 + }
31.188 +
31.189 +
31.190 + public Builder addSuppressWarnings(String... keys) {
31.191 + this.suppressWarnings.addAll(Arrays.asList(keys));
31.192 + return this;
31.193 + }
31.194 +
31.195 + public Builder setCustomizerProvider(CustomizerProvider customizer) {
31.196 + this.customizer = customizer;
31.197 + return this;
31.198 + }
31.199 +
31.200 + public Builder addOptions(Options... options) {
31.201 + this.options.addAll(Arrays.asList(options));
31.202 + return this;
31.203 + }
31.204 +
31.205 + public HintMetadata build() {
31.206 + return new HintMetadata(id, displayName, description, category, enabled, kind, severity, suppressWarnings, customizer, options);
31.207 + }
31.208 +
31.209 + }
31.210 +
31.211 + public enum Options {
31.212 + NON_GUI,
31.213 + QUERY,
31.214 + NO_BATCH,
31.215 + HEAVY;
31.216 +
31.217 + public static Set<Options> fromHintOptions(Hint.Options... options) {
31.218 + Set<Options> result = new HashSet<Options>();
31.219 +
31.220 + for (Hint.Options opt : options) {
31.221 + result.add(valueOf(opt.name()));
31.222 + }
31.223 +
31.224 + return result;
31.225 + }
31.226 + }
31.227 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/spi/HintProvider.java Wed May 08 21:47:42 2013 +0200
32.3 @@ -0,0 +1,54 @@
32.4 +/*
32.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
32.6 + *
32.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
32.8 + *
32.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
32.10 + * Other names may be trademarks of their respective owners.
32.11 + *
32.12 + * The contents of this file are subject to the terms of either the GNU
32.13 + * General Public License Version 2 only ("GPL") or the Common
32.14 + * Development and Distribution License("CDDL") (collectively, the
32.15 + * "License"). You may not use this file except in compliance with the
32.16 + * License. You can obtain a copy of the License at
32.17 + * http://www.netbeans.org/cddl-gplv2.html
32.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
32.19 + * specific language governing permissions and limitations under the
32.20 + * License. When distributing the software, include this License Header
32.21 + * Notice in each file and include the License file at
32.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
32.23 + * particular file as subject to the "Classpath" exception as provided
32.24 + * by Oracle in the GPL Version 2 section of the License file that
32.25 + * accompanied this code. If applicable, add the following below the
32.26 + * License Header, with the fields enclosed by brackets [] replaced by
32.27 + * your own identifying information:
32.28 + * "Portions Copyrighted [year] [name of copyright owner]"
32.29 + *
32.30 + * If you wish your version of this file to be governed by only the CDDL
32.31 + * or only the GPL Version 2, indicate your decision by adding
32.32 + * "[Contributor] elects to include this software in this distribution
32.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
32.34 + * single choice of license, a recipient has the option to distribute
32.35 + * your version of this file under either the CDDL, the GPL Version 2 or
32.36 + * to extend the choice of license to its licensees as provided above.
32.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
32.38 + * Version 2 license, then the option applies only if the new code is
32.39 + * made subject to such option by the copyright holder.
32.40 + *
32.41 + * Contributor(s):
32.42 + *
32.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
32.44 + */
32.45 +
32.46 +package org.netbeans.modules.java.hints.providers.spi;
32.47 +
32.48 +import java.util.Collection;
32.49 +import java.util.Map;
32.50 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
32.51 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
32.52 +
32.53 +public interface HintProvider {
32.54 +
32.55 + public Map<HintMetadata, ? extends Collection<? extends HintDescription>> computeHints();
32.56 +
32.57 +}
33.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
33.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/spi/PositionRefresherHelper.java Wed May 08 21:47:42 2013 +0200
33.3 @@ -0,0 +1,105 @@
33.4 +/*
33.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33.6 + *
33.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
33.8 + *
33.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
33.10 + * Other names may be trademarks of their respective owners.
33.11 + *
33.12 + * The contents of this file are subject to the terms of either the GNU
33.13 + * General Public License Version 2 only ("GPL") or the Common
33.14 + * Development and Distribution License("CDDL") (collectively, the
33.15 + * "License"). You may not use this file except in compliance with the
33.16 + * License. You can obtain a copy of the License at
33.17 + * http://www.netbeans.org/cddl-gplv2.html
33.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
33.19 + * specific language governing permissions and limitations under the
33.20 + * License. When distributing the software, include this License Header
33.21 + * Notice in each file and include the License file at
33.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
33.23 + * particular file as subject to the "Classpath" exception as provided
33.24 + * by Oracle in the GPL Version 2 section of the License file that
33.25 + * accompanied this code. If applicable, add the following below the
33.26 + * License Header, with the fields enclosed by brackets [] replaced by
33.27 + * your own identifying information:
33.28 + * "Portions Copyrighted [year] [name of copyright owner]"
33.29 + *
33.30 + * If you wish your version of this file to be governed by only the CDDL
33.31 + * or only the GPL Version 2, indicate your decision by adding
33.32 + * "[Contributor] elects to include this software in this distribution
33.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
33.34 + * single choice of license, a recipient has the option to distribute
33.35 + * your version of this file under either the CDDL, the GPL Version 2 or
33.36 + * to extend the choice of license to its licensees as provided above.
33.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
33.38 + * Version 2 license, then the option applies only if the new code is
33.39 + * made subject to such option by the copyright holder.
33.40 + *
33.41 + * Contributor(s):
33.42 + *
33.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
33.44 + */
33.45 +package org.netbeans.modules.java.hints.providers.spi;
33.46 +
33.47 +import java.util.List;
33.48 +import javax.swing.text.Document;
33.49 +import org.netbeans.api.annotations.common.CheckForNull;
33.50 +import org.netbeans.api.java.source.CompilationInfo;
33.51 +import org.netbeans.lib.editor.util.swing.DocumentUtilities;
33.52 +import org.netbeans.spi.editor.hints.Context;
33.53 +import org.netbeans.spi.editor.hints.ErrorDescription;
33.54 +import org.netbeans.modules.java.hints.providers.spi.PositionRefresherHelper.DocumentVersion;
33.55 +
33.56 +/**TODO: should be public?
33.57 + *
33.58 + * @author lahvac
33.59 + */
33.60 +public abstract class PositionRefresherHelper<V extends DocumentVersion> {
33.61 +
33.62 + private final Object documentKey = new Object();
33.63 + private final String key;
33.64 +
33.65 + protected PositionRefresherHelper(String key) {
33.66 + this.key = key;
33.67 + }
33.68 +
33.69 + protected abstract boolean isUpToDate(Context context, Document doc, V oldVersion);
33.70 + /**XXX: should be protected*/public abstract List<ErrorDescription> getErrorDescriptionsAt(CompilationInfo info, Context context, Document doc) throws Exception;
33.71 +
33.72 + protected final void setVersion(Document doc, V version) {
33.73 + if (doc != null) {
33.74 + doc.putProperty(documentKey, version);
33.75 + }
33.76 + }
33.77 +
33.78 + protected @CheckForNull V getUpToDateDocumentVersion(Context context, Document doc) {
33.79 + V oldVersion = (V) doc.getProperty(documentKey);
33.80 +
33.81 + if (oldVersion == null) return null;
33.82 +
33.83 + if (((DocumentVersion) oldVersion).version != DocumentUtilities.getDocumentVersion(doc)) return null;
33.84 +
33.85 + return oldVersion;
33.86 + }
33.87 +
33.88 + /**XXX*/ public boolean upToDateCheck(Context context, Document doc) {
33.89 + V oldVersion = getUpToDateDocumentVersion(context, doc);
33.90 +
33.91 + if (oldVersion == null) return false;
33.92 +
33.93 + return isUpToDate(context, doc, oldVersion);
33.94 + }
33.95 +
33.96 + /**XXX*/ public String getKey() {
33.97 + return key;
33.98 + }
33.99 +
33.100 + public static class DocumentVersion {
33.101 + private final long version;
33.102 +
33.103 + public DocumentVersion(Document doc) {
33.104 + this.version = doc != null ? DocumentUtilities.getDocumentVersion(doc) : 0;
33.105 + }
33.106 +
33.107 + }
33.108 +}
34.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
34.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/providers/spi/Trigger.java Wed May 08 21:47:42 2013 +0200
34.3 @@ -0,0 +1,159 @@
34.4 +/*
34.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
34.6 + *
34.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
34.8 + *
34.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
34.10 + * Other names may be trademarks of their respective owners.
34.11 + *
34.12 + * The contents of this file are subject to the terms of either the GNU
34.13 + * General Public License Version 2 only ("GPL") or the Common
34.14 + * Development and Distribution License("CDDL") (collectively, the
34.15 + * "License"). You may not use this file except in compliance with the
34.16 + * License. You can obtain a copy of the License at
34.17 + * http://www.netbeans.org/cddl-gplv2.html
34.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
34.19 + * specific language governing permissions and limitations under the
34.20 + * License. When distributing the software, include this License Header
34.21 + * Notice in each file and include the License file at
34.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
34.23 + * particular file as subject to the "Classpath" exception as provided
34.24 + * by Oracle in the GPL Version 2 section of the License file that
34.25 + * accompanied this code. If applicable, add the following below the
34.26 + * License Header, with the fields enclosed by brackets [] replaced by
34.27 + * your own identifying information:
34.28 + * "Portions Copyrighted [year] [name of copyright owner]"
34.29 + *
34.30 + * If you wish your version of this file to be governed by only the CDDL
34.31 + * or only the GPL Version 2, indicate your decision by adding
34.32 + * "[Contributor] elects to include this software in this distribution
34.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
34.34 + * single choice of license, a recipient has the option to distribute
34.35 + * your version of this file under either the CDDL, the GPL Version 2 or
34.36 + * to extend the choice of license to its licensees as provided above.
34.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
34.38 + * Version 2 license, then the option applies only if the new code is
34.39 + * made subject to such option by the copyright holder.
34.40 + *
34.41 + * Contributor(s):
34.42 + *
34.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
34.44 + */
34.45 +package org.netbeans.modules.java.hints.providers.spi;
34.46 +
34.47 +import com.sun.source.tree.Tree;
34.48 +import com.sun.source.tree.Tree.Kind;
34.49 +import java.util.Arrays;
34.50 +import java.util.Map;
34.51 +import java.util.Set;
34.52 +import org.netbeans.api.java.source.matching.Pattern;
34.53 +import org.openide.util.Parameters;
34.54 +
34.55 +/**A base class for triggers.
34.56 + *
34.57 + * @author lahvac
34.58 + */
34.59 +public abstract class Trigger {
34.60 +
34.61 + Trigger() {}
34.62 +
34.63 + /**Invoke the given hint's worker on the specified {@link Tree.Kind}(s).
34.64 + *
34.65 + */
34.66 + public static final class Kinds extends Trigger {
34.67 + private final Set<Kind> kinds;
34.68 +
34.69 + /**Create the trigger for the specified set of {@link Tree.Kind}s.
34.70 + *
34.71 + * @param kinds on which the hint's worker should be invoked.
34.72 + */
34.73 + public Kinds(Set<Kind> kinds) {
34.74 + this.kinds = kinds;
34.75 + }
34.76 +
34.77 + public Iterable<? extends Kind> getKinds() {
34.78 + return kinds;
34.79 + }
34.80 +
34.81 + @Override
34.82 + public String toString() {
34.83 + return kinds.toString();
34.84 + }
34.85 + }
34.86 +
34.87 + /**Invoke the hint's worker on tree nodes that match the given pattern.
34.88 + *
34.89 + */
34.90 + public static final class PatternDescription extends Trigger {
34.91 +
34.92 + private final String pattern;
34.93 + private final Map<String, String> constraints;
34.94 + private final Iterable<? extends String> imports;
34.95 +
34.96 + private PatternDescription(String pattern, Map<String, String> constraints, String... imports) {
34.97 + this.pattern = pattern;
34.98 + this.constraints = constraints;
34.99 + this.imports = Arrays.asList(imports);
34.100 + }
34.101 +
34.102 + /** Create the trigger to invoke the hint's worker on tree nodes that match the given pattern.
34.103 + *
34.104 + * @param pattern which will be interpreted as a pattern with free variables ({@link Pattern#createPatternWithFreeVariables(com.sun.source.util.TreePath, java.util.Map) }.
34.105 + * @param constraints are expected to be mapping from a free variable name to the expected type.
34.106 + * @param XXX: document the imports
34.107 + * @return the created trigger.
34.108 + */
34.109 + public static PatternDescription create(String pattern, Map<String, String> constraints, String... imports) {
34.110 + Parameters.notNull("pattern", pattern);
34.111 + Parameters.notNull("constraints", constraints);
34.112 + Parameters.notNull("imports", imports);
34.113 +
34.114 + return new PatternDescription(pattern, constraints, imports);
34.115 + }
34.116 +
34.117 + @Override
34.118 + public boolean equals(Object obj) {
34.119 + if (obj == null) {
34.120 + return false;
34.121 + }
34.122 + if (getClass() != obj.getClass()) {
34.123 + return false;
34.124 + }
34.125 + final PatternDescription other = (PatternDescription) obj;
34.126 + if ((this.pattern == null) ? (other.pattern != null) : !this.pattern.equals(other.pattern)) {
34.127 + return false;
34.128 + }
34.129 + if (this.constraints != other.constraints && (this.constraints == null || !this.constraints.equals(other.constraints))) {
34.130 + return false;
34.131 + }
34.132 + return true;
34.133 + }
34.134 +
34.135 + @Override
34.136 + public int hashCode() {
34.137 + int hash = 7;
34.138 + hash = 71 * hash + (this.pattern != null ? this.pattern.hashCode() : 0);
34.139 + hash = 71 * hash + (this.constraints != null ? this.constraints.hashCode() : 0);
34.140 + return hash;
34.141 + }
34.142 +
34.143 + public String getPattern() {
34.144 + return pattern;
34.145 + }
34.146 +
34.147 + public Map<String, String> getConstraints() {
34.148 + return constraints;
34.149 + }
34.150 +
34.151 + public Iterable<? extends String> getImports() {
34.152 + return imports;
34.153 + }
34.154 +
34.155 + @Override
34.156 + public String toString() {
34.157 + return pattern;
34.158 + }
34.159 +
34.160 + }
34.161 +
34.162 +}
35.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
35.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Bundle.properties Wed May 08 21:47:42 2013 +0200
35.3 @@ -0,0 +1,4 @@
35.4 +OpenIDE-Module-Name=Java Hints SPI
35.5 +
35.6 +#refresh hints
35.7 +Refresh_hints=Refresh Hints
36.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
36.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Hacks.java Wed May 08 21:47:42 2013 +0200
36.3 @@ -0,0 +1,219 @@
36.4 +/*
36.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
36.6 + *
36.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
36.8 + *
36.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
36.10 + * Other names may be trademarks of their respective owners.
36.11 + *
36.12 + * The contents of this file are subject to the terms of either the GNU
36.13 + * General Public License Version 2 only ("GPL") or the Common
36.14 + * Development and Distribution License("CDDL") (collectively, the
36.15 + * "License"). You may not use this file except in compliance with the
36.16 + * License. You can obtain a copy of the License at
36.17 + * http://www.netbeans.org/cddl-gplv2.html
36.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
36.19 + * specific language governing permissions and limitations under the
36.20 + * License. When distributing the software, include this License Header
36.21 + * Notice in each file and include the License file at
36.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
36.23 + * particular file as subject to the "Classpath" exception as provided
36.24 + * by Oracle in the GPL Version 2 section of the License file that
36.25 + * accompanied this code. If applicable, add the following below the
36.26 + * License Header, with the fields enclosed by brackets [] replaced by
36.27 + * your own identifying information:
36.28 + * "Portions Copyrighted [year] [name of copyright owner]"
36.29 + *
36.30 + * If you wish your version of this file to be governed by only the CDDL
36.31 + * or only the GPL Version 2, indicate your decision by adding
36.32 + * "[Contributor] elects to include this software in this distribution
36.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
36.34 + * single choice of license, a recipient has the option to distribute
36.35 + * your version of this file under either the CDDL, the GPL Version 2 or
36.36 + * to extend the choice of license to its licensees as provided above.
36.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
36.38 + * Version 2 license, then the option applies only if the new code is
36.39 + * made subject to such option by the copyright holder.
36.40 + *
36.41 + * Contributor(s):
36.42 + *
36.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
36.44 + */
36.45 +
36.46 +package org.netbeans.modules.java.hints.spiimpl;
36.47 +
36.48 +import com.sun.source.tree.BlockTree;
36.49 +import com.sun.source.tree.CompilationUnitTree;
36.50 +import com.sun.source.tree.MethodTree;
36.51 +import com.sun.source.tree.Scope;
36.52 +import com.sun.source.tree.Tree;
36.53 +import com.sun.source.util.TreePath;
36.54 +import com.sun.source.util.TreePathScanner;
36.55 +import com.sun.tools.javac.api.JavacTaskImpl;
36.56 +import com.sun.tools.javac.code.Symbol.ClassSymbol;
36.57 +import com.sun.tools.javac.comp.AttrContext;
36.58 +import com.sun.tools.javac.comp.Enter;
36.59 +import com.sun.tools.javac.comp.Env;
36.60 +import com.sun.tools.javac.main.JavaCompiler;
36.61 +import com.sun.tools.javac.tree.JCTree;
36.62 +import com.sun.tools.javac.tree.JCTree.JCErroneous;
36.63 +import com.sun.tools.javac.util.Context;
36.64 +import com.sun.tools.javac.util.Log;
36.65 +import java.io.File;
36.66 +import java.io.IOException;
36.67 +import javax.lang.model.element.Element;
36.68 +import javax.lang.model.element.TypeElement;
36.69 +import javax.lang.model.element.VariableElement;
36.70 +import javax.lang.model.type.TypeMirror;
36.71 +import javax.tools.JavaFileObject;
36.72 +import org.netbeans.api.annotations.common.CheckForNull;
36.73 +import org.netbeans.api.annotations.common.NonNull;
36.74 +import org.netbeans.api.java.source.CompilationInfo;
36.75 +import org.netbeans.api.java.source.TreeUtilities;
36.76 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
36.77 +import org.netbeans.modules.java.source.JavaSourceAccessor;
36.78 +import org.netbeans.modules.java.source.parsing.FileObjects;
36.79 +import org.openide.util.Exceptions;
36.80 +
36.81 +/**
36.82 + *
36.83 + * @author lahvac
36.84 + */
36.85 +public class Hacks {
36.86 +
36.87 + //XXX: copied from Utilities, for declarative hints, different import management:
36.88 + private static long inc;
36.89 +
36.90 + public static Scope constructScope(CompilationInfo info, String... importedClasses) {
36.91 + StringBuilder clazz = new StringBuilder();
36.92 +
36.93 + clazz.append("package $$;\n");
36.94 +
36.95 + for (String i : importedClasses) {
36.96 + clazz.append("import ").append(i).append(";\n");
36.97 + }
36.98 +
36.99 + clazz.append("public class $").append(inc++).append("{");
36.100 +
36.101 + clazz.append("private void test() {\n");
36.102 + clazz.append("}\n");
36.103 + clazz.append("}\n");
36.104 +
36.105 + JavacTaskImpl jti = JavaSourceAccessor.getINSTANCE().getJavacTask(info);
36.106 + Context context = jti.getContext();
36.107 +
36.108 + JavaCompiler jc = JavaCompiler.instance(context);
36.109 + Log.instance(context).nerrors = 0;
36.110 +
36.111 + JavaFileObject jfo = FileObjects.memoryFileObject("$$", "$", new File("/tmp/t.java").toURI(), System.currentTimeMillis(), clazz.toString());
36.112 + boolean oldSkipAPs = jc.skipAnnotationProcessing;
36.113 +
36.114 + try {
36.115 + jc.skipAnnotationProcessing = true;
36.116 +
36.117 + Iterable<? extends CompilationUnitTree> parsed = jti.parse(jfo);
36.118 + CompilationUnitTree cut = parsed.iterator().next();
36.119 +
36.120 + jti.analyze(jti.enter(parsed));
36.121 +
36.122 + return new ScannerImpl().scan(cut, info);
36.123 + } catch (IOException ex) {
36.124 + Exceptions.printStackTrace(ex);
36.125 + return null;
36.126 + } finally {
36.127 + jc.skipAnnotationProcessing = oldSkipAPs;
36.128 + }
36.129 + }
36.130 +
36.131 + private static final class ScannerImpl extends TreePathScanner<Scope, CompilationInfo> {
36.132 +
36.133 + @Override
36.134 + public Scope visitBlock(BlockTree node, CompilationInfo p) {
36.135 + return p.getTrees().getScope(getCurrentPath());
36.136 + }
36.137 +
36.138 + @Override
36.139 + public Scope visitMethod(MethodTree node, CompilationInfo p) {
36.140 + if (node.getReturnType() == null) {
36.141 + return null;
36.142 + }
36.143 + return super.visitMethod(node, p);
36.144 + }
36.145 +
36.146 + @Override
36.147 + public Scope reduce(Scope r1, Scope r2) {
36.148 + return r1 != null ? r1 : r2;
36.149 + }
36.150 +
36.151 + }
36.152 +
36.153 +
36.154 + public static Tree createRenameTree(@NonNull Tree originalTree, @NonNull String newName) {
36.155 + return new RenameTree(originalTree, newName);
36.156 + }
36.157 +
36.158 + public static final class RenameTree extends JCErroneous {
36.159 +
36.160 + public final Tree originalTree;
36.161 + public final String newName;
36.162 +
36.163 + public RenameTree(@NonNull Tree originalTree, @NonNull String newName) {
36.164 + super(com.sun.tools.javac.util.List.<JCTree>nil());
36.165 + this.originalTree = originalTree;
36.166 + this.newName = newName;
36.167 + }
36.168 +
36.169 + }
36.170 +
36.171 + public static @CheckForNull TypeMirror parseFQNType(@NonNull CompilationInfo info, @NonNull String spec) {
36.172 + if (spec.length() == 0) {
36.173 + return null;
36.174 + }
36.175 +
36.176 + TypeElement jlObject = info.getElements().getTypeElement("java.lang.Object");
36.177 +
36.178 + //XXX:
36.179 + TypeElement scope;
36.180 +
36.181 + if (info.getTopLevelElements().isEmpty()) {
36.182 + scope = jlObject;
36.183 + } else {
36.184 + scope = info.getTopLevelElements().iterator().next();
36.185 + }
36.186 + //XXX end
36.187 +
36.188 + return info.getTreeUtilities().parseType(spec, /*XXX: jlObject*/scope);
36.189 + }
36.190 +
36.191 + public static VariableElement attributeThis(CompilationInfo info, TreePath tp) {
36.192 + //XXX:
36.193 + while (tp != null) {
36.194 + if (TreeUtilities.CLASS_TREE_KINDS.contains(tp.getLeaf().getKind())) {
36.195 + Element currentElement = info.getTrees().getElement(tp);
36.196 +
36.197 + if (currentElement == null || !(currentElement instanceof ClassSymbol)) return null;
36.198 +
36.199 + Enter enter = Enter.instance(JavaSourceAccessor.getINSTANCE().getJavacTask(info).getContext());
36.200 + Env<AttrContext> env = enter.getEnv((ClassSymbol) currentElement);
36.201 +
36.202 + if (env == null) return null;
36.203 +
36.204 + for (Element el : env.info.getLocalElements()) {
36.205 + if (el.getSimpleName().contentEquals("this")) {
36.206 + return (VariableElement) el;
36.207 + }
36.208 + }
36.209 +
36.210 + return null;
36.211 + }
36.212 +
36.213 + tp = tp.getParentPath();
36.214 + }
36.215 +
36.216 + return null;
36.217 + }
36.218 +
36.219 + public static interface InspectAndTransformOpener {
36.220 + public void openIAT(HintMetadata hm);
36.221 + }
36.222 +}
37.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
37.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JackpotTrees.java Wed May 08 21:47:42 2013 +0200
37.3 @@ -0,0 +1,246 @@
37.4 +/*
37.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
37.6 + *
37.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
37.8 + *
37.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
37.10 + * Other names may be trademarks of their respective owners.
37.11 + *
37.12 + * The contents of this file are subject to the terms of either the GNU
37.13 + * General Public License Version 2 only ("GPL") or the Common
37.14 + * Development and Distribution License("CDDL") (collectively, the
37.15 + * "License"). You may not use this file except in compliance with the
37.16 + * License. You can obtain a copy of the License at
37.17 + * http://www.netbeans.org/cddl-gplv2.html
37.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
37.19 + * specific language governing permissions and limitations under the
37.20 + * License. When distributing the software, include this License Header
37.21 + * Notice in each file and include the License file at
37.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
37.23 + * particular file as subject to the "Classpath" exception as provided
37.24 + * by Oracle in the GPL Version 2 section of the License file that
37.25 + * accompanied this code. If applicable, add the following below the
37.26 + * License Header, with the fields enclosed by brackets [] replaced by
37.27 + * your own identifying information:
37.28 + * "Portions Copyrighted [year] [name of copyright owner]"
37.29 + *
37.30 + * If you wish your version of this file to be governed by only the CDDL
37.31 + * or only the GPL Version 2, indicate your decision by adding
37.32 + * "[Contributor] elects to include this software in this distribution
37.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
37.34 + * single choice of license, a recipient has the option to distribute
37.35 + * your version of this file under either the CDDL, the GPL Version 2 or
37.36 + * to extend the choice of license to its licensees as provided above.
37.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
37.38 + * Version 2 license, then the option applies only if the new code is
37.39 + * made subject to such option by the copyright holder.
37.40 + *
37.41 + * Contributor(s):
37.42 + *
37.43 + * Portions Copyrighted 2010 Sun Microsystems, Inc.
37.44 + */
37.45 +
37.46 +package org.netbeans.modules.java.hints.spiimpl;
37.47 +
37.48 +import com.sun.source.tree.IdentifierTree;
37.49 +import com.sun.source.tree.TreeVisitor;
37.50 +import com.sun.tools.javac.code.Symbol.VarSymbol;
37.51 +import com.sun.tools.javac.code.Symtab;
37.52 +import com.sun.tools.javac.tree.JCTree;
37.53 +import com.sun.tools.javac.tree.JCTree.JCAnnotation;
37.54 +import com.sun.tools.javac.tree.JCTree.JCBlock;
37.55 +import com.sun.tools.javac.tree.JCTree.JCCase;
37.56 +import com.sun.tools.javac.tree.JCTree.JCCatch;
37.57 +import com.sun.tools.javac.tree.JCTree.JCModifiers;
37.58 +import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
37.59 +import com.sun.tools.javac.tree.TreeMaker;
37.60 +import com.sun.tools.javac.util.Context;
37.61 +import com.sun.tools.javac.util.List;
37.62 +import com.sun.tools.javac.util.Name;
37.63 +
37.64 +
37.65 +/**
37.66 + *
37.67 + * @author lahvac
37.68 + */
37.69 +public class JackpotTrees {
37.70 + public static class AnnotationWildcard extends JCAnnotation implements IdentifierTree {
37.71 +
37.72 + private final Name ident;
37.73 + private final JCIdent jcIdent;
37.74 +
37.75 + public AnnotationWildcard(Name ident, JCIdent jcIdent) {
37.76 + super(Tag.ANNOTATION, jcIdent, List.<JCExpression>nil());
37.77 + this.ident = ident;
37.78 + this.jcIdent = jcIdent;
37.79 + }
37.80 +
37.81 + public Name getName() {
37.82 + return ident;
37.83 + }
37.84 +
37.85 + @Override
37.86 + public Kind getKind() {
37.87 + return Kind.IDENTIFIER;
37.88 + }
37.89 +
37.90 + @Override
37.91 + public void accept(Visitor v) {
37.92 + v.visitIdent(jcIdent);
37.93 + }
37.94 +
37.95 + @Override
37.96 + public <R, D> R accept(TreeVisitor<R, D> v, D d) {
37.97 + return v.visitIdentifier(this, d);
37.98 + }
37.99 +
37.100 + @Override
37.101 + public String toString() {
37.102 + return ident.toString();
37.103 + }
37.104 +
37.105 + }
37.106 +
37.107 + public static class CatchWildcard extends JCCatch implements IdentifierTree {
37.108 +
37.109 + private final Name ident;
37.110 + private final JCIdent jcIdent;
37.111 +
37.112 + public CatchWildcard(Context ctx, Name ident, JCIdent jcIdent) {
37.113 + super(new FakeVariable(ctx, ident, jcIdent), TreeMaker.instance(ctx).Block(0, List.<JCStatement>nil()));
37.114 + this.ident = ident;
37.115 + this.jcIdent = jcIdent;
37.116 + }
37.117 +
37.118 + public Name getName() {
37.119 + return ident;
37.120 + }
37.121 +
37.122 + @Override
37.123 + public Kind getKind() {
37.124 + return Kind.IDENTIFIER;
37.125 + }
37.126 +
37.127 + @Override
37.128 + public void accept(Visitor v) {
37.129 + v.visitIdent(jcIdent);
37.130 + }
37.131 +
37.132 + @Override
37.133 + public <R, D> R accept(TreeVisitor<R, D> v, D d) {
37.134 + return v.visitIdentifier(this, d);
37.135 + }
37.136 +
37.137 + @Override
37.138 + public String toString() {
37.139 + return "catch " + ident.toString();
37.140 + }
37.141 +
37.142 + }
37.143 +
37.144 + public static class VariableWildcard extends FakeVariable implements IdentifierTree {
37.145 +
37.146 + private final Name ident;
37.147 +
37.148 + public VariableWildcard(Context ctx, Name ident, JCIdent jcIdent) {
37.149 + super(ctx, ident, jcIdent);
37.150 + this.ident = ident;
37.151 + }
37.152 +
37.153 + public Name getName() {
37.154 + return ident;
37.155 + }
37.156 +
37.157 + @Override
37.158 + public Kind getKind() {
37.159 + return Kind.IDENTIFIER;
37.160 + }
37.161 +
37.162 + @Override
37.163 + public <R, D> R accept(TreeVisitor<R, D> v, D d) {
37.164 + return v.visitIdentifier(this, d);
37.165 + }
37.166 +
37.167 + @Override
37.168 + public String toString() {
37.169 + return ident.toString();
37.170 + }
37.171 + }
37.172 +
37.173 + private static class FakeVariable extends JCVariableDecl {
37.174 +
37.175 + private final JCIdent jcIdent;
37.176 +
37.177 + public FakeVariable(Context ctx, Name ident, JCIdent jcIdent) {
37.178 + super(new FakeModifiers(), ident, createType(ctx), null, null);
37.179 + this.sym = new VarSymbol(0, name, type, Symtab.instance(ctx).errSymbol);
37.180 + this.type = vartype.type;
37.181 + this.jcIdent = jcIdent;
37.182 + }
37.183 +
37.184 + private static JCErroneous createType(Context ctx) {
37.185 + JCErroneous err = new JCErroneous(List.<JCTree>nil()) {};
37.186 +
37.187 + err.type = Symtab.instance(ctx).errType;
37.188 +
37.189 + return err;
37.190 + }
37.191 +
37.192 + @Override
37.193 + public void accept(Visitor v) {
37.194 + v.visitIdent(jcIdent);
37.195 + }
37.196 +
37.197 + }
37.198 +
37.199 + private static class FakeModifiers extends JCModifiers {
37.200 + public FakeModifiers() {
37.201 + super(0, List.<JCAnnotation>nil());
37.202 + }
37.203 + }
37.204 +
37.205 + public static class CaseWildcard extends JCCase implements IdentifierTree {
37.206 +
37.207 + private final Name ident;
37.208 + private final JCIdent jcIdent;
37.209 +
37.210 + public CaseWildcard(Context ctx, Name ident, JCIdent jcIdent) {
37.211 + super(jcIdent, List.<JCStatement>nil());
37.212 + this.ident = ident;
37.213 + this.jcIdent = jcIdent;
37.214 + }
37.215 +
37.216 + public Name getName() {
37.217 + return ident;
37.218 + }
37.219 +
37.220 + @Override
37.221 + public Kind getKind() {
37.222 + return Kind.IDENTIFIER;
37.223 + }
37.224 +
37.225 + @Override
37.226 + public void accept(Visitor v) {
37.227 + v.visitIdent(jcIdent);
37.228 + }
37.229 +
37.230 + @Override
37.231 + public <R, D> R accept(TreeVisitor<R, D> v, D d) {
37.232 + return v.visitIdentifier(this, d);
37.233 + }
37.234 +
37.235 + @Override
37.236 + public String toString() {
37.237 + return "case " + ident.toString();
37.238 + }
37.239 +
37.240 + }
37.241 +
37.242 + public static class FakeBlock extends JCBlock {
37.243 +
37.244 + public FakeBlock(long flags, List<JCStatement> stats) {
37.245 + super(flags, stats);
37.246 + }
37.247 +
37.248 + }
37.249 +}
38.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
38.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JavaFixImpl.java Wed May 08 21:47:42 2013 +0200
38.3 @@ -0,0 +1,146 @@
38.4 +/*
38.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
38.6 + *
38.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
38.8 + *
38.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
38.10 + * Other names may be trademarks of their respective owners.
38.11 + *
38.12 + * The contents of this file are subject to the terms of either the GNU
38.13 + * General Public License Version 2 only ("GPL") or the Common
38.14 + * Development and Distribution License("CDDL") (collectively, the
38.15 + * "License"). You may not use this file except in compliance with the
38.16 + * License. You can obtain a copy of the License at
38.17 + * http://www.netbeans.org/cddl-gplv2.html
38.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
38.19 + * specific language governing permissions and limitations under the
38.20 + * License. When distributing the software, include this License Header
38.21 + * Notice in each file and include the License file at
38.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
38.23 + * particular file as subject to the "Classpath" exception as provided
38.24 + * by Oracle in the GPL Version 2 section of the License file that
38.25 + * accompanied this code. If applicable, add the following below the
38.26 + * License Header, with the fields enclosed by brackets [] replaced by
38.27 + * your own identifying information:
38.28 + * "Portions Copyrighted [year] [name of copyright owner]"
38.29 + *
38.30 + * If you wish your version of this file to be governed by only the CDDL
38.31 + * or only the GPL Version 2, indicate your decision by adding
38.32 + * "[Contributor] elects to include this software in this distribution
38.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
38.34 + * single choice of license, a recipient has the option to distribute
38.35 + * your version of this file under either the CDDL, the GPL Version 2 or
38.36 + * to extend the choice of license to its licensees as provided above.
38.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
38.38 + * Version 2 license, then the option applies only if the new code is
38.39 + * made subject to such option by the copyright holder.
38.40 + *
38.41 + * Contributor(s):
38.42 + *
38.43 + * Portions Copyrighted 2008-2009 Sun Microsystems, Inc.
38.44 + */
38.45 +
38.46 +package org.netbeans.modules.java.hints.spiimpl;
38.47 +
38.48 +import com.sun.source.util.TreePath;
38.49 +import java.util.ArrayList;
38.50 +import java.util.Collection;
38.51 +import java.util.Collections;
38.52 +import java.util.HashMap;
38.53 +import java.util.IdentityHashMap;
38.54 +import java.util.List;
38.55 +import java.util.Map;
38.56 +import java.util.Set;
38.57 +import javax.lang.model.type.TypeMirror;
38.58 +import org.netbeans.api.java.source.CompilationInfo;
38.59 +import org.netbeans.api.java.source.JavaSource;
38.60 +import org.netbeans.api.java.source.JavaSource.Phase;
38.61 +import org.netbeans.api.java.source.ModificationResult.Difference;
38.62 +import org.netbeans.api.java.source.Task;
38.63 +import org.netbeans.api.java.source.WorkingCopy;
38.64 +import org.netbeans.api.project.Project;
38.65 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchUtilities;
38.66 +import org.netbeans.modules.java.source.JavaSourceAccessor;
38.67 +import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
38.68 +import org.netbeans.spi.editor.hints.ChangeInfo;
38.69 +import org.netbeans.spi.editor.hints.Fix;
38.70 +import org.netbeans.spi.java.hints.HintContext;
38.71 +import org.netbeans.spi.java.hints.JavaFix;
38.72 +import org.openide.filesystems.FileObject;
38.73 +import org.openide.util.Exceptions;
38.74 +
38.75 +/**TODO: move to better package
38.76 + *
38.77 + * @author Jan Lahoda
38.78 + */
38.79 +public final class JavaFixImpl implements Fix {
38.80 +
38.81 + public final JavaFix jf;
38.82 +
38.83 + public JavaFixImpl(JavaFix jf) {
38.84 + this.jf = jf;
38.85 + }
38.86 +
38.87 + public String getText() {
38.88 + return Accessor.INSTANCE.getText(jf);
38.89 + }
38.90 +
38.91 + public ChangeInfo implement() throws Exception {
38.92 + FileObject file = Accessor.INSTANCE.getFile(jf);
38.93 +
38.94 + BatchUtilities.fixDependencies(file, Collections.singletonList(jf), new IdentityHashMap<Project, Set<String>>());
38.95 +
38.96 + JavaSource js = JavaSource.forFileObject(file);
38.97 +
38.98 + js.runModificationTask(new Task<WorkingCopy>() {
38.99 + public void run(WorkingCopy wc) throws Exception {
38.100 + if (wc.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {
38.101 + return;
38.102 + }
38.103 +
38.104 + Map<FileObject, byte[]> resourceContentChanges = new HashMap<FileObject, byte[]>();
38.105 + Accessor.INSTANCE.process(jf, wc, true, resourceContentChanges, /*Ignored in editor:*/new ArrayList<RefactoringElementImplementation>());
38.106 + Map<FileObject, List<Difference>> resourceContentDiffs = new HashMap<FileObject, List<Difference>>();
38.107 + BatchUtilities.addResourceContentChanges(resourceContentChanges, resourceContentDiffs);
38.108 + JavaSourceAccessor.getINSTANCE().createModificationResult(resourceContentDiffs, Collections.<Object, int[]>emptyMap()).commit();
38.109 + }
38.110 + }).commit();
38.111 +
38.112 + return null;
38.113 + }
38.114 +
38.115 + @Override
38.116 + public boolean equals(Object obj) {
38.117 + if (obj instanceof JavaFixImpl) {
38.118 + return jf.equals(((JavaFixImpl)obj).jf);
38.119 + }
38.120 + return super.equals(obj);
38.121 + }
38.122 +
38.123 + @Override
38.124 + public int hashCode() {
38.125 + return jf.hashCode();
38.126 + }
38.127 +
38.128 + public static abstract class Accessor {
38.129 +
38.130 + static {
38.131 + try {
38.132 + Class.forName(JavaFix.class.getCanonicalName(), true, JavaFix.class.getClassLoader());
38.133 + } catch (ClassNotFoundException ex) {
38.134 + Exceptions.printStackTrace(ex);
38.135 + }
38.136 + }
38.137 +
38.138 + public static Accessor INSTANCE;
38.139 +
38.140 + public abstract String getText(JavaFix jf);
38.141 + public abstract ChangeInfo process(JavaFix jf, WorkingCopy wc, boolean canShowUI, Map<FileObject, byte[]> resourceContent, Collection<? super RefactoringElementImplementation> fileChanges) throws Exception;
38.142 + public abstract FileObject getFile(JavaFix jf);
38.143 + public abstract Map<String, String> getOptions(JavaFix jf);
38.144 + public abstract Fix rewriteFix(CompilationInfo info, String displayName, TreePath what, final String to, Map<String, TreePath> parameters, Map<String, Collection<? extends TreePath>> parametersMulti, final Map<String, String> parameterNames, Map<String, TypeMirror> constraints, Map<String, String> options, String... imports);
38.145 + public abstract Fix createSuppressWarningsFix(CompilationInfo compilationInfo, TreePath treePath, String... keys);
38.146 + public abstract List<Fix> createSuppressWarnings(CompilationInfo compilationInfo, TreePath treePath, String... keys);
38.147 + public abstract List<Fix> resolveDefaultFixes(HintContext ctx, Fix... provided);
38.148 + }
38.149 +}
39.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
39.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/JavaHintsPositionRefresher.java Wed May 08 21:47:42 2013 +0200
39.3 @@ -0,0 +1,157 @@
39.4 +/*
39.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
39.6 + *
39.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
39.8 + *
39.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
39.10 + * Other names may be trademarks of their respective owners.
39.11 + *
39.12 + * The contents of this file are subject to the terms of either the GNU
39.13 + * General Public License Version 2 only ("GPL") or the Common
39.14 + * Development and Distribution License("CDDL") (collectively, the
39.15 + * "License"). You may not use this file except in compliance with the
39.16 + * License. You can obtain a copy of the License at
39.17 + * http://www.netbeans.org/cddl-gplv2.html
39.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
39.19 + * specific language governing permissions and limitations under the
39.20 + * License. When distributing the software, include this License Header
39.21 + * Notice in each file and include the License file at
39.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
39.23 + * particular file as subject to the "Classpath" exception as provided
39.24 + * by Oracle in the GPL Version 2 section of the License file that
39.25 + * accompanied this code. If applicable, add the following below the
39.26 + * License Header, with the fields enclosed by brackets [] replaced by
39.27 + * your own identifying information:
39.28 + * "Portions Copyrighted [year] [name of copyright owner]"
39.29 + *
39.30 + * If you wish your version of this file to be governed by only the CDDL
39.31 + * or only the GPL Version 2, indicate your decision by adding
39.32 + * "[Contributor] elects to include this software in this distribution
39.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
39.34 + * single choice of license, a recipient has the option to distribute
39.35 + * your version of this file under either the CDDL, the GPL Version 2 or
39.36 + * to extend the choice of license to its licensees as provided above.
39.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
39.38 + * Version 2 license, then the option applies only if the new code is
39.39 + * made subject to such option by the copyright holder.
39.40 + *
39.41 + * Contributor(s):
39.42 + *
39.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
39.44 + */
39.45 +
39.46 +package org.netbeans.modules.java.hints.spiimpl;
39.47 +
39.48 +import java.io.IOException;
39.49 +import java.util.ArrayList;
39.50 +import java.util.Collections;
39.51 +import java.util.HashMap;
39.52 +import java.util.Iterator;
39.53 +import java.util.List;
39.54 +import java.util.Map;
39.55 +import java.util.logging.Level;
39.56 +import java.util.logging.Logger;
39.57 +import javax.swing.text.Document;
39.58 +import org.netbeans.api.editor.mimelookup.MimeLookup;
39.59 +import org.netbeans.api.editor.mimelookup.MimeRegistration;
39.60 +import org.netbeans.api.java.source.CompilationController;
39.61 +import org.netbeans.api.java.source.JavaSource;
39.62 +import org.netbeans.api.java.source.JavaSource.Phase;
39.63 +import org.netbeans.api.java.source.Task;
39.64 +import org.netbeans.api.progress.ProgressUtils;
39.65 +import org.netbeans.spi.editor.hints.Context;
39.66 +import org.netbeans.spi.editor.hints.ErrorDescription;
39.67 +import org.netbeans.spi.editor.hints.PositionRefresher;
39.68 +import org.netbeans.modules.java.hints.providers.spi.PositionRefresherHelper;
39.69 +import org.openide.util.Exceptions;
39.70 +import org.openide.util.NbBundle;
39.71 +
39.72 +/**
39.73 + * Refreshes all Java Hints on current line upon Alt-Enter or mouseclick
39.74 + * @author Max Sauer
39.75 + */
39.76 +@MimeRegistration(mimeType="text/x-java", service=PositionRefresher.class)
39.77 +public class JavaHintsPositionRefresher implements PositionRefresher {
39.78 +
39.79 + private static final Logger LOG = Logger.getLogger(JavaHintsPositionRefresher.class.getName());
39.80 +
39.81 + @Override
39.82 + public Map<String, List<ErrorDescription>> getErrorDescriptionsAt(final Context context, final Document doc) {
39.83 + final List<PositionRefresherHelper> refreshers = new ArrayList<PositionRefresherHelper>(MimeLookup.getLookup("text/x-java").lookupAll(PositionRefresherHelper.class));
39.84 +
39.85 + for (Iterator<PositionRefresherHelper> it = refreshers.iterator(); it.hasNext();) {
39.86 + PositionRefresherHelper h = it.next();
39.87 +
39.88 + if (h.upToDateCheck(context, doc)) {
39.89 + LOG.log(Level.FINE, "Not computing warnings for {0}, results are up-to-date.", h.getKey());
39.90 + it.remove();
39.91 + } else {
39.92 + LOG.log(Level.FINE, "Will compute warnings for {0}, results not up-to-date.", h.getKey());
39.93 + }
39.94 + }
39.95 +
39.96 + if (refreshers.isEmpty()) return Collections.emptyMap();
39.97 +
39.98 + final JavaSource js = JavaSource.forDocument(doc);
39.99 +
39.100 + if (js == null) {
39.101 + LOG.log(Level.FINE, "No JavaSource associated to: {0}", new Object[] {doc, doc.getProperty(Document.StreamDescriptionProperty)});
39.102 + return Collections.emptyMap();
39.103 + }
39.104 +
39.105 + final Map<String, List<ErrorDescription>> eds = new HashMap<String, List<ErrorDescription>>();
39.106 +
39.107 + Runnable r = new Runnable() {
39.108 +
39.109 + public void run() {
39.110 + try {
39.111 + js.runUserActionTask(new RefreshTask(eds, refreshers, context, doc), true);
39.112 + } catch (IOException ex) {
39.113 + Exceptions.printStackTrace(ex);
39.114 + }
39.115 + }
39.116 + };
39.117 +
39.118 + ProgressUtils.runOffEventDispatchThread(r, NbBundle.getMessage(JavaHintsPositionRefresher.class, "Refresh_hints"), context.getCancel(), false); // NOI18N
39.119 +
39.120 + return eds;
39.121 + }
39.122 +
39.123 +
39.124 + private class RefreshTask implements Task<CompilationController> {
39.125 +
39.126 + private final Map<String, List<ErrorDescription>> eds;
39.127 + private final List<PositionRefresherHelper> refreshers;
39.128 + private final Context ctx;
39.129 + private final Document doc;
39.130 +
39.131 + public RefreshTask(Map<String, List<ErrorDescription>> eds, List<PositionRefresherHelper> refreshers, Context ctx, Document doc) {
39.132 + this.eds = eds;
39.133 + this.refreshers = refreshers;
39.134 + this.ctx = ctx;
39.135 + this.doc = doc;
39.136 + }
39.137 +
39.138 + public void run(CompilationController controller) throws Exception {
39.139 + if (controller.toPhase(JavaSource.Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {
39.140 + return ;
39.141 + }
39.142 +
39.143 + Document doc = controller.getDocument();
39.144 +
39.145 + if (doc == null) {
39.146 + return;
39.147 + }
39.148 +
39.149 + for (PositionRefresherHelper h : refreshers) {
39.150 + if (ctx.isCanceled()) {
39.151 + return;
39.152 + }
39.153 +
39.154 + eds.put(h.getKey(), h.getErrorDescriptionsAt(controller, ctx, doc));
39.155 + }
39.156 + }
39.157 +
39.158 + }
39.159 +
39.160 +}
40.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
40.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/MessageImpl.java Wed May 08 21:47:42 2013 +0200
40.3 @@ -0,0 +1,61 @@
40.4 +/*
40.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
40.6 + *
40.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
40.8 + *
40.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
40.10 + * Other names may be trademarks of their respective owners.
40.11 + *
40.12 + * The contents of this file are subject to the terms of either the GNU
40.13 + * General Public License Version 2 only ("GPL") or the Common
40.14 + * Development and Distribution License("CDDL") (collectively, the
40.15 + * "License"). You may not use this file except in compliance with the
40.16 + * License. You can obtain a copy of the License at
40.17 + * http://www.netbeans.org/cddl-gplv2.html
40.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
40.19 + * specific language governing permissions and limitations under the
40.20 + * License. When distributing the software, include this License Header
40.21 + * Notice in each file and include the License file at
40.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
40.23 + * particular file as subject to the "Classpath" exception as provided
40.24 + * by Oracle in the GPL Version 2 section of the License file that
40.25 + * accompanied this code. If applicable, add the following below the
40.26 + * License Header, with the fields enclosed by brackets [] replaced by
40.27 + * your own identifying information:
40.28 + * "Portions Copyrighted [year] [name of copyright owner]"
40.29 + *
40.30 + * If you wish your version of this file to be governed by only the CDDL
40.31 + * or only the GPL Version 2, indicate your decision by adding
40.32 + * "[Contributor] elects to include this software in this distribution
40.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
40.34 + * single choice of license, a recipient has the option to distribute
40.35 + * your version of this file under either the CDDL, the GPL Version 2 or
40.36 + * to extend the choice of license to its licensees as provided above.
40.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
40.38 + * Version 2 license, then the option applies only if the new code is
40.39 + * made subject to such option by the copyright holder.
40.40 + *
40.41 + * Contributor(s):
40.42 + *
40.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
40.44 + */
40.45 +
40.46 +package org.netbeans.modules.java.hints.spiimpl;
40.47 +
40.48 +import org.netbeans.spi.java.hints.HintContext.MessageKind;
40.49 +
40.50 +/**
40.51 + *
40.52 + * @author lahvacc
40.53 + */
40.54 +public class MessageImpl {
40.55 +
40.56 + public final MessageKind kind;
40.57 + public final String text;
40.58 +
40.59 + public MessageImpl(MessageKind kind, String text) {
40.60 + this.kind = kind;
40.61 + this.text = text;
40.62 + }
40.63 +
40.64 +}
41.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
41.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/RulesManager.java Wed May 08 21:47:42 2013 +0200
41.3 @@ -0,0 +1,68 @@
41.4 +/*
41.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
41.6 + *
41.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
41.8 + *
41.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
41.10 + * Other names may be trademarks of their respective owners.
41.11 + *
41.12 + * The contents of this file are subject to the terms of either the GNU
41.13 + * General Public License Version 2 only ("GPL") or the Common
41.14 + * Development and Distribution License("CDDL") (collectively, the
41.15 + * "License"). You may not use this file except in compliance with the
41.16 + * License. You can obtain a copy of the License at
41.17 + * http://www.netbeans.org/cddl-gplv2.html
41.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
41.19 + * specific language governing permissions and limitations under the
41.20 + * License. When distributing the software, include this License Header
41.21 + * Notice in each file and include the License file at
41.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
41.23 + * particular file as subject to the "Classpath" exception as provided
41.24 + * by Oracle in the GPL Version 2 section of the License file that
41.25 + * accompanied this code. If applicable, add the following below the
41.26 + * License Header, with the fields enclosed by brackets [] replaced by
41.27 + * your own identifying information:
41.28 + * "Portions Copyrighted [year] [name of copyright owner]"
41.29 + *
41.30 + * If you wish your version of this file to be governed by only the CDDL
41.31 + * or only the GPL Version 2, indicate your decision by adding
41.32 + * "[Contributor] elects to include this software in this distribution
41.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
41.34 + * single choice of license, a recipient has the option to distribute
41.35 + * your version of this file under either the CDDL, the GPL Version 2 or
41.36 + * to extend the choice of license to its licensees as provided above.
41.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
41.38 + * Version 2 license, then the option applies only if the new code is
41.39 + * made subject to such option by the copyright holder.
41.40 + *
41.41 + * Contributor(s):
41.42 + *
41.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
41.44 + */
41.45 +
41.46 +package org.netbeans.modules.java.hints.spiimpl;
41.47 +
41.48 +import java.util.Collection;
41.49 +import java.util.Map;
41.50 +import java.util.concurrent.atomic.AtomicBoolean;
41.51 +import org.netbeans.api.annotations.common.NullAllowed;
41.52 +import org.netbeans.api.java.classpath.ClassPath;
41.53 +import org.netbeans.api.java.source.CompilationInfo;
41.54 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
41.55 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
41.56 +import org.openide.util.Lookup;
41.57 +
41.58 +/**
41.59 + *
41.60 + * @author lahvac
41.61 + */
41.62 +public abstract class RulesManager {
41.63 +
41.64 + public static RulesManager getInstance() {
41.65 + return Lookup.getDefault().lookup(RulesManager.class);
41.66 + }
41.67 +
41.68 + public abstract Map<HintMetadata, ? extends Collection<? extends HintDescription>> readHints(@NullAllowed CompilationInfo info, @NullAllowed Collection<? extends ClassPath> from, @NullAllowed AtomicBoolean cancel);
41.69 + public abstract void reload(); //XXX
41.70 +
41.71 +}
42.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
42.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/RulesManagerImpl.java Wed May 08 21:47:42 2013 +0200
42.3 @@ -0,0 +1,140 @@
42.4 +/*
42.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
42.6 + *
42.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
42.8 + *
42.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
42.10 + * Other names may be trademarks of their respective owners.
42.11 + *
42.12 + * The contents of this file are subject to the terms of either the GNU
42.13 + * General Public License Version 2 only ("GPL") or the Common
42.14 + * Development and Distribution License("CDDL") (collectively, the
42.15 + * "License"). You may not use this file except in compliance with the
42.16 + * License. You can obtain a copy of the License at
42.17 + * http://www.netbeans.org/cddl-gplv2.html
42.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
42.19 + * specific language governing permissions and limitations under the
42.20 + * License. When distributing the software, include this License Header
42.21 + * Notice in each file and include the License file at
42.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
42.23 + * particular file as subject to the "Classpath" exception as provided
42.24 + * by Oracle in the GPL Version 2 section of the License file that
42.25 + * accompanied this code. If applicable, add the following below the
42.26 + * License Header, with the fields enclosed by brackets [] replaced by
42.27 + * your own identifying information:
42.28 + * "Portions Copyrighted [year] [name of copyright owner]"
42.29 + *
42.30 + * If you wish your version of this file to be governed by only the CDDL
42.31 + * or only the GPL Version 2, indicate your decision by adding
42.32 + * "[Contributor] elects to include this software in this distribution
42.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
42.34 + * single choice of license, a recipient has the option to distribute
42.35 + * your version of this file under either the CDDL, the GPL Version 2 or
42.36 + * to extend the choice of license to its licensees as provided above.
42.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
42.38 + * Version 2 license, then the option applies only if the new code is
42.39 + * made subject to such option by the copyright holder.
42.40 + *
42.41 + * Contributor(s):
42.42 + *
42.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
42.44 + */
42.45 +
42.46 +package org.netbeans.modules.java.hints.spiimpl;
42.47 +
42.48 +import java.util.ArrayList;
42.49 +import java.util.Collection;
42.50 +import java.util.Collections;
42.51 +import java.util.HashMap;
42.52 +import java.util.LinkedList;
42.53 +import java.util.Map;
42.54 +import java.util.Map.Entry;
42.55 +import java.util.concurrent.atomic.AtomicBoolean;
42.56 +import org.netbeans.api.java.classpath.ClassPath;
42.57 +import org.netbeans.api.java.source.ClasspathInfo;
42.58 +import org.netbeans.api.java.source.ClasspathInfo.PathKind;
42.59 +import org.netbeans.api.java.source.CompilationInfo;
42.60 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
42.61 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
42.62 +import org.netbeans.modules.java.hints.providers.spi.ClassPathBasedHintProvider;
42.63 +import org.netbeans.modules.java.hints.providers.spi.ElementBasedHintProvider;
42.64 +import org.netbeans.modules.java.hints.providers.spi.HintProvider;
42.65 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
42.66 +import org.openide.util.Lookup;
42.67 +import org.openide.util.lookup.ServiceProvider;
42.68 +
42.69 +/**
42.70 + *
42.71 + * @author lahvac
42.72 + */
42.73 +@ServiceProvider(service=RulesManager.class)
42.74 +public class RulesManagerImpl extends RulesManager {
42.75 +
42.76 + private final Map<HintMetadata, Collection<HintDescription>> globalHints = new HashMap<HintMetadata, Collection<HintDescription>>();
42.77 +
42.78 + public RulesManagerImpl() {
42.79 + reload();
42.80 + }
42.81 +
42.82 + @Override
42.83 + public void reload() {
42.84 + globalHints.clear();
42.85 +
42.86 + for (HintProvider p : Lookup.getDefault().lookupAll(HintProvider.class)) {
42.87 + Map<HintMetadata, ? extends Collection<? extends HintDescription>> pHints = p.computeHints();
42.88 +
42.89 + if (pHints != null) {
42.90 + for (Entry<HintMetadata, ? extends Collection<? extends HintDescription>> e : pHints.entrySet()) {
42.91 + globalHints.put(e.getKey(), new ArrayList<HintDescription>(e.getValue()));
42.92 + }
42.93 + }
42.94 + }
42.95 + }
42.96 +
42.97 + @Override
42.98 + public Map<HintMetadata, ? extends Collection<? extends HintDescription>> readHints(CompilationInfo info, Collection<? extends ClassPath> from, AtomicBoolean cancel) {
42.99 + Map<HintMetadata, Collection<HintDescription>> result = new HashMap<HintMetadata, Collection<HintDescription>>(globalHints);
42.100 +
42.101 + if (info != null) {
42.102 + for (ElementBasedHintProvider provider : Lookup.getDefault().lookupAll(ElementBasedHintProvider.class)) {
42.103 + sortByMetadata(provider.computeHints(info), result);
42.104 + }
42.105 + }
42.106 +
42.107 + if (from == null) {
42.108 + if (info != null) {
42.109 + ClasspathInfo cpInfo = info.getClasspathInfo();
42.110 + LinkedList<ClassPath> cps = new LinkedList<ClassPath>();
42.111 +
42.112 + cps.add(cpInfo.getClassPath(PathKind.BOOT));
42.113 + cps.add(cpInfo.getClassPath(PathKind.COMPILE));
42.114 + cps.add(cpInfo.getClassPath(PathKind.SOURCE));
42.115 +
42.116 + from = cps;
42.117 + } else {
42.118 + from = Collections.emptyList();
42.119 + }
42.120 + }
42.121 +
42.122 + ClassPath compound = ClassPathSupport.createProxyClassPath(from.toArray(new ClassPath[0]));
42.123 +
42.124 + for (ClassPathBasedHintProvider p : Lookup.getDefault().lookupAll(ClassPathBasedHintProvider.class)) {
42.125 + sortByMetadata(p.computeHints(compound), result);
42.126 + }
42.127 +
42.128 + return result;
42.129 + }
42.130 +
42.131 + public static void sortByMetadata(Collection<? extends HintDescription> listedHints, Map<HintMetadata, Collection<HintDescription>> into) {
42.132 + for (HintDescription hd : listedHints) {
42.133 + Collection<HintDescription> h = into.get(hd.getMetadata());
42.134 +
42.135 + if (h == null) {
42.136 + into.put(hd.getMetadata(), h = new ArrayList<HintDescription>());
42.137 + }
42.138 +
42.139 + h.add(hd);
42.140 + }
42.141 + }
42.142 +
42.143 +}
43.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
43.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/SPIAccessor.java Wed May 08 21:47:42 2013 +0200
43.3 @@ -0,0 +1,85 @@
43.4 +/*
43.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
43.6 + *
43.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
43.8 + *
43.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
43.10 + * Other names may be trademarks of their respective owners.
43.11 + *
43.12 + * The contents of this file are subject to the terms of either the GNU
43.13 + * General Public License Version 2 only ("GPL") or the Common
43.14 + * Development and Distribution License("CDDL") (collectively, the
43.15 + * "License"). You may not use this file except in compliance with the
43.16 + * License. You can obtain a copy of the License at
43.17 + * http://www.netbeans.org/cddl-gplv2.html
43.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
43.19 + * specific language governing permissions and limitations under the
43.20 + * License. When distributing the software, include this License Header
43.21 + * Notice in each file and include the License file at
43.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
43.23 + * particular file as subject to the "Classpath" exception as provided
43.24 + * by Oracle in the GPL Version 2 section of the License file that
43.25 + * accompanied this code. If applicable, add the following below the
43.26 + * License Header, with the fields enclosed by brackets [] replaced by
43.27 + * your own identifying information:
43.28 + * "Portions Copyrighted [year] [name of copyright owner]"
43.29 + *
43.30 + * If you wish your version of this file to be governed by only the CDDL
43.31 + * or only the GPL Version 2, indicate your decision by adding
43.32 + * "[Contributor] elects to include this software in this distribution
43.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
43.34 + * single choice of license, a recipient has the option to distribute
43.35 + * your version of this file under either the CDDL, the GPL Version 2 or
43.36 + * to extend the choice of license to its licensees as provided above.
43.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
43.38 + * Version 2 license, then the option applies only if the new code is
43.39 + * made subject to such option by the copyright holder.
43.40 + *
43.41 + * Contributor(s):
43.42 + *
43.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
43.44 + */
43.45 +package org.netbeans.modules.java.hints.spiimpl;
43.46 +
43.47 +import com.sun.source.util.TreePath;
43.48 +import java.util.Collection;
43.49 +import java.util.Map;
43.50 +import java.util.concurrent.atomic.AtomicBoolean;
43.51 +import javax.lang.model.type.TypeMirror;
43.52 +import org.netbeans.api.java.source.CompilationInfo;
43.53 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
43.54 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
43.55 +import org.netbeans.spi.java.hints.HintContext;
43.56 +import org.openide.util.Exceptions;
43.57 +
43.58 +/**
43.59 + *
43.60 + * @author lahvac
43.61 + */
43.62 +public abstract class SPIAccessor {
43.63 +
43.64 + private static volatile SPIAccessor accessor;
43.65 +
43.66 + public static synchronized SPIAccessor getINSTANCE() {
43.67 + if (accessor == null) {
43.68 + try {
43.69 + Class.forName(HintContext.class.getName(), true, HintContext.class.getClassLoader());
43.70 + assert accessor != null;
43.71 + } catch (ClassNotFoundException e) {
43.72 + Exceptions.printStackTrace(e);
43.73 + }
43.74 + }
43.75 + return accessor;
43.76 + }
43.77 +
43.78 + public static void setINSTANCE(SPIAccessor instance) {
43.79 + assert instance != null;
43.80 + accessor = instance;
43.81 + }
43.82 +
43.83 + public abstract HintContext createHintContext(CompilationInfo info, HintsSettings settings, HintMetadata metadata, TreePath path, Map<String, TreePath> variables, Map<String, Collection<? extends TreePath>> multiVariables, Map<String, String> variableNames, Map<String, TypeMirror> constraints, Collection<? super MessageImpl> problems, boolean bulkMode, AtomicBoolean cancel, int caret);
43.84 + public abstract HintContext createHintContext(CompilationInfo info, HintsSettings settings, HintMetadata metadata, TreePath path, Map<String, TreePath> variables, Map<String, Collection<? extends TreePath>> multiVariables, Map<String, String> variableNames);
43.85 + public abstract HintMetadata getHintMetadata(HintContext ctx);
43.86 + public abstract HintsSettings getHintSettings(HintContext ctx);
43.87 +
43.88 +}
44.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
44.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/SyntheticFix.java Wed May 08 21:47:42 2013 +0200
44.3 @@ -0,0 +1,46 @@
44.4 +/*
44.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
44.6 + *
44.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
44.8 + *
44.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
44.10 + * Other names may be trademarks of their respective owners.
44.11 + *
44.12 + * The contents of this file are subject to the terms of either the GNU
44.13 + * General Public License Version 2 only ("GPL") or the Common Development and
44.14 + * Distribution License("CDDL") (collectively, the "License"). You may not use
44.15 + * this file except in compliance with the License. You can obtain a copy of
44.16 + * the License at http://www.netbeans.org/cddl-gplv2.html or
44.17 + * nbbuild/licenses/CDDL-GPL-2-CP. See the License for the specific language
44.18 + * governing permissions and limitations under the License. When distributing
44.19 + * the software, include this License Header Notice in each file and include
44.20 + * the License file at nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
44.21 + * particular file as subject to the "Classpath" exception as provided by
44.22 + * Oracle in the GPL Version 2 section of the License file that accompanied
44.23 + * this code. If applicable, add the following below the License Header, with
44.24 + * the fields enclosed by brackets [] replaced by your own identifying
44.25 + * information: "Portions Copyrighted [year] [name of copyright owner]"
44.26 + *
44.27 + * If you wish your version of this file to be governed by only the CDDL or
44.28 + * only the GPL Version 2, indicate your decision by adding "[Contributor]
44.29 + * elects to include this software in this distribution under the [CDDL or GPL
44.30 + * Version 2] license." If you do not indicate a single choice of license, a
44.31 + * recipient has the option to distribute your version of this file under
44.32 + * either the CDDL, the GPL Version 2 or to extend the choice of license to its
44.33 + * licensees as provided above. However, if you add GPL Version 2 code and
44.34 + * therefore, elected the GPL Version 2 license, then the option applies only
44.35 + * if the new code is made subject to such option by the copyright holder.
44.36 + *
44.37 + * Contributor(s):
44.38 + *
44.39 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
44.40 + */
44.41 +package org.netbeans.modules.java.hints.spiimpl;
44.42 +
44.43 +/**
44.44 + *
44.45 + * @author lahvac
44.46 + */
44.47 +public interface SyntheticFix {
44.48 +
44.49 +}
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/Utilities.java Wed May 08 21:47:42 2013 +0200
45.3 @@ -0,0 +1,1538 @@
45.4 +/*
45.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
45.6 + *
45.7 + * Copyright 2008-2010 Sun Microsystems, Inc. All rights reserved.
45.8 + *
45.9 + * The contents of this file are subject to the terms of either the GNU
45.10 + * General Public License Version 2 only ("GPL") or the Common
45.11 + * Development and Distribution License("CDDL") (collectively, the
45.12 + * "License"). You may not use this file except in compliance with the
45.13 + * License. You can obtain a copy of the License at
45.14 + * http://www.netbeans.org/cddl-gplv2.html
45.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
45.16 + * specific language governing permissions and limitations under the
45.17 + * License. When distributing the software, include this License Header
45.18 + * Notice in each file and include the License file at
45.19 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
45.20 + * particular file as subject to the "Classpath" exception as provided
45.21 + * by Sun in the GPL Version 2 section of the License file that
45.22 + * accompanied this code. If applicable, add the following below the
45.23 + * License Header, with the fields enclosed by brackets [] replaced by
45.24 + * your own identifying information:
45.25 + * "Portions Copyrighted [year] [name of copyright owner]"
45.26 + *
45.27 + * If you wish your version of this file to be governed by only the CDDL
45.28 + * or only the GPL Version 2, indicate your decision by adding
45.29 + * "[Contributor] elects to include this software in this distribution
45.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
45.31 + * single choice of license, a recipient has the option to distribute
45.32 + * your version of this file under either the CDDL, the GPL Version 2 or
45.33 + * to extend the choice of license to its licensees as provided above.
45.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
45.35 + * Version 2 license, then the option applies only if the new code is
45.36 + * made subject to such option by the copyright holder.
45.37 + *
45.38 + * Contributor(s):
45.39 + *
45.40 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
45.41 + */
45.42 +
45.43 +package org.netbeans.modules.java.hints.spiimpl;
45.44 +
45.45 +import com.sun.source.tree.AnnotationTree;
45.46 +import com.sun.source.tree.AssignmentTree;
45.47 +import com.sun.source.tree.BlockTree;
45.48 +import com.sun.source.tree.ClassTree;
45.49 +import com.sun.source.tree.CompilationUnitTree;
45.50 +import com.sun.source.tree.ExpressionStatementTree;
45.51 +import com.sun.source.tree.ExpressionTree;
45.52 +import com.sun.source.tree.IdentifierTree;
45.53 +import com.sun.source.tree.ImportTree;
45.54 +import com.sun.source.tree.LiteralTree;
45.55 +import com.sun.source.tree.MemberSelectTree;
45.56 +import com.sun.source.tree.MethodInvocationTree;
45.57 +import com.sun.source.tree.MethodTree;
45.58 +import com.sun.source.tree.ModifiersTree;
45.59 +import com.sun.source.tree.NewArrayTree;
45.60 +import com.sun.source.tree.NewClassTree;
45.61 +import com.sun.source.tree.Scope;
45.62 +import com.sun.source.tree.StatementTree;
45.63 +import com.sun.source.tree.SwitchTree;
45.64 +import com.sun.source.tree.Tree;
45.65 +import com.sun.source.tree.Tree.Kind;
45.66 +import com.sun.source.tree.TypeParameterTree;
45.67 +import com.sun.source.tree.VariableTree;
45.68 +import com.sun.source.util.SourcePositions;
45.69 +import com.sun.source.util.TreePath;
45.70 +import com.sun.source.util.TreePathScanner;
45.71 +import com.sun.source.util.TreeScanner;
45.72 +import com.sun.source.util.Trees;
45.73 +import com.sun.tools.javac.api.JavacScope;
45.74 +import com.sun.tools.javac.api.JavacTaskImpl;
45.75 +import com.sun.tools.javac.api.JavacTrees;
45.76 +import com.sun.tools.javac.code.Flags;
45.77 +import com.sun.tools.javac.code.Symtab;
45.78 +import com.sun.tools.javac.code.Type;
45.79 +import com.sun.tools.javac.comp.Attr;
45.80 +import com.sun.tools.javac.comp.AttrContext;
45.81 +import com.sun.tools.javac.comp.Env;
45.82 +import com.sun.tools.javac.comp.Todo;
45.83 +import com.sun.tools.javac.main.JavaCompiler;
45.84 +import com.sun.tools.javac.parser.JavacParser;
45.85 +import com.sun.tools.javac.parser.Lexer;
45.86 +import com.sun.tools.javac.parser.Parser;
45.87 +import com.sun.tools.javac.parser.ParserFactory;
45.88 +import com.sun.tools.javac.parser.Scanner;
45.89 +import com.sun.tools.javac.parser.ScannerFactory;
45.90 +import com.sun.tools.javac.parser.Tokens.Token;
45.91 +import com.sun.tools.javac.parser.Tokens.TokenKind;
45.92 +import com.sun.tools.javac.tree.JCTree;
45.93 +import com.sun.tools.javac.tree.JCTree.JCCase;
45.94 +import com.sun.tools.javac.tree.JCTree.JCCatch;
45.95 +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
45.96 +import com.sun.tools.javac.tree.JCTree.JCExpression;
45.97 +import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
45.98 +import com.sun.tools.javac.tree.JCTree.JCIdent;
45.99 +import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
45.100 +import com.sun.tools.javac.tree.JCTree.JCModifiers;
45.101 +import com.sun.tools.javac.tree.JCTree.JCStatement;
45.102 +import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
45.103 +import com.sun.tools.javac.util.Context;
45.104 +import com.sun.tools.javac.util.JCDiagnostic;
45.105 +import com.sun.tools.javac.util.ListBuffer;
45.106 +import com.sun.tools.javac.util.Log;
45.107 +import com.sun.tools.javac.util.Names;
45.108 +import com.sun.tools.javadoc.Messager;
45.109 +import java.io.File;
45.110 +import java.io.IOException;
45.111 +import java.net.URI;
45.112 +import java.nio.CharBuffer;
45.113 +import java.util.Arrays;
45.114 +import java.util.Collection;
45.115 +import java.util.Collections;
45.116 +import java.util.EnumSet;
45.117 +import java.util.HashMap;
45.118 +import java.util.HashSet;
45.119 +import java.util.Iterator;
45.120 +import java.util.LinkedList;
45.121 +import java.util.List;
45.122 +import java.util.Locale;
45.123 +import java.util.Map;
45.124 +import java.util.Map.Entry;
45.125 +import java.util.Set;
45.126 +import java.util.concurrent.atomic.AtomicBoolean;
45.127 +import javax.lang.model.element.AnnotationMirror;
45.128 +import javax.lang.model.element.AnnotationValue;
45.129 +import javax.lang.model.element.AnnotationValueVisitor;
45.130 +import javax.lang.model.element.Element;
45.131 +import javax.lang.model.element.ElementKind;
45.132 +import javax.lang.model.element.ExecutableElement;
45.133 +import javax.lang.model.element.Modifier;
45.134 +import javax.lang.model.element.Name;
45.135 +import javax.lang.model.element.TypeElement;
45.136 +import javax.lang.model.element.VariableElement;
45.137 +import javax.lang.model.type.TypeKind;
45.138 +import javax.lang.model.type.TypeMirror;
45.139 +import javax.lang.model.util.Elements;
45.140 +import javax.tools.Diagnostic;
45.141 +import javax.tools.JavaCompiler.CompilationTask;
45.142 +import javax.tools.JavaFileObject;
45.143 +import javax.tools.SimpleJavaFileObject;
45.144 +import org.netbeans.api.annotations.common.CheckForNull;
45.145 +import org.netbeans.api.annotations.common.NonNull;
45.146 +import org.netbeans.api.java.classpath.ClassPath;
45.147 +import org.netbeans.api.java.platform.JavaPlatform;
45.148 +import org.netbeans.api.java.platform.JavaPlatformManager;
45.149 +import org.netbeans.api.java.queries.SourceForBinaryQuery;
45.150 +import org.netbeans.api.java.queries.SourceForBinaryQuery.Result2;
45.151 +import org.netbeans.api.java.source.ClasspathInfo;
45.152 +import org.netbeans.api.java.source.CompilationInfo;
45.153 +import org.netbeans.api.java.source.CompilationInfo.CacheClearPolicy;
45.154 +import org.netbeans.api.java.source.SourceUtils;
45.155 +import org.netbeans.api.java.source.TreeMaker;
45.156 +import org.netbeans.modules.java.hints.providers.spi.ClassPathBasedHintProvider;
45.157 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
45.158 +import org.netbeans.modules.java.hints.providers.spi.Trigger.PatternDescription;
45.159 +import org.netbeans.modules.java.hints.spiimpl.JackpotTrees.CatchWildcard;
45.160 +import org.netbeans.modules.java.hints.spiimpl.JackpotTrees.VariableWildcard;
45.161 +import org.netbeans.modules.java.source.JavaSourceAccessor;
45.162 +import org.netbeans.modules.java.source.builder.TreeFactory;
45.163 +import org.netbeans.lib.nbjavac.services.CancelService;
45.164 +import org.netbeans.lib.nbjavac.services.NBParserFactory.NBJavacParser;
45.165 +import org.netbeans.lib.nbjavac.services.NBParserFactory;
45.166 +import org.netbeans.modules.java.hints.spiimpl.JackpotTrees.AnnotationWildcard;
45.167 +import org.netbeans.modules.java.hints.spiimpl.JackpotTrees.FakeBlock;
45.168 +import org.netbeans.modules.java.source.parsing.FileObjects;
45.169 +import org.netbeans.modules.java.source.pretty.ImportAnalysis2;
45.170 +import org.netbeans.modules.java.source.transform.ImmutableTreeTranslator;
45.171 +import org.netbeans.spi.editor.hints.Severity;
45.172 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
45.173 +import org.openide.filesystems.FileObject;
45.174 +import org.openide.filesystems.FileUtil;
45.175 +import org.openide.util.Lookup;
45.176 +import org.openide.util.NbCollections;
45.177 +import org.openide.util.lookup.ServiceProvider;
45.178 +
45.179 +/**
45.180 + *
45.181 + * @author Jan Lahoda
45.182 + */
45.183 +public class Utilities {
45.184 +
45.185 + private Utilities() {}
45.186 +
45.187 + public static Set<Severity> disableErrors(FileObject file) {
45.188 + if (file.getAttribute(DISABLE_ERRORS) != null) {
45.189 + return EnumSet.allOf(Severity.class);
45.190 + }
45.191 + if (!file.canWrite() && FileUtil.getArchiveFile(file) != null) {
45.192 + return EnumSet.allOf(Severity.class);
45.193 + }
45.194 +
45.195 + return EnumSet.noneOf(Severity.class);
45.196 + }
45.197 +
45.198 + private static final String DISABLE_ERRORS = "disable-java-errors";
45.199 +
45.200 +
45.201 + public static <E> Iterable<E> checkedIterableByFilter(final Iterable raw, final Class<E> type, final boolean strict) {
45.202 + return new Iterable<E>() {
45.203 + public Iterator<E> iterator() {
45.204 + return NbCollections.checkedIteratorByFilter(raw.iterator(), type, strict);
45.205 + }
45.206 + };
45.207 + }
45.208 +
45.209 +// public static AnnotationTree constructConstraint(WorkingCopy wc, String name, TypeMirror tm) {
45.210 +// TreeMaker make = wc.getTreeMaker();
45.211 +// ExpressionTree variable = prepareAssignment(make, "variable", make.Literal(name));
45.212 +// ExpressionTree type = prepareAssignment(make, "type", make.MemberSelect((ExpressionTree) make.Type(wc.getTypes().erasure(tm)), "class"));
45.213 +// TypeElement constraint = wc.getElements().getTypeElement(Annotations.CONSTRAINT.toFQN());
45.214 +//
45.215 +// return make.Annotation(make.QualIdent(constraint), Arrays.asList(variable, type));
45.216 +// }
45.217 +
45.218 + public static ExpressionTree prepareAssignment(TreeMaker make, String name, ExpressionTree value) {
45.219 + return make.Assignment(make.Identifier(name), value);
45.220 + }
45.221 +
45.222 + public static ExpressionTree findValue(AnnotationTree m, String name) {
45.223 + for (ExpressionTree et : m.getArguments()) {
45.224 + if (et.getKind() == Kind.ASSIGNMENT) {
45.225 + AssignmentTree at = (AssignmentTree) et;
45.226 + String varName = ((IdentifierTree) at.getVariable()).getName().toString();
45.227 +
45.228 + if (varName.equals(name)) {
45.229 + return at.getExpression();
45.230 + }
45.231 + }
45.232 +
45.233 + if (et instanceof LiteralTree/*XXX*/ && "value".equals(name)) {
45.234 + return et;
45.235 + }
45.236 + }
45.237 +
45.238 + return null;
45.239 + }
45.240 +
45.241 + public static List<AnnotationTree> findArrayValue(AnnotationTree at, String name) {
45.242 + ExpressionTree fixesArray = findValue(at, name);
45.243 + List<AnnotationTree> fixes = new LinkedList<AnnotationTree>();
45.244 +
45.245 + if (fixesArray != null && fixesArray.getKind() == Kind.NEW_ARRAY) {
45.246 + NewArrayTree trees = (NewArrayTree) fixesArray;
45.247 +
45.248 + for (ExpressionTree fix : trees.getInitializers()) {
45.249 + if (fix.getKind() == Kind.ANNOTATION) {
45.250 + fixes.add((AnnotationTree) fix);
45.251 + }
45.252 + }
45.253 + }
45.254 +
45.255 + if (fixesArray != null && fixesArray.getKind() == Kind.ANNOTATION) {
45.256 + fixes.add((AnnotationTree) fixesArray);
45.257 + }
45.258 +
45.259 + return fixes;
45.260 + }
45.261 +
45.262 + public static boolean isPureMemberSelect(Tree mst, boolean allowVariables) {
45.263 + switch (mst.getKind()) {
45.264 + case IDENTIFIER: return allowVariables || ((IdentifierTree) mst).getName().charAt(0) != '$';
45.265 + case MEMBER_SELECT: return isPureMemberSelect(((MemberSelectTree) mst).getExpression(), allowVariables);
45.266 + default: return false;
45.267 + }
45.268 + }
45.269 +
45.270 + public static Map<String, Collection<HintDescription>> sortOutHints(Iterable<? extends HintDescription> hints, Map<String, Collection<HintDescription>> output) {
45.271 + for (HintDescription d : hints) {
45.272 + Collection<HintDescription> h = output.get(d.getMetadata().displayName);
45.273 +
45.274 + if (h == null) {
45.275 + output.put(d.getMetadata().displayName, h = new LinkedList<HintDescription>());
45.276 + }
45.277 +
45.278 + h.add(d);
45.279 + }
45.280 +
45.281 + return output;
45.282 + }
45.283 +
45.284 + public static List<HintDescription> listAllHints(Set<ClassPath> cps) {
45.285 + List<HintDescription> result = new LinkedList<HintDescription>();
45.286 +
45.287 + for (Collection<? extends HintDescription> hints : RulesManager.getInstance().readHints(null, cps, new AtomicBoolean()).values()) {
45.288 + for (HintDescription hd : hints) {
45.289 + if (!(hd.getTrigger() instanceof PatternDescription)) continue; //TODO: only pattern based hints are currently supported
45.290 + result.add(hd);
45.291 + }
45.292 + }
45.293 +
45.294 + result.addAll(listClassPathHints(Collections.<ClassPath>emptySet(), cps));
45.295 +
45.296 + return result;
45.297 + }
45.298 +
45.299 + public static List<HintDescription> listClassPathHints(Set<ClassPath> sourceCPs, Set<ClassPath> binaryCPs) {
45.300 + List<HintDescription> result = new LinkedList<HintDescription>();
45.301 + Set<FileObject> roots = new HashSet<FileObject>();
45.302 +
45.303 + for (ClassPath cp : binaryCPs) {
45.304 + for (FileObject r : cp.getRoots()) {
45.305 + Result2 src = SourceForBinaryQuery.findSourceRoots2(r.toURL());
45.306 +
45.307 + if (src != null && src.preferSources()) {
45.308 + roots.addAll(Arrays.asList(src.getRoots()));
45.309 + } else {
45.310 + roots.add(r);
45.311 + }
45.312 + }
45.313 + }
45.314 +
45.315 + Set<ClassPath> cps = new HashSet<ClassPath>(sourceCPs);
45.316 +
45.317 + cps.add(ClassPathSupport.createClassPath(roots.toArray(new FileObject[0])));
45.318 +
45.319 + ClassPath cp = ClassPathSupport.createProxyClassPath(cps.toArray(new ClassPath[0]));
45.320 +
45.321 + for (ClassPathBasedHintProvider p : Lookup.getDefault().lookupAll(ClassPathBasedHintProvider.class)) {
45.322 + result.addAll(p.computeHints(cp));
45.323 + }
45.324 +
45.325 + return result;
45.326 + }
45.327 +
45.328 + public static Tree parseAndAttribute(CompilationInfo info, String pattern, Scope scope) {
45.329 + return parseAndAttribute(info, pattern, scope, null);
45.330 + }
45.331 +
45.332 + public static Tree parseAndAttribute(CompilationInfo info, String pattern, Scope scope, Collection<Diagnostic<? extends JavaFileObject>> errors) {
45.333 + return parseAndAttribute(info, JavaSourceAccessor.getINSTANCE().getJavacTask(info), pattern, scope, errors);
45.334 + }
45.335 +
45.336 + public static Tree parseAndAttribute(CompilationInfo info, String pattern, Scope scope, SourcePositions[] sourcePositions, Collection<Diagnostic<? extends JavaFileObject>> errors) {
45.337 + return parseAndAttribute(info, JavaSourceAccessor.getINSTANCE().getJavacTask(info), pattern, scope, sourcePositions, errors);
45.338 + }
45.339 +
45.340 + public static Tree parseAndAttribute(JavacTaskImpl jti, String pattern) {
45.341 + return parseAndAttribute(jti, pattern, null);
45.342 + }
45.343 +
45.344 + public static Tree parseAndAttribute(JavacTaskImpl jti, String pattern, Collection<Diagnostic<? extends JavaFileObject>> errors) {
45.345 + return parseAndAttribute(null, jti, pattern, null, errors);
45.346 + }
45.347 +
45.348 + public static Tree parseAndAttribute(JavacTaskImpl jti, String pattern, SourcePositions[] sourcePositions, Collection<Diagnostic<? extends JavaFileObject>> errors) {
45.349 + return parseAndAttribute(null, jti, pattern, null, sourcePositions, errors);
45.350 + }
45.351 +
45.352 + private static Tree parseAndAttribute(CompilationInfo info, JavacTaskImpl jti, String pattern, Scope scope, Collection<Diagnostic<? extends JavaFileObject>> errors) {
45.353 + return parseAndAttribute(info, jti, pattern, scope, new SourcePositions[1], errors);
45.354 + }
45.355 +
45.356 + private static Tree parseAndAttribute(CompilationInfo info, JavacTaskImpl jti, String pattern, Scope scope, SourcePositions[] sourcePositions, Collection<Diagnostic<? extends JavaFileObject>> errors) {
45.357 + Context c = jti.getContext();
45.358 + TreeFactory make = TreeFactory.instance(c);
45.359 + List<Diagnostic<? extends JavaFileObject>> patternTreeErrors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
45.360 + Tree patternTree = !isStatement(pattern) ? parseExpression(c, pattern, true, sourcePositions, patternTreeErrors) : null;
45.361 + int offset = 0;
45.362 + boolean expression = true;
45.363 + boolean classMember = false;
45.364 +
45.365 + if (pattern.startsWith("case ")) {//XXX: should be a lexer token
45.366 + List<Diagnostic<? extends JavaFileObject>> currentPatternTreeErrors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
45.367 + Tree switchTree = parseStatement(c, "switch ($$foo) {" + pattern + "}", sourcePositions, currentPatternTreeErrors);
45.368 +
45.369 + offset = "switch ($$foo) {".length();
45.370 + patternTreeErrors = currentPatternTreeErrors;
45.371 + patternTree = ((SwitchTree) switchTree).getCases().get(0);
45.372 + }
45.373 +
45.374 + if (patternTree == null || isErrorTree(patternTree)) {
45.375 + SourcePositions[] currentPatternTreePositions = new SourcePositions[1];
45.376 + List<Diagnostic<? extends JavaFileObject>> currentPatternTreeErrors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
45.377 + Tree currentPatternTree = parseStatement(c, "{" + pattern + "}", currentPatternTreePositions, currentPatternTreeErrors);
45.378 +
45.379 + assert currentPatternTree.getKind() == Kind.BLOCK : currentPatternTree.getKind();
45.380 +
45.381 + List<? extends StatementTree> statements = ((BlockTree) currentPatternTree).getStatements();
45.382 +
45.383 + if (statements.size() == 1) {
45.384 + currentPatternTree = statements.get(0);
45.385 + } else {
45.386 + com.sun.tools.javac.util.List<JCStatement> newStatements = com.sun.tools.javac.util.List.<JCStatement>nil();
45.387 +
45.388 + if (!statements.isEmpty() && !Utilities.isMultistatementWildcardTree(statements.get(0)))
45.389 + newStatements = newStatements.append((JCStatement) make.ExpressionStatement(make.Identifier("$$1$")));
45.390 + for (StatementTree st : statements) {
45.391 + newStatements = newStatements.append((JCStatement) st);
45.392 + }
45.393 + if (!statements.isEmpty() && !Utilities.isMultistatementWildcardTree(statements.get(statements.size() - 1)))
45.394 + newStatements = newStatements.append((JCStatement) make.ExpressionStatement(make.Identifier("$$2$")));
45.395 +
45.396 + currentPatternTree = new FakeBlock(0L, newStatements);
45.397 + }
45.398 +
45.399 + if (!currentPatternTreeErrors.isEmpty() || containsError(currentPatternTree)) {
45.400 + //maybe a class member?
45.401 + SourcePositions[] classPatternTreePositions = new SourcePositions[1];
45.402 + List<Diagnostic<? extends JavaFileObject>> classPatternTreeErrors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
45.403 + Tree classPatternTree = parseExpression(c, "new Object() {" + pattern + "}", false, classPatternTreePositions, classPatternTreeErrors);
45.404 +
45.405 + if (!containsError(classPatternTree)) {
45.406 + sourcePositions[0] = classPatternTreePositions[0];
45.407 + offset = "new Object() {".length();
45.408 + patternTreeErrors = classPatternTreeErrors;
45.409 + patternTree = classPatternTree;
45.410 + classMember = true;
45.411 + } else {
45.412 + sourcePositions[0] = currentPatternTreePositions[0];
45.413 + offset = 1;
45.414 + patternTreeErrors = currentPatternTreeErrors;
45.415 + patternTree = currentPatternTree;
45.416 + }
45.417 + } else {
45.418 + sourcePositions[0] = currentPatternTreePositions[0];
45.419 + offset = 1;
45.420 + patternTreeErrors = currentPatternTreeErrors;
45.421 + patternTree = currentPatternTree;
45.422 + }
45.423 +
45.424 + expression = false;
45.425 + }
45.426 +
45.427 + if (scope != null) {
45.428 + TypeMirror type = attributeTree(jti, patternTree, scope, patternTreeErrors);
45.429 +
45.430 + if (isError(type) && expression) {
45.431 + //maybe type?
45.432 + if (Utilities.isPureMemberSelect(patternTree, false)) {
45.433 + SourcePositions[] varPositions = new SourcePositions[1];
45.434 + List<Diagnostic<? extends JavaFileObject>> varErrors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
45.435 + Tree var = parseExpression(c, pattern + ".Class.class;", false, varPositions, varErrors);
45.436 +
45.437 + attributeTree(jti, var, scope, varErrors);
45.438 +
45.439 + ExpressionTree typeTree = ((MemberSelectTree) ((MemberSelectTree) var).getExpression()).getExpression();
45.440 + final Symtab symtab = Symtab.instance(c);
45.441 + final Elements el = jti.getElements();
45.442 + final Trees trees = JavacTrees.instance(c);
45.443 + CompilationUnitTree cut = ((JavacScope) scope).getEnv().toplevel;
45.444 + final boolean[] found = new boolean[1];
45.445 +
45.446 + new TreePathScanner<Void, Void>() {
45.447 + @Override public Void visitMemberSelect(MemberSelectTree node, Void p) {
45.448 + Element currentElement = trees.getElement(getCurrentPath());
45.449 +
45.450 + if (!isError(currentElement)) {
45.451 + if (currentElement.getKind() == ElementKind.PACKAGE && el.getPackageElement(node.toString()) == null) {
45.452 + ((JCFieldAccess) node).sym = symtab.errSymbol;
45.453 + ((JCFieldAccess) node).type = symtab.errType;
45.454 + } else {
45.455 + found[0] = true;
45.456 + return null;
45.457 + }
45.458 + }
45.459 +
45.460 + return super.visitMemberSelect(node, p);
45.461 + }
45.462 + @Override public Void visitIdentifier(IdentifierTree node, Void p) {
45.463 + Element currentElement = trees.getElement(getCurrentPath());
45.464 +
45.465 + if (!isError(currentElement)) {
45.466 + if (currentElement.getKind() == ElementKind.PACKAGE && el.getPackageElement(node.toString()) == null) {
45.467 + ((JCIdent) node).sym = symtab.errSymbol;
45.468 + ((JCIdent) node).type = symtab.errType;
45.469 + } else {
45.470 + found[0] = true;
45.471 + return null;
45.472 + }
45.473 + }
45.474 + return super.visitIdentifier(node, p);
45.475 + }
45.476 +
45.477 + }.scan(new TreePath(new TreePath(cut), typeTree), null);
45.478 +
45.479 + if (found[0]) {
45.480 + sourcePositions[0] = varPositions[0];
45.481 + offset = 0;
45.482 + patternTreeErrors = varErrors;
45.483 + patternTree = typeTree;
45.484 + }
45.485 + }
45.486 + }
45.487 + }
45.488 +
45.489 + if (classMember) {
45.490 + List<? extends Tree> members = ((NewClassTree) patternTree).getClassBody().getMembers();
45.491 +
45.492 + int syntheticOffset = !members.isEmpty() && members.get(0).getKind() == Kind.METHOD && (((JCMethodDecl) members.get(0)).mods.flags & Flags.GENERATEDCONSTR) != 0 ? 1 : 0;
45.493 +
45.494 + if (members.size() > 1 + syntheticOffset) {
45.495 + ModifiersTree mt = make.Modifiers(EnumSet.noneOf(Modifier.class));
45.496 + List<Tree> newMembers = new LinkedList<Tree>();
45.497 +
45.498 + newMembers.add(make.ExpressionStatement(make.Identifier("$$1$")));
45.499 + newMembers.addAll(members.subList(syntheticOffset, members.size()));
45.500 +
45.501 + patternTree = make.Class(mt, "$", Collections.<TypeParameterTree>emptyList(), null, Collections.<Tree>emptyList(), newMembers);
45.502 + } else {
45.503 + patternTree = members.get(0 + syntheticOffset);
45.504 + }
45.505 + }
45.506 +
45.507 + if (errors != null) {
45.508 + for (Diagnostic<? extends JavaFileObject> d : patternTreeErrors) {
45.509 + errors.add(new OffsetDiagnostic<JavaFileObject>(d, -offset));
45.510 + }
45.511 + }
45.512 +
45.513 + sourcePositions[0] = new OffsetSourcePositions(sourcePositions[0], -offset);
45.514 +
45.515 + return patternTree;
45.516 + }
45.517 +
45.518 + static boolean isError(Element el) {
45.519 + return (el == null || (el.getKind() == ElementKind.CLASS) && isError(((TypeElement) el).asType()));
45.520 + }
45.521 +
45.522 + private static boolean isError(TypeMirror type) {
45.523 + return type == null || type.getKind() == TypeKind.ERROR;
45.524 + }
45.525 +
45.526 + private static boolean isStatement(String pattern) {
45.527 + return pattern.trim().endsWith(";");
45.528 + }
45.529 +
45.530 + private static boolean isErrorTree(Tree t) {
45.531 + return t.getKind() == Kind.ERRONEOUS || (t.getKind() == Kind.IDENTIFIER && ((IdentifierTree) t).getName().contentEquals("<error>")); //TODO: <error>...
45.532 + }
45.533 +
45.534 + private static boolean containsError(Tree t) {
45.535 + return new TreeScanner<Boolean, Void>() {
45.536 + @Override
45.537 + public Boolean scan(Tree node, Void p) {
45.538 + if (node != null && isErrorTree(node)) {
45.539 + return true;
45.540 + }
45.541 + return super.scan(node, p) ==Boolean.TRUE;
45.542 + }
45.543 + @Override
45.544 + public Boolean reduce(Boolean r1, Boolean r2) {
45.545 + return r1 == Boolean.TRUE || r2 == Boolean.TRUE;
45.546 + }
45.547 + }.scan(t, null);
45.548 + }
45.549 +
45.550 + private static JCStatement parseStatement(Context context, CharSequence stmt, SourcePositions[] pos, final List<Diagnostic<? extends JavaFileObject>> errors) {
45.551 + if (stmt == null || (pos != null && pos.length != 1))
45.552 + throw new IllegalArgumentException();
45.553 + JavaCompiler compiler = JavaCompiler.instance(context);
45.554 + JavaFileObject prev = compiler.log.useSource(new DummyJFO());
45.555 + Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(compiler.log) {
45.556 + @Override
45.557 + public void report(JCDiagnostic diag) {
45.558 + errors.add(diag);
45.559 + }
45.560 + };
45.561 + try {
45.562 + CharBuffer buf = CharBuffer.wrap((stmt+"\u0000").toCharArray(), 0, stmt.length());
45.563 + ParserFactory factory = ParserFactory.instance(context);
45.564 + ScannerFactory scannerFactory = ScannerFactory.instance(context);
45.565 + Names names = Names.instance(context);
45.566 + Parser parser = new JackpotJavacParser(context, (NBParserFactory) factory, scannerFactory.newScanner(buf, false), false, false, CancelService.instance(context), names);
45.567 + if (parser instanceof JavacParser) {
45.568 + if (pos != null)
45.569 + pos[0] = new ParserSourcePositions((JavacParser)parser);
45.570 + return parser.parseStatement();
45.571 + }
45.572 + return null;
45.573 + } finally {
45.574 + compiler.log.useSource(prev);
45.575 + compiler.log.popDiagnosticHandler(discardHandler);
45.576 + }
45.577 + }
45.578 +
45.579 + private static JCExpression parseExpression(Context context, CharSequence expr, boolean onlyFullInput, SourcePositions[] pos, final List<Diagnostic<? extends JavaFileObject>> errors) {
45.580 + if (expr == null || (pos != null && pos.length != 1))
45.581 + throw new IllegalArgumentException();
45.582 + JavaCompiler compiler = JavaCompiler.instance(context);
45.583 + JavaFileObject prev = compiler.log.useSource(new DummyJFO());
45.584 + Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(compiler.log) {
45.585 + @Override
45.586 + public void report(JCDiagnostic diag) {
45.587 + errors.add(diag);
45.588 + }
45.589 + };
45.590 + try {
45.591 + CharBuffer buf = CharBuffer.wrap((expr+"\u0000").toCharArray(), 0, expr.length());
45.592 + ParserFactory factory = ParserFactory.instance(context);
45.593 + ScannerFactory scannerFactory = ScannerFactory.instance(context);
45.594 + Names names = Names.instance(context);
45.595 + Scanner scanner = scannerFactory.newScanner(buf, false);
45.596 + Parser parser = new JackpotJavacParser(context, (NBParserFactory) factory, scanner, false, false, CancelService.instance(context), names);
45.597 + if (parser instanceof JavacParser) {
45.598 + if (pos != null)
45.599 + pos[0] = new ParserSourcePositions((JavacParser)parser);
45.600 + JCExpression result = parser.parseExpression();
45.601 +
45.602 + if (!onlyFullInput || scanner.token().kind == TokenKind.EOF) {
45.603 + return result;
45.604 + }
45.605 + }
45.606 + return null;
45.607 + } finally {
45.608 + compiler.log.useSource(prev);
45.609 + compiler.log.popDiagnosticHandler(discardHandler);
45.610 + }
45.611 + }
45.612 +
45.613 + private static TypeMirror attributeTree(JavacTaskImpl jti, Tree tree, Scope scope, final List<Diagnostic<? extends JavaFileObject>> errors) {
45.614 + Log log = Log.instance(jti.getContext());
45.615 + JavaFileObject prev = log.useSource(new DummyJFO());
45.616 + Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(log) {
45.617 + @Override
45.618 + public void report(JCDiagnostic diag) {
45.619 + errors.add(diag);
45.620 + }
45.621 + };
45.622 + try {
45.623 + Attr attr = Attr.instance(jti.getContext());
45.624 + Env<AttrContext> env = ((JavacScope) scope).getEnv();
45.625 + if (tree instanceof JCExpression)
45.626 + return attr.attribExpr((JCTree) tree,env, Type.noType);
45.627 + return attr.attribStat((JCTree) tree,env);
45.628 + } finally {
45.629 + log.useSource(prev);
45.630 + log.popDiagnosticHandler(discardHandler);
45.631 + }
45.632 + }
45.633 +
45.634 + public static @CheckForNull CharSequence getWildcardTreeName(@NonNull Tree t) {
45.635 + if (t.getKind() == Kind.EXPRESSION_STATEMENT && ((ExpressionStatementTree) t).getExpression().getKind() == Kind.IDENTIFIER) {
45.636 + IdentifierTree identTree = (IdentifierTree) ((ExpressionStatementTree) t).getExpression();
45.637 +
45.638 + return identTree.getName().toString();
45.639 + }
45.640 +
45.641 + if (t.getKind() == Kind.IDENTIFIER) {
45.642 + IdentifierTree identTree = (IdentifierTree) t;
45.643 + String name = identTree.getName().toString();
45.644 +
45.645 + if (name.startsWith("$")) {
45.646 + return name;
45.647 + }
45.648 + }
45.649 +
45.650 + if (t.getKind() == Kind.TYPE_PARAMETER) {
45.651 + String name = ((TypeParameterTree) t).getName().toString();
45.652 +
45.653 + if (name.startsWith("$")) {
45.654 + return name;
45.655 + }
45.656 + }
45.657 +
45.658 + return null;
45.659 + }
45.660 +
45.661 + public static boolean isMultistatementWildcard(@NonNull CharSequence name) {
45.662 + return name.charAt(name.length() - 1) == '$';
45.663 + }
45.664 +
45.665 + public static boolean isMultistatementWildcardTree(Tree tree) {
45.666 + CharSequence name = Utilities.getWildcardTreeName(tree);
45.667 +
45.668 + return name != null && Utilities.isMultistatementWildcard(name);
45.669 + }
45.670 +
45.671 + private static long inc;
45.672 +
45.673 + public static Scope constructScope(CompilationInfo info, Map<String, TypeMirror> constraints) {
45.674 + return constructScope(info, constraints, Collections.<String>emptyList());
45.675 + }
45.676 +
45.677 + public static Scope constructScope(CompilationInfo info, Map<String, TypeMirror> constraints, Iterable<? extends String> auxiliaryImports) {
45.678 + ScopeDescription desc = new ScopeDescription(constraints, auxiliaryImports);
45.679 + Scope result = (Scope) info.getCachedValue(desc);
45.680 +
45.681 + if (result != null) return result;
45.682 +
45.683 + StringBuilder clazz = new StringBuilder();
45.684 +
45.685 + clazz.append("package $;");
45.686 +
45.687 + for (String i : auxiliaryImports) {
45.688 + clazz.append(i);
45.689 + }
45.690 +
45.691 + long count = inc++;
45.692 +
45.693 + clazz.append("public class $" + count + "{");
45.694 +
45.695 + for (Entry<String, TypeMirror> e : constraints.entrySet()) {
45.696 + if (e.getValue() != null) {
45.697 + clazz.append("private ");
45.698 + clazz.append(e.getValue().toString()); //XXX
45.699 + clazz.append(" ");
45.700 + clazz.append(e.getKey());
45.701 + clazz.append(";\n");
45.702 + }
45.703 + }
45.704 +
45.705 + clazz.append("private void test() {\n");
45.706 + clazz.append("}\n");
45.707 + clazz.append("}\n");
45.708 +
45.709 + JavacTaskImpl jti = JavaSourceAccessor.getINSTANCE().getJavacTask(info);
45.710 + Context context = jti.getContext();
45.711 + JavaCompiler compiler = JavaCompiler.instance(context);
45.712 + Log log = Log.instance(context);
45.713 + Log.DiagnosticHandler discardHandler = new Log.DiscardDiagnosticHandler(compiler.log);
45.714 +
45.715 + JavaFileObject jfo = FileObjects.memoryFileObject("$", "$", new File("/tmp/$" + count + ".java").toURI(), System.currentTimeMillis(), clazz.toString());
45.716 +
45.717 + boolean oldSkipAPs = compiler.skipAnnotationProcessing;
45.718 +
45.719 + try {
45.720 + compiler.skipAnnotationProcessing = true;
45.721 +
45.722 + JCCompilationUnit cut = compiler.parse(jfo);
45.723 +
45.724 + compiler.enterTrees(com.sun.tools.javac.util.List.of(cut));
45.725 +
45.726 + Todo todo = compiler.todo;
45.727 + ListBuffer<Env<AttrContext>> defer = ListBuffer.<Env<AttrContext>>lb();
45.728 +
45.729 + while (todo.peek() != null) {
45.730 + Env<AttrContext> env = todo.remove();
45.731 +
45.732 + if (env.toplevel == cut)
45.733 + compiler.attribute(env);
45.734 + else
45.735 + defer = defer.append(env);
45.736 + }
45.737 +
45.738 + todo.addAll(defer);
45.739 +
45.740 + Scope res = new ScannerImpl().scan(cut, info);
45.741 +
45.742 + info.putCachedValue(desc, res, CacheClearPolicy.ON_SIGNATURE_CHANGE);
45.743 +
45.744 + return res;
45.745 + } finally {
45.746 + log.popDiagnosticHandler(discardHandler);
45.747 + compiler.skipAnnotationProcessing = oldSkipAPs;
45.748 + }
45.749 + }
45.750 +
45.751 + private static final class ScannerImpl extends TreePathScanner<Scope, CompilationInfo> {
45.752 +
45.753 + @Override
45.754 + public Scope visitBlock(BlockTree node, CompilationInfo p) {
45.755 + return p.getTrees().getScope(getCurrentPath());
45.756 + }
45.757 +
45.758 + @Override
45.759 + public Scope visitMethod(MethodTree node, CompilationInfo p) {
45.760 + if (node.getReturnType() == null) {
45.761 + return null;
45.762 + }
45.763 + return super.visitMethod(node, p);
45.764 + }
45.765 +
45.766 + @Override
45.767 + public Scope reduce(Scope r1, Scope r2) {
45.768 + return r1 != null ? r1 : r2;
45.769 + }
45.770 +
45.771 + }
45.772 +
45.773 + private static final class ScopeDescription {
45.774 + private final Map<String, TypeMirror> constraints;
45.775 + private final Iterable<? extends String> auxiliaryImports;
45.776 +
45.777 + public ScopeDescription(Map<String, TypeMirror> constraints, Iterable<? extends String> auxiliaryImports) {
45.778 + this.constraints = constraints;
45.779 + this.auxiliaryImports = auxiliaryImports;
45.780 + }
45.781 +
45.782 + @Override
45.783 + public boolean equals(Object obj) {
45.784 + if (obj == null) {
45.785 + return false;
45.786 + }
45.787 + if (getClass() != obj.getClass()) {
45.788 + return false;
45.789 + }
45.790 + final ScopeDescription other = (ScopeDescription) obj;
45.791 + if (this.constraints != other.constraints && (this.constraints == null || !this.constraints.equals(other.constraints))) {
45.792 + return false;
45.793 + }
45.794 + if (this.auxiliaryImports != other.auxiliaryImports && (this.auxiliaryImports == null || !this.auxiliaryImports.equals(other.auxiliaryImports))) {
45.795 + return false;
45.796 + }
45.797 + return true;
45.798 + }
45.799 +
45.800 + @Override
45.801 + public int hashCode() {
45.802 + int hash = 7;
45.803 + hash = 47 * hash + (this.constraints != null ? this.constraints.hashCode() : 0);
45.804 + hash = 47 * hash + (this.auxiliaryImports != null ? this.auxiliaryImports.hashCode() : 0);
45.805 + return hash;
45.806 + }
45.807 +
45.808 + }
45.809 +
45.810 +// private static Scope constructScope2(CompilationInfo info, Map<String, TypeMirror> constraints) {
45.811 +// JavacScope s = (JavacScope) info.getTrees().getScope(new TreePath(info.getCompilationUnit()));
45.812 +// Env<AttrContext> env = s.getEnv();
45.813 +//
45.814 +// env = env.dup(env.tree);
45.815 +//
45.816 +// env.info.
45.817 +// }
45.818 +
45.819 + public static String toHumanReadableTime(double d) {
45.820 + StringBuilder result = new StringBuilder();
45.821 + long inSeconds = (long) (d / 1000);
45.822 + int seconds = (int) (inSeconds % 60);
45.823 + long inMinutes = inSeconds / 60;
45.824 + int minutes = (int) (inMinutes % 60);
45.825 + long inHours = inMinutes / 60;
45.826 +
45.827 + if (inHours > 0) {
45.828 + result.append(inHours);
45.829 + result.append("h");
45.830 + }
45.831 +
45.832 + if (minutes > 0) {
45.833 + result.append(minutes);
45.834 + result.append("m");
45.835 + }
45.836 +
45.837 + result.append(seconds);
45.838 + result.append("s");
45.839 +
45.840 + return result.toString();
45.841 + }
45.842 +
45.843 + public static ClasspathInfo createUniversalCPInfo() {
45.844 + return Lookup.getDefault().lookup(SPI.class).createUniversalCPInfo();
45.845 + }
45.846 +
45.847 + @SuppressWarnings("deprecation")
45.848 + public static void waitScanFinished() throws InterruptedException {
45.849 + SourceUtils.waitScanFinished();
45.850 + }
45.851 +
45.852 + public static Set<? extends String> findSuppressedWarnings(CompilationInfo info, TreePath path) {
45.853 + //TODO: cache?
45.854 + Set<String> keys = new HashSet<String>();
45.855 +
45.856 + while (path != null) {
45.857 + Tree leaf = path.getLeaf();
45.858 +
45.859 + switch (leaf.getKind()) {
45.860 + case METHOD:
45.861 + handleSuppressWarnings(info, path, ((MethodTree) leaf).getModifiers(), keys);
45.862 + break;
45.863 + case CLASS:
45.864 + handleSuppressWarnings(info, path, ((ClassTree) leaf).getModifiers(), keys);
45.865 + break;
45.866 + case VARIABLE:
45.867 + handleSuppressWarnings(info, path, ((VariableTree) leaf).getModifiers(), keys);
45.868 + break;
45.869 + }
45.870 +
45.871 + path = path.getParentPath();
45.872 + }
45.873 +
45.874 + return Collections.unmodifiableSet(keys);
45.875 + }
45.876 +
45.877 + private static void handleSuppressWarnings(CompilationInfo info, TreePath path, ModifiersTree modifiers, final Set<String> keys) {
45.878 + Element el = info.getTrees().getElement(path);
45.879 +
45.880 + if (el == null) {
45.881 + return ;
45.882 + }
45.883 +
45.884 + for (AnnotationMirror am : el.getAnnotationMirrors()) {
45.885 + Name fqn = ((TypeElement) am.getAnnotationType().asElement()).getQualifiedName();
45.886 +
45.887 + if (!fqn.contentEquals("java.lang.SuppressWarnings")) {
45.888 + continue;
45.889 + }
45.890 +
45.891 + for (Entry<? extends ExecutableElement, ? extends AnnotationValue> e : am.getElementValues().entrySet()) {
45.892 + if (!e.getKey().getSimpleName().contentEquals("value"))
45.893 + continue;
45.894 +
45.895 + e.getValue().accept(new AnnotationValueVisitor<Void, Void>() {
45.896 + public Void visit(AnnotationValue av, Void p) {
45.897 + av.accept(this, p);
45.898 + return null;
45.899 + }
45.900 + public Void visit(AnnotationValue av) {
45.901 + av.accept(this, null);
45.902 + return null;
45.903 + }
45.904 + public Void visitBoolean(boolean b, Void p) {
45.905 + return null;
45.906 + }
45.907 + public Void visitByte(byte b, Void p) {
45.908 + return null;
45.909 + }
45.910 + public Void visitChar(char c, Void p) {
45.911 + return null;
45.912 + }
45.913 + public Void visitDouble(double d, Void p) {
45.914 + return null;
45.915 + }
45.916 + public Void visitFloat(float f, Void p) {
45.917 + return null;
45.918 + }
45.919 + public Void visitInt(int i, Void p) {
45.920 + return null;
45.921 + }
45.922 + public Void visitLong(long i, Void p) {
45.923 + return null;
45.924 + }
45.925 + public Void visitShort(short s, Void p) {
45.926 + return null;
45.927 + }
45.928 + public Void visitString(String s, Void p) {
45.929 + keys.add(s);
45.930 + return null;
45.931 + }
45.932 + public Void visitType(TypeMirror t, Void p) {
45.933 + return null;
45.934 + }
45.935 + public Void visitEnumConstant(VariableElement c, Void p) {
45.936 + return null;
45.937 + }
45.938 + public Void visitAnnotation(AnnotationMirror a, Void p) {
45.939 + return null;
45.940 + }
45.941 + public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
45.942 + for (AnnotationValue av : vals) {
45.943 + av.accept(this, p);
45.944 + }
45.945 + return null;
45.946 + }
45.947 + public Void visitUnknown(AnnotationValue av, Void p) {
45.948 + return null;
45.949 + }
45.950 + }, null);
45.951 + }
45.952 + }
45.953 + }
45.954 +
45.955 + public static Tree generalizePattern(CompilationInfo info, TreePath original) {
45.956 + return generalizePattern(JavaSourceAccessor.getINSTANCE().getJavacTask(info), original);
45.957 + }
45.958 +
45.959 + public static Tree generalizePattern(CompilationTask task, TreePath original) {
45.960 + JavacTaskImpl jti = (JavacTaskImpl) task;
45.961 + com.sun.tools.javac.util.Context c = jti.getContext();
45.962 + TreeFactory make = TreeFactory.instance(c);
45.963 + Trees javacTrees = Trees.instance(task);
45.964 + GeneralizePattern gp = new GeneralizePattern(javacTrees, make);
45.965 +
45.966 + gp.scan(original, null);
45.967 +
45.968 + GeneralizePatternITT itt = new GeneralizePatternITT(gp.tree2Variable);
45.969 +
45.970 + itt.attach(c, new NoImports(c), null);
45.971 +
45.972 + return itt.translate(original.getLeaf());
45.973 + }
45.974 +
45.975 + public static Tree generalizePattern(CompilationInfo info, TreePath original, int firstStatement, int lastStatement) {
45.976 + JavacTaskImpl jti = JavaSourceAccessor.getINSTANCE().getJavacTask(info);
45.977 + com.sun.tools.javac.util.Context c = jti.getContext();
45.978 + TreeFactory make = TreeFactory.instance(c);
45.979 + Tree translated = Utilities.generalizePattern(jti, original);
45.980 +
45.981 + assert translated.getKind() == Kind.BLOCK;
45.982 +
45.983 + List<StatementTree> newStatements = new LinkedList<StatementTree>();
45.984 + BlockTree block = (BlockTree) translated;
45.985 +
45.986 + if (firstStatement != lastStatement) {
45.987 + newStatements.add(make.ExpressionStatement(make.Identifier("$s0$")));
45.988 + newStatements.addAll(block.getStatements().subList(firstStatement, lastStatement + 1));
45.989 + newStatements.add(make.ExpressionStatement(make.Identifier("$s1$")));
45.990 +
45.991 + translated = make.Block(newStatements, block.isStatic());
45.992 + } else {
45.993 + translated = block.getStatements().get(firstStatement);
45.994 + }
45.995 +
45.996 + return translated;
45.997 + }
45.998 +
45.999 + public interface SPI {
45.1000 + public ClasspathInfo createUniversalCPInfo();
45.1001 + }
45.1002 +
45.1003 + @ServiceProvider(service=SPI.class)
45.1004 + public static final class NbSPIImpl implements SPI {
45.1005 +
45.1006 + public ClasspathInfo createUniversalCPInfo() {
45.1007 + JavaPlatform select = JavaPlatform.getDefault();
45.1008 +
45.1009 + if (select.getSpecification().getVersion() != null) {
45.1010 + for (JavaPlatform p : JavaPlatformManager.getDefault().getInstalledPlatforms()) {
45.1011 + if (!"j2se".equals(p.getSpecification().getName()) || p.getSpecification().getVersion() == null) continue;
45.1012 + if (p.getSpecification().getVersion().compareTo(select.getSpecification().getVersion()) > 0) {
45.1013 + select = p;
45.1014 + }
45.1015 + }
45.1016 + }
45.1017 +
45.1018 + return ClasspathInfo.create(select.getBootstrapLibraries(), ClassPath.EMPTY, ClassPath.EMPTY);
45.1019 + }
45.1020 +
45.1021 + }
45.1022 +
45.1023 + private static final class GeneralizePattern extends TreePathScanner<Void, Void> {
45.1024 +
45.1025 + public final Map<Tree, Tree> tree2Variable = new HashMap<Tree, Tree>();
45.1026 + private final Map<Element, String> element2Variable = new HashMap<Element, String>();
45.1027 + private final Trees javacTrees;
45.1028 + private final TreeFactory make;
45.1029 +
45.1030 + private int currentVariableIndex = 0;
45.1031 +
45.1032 + public GeneralizePattern(Trees javacTrees, TreeFactory make) {
45.1033 + this.javacTrees = javacTrees;
45.1034 + this.make = make;
45.1035 + }
45.1036 +
45.1037 + private @NonNull String getVariable(@NonNull Element el) {
45.1038 + String var = element2Variable.get(el);
45.1039 +
45.1040 + if (var == null) {
45.1041 + element2Variable.put(el, var = "$" + currentVariableIndex++);
45.1042 + }
45.1043 +
45.1044 + return var;
45.1045 + }
45.1046 +
45.1047 + private boolean shouldBeGeneralized(@NonNull Element el) {
45.1048 + if (el.getModifiers().contains(Modifier.PRIVATE)) {
45.1049 + return true;
45.1050 + }
45.1051 +
45.1052 + switch (el.getKind()) {
45.1053 + case LOCAL_VARIABLE:
45.1054 + case EXCEPTION_PARAMETER:
45.1055 + case PARAMETER:
45.1056 + return true;
45.1057 + }
45.1058 +
45.1059 + return false;
45.1060 + }
45.1061 +
45.1062 + @Override
45.1063 + public Void visitIdentifier(IdentifierTree node, Void p) {
45.1064 + Element e = javacTrees.getElement(getCurrentPath());
45.1065 +
45.1066 + if (e != null && shouldBeGeneralized(e)) {
45.1067 + tree2Variable.put(node, make.Identifier(getVariable(e)));
45.1068 + }
45.1069 +
45.1070 + return super.visitIdentifier(node, p);
45.1071 + }
45.1072 +
45.1073 + @Override
45.1074 + public Void visitVariable(VariableTree node, Void p) {
45.1075 + Element e = javacTrees.getElement(getCurrentPath());
45.1076 +
45.1077 + if (e != null && shouldBeGeneralized(e)) {
45.1078 + VariableTree nue = make.Variable(node.getModifiers(), getVariable(e), node.getType(), node.getInitializer());
45.1079 +
45.1080 + tree2Variable.put(node, nue);
45.1081 + }
45.1082 +
45.1083 + return super.visitVariable(node, p);
45.1084 + }
45.1085 +
45.1086 + @Override
45.1087 + public Void visitNewClass(NewClassTree node, Void p) {
45.1088 + //XXX:
45.1089 + if (node.getEnclosingExpression() != null) {
45.1090 + tree2Variable.put(node, make.Identifier("$" + currentVariableIndex++));
45.1091 + return null;
45.1092 + }
45.1093 +
45.1094 + NewClassTree nue = make.NewClass(node.getEnclosingExpression(), Collections.<ExpressionTree>singletonList(make.Identifier("$" + currentVariableIndex++ + "$")), make.Identifier("$" + currentVariableIndex++), Collections.<ExpressionTree>singletonList(make.Identifier("$" + currentVariableIndex++ + "$")), null);
45.1095 +
45.1096 + tree2Variable.put(node, nue);
45.1097 +
45.1098 + return null;
45.1099 + }
45.1100 +
45.1101 + }
45.1102 +
45.1103 + private static final class GeneralizePatternITT extends ImmutableTreeTranslator {
45.1104 +
45.1105 + private final Map<Tree, Tree> tree2Variable;
45.1106 +
45.1107 + public GeneralizePatternITT(Map<Tree, Tree> tree2Variable) {
45.1108 + super(null);
45.1109 + this.tree2Variable = tree2Variable;
45.1110 + }
45.1111 +
45.1112 + @Override
45.1113 + public Tree translate(Tree tree) {
45.1114 + Tree var = tree2Variable.remove(tree);
45.1115 +
45.1116 + if (var != null) {
45.1117 + return super.translate(var);
45.1118 + }
45.1119 +
45.1120 + return super.translate(tree);
45.1121 + }
45.1122 +
45.1123 + }
45.1124 +
45.1125 + private static final class NoImports extends ImportAnalysis2 {
45.1126 +
45.1127 + public NoImports(Context env) {
45.1128 + super(env);
45.1129 + }
45.1130 +
45.1131 + @Override
45.1132 + public void classEntered(ClassTree clazz) {}
45.1133 +
45.1134 + @Override
45.1135 + public void enterVisibleThroughClasses(ClassTree clazz) {}
45.1136 +
45.1137 + @Override
45.1138 + public void classLeft() {}
45.1139 +
45.1140 + @Override
45.1141 + public ExpressionTree resolveImport(MemberSelectTree orig, Element element) {
45.1142 + return orig;
45.1143 + }
45.1144 +
45.1145 + @Override
45.1146 + public void setCompilationUnit(CompilationUnitTree cut) {}
45.1147 +
45.1148 + @Override
45.1149 + public void setImports(List<? extends ImportTree> importsToAdd) {}
45.1150 +
45.1151 + @Override
45.1152 + public Set<? extends Element> getImports() {
45.1153 + return Collections.emptySet();
45.1154 + }
45.1155 +
45.1156 + @Override
45.1157 + public void setPackage(ExpressionTree packageNameTree) {}
45.1158 +
45.1159 + }
45.1160 +
45.1161 + public static long patternValue(Tree pattern) {
45.1162 + class VisitorImpl extends TreeScanner<Void, Void> {
45.1163 + private int value;
45.1164 + @Override
45.1165 + public Void scan(Tree node, Void p) {
45.1166 + if (node != null) value++;
45.1167 + return super.scan(node, p);
45.1168 + }
45.1169 + @Override
45.1170 + public Void visitIdentifier(IdentifierTree node, Void p) {
45.1171 + if (node.getName().toString().startsWith("$")) value--;
45.1172 +
45.1173 + return super.visitIdentifier(node, p);
45.1174 + }
45.1175 + @Override
45.1176 + public Void visitNewClass(NewClassTree node, Void p) {
45.1177 + return null;
45.1178 + }
45.1179 + }
45.1180 +
45.1181 + VisitorImpl vi = new VisitorImpl();
45.1182 +
45.1183 + vi.scan(pattern, null);
45.1184 +
45.1185 + return vi.value;
45.1186 + }
45.1187 +
45.1188 + public static boolean containsMultistatementTrees(List<? extends Tree> statements) {
45.1189 + for (Tree t : statements) {
45.1190 + if (Utilities.isMultistatementWildcardTree(t)) {
45.1191 + return true;
45.1192 + }
45.1193 + }
45.1194 +
45.1195 + return false;
45.1196 + }
45.1197 +
45.1198 + public static boolean isJavadocSupported(CompilationInfo info) {
45.1199 + Context c = JavaSourceAccessor.getINSTANCE().getJavacTask(info).getContext();
45.1200 +
45.1201 + try {
45.1202 + return c.get(Log.logKey) instanceof Messager;
45.1203 + } catch (NoClassDefFoundError e) {
45.1204 + return false;
45.1205 + }
45.1206 + }
45.1207 +
45.1208 + private static class JackpotJavacParser extends NBJavacParser {
45.1209 +
45.1210 + private final Context ctx;
45.1211 + private final com.sun.tools.javac.util.Name dollar;
45.1212 + public JackpotJavacParser(Context ctx, NBParserFactory fac,
45.1213 + Lexer S,
45.1214 + boolean keepDocComments,
45.1215 + boolean keepLineMap,
45.1216 + CancelService cancelService,
45.1217 + Names names) {
45.1218 + super(fac, S, keepDocComments, keepLineMap, true, cancelService);
45.1219 + this.ctx = ctx;
45.1220 + this.dollar = names.fromString("$");
45.1221 + }
45.1222 +
45.1223 + @Override
45.1224 + protected JCModifiers modifiersOpt(JCModifiers partial) {
45.1225 + if (token.kind == TokenKind.IDENTIFIER) {
45.1226 + String ident = token.name().toString();
45.1227 +
45.1228 + if (Utilities.isMultistatementWildcard(ident)) {
45.1229 + com.sun.tools.javac.util.Name name = token.name();
45.1230 +
45.1231 + nextToken();
45.1232 +
45.1233 + JCModifiers result = super.modifiersOpt(partial);
45.1234 +
45.1235 + result.annotations = result.annotations.prepend(new AnnotationWildcard(name, F.Ident(name)));
45.1236 +
45.1237 + return result;
45.1238 + }
45.1239 + }
45.1240 +
45.1241 + return super.modifiersOpt(partial);
45.1242 + }
45.1243 +
45.1244 + @Override
45.1245 + public JCVariableDecl formalParameter(boolean lambdaParam) {
45.1246 + if (token.kind == TokenKind.IDENTIFIER) {
45.1247 + if (token.name().startsWith(dollar)) {
45.1248 + com.sun.tools.javac.util.Name name = token.name();
45.1249 +
45.1250 + Token peeked = S.token(1);
45.1251 +
45.1252 + if (peeked.kind == TokenKind.COMMA || peeked.kind == TokenKind.RPAREN) {
45.1253 + nextToken();
45.1254 + return new VariableWildcard(ctx, name, F.Ident(name));
45.1255 + }
45.1256 + }
45.1257 + }
45.1258 +
45.1259 + return super.formalParameter(lambdaParam);
45.1260 + }
45.1261 +
45.1262 + @Override
45.1263 + protected JCVariableDecl implicitParameter() {
45.1264 + if (token.kind == TokenKind.IDENTIFIER) {
45.1265 + if (token.name().startsWith(dollar)) {
45.1266 + com.sun.tools.javac.util.Name name = token.name();
45.1267 +
45.1268 + Token peeked = S.token(1);
45.1269 +
45.1270 + if (peeked.kind == TokenKind.COMMA || peeked.kind == TokenKind.RPAREN) {
45.1271 + nextToken();
45.1272 + return new VariableWildcard(ctx, name, F.Ident(name));
45.1273 + }
45.1274 + }
45.1275 + }
45.1276 +
45.1277 + return super.implicitParameter();
45.1278 + }
45.1279 +
45.1280 + @Override
45.1281 + protected JCCatch catchClause() {
45.1282 + if (token.kind == TokenKind.CATCH) {
45.1283 + Token peeked = S.token(1);
45.1284 +
45.1285 + if ( peeked.kind == TokenKind.IDENTIFIER
45.1286 + && Utilities.isMultistatementWildcard(peeked.name().toString())) {
45.1287 + accept(TokenKind.CATCH);
45.1288 +
45.1289 + com.sun.tools.javac.util.Name name = token.name();
45.1290 +
45.1291 + accept(TokenKind.IDENTIFIER);
45.1292 +
45.1293 + return new CatchWildcard(ctx, name, F.Ident(name));
45.1294 + } else {
45.1295 + nextToken();
45.1296 + }
45.1297 + }
45.1298 + return super.catchClause();
45.1299 + }
45.1300 +
45.1301 + @Override
45.1302 + public com.sun.tools.javac.util.List<JCTree> classOrInterfaceBodyDeclaration(com.sun.tools.javac.util.Name className, boolean isInterface) {
45.1303 + if (token.kind == TokenKind.IDENTIFIER) {
45.1304 + if (token.name().startsWith(dollar)) {
45.1305 + com.sun.tools.javac.util.Name name = token.name();
45.1306 +
45.1307 + Token peeked = S.token(1);
45.1308 +
45.1309 + if (peeked.kind == TokenKind.SEMI) {
45.1310 + nextToken();
45.1311 + nextToken();
45.1312 +
45.1313 + return com.sun.tools.javac.util.List.<JCTree>of(F.Ident(name));
45.1314 + }
45.1315 + }
45.1316 + }
45.1317 + return super.classOrInterfaceBodyDeclaration(className, isInterface);
45.1318 + }
45.1319 +
45.1320 + @Override
45.1321 + protected JCExpression checkExprStat(JCExpression t) {
45.1322 + if (t.getTag() == JCTree.Tag.IDENT) {
45.1323 + if (((IdentifierTree) t).getName().toString().startsWith("$")) {
45.1324 + return t;
45.1325 + }
45.1326 + }
45.1327 + return super.checkExprStat(t);
45.1328 + }
45.1329 +
45.1330 + @Override
45.1331 + protected JCCase switchBlockStatementGroup() {
45.1332 + if (token.kind == TokenKind.CASE) {
45.1333 + Token peeked = S.token(1);
45.1334 +
45.1335 + if (peeked.kind == TokenKind.IDENTIFIER) {
45.1336 + String ident = peeked.name().toString();
45.1337 +
45.1338 + if (ident.startsWith("$") && ident.endsWith("$")) {
45.1339 + nextToken();
45.1340 +
45.1341 + int pos = token.pos;
45.1342 + com.sun.tools.javac.util.Name name = token.name();
45.1343 +
45.1344 + nextToken();
45.1345 +
45.1346 + if (token.kind == TokenKind.SEMI) {
45.1347 + nextToken();
45.1348 + }
45.1349 +
45.1350 + return new JackpotTrees.CaseWildcard(ctx, name, F.at(pos).Ident(name));
45.1351 + }
45.1352 + }
45.1353 + }
45.1354 +
45.1355 + return super.switchBlockStatementGroup();
45.1356 + }
45.1357 +
45.1358 +
45.1359 + @Override
45.1360 + protected JCTree resource() {
45.1361 + if (token.kind == TokenKind.IDENTIFIER && token.name().startsWith(dollar)) {
45.1362 + Token peeked = S.token(1);
45.1363 +
45.1364 + if (peeked.kind == TokenKind.SEMI || peeked.kind == TokenKind.RPAREN) {
45.1365 + int pos = token.pos;
45.1366 + com.sun.tools.javac.util.Name name = token.name();
45.1367 +
45.1368 + nextToken();
45.1369 +
45.1370 + return F.at(pos).Ident(name);
45.1371 + }
45.1372 + }
45.1373 + return super.resource();
45.1374 + }
45.1375 +
45.1376 + }
45.1377 +
45.1378 + private static final class DummyJFO extends SimpleJavaFileObject {
45.1379 + private DummyJFO() {
45.1380 + super(URI.create("dummy.java"), JavaFileObject.Kind.SOURCE);
45.1381 + }
45.1382 + @Override
45.1383 + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
45.1384 + return "";
45.1385 + }
45.1386 + };
45.1387 +
45.1388 + /**
45.1389 + * Only for members (i.e. generated constructor):
45.1390 + */
45.1391 + public static List<? extends Tree> filterHidden(TreePath basePath, Iterable<? extends Tree> members) {
45.1392 + List<Tree> result = new LinkedList<Tree>();
45.1393 +
45.1394 + for (Tree t : members) {
45.1395 + if (!isSynthetic(basePath != null ? basePath.getCompilationUnit() : null, t)) {
45.1396 + result.add(t);
45.1397 + }
45.1398 + }
45.1399 +
45.1400 + return result;
45.1401 + }
45.1402 +
45.1403 + private static boolean isSynthetic(CompilationUnitTree cut, Tree leaf) throws NullPointerException {
45.1404 + JCTree tree = (JCTree) leaf;
45.1405 +
45.1406 + if (tree.pos == (-1))
45.1407 + return true;
45.1408 +
45.1409 + if (leaf.getKind() == Kind.METHOD) {
45.1410 + //check for synthetic constructor:
45.1411 + return (((JCMethodDecl)leaf).mods.flags & Flags.GENERATEDCONSTR) != 0L;
45.1412 + }
45.1413 +
45.1414 + //check for synthetic superconstructor call:
45.1415 + if (cut != null && leaf.getKind() == Kind.EXPRESSION_STATEMENT) {
45.1416 + ExpressionStatementTree est = (ExpressionStatementTree) leaf;
45.1417 +
45.1418 + if (est.getExpression().getKind() == Kind.METHOD_INVOCATION) {
45.1419 + MethodInvocationTree mit = (MethodInvocationTree) est.getExpression();
45.1420 +
45.1421 + if (mit.getMethodSelect().getKind() == Kind.IDENTIFIER) {
45.1422 + IdentifierTree it = (IdentifierTree) mit.getMethodSelect();
45.1423 +
45.1424 + if ("super".equals(it.getName().toString())) {
45.1425 + return ((JCCompilationUnit) cut).endPositions.getEndPos(tree) == (-1);
45.1426 + }
45.1427 + }
45.1428 + }
45.1429 + }
45.1430 +
45.1431 + return false;
45.1432 + }
45.1433 +
45.1434 + public static boolean isFakeBlock(Tree t) {
45.1435 + return t instanceof FakeBlock;
45.1436 + }
45.1437 +
45.1438 + public static boolean isFakeClass(Tree t) {
45.1439 + if (!(t instanceof ClassTree)) {
45.1440 + return false;
45.1441 + }
45.1442 +
45.1443 + ClassTree ct = (ClassTree) t;
45.1444 +
45.1445 + if (ct.getMembers().isEmpty()) {
45.1446 + return false;
45.1447 + }
45.1448 +
45.1449 + CharSequence wildcardTreeName = Utilities.getWildcardTreeName(ct.getMembers().get(0));
45.1450 +
45.1451 + if (wildcardTreeName == null) {
45.1452 + return false;
45.1453 + }
45.1454 +
45.1455 + return wildcardTreeName.toString().startsWith("$$");
45.1456 + }
45.1457 +
45.1458 + private static final class OffsetSourcePositions implements SourcePositions {
45.1459 +
45.1460 + private final SourcePositions delegate;
45.1461 + private final long offset;
45.1462 +
45.1463 + public OffsetSourcePositions(SourcePositions delegate, long offset) {
45.1464 + this.delegate = delegate;
45.1465 + this.offset = offset;
45.1466 + }
45.1467 +
45.1468 + public long getStartPosition(CompilationUnitTree cut, Tree tree) {
45.1469 + return delegate.getStartPosition(cut, tree) + offset;
45.1470 + }
45.1471 +
45.1472 + public long getEndPosition(CompilationUnitTree cut, Tree tree) {
45.1473 + return delegate.getEndPosition(cut, tree) + offset;
45.1474 + }
45.1475 +
45.1476 + }
45.1477 +
45.1478 + private static final class OffsetDiagnostic<S> implements Diagnostic<S> {
45.1479 + private final Diagnostic<? extends S> delegate;
45.1480 + private final long offset;
45.1481 +
45.1482 + public OffsetDiagnostic(Diagnostic<? extends S> delegate, long offset) {
45.1483 + this.delegate = delegate;
45.1484 + this.offset = offset;
45.1485 + }
45.1486 +
45.1487 + public Diagnostic.Kind getKind() {
45.1488 + return delegate.getKind();
45.1489 + }
45.1490 +
45.1491 + public S getSource() {
45.1492 + return delegate.getSource();
45.1493 + }
45.1494 +
45.1495 + public long getPosition() {
45.1496 + return delegate.getPosition() + offset;
45.1497 + }
45.1498 +
45.1499 + public long getStartPosition() {
45.1500 + return delegate.getStartPosition() + offset;
45.1501 + }
45.1502 +
45.1503 + public long getEndPosition() {
45.1504 + return delegate.getEndPosition() + offset;
45.1505 + }
45.1506 +
45.1507 + public long getLineNumber() {
45.1508 + throw new UnsupportedOperationException("Not supported yet.");
45.1509 + }
45.1510 +
45.1511 + public long getColumnNumber() {
45.1512 + throw new UnsupportedOperationException("Not supported yet.");
45.1513 + }
45.1514 +
45.1515 + public String getCode() {
45.1516 + return delegate.getCode();
45.1517 + }
45.1518 +
45.1519 + public String getMessage(Locale locale) {
45.1520 + return delegate.getMessage(locale);
45.1521 + }
45.1522 +
45.1523 + }
45.1524 +
45.1525 + private static class ParserSourcePositions implements SourcePositions {
45.1526 +
45.1527 + private JavacParser parser;
45.1528 +
45.1529 + private ParserSourcePositions(JavacParser parser) {
45.1530 + this.parser = parser;
45.1531 + }
45.1532 +
45.1533 + public long getStartPosition(CompilationUnitTree file, Tree tree) {
45.1534 + return parser.getStartPos((JCTree)tree);
45.1535 + }
45.1536 +
45.1537 + public long getEndPosition(CompilationUnitTree file, Tree tree) {
45.1538 + return parser.getEndPos((JCTree)tree);
45.1539 + }
45.1540 + }
45.1541 +}
46.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
46.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java Wed May 08 21:47:42 2013 +0200
46.3 @@ -0,0 +1,643 @@
46.4 +/*
46.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
46.6 + *
46.7 + * Copyright 2009-2011 Oracle and/or its affiliates. All rights reserved.
46.8 + *
46.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
46.10 + * Other names may be trademarks of their respective owners.
46.11 + *
46.12 + * The contents of this file are subject to the terms of either the GNU
46.13 + * General Public License Version 2 only ("GPL") or the Common
46.14 + * Development and Distribution License("CDDL") (collectively, the
46.15 + * "License"). You may not use this file except in compliance with the
46.16 + * License. You can obtain a copy of the License at
46.17 + * http://www.netbeans.org/cddl-gplv2.html
46.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
46.19 + * specific language governing permissions and limitations under the
46.20 + * License. When distributing the software, include this License Header
46.21 + * Notice in each file and include the License file at
46.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
46.23 + * particular file as subject to the "Classpath" exception as provided
46.24 + * by Oracle in the GPL Version 2 section of the License file that
46.25 + * accompanied this code. If applicable, add the following below the
46.26 + * License Header, with the fields enclosed by brackets [] replaced by
46.27 + * your own identifying information:
46.28 + * "Portions Copyrighted [year] [name of copyright owner]"
46.29 + *
46.30 + * If you wish your version of this file to be governed by only the CDDL
46.31 + * or only the GPL Version 2, indicate your decision by adding
46.32 + * "[Contributor] elects to include this software in this distribution
46.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
46.34 + * single choice of license, a recipient has the option to distribute
46.35 + * your version of this file under either the CDDL, the GPL Version 2 or
46.36 + * to extend the choice of license to its licensees as provided above.
46.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
46.38 + * Version 2 license, then the option applies only if the new code is
46.39 + * made subject to such option by the copyright holder.
46.40 + *
46.41 + * Contributor(s):
46.42 + *
46.43 + * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
46.44 + */
46.45 +package org.netbeans.modules.java.hints.spiimpl.batch;
46.46 +
46.47 +import org.netbeans.spi.java.hints.HintContext.MessageKind;
46.48 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
46.49 +import com.sun.source.tree.Tree;
46.50 +import com.sun.source.util.TreePath;
46.51 +import java.io.IOException;
46.52 +import java.io.OutputStreamWriter;
46.53 +import java.io.Writer;
46.54 +import java.nio.ByteBuffer;
46.55 +import java.util.ArrayList;
46.56 +import java.util.Collection;
46.57 +import java.util.HashMap;
46.58 +import java.util.HashSet;
46.59 +import java.util.LinkedList;
46.60 +import java.util.List;
46.61 +import java.util.Map;
46.62 +import java.util.Map.Entry;
46.63 +import java.util.Set;
46.64 +import java.util.concurrent.Callable;
46.65 +import java.util.concurrent.atomic.AtomicBoolean;
46.66 +import java.util.concurrent.atomic.AtomicInteger;
46.67 +import java.util.concurrent.atomic.AtomicReference;
46.68 +import java.util.logging.Level;
46.69 +import java.util.logging.Logger;
46.70 +import org.netbeans.api.annotations.common.NonNull;
46.71 +import org.netbeans.api.annotations.common.NullAllowed;
46.72 +import org.netbeans.api.fileinfo.NonRecursiveFolder;
46.73 +import org.netbeans.api.java.classpath.ClassPath;
46.74 +import org.netbeans.api.java.classpath.GlobalPathRegistry;
46.75 +import org.netbeans.api.java.source.ClasspathInfo;
46.76 +import org.netbeans.api.java.source.ClasspathInfo.PathKind;
46.77 +import org.netbeans.api.java.source.CompilationController;
46.78 +import org.netbeans.api.java.source.CompilationInfo;
46.79 +import org.netbeans.api.java.source.JavaSource;
46.80 +import org.netbeans.api.java.source.JavaSource.Phase;
46.81 +import org.netbeans.api.java.source.Task;
46.82 +import org.netbeans.api.queries.FileEncodingQuery;
46.83 +import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
46.84 +import org.netbeans.modules.java.hints.spiimpl.Utilities;
46.85 +import org.netbeans.modules.java.hints.spiimpl.hints.HintsInvoker;
46.86 +import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch;
46.87 +import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch.BulkPattern;
46.88 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.AdditionalQueryConstraints;
46.89 +import org.netbeans.modules.java.hints.providers.spi.Trigger.PatternDescription;
46.90 +import org.netbeans.spi.editor.hints.ErrorDescription;
46.91 +import org.netbeans.api.java.source.matching.Matcher;
46.92 +import org.netbeans.api.java.source.matching.Pattern;
46.93 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
46.94 +import org.openide.filesystems.FileObject;
46.95 +import org.openide.filesystems.FileUtil;
46.96 +import org.openide.util.Exceptions;
46.97 +
46.98 +/**
46.99 + *
46.100 + * @author lahvac
46.101 + */
46.102 +public class BatchSearch {
46.103 +
46.104 + private static final Logger LOG = Logger.getLogger(BatchSearch.class.getName());
46.105 +
46.106 + public static BatchResult findOccurrences(Iterable<? extends HintDescription> patterns, Scope scope) {
46.107 + return findOccurrences(patterns, scope, new ProgressHandleWrapper(null), HintsSettings.getGlobalSettings());
46.108 + }
46.109 +
46.110 + public static BatchResult findOccurrences(final Iterable<? extends HintDescription> patterns, final Scope scope, final ProgressHandleWrapper progress, @NullAllowed HintsSettings settingsProvider) {
46.111 + return findOccurrencesLocal(patterns, scope.getIndexMapper(patterns), scope.getTodo(), progress, settingsProvider);
46.112 + }
46.113 +
46.114 + private static BatchResult findOccurrencesLocal(final Iterable<? extends HintDescription> patterns, final MapIndices indexMapper, final Collection<? extends Folder> todo, final ProgressHandleWrapper progress, final @NullAllowed HintsSettings settingsProvider) {
46.115 + final BatchResult[] result = new BatchResult[1];
46.116 +
46.117 + try {
46.118 + JavaSource.create(Utilities.createUniversalCPInfo()).runUserActionTask(new Task<CompilationController>() {
46.119 + public void run(CompilationController parameter) throws Exception {
46.120 + result[0] = findOccurrencesLocalImpl(parameter, patterns, indexMapper, todo, progress, settingsProvider);
46.121 + }
46.122 + }, true);
46.123 + } catch (IOException ex) {
46.124 + throw new IllegalStateException(ex);
46.125 + }
46.126 +
46.127 + return result[0];
46.128 + }
46.129 +
46.130 + private static BatchResult findOccurrencesLocalImpl(final CompilationInfo info, final Iterable<? extends HintDescription> patterns, MapIndices indexMapper, Collection<? extends Folder> todo, ProgressHandleWrapper progress, HintsSettings settingsProvider) {
46.131 + boolean hasKindPatterns = false;
46.132 +
46.133 + for (HintDescription pattern : patterns) {
46.134 + if (!(pattern.getTrigger() instanceof PatternDescription)) {
46.135 + hasKindPatterns = true;
46.136 + break;
46.137 + }
46.138 + }
46.139 +
46.140 + final Callable<BulkPattern> bulkPattern = hasKindPatterns ? null : new Callable<BulkPattern>() {
46.141 + private final AtomicReference<BulkPattern> pattern = new AtomicReference<BulkPattern>();
46.142 + public BulkPattern call() {
46.143 + if (pattern.get() == null) {
46.144 + pattern.set(preparePattern(patterns, info));
46.145 + }
46.146 +
46.147 + return pattern.get();
46.148 + }
46.149 + };
46.150 + final Map<IndexEnquirer, Collection<? extends Resource>> result = new HashMap<IndexEnquirer, Collection<? extends Resource>>();
46.151 + final Collection<MessageImpl> problems = new LinkedList<MessageImpl>();
46.152 + ProgressHandleWrapper innerForAll = progress.startNextPartWithEmbedding(ProgressHandleWrapper.prepareParts(2 * todo.size()));
46.153 +
46.154 + for (final Folder src : todo) {
46.155 + LOG.log(Level.FINE, "Processing: {0}", FileUtil.getFileDisplayName(src.getFileObject()));
46.156 +
46.157 + IndexEnquirer indexEnquirer;// = indexMapper.findIndex(src.getFileObject(), innerForAll, src.isRecursive());
46.158 +
46.159 +// if (indexEnquirer == null) {
46.160 + indexEnquirer = new FileSystemBasedIndexEnquirer(src.getFileObject(), src.isRecursive());
46.161 +// }
46.162 +
46.163 + Collection<? extends Resource> occurrences = indexEnquirer.findResources(patterns, innerForAll, bulkPattern, problems, settingsProvider);
46.164 +
46.165 + if (!occurrences.isEmpty()) {
46.166 + result.put(indexEnquirer, occurrences);
46.167 + }
46.168 +
46.169 + innerForAll.tick();
46.170 + }
46.171 +
46.172 + return new BatchResult(result, problems);
46.173 + }
46.174 +
46.175 + private static BulkPattern preparePattern(final Iterable<? extends HintDescription> patterns, CompilationInfo info) {
46.176 + Collection<String> code = new LinkedList<String>();
46.177 + Collection<Tree> trees = new LinkedList<Tree>();
46.178 + Collection<AdditionalQueryConstraints> additionalConstraints = new LinkedList<AdditionalQueryConstraints>();
46.179 +
46.180 + for (HintDescription pattern : patterns) {
46.181 + String textPattern = ((PatternDescription) pattern.getTrigger()).getPattern();
46.182 +
46.183 + code.add(textPattern);
46.184 + trees.add(Utilities.parseAndAttribute(info, textPattern, null));
46.185 + additionalConstraints.add(pattern.getAdditionalConstraints());
46.186 + }
46.187 +
46.188 + return BulkSearch.getDefault().create(code, trees, additionalConstraints, new AtomicBoolean());
46.189 + }
46.190 +
46.191 + public static void getVerifiedSpans(BatchResult candidates, @NonNull ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, final Collection<? super MessageImpl> problems, AtomicBoolean cancel) {
46.192 + getVerifiedSpans(candidates, progress, callback, false, problems, cancel);
46.193 + }
46.194 +
46.195 + public static void getVerifiedSpans(BatchResult candidates, @NonNull ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, final Collection<? super MessageImpl> problems, AtomicBoolean cancel) {
46.196 + int[] parts = new int[candidates.projectId2Resources.size()];
46.197 + int index = 0;
46.198 +
46.199 + for (Entry<? extends IndexEnquirer, ? extends Collection<? extends Resource>> e : candidates.projectId2Resources.entrySet()) {
46.200 + parts[index++] = e.getValue().size();
46.201 + }
46.202 +
46.203 + ProgressHandleWrapper inner = progress.startNextPartWithEmbedding(parts);
46.204 +
46.205 + for (Entry<? extends IndexEnquirer, ? extends Collection<? extends Resource>> e : candidates.projectId2Resources.entrySet()) {
46.206 + if (cancel.get())
46.207 + return;
46.208 + inner.startNextPart(e.getValue().size());
46.209 +
46.210 + e.getKey().validateResource(e.getValue(), inner, callback, doNotRegisterClassPath, problems, cancel);
46.211 + }
46.212 + }
46.213 +
46.214 + private static void getLocalVerifiedSpans(Collection<? extends Resource> resources, @NonNull final ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, final Collection<? super MessageImpl> problems, final AtomicBoolean cancel) {
46.215 + Collection<FileObject> files = new LinkedList<FileObject>();
46.216 + final Map<FileObject, Resource> file2Resource = new HashMap<FileObject, Resource>();
46.217 +
46.218 + for (Resource r : resources) {
46.219 + FileObject file = r.getResolvedFile();
46.220 +
46.221 + if (file != null) {
46.222 + files.add(file);
46.223 + file2Resource.put(file, r);
46.224 + } else {
46.225 + callback.cannotVerifySpan(r);
46.226 + progress.tick();
46.227 + }
46.228 + }
46.229 +
46.230 + Map<ClasspathInfo, Collection<FileObject>> cp2Files = BatchUtilities.sortFiles(files);
46.231 + ClassPath[] toRegister = null;
46.232 +
46.233 + if (!doNotRegisterClassPath) {
46.234 + Set<ClassPath> toRegisterSet = new HashSet<ClassPath>();
46.235 +
46.236 + for (ClasspathInfo cpInfo : cp2Files.keySet()) {
46.237 + toRegisterSet.add(cpInfo.getClassPath(PathKind.SOURCE));
46.238 + }
46.239 +
46.240 + toRegister = !toRegisterSet.isEmpty() ? toRegisterSet.toArray(new ClassPath[0]) : null;
46.241 +
46.242 + if (toRegister != null) {
46.243 + GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, toRegister);
46.244 + try {
46.245 + Utilities.waitScanFinished();
46.246 + } catch (InterruptedException ex) {
46.247 + Exceptions.printStackTrace(ex);
46.248 + }
46.249 + }
46.250 + }
46.251 +
46.252 + try {
46.253 + for (Entry<ClasspathInfo, Collection<FileObject>> e : cp2Files.entrySet()) {
46.254 + try {
46.255 + List<FileObject> toProcess = new ArrayList<FileObject>(e.getValue());
46.256 + final AtomicInteger currentPointer = new AtomicInteger();
46.257 + callback.groupStarted();
46.258 +
46.259 +// for (FileObject f : toProcess) {
46.260 + while (currentPointer.get() < toProcess.size()) {
46.261 + if (cancel.get())
46.262 + return;
46.263 + final AtomicBoolean stop = new AtomicBoolean();
46.264 +// JavaSource js = JavaSource.create(e.getKey(), f);
46.265 + JavaSource js = JavaSource.create(e.getKey(), toProcess.subList(currentPointer.get(), toProcess.size()));
46.266 +
46.267 + js.runUserActionTask(new Task<CompilationController>() {
46.268 + public void run(CompilationController parameter) throws Exception {
46.269 + if (stop.get()) return;
46.270 + if (cancel.get()) return;
46.271 +
46.272 + boolean cont = true;
46.273 +
46.274 + try {
46.275 + if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0)
46.276 + return ;
46.277 +
46.278 + progress.setMessage("processing: " + FileUtil.getFileDisplayName(parameter.getFileObject()));
46.279 + Resource r = file2Resource.get(parameter.getFileObject());
46.280 +
46.281 + HintsSettings settings = r.settings;
46.282 + Iterable<? extends HintDescription> enabledHints;
46.283 +
46.284 + if (settings == null) {
46.285 + settings = HintsSettings.getSettingsFor(parameter.getFileObject());
46.286 + List<HintDescription> hintsCopy = new ArrayList<>();
46.287 + for (HintDescription hd : r.hints) {
46.288 + if (settings.isEnabled(hd.getMetadata())) {
46.289 + hintsCopy.add(hd);
46.290 + }
46.291 + }
46.292 + enabledHints = hintsCopy;
46.293 + } else {
46.294 + enabledHints = r.hints;
46.295 + }
46.296 +
46.297 + List<ErrorDescription> hints = new HintsInvoker(settings, true, new AtomicBoolean()).computeHints(parameter, enabledHints, problems);
46.298 +
46.299 + assert hints != null;
46.300 +
46.301 + cont = callback.spansVerified(parameter, r, hints);
46.302 + } catch (ThreadDeath td) {
46.303 + throw td;
46.304 + } catch (Throwable t) {
46.305 + LOG.log(Level.INFO, "Exception while performing batch processing in " + FileUtil.getFileDisplayName(parameter.getFileObject()), t);
46.306 + problems.add(new MessageImpl(MessageKind.WARNING, "An exception occurred while processing file: " + FileUtil.getFileDisplayName(parameter.getFileObject()) + " (" + t.getLocalizedMessage() + ")."));
46.307 + }
46.308 +
46.309 + if (cont) {
46.310 + progress.tick();
46.311 + currentPointer.incrementAndGet();
46.312 + } else {
46.313 + stop.set(true);
46.314 + }
46.315 + }
46.316 + }, true);
46.317 + }
46.318 +
46.319 + callback.groupFinished();
46.320 + } catch (IOException ex) {
46.321 + Exceptions.printStackTrace(ex);
46.322 + }
46.323 + }
46.324 + } finally {
46.325 + if (toRegister != null) {
46.326 + GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, toRegister);
46.327 + }
46.328 + progress.finish();
46.329 + }
46.330 + }
46.331 +
46.332 + public interface VerifiedSpansCallBack {
46.333 + public void groupStarted();
46.334 + public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception;
46.335 + public void groupFinished();
46.336 + public void cannotVerifySpan(Resource r);
46.337 + }
46.338 +
46.339 +
46.340 + public static class Folder {
46.341 +
46.342 + private FileObject file;
46.343 + private NonRecursiveFolder folder;
46.344 +
46.345 + public Folder(FileObject file) {
46.346 + this.file = file;
46.347 + }
46.348 +
46.349 + public Folder(NonRecursiveFolder folder) {
46.350 + this.folder = folder;
46.351 + }
46.352 +
46.353 + public FileObject getFileObject() {
46.354 + if (file!=null) {
46.355 + return file;
46.356 + }
46.357 + return folder.getFolder();
46.358 +
46.359 + }
46.360 +
46.361 + private boolean isRecursive() {
46.362 + if (file!=null) {
46.363 + return file.isFolder();
46.364 + }
46.365 + return false;
46.366 + }
46.367 +
46.368 + public static Folder[] convert(FileObject... files) {
46.369 + Folder[] result = new Folder[files.length];
46.370 + for (int i=0;i<files.length;i++) {
46.371 + result[i] = new Folder(files[i]);
46.372 + }
46.373 + return result;
46.374 + }
46.375 +
46.376 + public static Folder[] convert(Collection list) {
46.377 + Folder[] result = new Folder[list.size()];
46.378 + int i=0;
46.379 + for (Object item:list) {
46.380 + if (item instanceof FileObject)
46.381 + result[i] = new Folder((FileObject) item);
46.382 + else
46.383 + result[i] = new Folder((NonRecursiveFolder) item);
46.384 + i++;
46.385 + }
46.386 + return result;
46.387 + }
46.388 +
46.389 + @Override
46.390 + public String toString() {
46.391 + return !isRecursive()?"Non":"" + "Recursive file " + getFileObject().getPath();
46.392 + }
46.393 +
46.394 +
46.395 + }
46.396 +
46.397 + public abstract static class Scope {
46.398 +
46.399 + public abstract String getDisplayName();
46.400 + public abstract Collection<? extends Folder> getTodo();
46.401 + public abstract MapIndices getIndexMapper(Iterable<? extends HintDescription> hints);
46.402 +
46.403 + }
46.404 +
46.405 + public static final class BatchResult {
46.406 +
46.407 + private final Map<? extends IndexEnquirer, ? extends Collection<? extends Resource>> projectId2Resources;
46.408 + public final Collection<? extends MessageImpl> problems;
46.409 +
46.410 + public BatchResult(Map<? extends IndexEnquirer, ? extends Collection<? extends Resource>> projectId2Resources, Collection<? extends MessageImpl> problems) {
46.411 + this.projectId2Resources = projectId2Resources;
46.412 + this.problems = problems;
46.413 + }
46.414 +
46.415 + public Collection<? extends Collection<? extends Resource>> getResources() {
46.416 + return projectId2Resources.values();
46.417 + }
46.418 +
46.419 + public Map<FileObject, Collection<? extends Resource>> getResourcesWithRoots() {
46.420 + Map<FileObject, Collection<? extends Resource>> result = new HashMap<FileObject, Collection<? extends Resource>>();
46.421 +
46.422 + for (Entry<? extends IndexEnquirer, ? extends Collection<? extends Resource>> e : projectId2Resources.entrySet()) {
46.423 + result.put(e.getKey().src, e.getValue());
46.424 + }
46.425 +
46.426 + return result;
46.427 + }
46.428 + }
46.429 +
46.430 + public static final class Resource {
46.431 + private final IndexEnquirer indexEnquirer;
46.432 + private final String relativePath;
46.433 + final Iterable<? extends HintDescription> hints;
46.434 + private final BulkPattern pattern;
46.435 + final HintsSettings settings;
46.436 +
46.437 + public Resource(IndexEnquirer indexEnquirer, String relativePath, Iterable<? extends HintDescription> hints, BulkPattern pattern, HintsSettings settings) {
46.438 + this.indexEnquirer = indexEnquirer;
46.439 + this.relativePath = relativePath;
46.440 + this.hints = hints;
46.441 + this.pattern = pattern;
46.442 + this.settings = settings;
46.443 + }
46.444 +
46.445 + public String getRelativePath() {
46.446 + return relativePath;
46.447 + }
46.448 +
46.449 + public Iterable<int[]> getCandidateSpans() {
46.450 + FileObject file = getResolvedFile();
46.451 + JavaSource js;
46.452 +
46.453 + if (file != null) {
46.454 + js = JavaSource.forFileObject(file);
46.455 + } else {
46.456 + CharSequence text = getSourceCode();
46.457 +
46.458 + if (text == null) {
46.459 + return null;
46.460 + }
46.461 +
46.462 + Writer out = null;
46.463 +
46.464 + try {
46.465 + file = FileUtil.createData(FileUtil.createMemoryFileSystem().getRoot(), relativePath);
46.466 + out = new OutputStreamWriter(file.getOutputStream());
46.467 +
46.468 + out.write(text.toString());
46.469 + } catch (IOException ex) {
46.470 + Exceptions.printStackTrace(ex);
46.471 + return null;
46.472 + } finally {
46.473 + if (out != null) {
46.474 + try {
46.475 + out.close();
46.476 + } catch (IOException ex) {
46.477 + Exceptions.printStackTrace(ex);
46.478 + }
46.479 + }
46.480 + }
46.481 +
46.482 + js = JavaSource.create(Utilities.createUniversalCPInfo(), file);
46.483 + }
46.484 +
46.485 + final List<int[]> span = new LinkedList<int[]>();
46.486 +
46.487 + try {
46.488 + js.runUserActionTask(new Task<CompilationController>() {
46.489 + public void run(CompilationController cc) throws Exception {
46.490 + cc.toPhase(Phase.PARSED);
46.491 +
46.492 + span.addAll(doComputeSpans(cc));
46.493 + }
46.494 + }, true);
46.495 + } catch (IOException ex) {
46.496 + Exceptions.printStackTrace(ex);
46.497 + }
46.498 +
46.499 + return span;
46.500 + }
46.501 +
46.502 + private Collection<int[]> doComputeSpans(CompilationInfo ci) {
46.503 + Collection<int[]> result = new LinkedList<int[]>();
46.504 + Map<String, Collection<TreePath>> found = BulkSearch.getDefault().match(ci, new AtomicBoolean(), new TreePath(ci.getCompilationUnit()), pattern);
46.505 +
46.506 + for (Entry<String, Collection<TreePath>> e : found.entrySet()) {
46.507 + Tree treePattern = Utilities.parseAndAttribute(ci, e.getKey(), null);
46.508 +
46.509 + for (TreePath tp : e.getValue()) {
46.510 + //XXX: this pass will not be performed on the web!!!
46.511 + if ( BulkSearch.getDefault().requiresLightweightVerification()
46.512 + && !Matcher.create(ci).setCancel(new AtomicBoolean()).setSearchRoot(tp).setTreeTopSearch().setUntypedMatching().match(Pattern.createSimplePattern(new TreePath(new TreePath(ci.getCompilationUnit()), treePattern))).iterator().hasNext()) {
46.513 + continue;
46.514 + }
46.515 + int[] span = new int[] {
46.516 + (int) ci.getTrees().getSourcePositions().getStartPosition(ci.getCompilationUnit(), tp.getLeaf()),
46.517 + (int) ci.getTrees().getSourcePositions().getEndPosition(ci.getCompilationUnit(), tp.getLeaf())
46.518 + };
46.519 +
46.520 + result.add(span);
46.521 + }
46.522 + }
46.523 +
46.524 + return result;
46.525 + }
46.526 +
46.527 + public FileObject getResolvedFile() {
46.528 + return indexEnquirer.src.getFileObject(relativePath);
46.529 + }
46.530 +
46.531 + public String getDisplayName() {
46.532 + FileObject file = getResolvedFile();
46.533 +
46.534 + if (file != null) {
46.535 + return FileUtil.getFileDisplayName(file);
46.536 + } else {
46.537 + return relativePath; //TODO:+container
46.538 + }
46.539 + }
46.540 +
46.541 + public CharSequence getSourceCode() {
46.542 + try {
46.543 + FileObject file = getResolvedFile();
46.544 + ByteBuffer bb = ByteBuffer.wrap(file.asBytes());
46.545 +
46.546 + return FileEncodingQuery.getEncoding(file).decode(bb);
46.547 + } catch (IOException ex) {
46.548 + Exceptions.printStackTrace(ex);
46.549 + return null;
46.550 + }
46.551 + }
46.552 +
46.553 + public FileObject getRoot() {
46.554 + return indexEnquirer.src;
46.555 + }
46.556 + }
46.557 +
46.558 + public static interface MapIndices {
46.559 + public IndexEnquirer findIndex(FileObject root, ProgressHandleWrapper progress, boolean recursive);
46.560 + }
46.561 +
46.562 + public static abstract class IndexEnquirer {
46.563 + final FileObject src;
46.564 + public IndexEnquirer(FileObject src) {
46.565 + this.src = src;
46.566 + }
46.567 + public abstract Collection<? extends Resource> findResources(Iterable<? extends HintDescription> hints, ProgressHandleWrapper progress, @NullAllowed Callable<BulkPattern> bulkPattern, Collection<? super MessageImpl> problems, HintsSettings settingsProvider);
46.568 + public abstract void validateResource(Collection<? extends Resource> resources, ProgressHandleWrapper progress, VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, Collection<? super MessageImpl> problems, AtomicBoolean cancel);
46.569 +// public int[] getEstimatedSpan(Resource r);
46.570 + }
46.571 +
46.572 + public static abstract class LocalIndexEnquirer extends IndexEnquirer {
46.573 + public LocalIndexEnquirer(FileObject src) {
46.574 + super(src);
46.575 + }
46.576 + public void validateResource(Collection<? extends Resource> resources, ProgressHandleWrapper progress, VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, Collection<? super MessageImpl> problems, AtomicBoolean cancel) {
46.577 + getLocalVerifiedSpans(resources, progress, callback, doNotRegisterClassPath, problems, cancel);
46.578 + }
46.579 + }
46.580 +
46.581 + public static final class FileSystemBasedIndexEnquirer extends LocalIndexEnquirer {
46.582 + private boolean recursive;
46.583 + public FileSystemBasedIndexEnquirer(FileObject src, boolean recursive) {
46.584 + super(src);
46.585 + this.recursive = recursive;
46.586 + }
46.587 + public Collection<? extends Resource> findResources(final Iterable<? extends HintDescription> hints, ProgressHandleWrapper progress, final @NullAllowed Callable<BulkPattern> bulkPattern, final Collection<? super MessageImpl> problems, final HintsSettings settingsProvider) {
46.588 + Collection<FileObject> files = new LinkedList<FileObject>();
46.589 +
46.590 + final ProgressHandleWrapper innerProgress = progress.startNextPartWithEmbedding(30, 70);
46.591 +
46.592 + BatchUtilities.recursive(src, src, files, innerProgress, 0, null, null, recursive);
46.593 +
46.594 + LOG.log(Level.FINE, "files: {0}", files);
46.595 +
46.596 + innerProgress.startNextPart(files.size());
46.597 +
46.598 + final Collection<Resource> result = new ArrayList<Resource>();
46.599 +
46.600 + if (!files.isEmpty()) {
46.601 + try {
46.602 + if (bulkPattern != null) {
46.603 + long start = System.currentTimeMillis();
46.604 +
46.605 + JavaSource.create(Utilities.createUniversalCPInfo(), files).runUserActionTask(new Task<CompilationController>() {
46.606 + public void run(CompilationController cc) throws Exception {
46.607 + if (cc.toPhase(Phase.PARSED).compareTo(Phase.PARSED) <0) {
46.608 + return ;
46.609 + }
46.610 +
46.611 + try {
46.612 + boolean matches = BulkSearch.getDefault().matches(cc, new AtomicBoolean(), new TreePath(cc.getCompilationUnit()), bulkPattern.call());
46.613 +
46.614 + if (matches) {
46.615 + result.add(new Resource(FileSystemBasedIndexEnquirer.this, FileUtil.getRelativePath(src, cc.getFileObject()), hints, bulkPattern.call(), settingsProvider));
46.616 + }
46.617 + } catch (ThreadDeath td) {
46.618 + throw td;
46.619 + } catch (Throwable t) {
46.620 + LOG.log(Level.INFO, "Exception while performing batch search in " + FileUtil.getFileDisplayName(cc.getFileObject()), t);
46.621 + problems.add(new MessageImpl(MessageKind.WARNING, "An exception occurred while testing file: " + FileUtil.getFileDisplayName(cc.getFileObject()) + " (" + t.getLocalizedMessage() + ")."));
46.622 + }
46.623 +
46.624 + innerProgress.tick();
46.625 + }
46.626 + }, true);
46.627 +
46.628 + long end = System.currentTimeMillis();
46.629 +
46.630 + LOG.log(Level.FINE, "took: {0}, per file: {1}", new Object[]{end - start, (end - start) / files.size()});
46.631 + } else {
46.632 + for (FileObject file : files) {
46.633 + result.add(new Resource(this, FileUtil.getRelativePath(src, file), hints, null, settingsProvider));
46.634 + }
46.635 + }
46.636 + } catch (IOException ex) {
46.637 + Exceptions.printStackTrace(ex);
46.638 + }
46.639 + }
46.640 +
46.641 + return result;
46.642 + }
46.643 +
46.644 + }
46.645 +
46.646 +}
47.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
47.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchUtilities.java Wed May 08 21:47:42 2013 +0200
47.3 @@ -0,0 +1,548 @@
47.4 +/*
47.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
47.6 + *
47.7 + * Copyright 2009-2011 Oracle and/or its affiliates. All rights reserved.
47.8 + *
47.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
47.10 + * Other names may be trademarks of their respective owners.
47.11 + *
47.12 + * The contents of this file are subject to the terms of either the GNU
47.13 + * General Public License Version 2 only ("GPL") or the Common
47.14 + * Development and Distribution License("CDDL") (collectively, the
47.15 + * "License"). You may not use this file except in compliance with the
47.16 + * License. You can obtain a copy of the License at
47.17 + * http://www.netbeans.org/cddl-gplv2.html
47.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
47.19 + * specific language governing permissions and limitations under the
47.20 + * License. When distributing the software, include this License Header
47.21 + * Notice in each file and include the License file at
47.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
47.23 + * particular file as subject to the "Classpath" exception as provided
47.24 + * by Oracle in the GPL Version 2 section of the License file that
47.25 + * accompanied this code. If applicable, add the following below the
47.26 + * License Header, with the fields enclosed by brackets [] replaced by
47.27 + * your own identifying information:
47.28 + * "Portions Copyrighted [year] [name of copyright owner]"
47.29 + *
47.30 + * If you wish your version of this file to be governed by only the CDDL
47.31 + * or only the GPL Version 2, indicate your decision by adding
47.32 + * "[Contributor] elects to include this software in this distribution
47.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
47.34 + * single choice of license, a recipient has the option to distribute
47.35 + * your version of this file under either the CDDL, the GPL Version 2 or
47.36 + * to extend the choice of license to its licensees as provided above.
47.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
47.38 + * Version 2 license, then the option applies only if the new code is
47.39 + * made subject to such option by the copyright holder.
47.40 + *
47.41 + * Contributor(s):
47.42 + *
47.43 + * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
47.44 + */
47.45 +package org.netbeans.modules.java.hints.spiimpl.batch;
47.46 +
47.47 +import com.sun.tools.javac.api.JavacTaskImpl;
47.48 +import com.sun.tools.javac.util.Log;
47.49 +import java.io.IOException;
47.50 +import java.lang.reflect.Constructor;
47.51 +import java.lang.reflect.Method;
47.52 +import java.nio.ByteBuffer;
47.53 +import java.nio.charset.Charset;
47.54 +import java.util.ArrayList;
47.55 +import java.util.Collection;
47.56 +import java.util.Collections;
47.57 +import java.util.HashMap;
47.58 +import java.util.HashSet;
47.59 +import java.util.IdentityHashMap;
47.60 +import java.util.Iterator;
47.61 +import java.util.LinkedHashMap;
47.62 +import java.util.LinkedHashSet;
47.63 +import java.util.LinkedList;
47.64 +import java.util.List;
47.65 +import java.util.Map;
47.66 +import java.util.Map.Entry;
47.67 +import java.util.Properties;
47.68 +import java.util.Set;
47.69 +import java.util.concurrent.atomic.AtomicBoolean;
47.70 +import java.util.logging.Level;
47.71 +import java.util.logging.Logger;
47.72 +import javax.swing.text.BadLocationException;
47.73 +import org.netbeans.api.annotations.common.NonNull;
47.74 +import org.netbeans.api.java.classpath.ClassPath;
47.75 +import org.netbeans.api.java.classpath.ClassPath.PathConversionMode;
47.76 +import org.netbeans.api.java.platform.JavaPlatformManager;
47.77 +import org.netbeans.api.java.source.ClasspathInfo;
47.78 +import org.netbeans.api.java.source.CompilationController;
47.79 +import org.netbeans.api.java.source.CompilationInfo;
47.80 +import org.netbeans.api.java.source.JavaSource;
47.81 +import org.netbeans.api.java.source.JavaSource.Phase;
47.82 +import org.netbeans.api.java.source.ModificationResult;
47.83 +import org.netbeans.api.java.source.ModificationResult.Difference;
47.84 +import org.netbeans.api.java.source.Task;
47.85 +import org.netbeans.api.java.source.WorkingCopy;
47.86 +import org.netbeans.api.project.FileOwnerQuery;
47.87 +import org.netbeans.api.project.Project;
47.88 +import org.netbeans.api.project.ProjectUtils;
47.89 +import org.netbeans.api.project.SourceGroup;
47.90 +import org.netbeans.api.project.Sources;
47.91 +import org.netbeans.api.queries.FileEncodingQuery;
47.92 +import org.netbeans.api.queries.VisibilityQuery;
47.93 +//import org.netbeans.modules.java.editor.semantic.SemanticHighlighter;
47.94 +import org.netbeans.modules.java.hints.spiimpl.JavaFixImpl;
47.95 +import org.netbeans.modules.java.hints.spiimpl.JavaFixImpl.Accessor;
47.96 +import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
47.97 +import org.netbeans.modules.java.hints.spiimpl.SyntheticFix;
47.98 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.BatchResult;
47.99 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Resource;
47.100 +import org.netbeans.modules.java.hints.spiimpl.ipi.upgrade.ProjectDependencyUpgrader;
47.101 +import org.netbeans.modules.java.source.JavaSourceAccessor;
47.102 +import org.netbeans.modules.java.source.parsing.CompilationInfoImpl;
47.103 +import org.netbeans.modules.java.source.save.DiffUtilities;
47.104 +import org.netbeans.modules.java.source.save.ElementOverlay;
47.105 +import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
47.106 +import org.netbeans.spi.editor.hints.ErrorDescription;
47.107 +import org.netbeans.spi.editor.hints.Fix;
47.108 +import org.netbeans.spi.java.hints.HintContext.MessageKind;
47.109 +import org.netbeans.spi.java.hints.JavaFix;
47.110 +import org.openide.filesystems.FileObject;
47.111 +import org.openide.filesystems.FileUtil;
47.112 +import org.openide.util.Exceptions;
47.113 +import org.openide.util.Lookup;
47.114 +
47.115 +/**
47.116 + *
47.117 + * @author Jan Lahoda
47.118 + */
47.119 +public class BatchUtilities {
47.120 +
47.121 + private static final Logger LOG = Logger.getLogger(BatchUtilities.class.getName());
47.122 +
47.123 + public static Collection<ModificationResult> applyFixes(BatchResult candidates, @NonNull final ProgressHandleWrapper progress, AtomicBoolean cancel, final Collection<? super MessageImpl> problems) {
47.124 + return applyFixes(candidates, progress, cancel, new ArrayList<RefactoringElementImplementation>(), problems);
47.125 + }
47.126 +
47.127 + public static Collection<ModificationResult> applyFixes(BatchResult candidates, @NonNull final ProgressHandleWrapper progress, AtomicBoolean cancel, final Collection<? super RefactoringElementImplementation> fileChanges, final Collection<? super MessageImpl> problems) {
47.128 + return applyFixes(candidates, progress, cancel, fileChanges, null, problems);
47.129 + }
47.130 +
47.131 + public static Collection<ModificationResult> applyFixes(BatchResult candidates, @NonNull final ProgressHandleWrapper progress, AtomicBoolean cancel, final Collection<? super RefactoringElementImplementation> fileChanges, final Map<JavaFix, ModificationResult> changesPerFix, final Collection<? super MessageImpl> problems) {
47.132 + return applyFixes(candidates, progress, cancel, fileChanges, changesPerFix, false, problems);
47.133 + }
47.134 +
47.135 + public static Collection<ModificationResult> applyFixes(BatchResult candidates, @NonNull final ProgressHandleWrapper progress, AtomicBoolean cancel, final Collection<? super RefactoringElementImplementation> fileChanges, final Map<JavaFix, ModificationResult> changesPerFix, boolean doNotRegisterClassPath, final Collection<? super MessageImpl> problems) {
47.136 + final Map<Project, Set<String>> processedDependencyChanges = new IdentityHashMap<Project, Set<String>>();
47.137 + final Map<FileObject, List<ModificationResult.Difference>> result = new LinkedHashMap<FileObject, List<ModificationResult.Difference>>();
47.138 + final Map<FileObject, byte[]> resourceContentChanges = new HashMap<FileObject, byte[]>();
47.139 +
47.140 + BatchSearch.VerifiedSpansCallBack callback = new BatchSearch.VerifiedSpansCallBack() {
47.141 + private ElementOverlay overlay;
47.142 + public void groupStarted() {
47.143 + overlay = ElementOverlay.getOrCreateOverlay();
47.144 + }
47.145 + public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
47.146 + if (hints.isEmpty()) return true;
47.147 +
47.148 + Constructor<WorkingCopy> wcConstr = WorkingCopy.class.getDeclaredConstructor(CompilationInfoImpl.class, ElementOverlay.class);
47.149 + wcConstr.setAccessible(true);
47.150 +
47.151 +// final WorkingCopy copy = new WorkingCopy(JavaSourceAccessor.getINSTANCE().getCompilationInfoImpl(parameter), overlay);
47.152 + WorkingCopy copy = wcConstr.newInstance(JavaSourceAccessor.getINSTANCE().getCompilationInfoImpl(wc), overlay);
47.153 + Method setJavaSource = CompilationInfo.class.getDeclaredMethod("setJavaSource", JavaSource.class);
47.154 + setJavaSource.setAccessible(true);
47.155 +
47.156 +// copy.setJavaSource(JavaSource.this);
47.157 + setJavaSource.invoke(copy, wc.getJavaSource());
47.158 +
47.159 + copy.toPhase(Phase.RESOLVED);
47.160 + progress.tick();
47.161 +
47.162 + if (applyFixes(copy, processedDependencyChanges, hints, resourceContentChanges, fileChanges, changesPerFix, problems)) {
47.163 + return false;
47.164 + }
47.165 +
47.166 + final JavacTaskImpl jt = JavaSourceAccessor.getINSTANCE().getJavacTask(copy);
47.167 + Log.instance(jt.getContext()).nerrors = 0;
47.168 + Method getChanges = WorkingCopy.class.getDeclaredMethod("getChanges", Map.class);
47.169 + getChanges.setAccessible(true);
47.170 +
47.171 + result.put(copy.getFileObject(), (List<ModificationResult.Difference>) getChanges.invoke(copy, new HashMap<Object, int[]>()));
47.172 +
47.173 + if (LOG.isLoggable(Level.FINE)) {
47.174 + LOG.log(Level.FINE, "fixes applied to: {0}", FileUtil.getFileDisplayName(wc.getFileObject()));
47.175 + }
47.176 +
47.177 + return true;
47.178 + }
47.179 +
47.180 + public void groupFinished() {
47.181 + overlay = null;
47.182 + }
47.183 +
47.184 + public void cannotVerifySpan(Resource r) {
47.185 + problems.add(new MessageImpl(MessageKind.WARNING, "Cannot parse: " + r.getRelativePath()));
47.186 + }
47.187 + };
47.188 +
47.189 + BatchSearch.getVerifiedSpans(candidates, progress, callback, doNotRegisterClassPath, problems, cancel);
47.190 +
47.191 + addResourceContentChanges(resourceContentChanges, result);
47.192 +
47.193 + return Collections.singletonList(JavaSourceAccessor.getINSTANCE().createModificationResult(result, Collections.<Object, int[]>emptyMap()));
47.194 + }
47.195 +
47.196 + public static void addResourceContentChanges(final Map<FileObject, byte[]> resourceContentChanges, final Map<FileObject, List<Difference>> result) {
47.197 + for (Entry<FileObject, byte[]> e : resourceContentChanges.entrySet()) {
47.198 + try {
47.199 + byte[] origBytes = e.getKey().asBytes();
47.200 + Charset encoding = FileEncodingQuery.getEncoding(e.getKey());
47.201 + String origContent = encoding.newDecoder().decode(ByteBuffer.wrap(origBytes)).toString();
47.202 + String newContent = encoding.newDecoder().decode(ByteBuffer.wrap(e.getValue())).toString();
47.203 +
47.204 + result.put(e.getKey(), DiffUtilities.diff2ModificationResultDifference(e.getKey(), null, Collections.<Integer, String>emptyMap(), origContent, newContent));
47.205 + } catch (BadLocationException ex) {
47.206 + Exceptions.printStackTrace(ex);
47.207 + } catch (IOException ex) {
47.208 + Exceptions.printStackTrace(ex);
47.209 + }
47.210 + }
47.211 + }
47.212 +
47.213 + private static String positionToString(ErrorDescription ed) {
47.214 + try {
47.215 + return ed.getFile().getNameExt() + ":" + ed.getRange().getBegin().getLine();
47.216 + } catch (IOException ex) {
47.217 + LOG.log(Level.FINE, null, ex);
47.218 + return ed.getFile().getNameExt();
47.219 + }
47.220 + }
47.221 +
47.222 +// public static void removeUnusedImports(Collection<? extends FileObject> files) throws IOException {
47.223 +// Map<ClasspathInfo, Collection<FileObject>> sortedFastFiles = sortFiles(files);
47.224 +//
47.225 +// for (Entry<ClasspathInfo, Collection<FileObject>> e : sortedFastFiles.entrySet()) {
47.226 +// JavaSource.create(e.getKey(), e.getValue()).runModificationTask(new RemoveUnusedImports()).commit();
47.227 +// }
47.228 +// }
47.229 +//
47.230 +// private static final class RemoveUnusedImports implements Task<WorkingCopy> {
47.231 +// public void run(WorkingCopy wc) throws IOException {
47.232 +// Document doc = wc.getSnapshot().getSource().getDocument(true);
47.233 +//
47.234 +// if (wc.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) {
47.235 +// return;
47.236 +// }
47.237 +//
47.238 +// //compute imports to remove:
47.239 +// List<TreePathHandle> unusedImports = SemanticHighlighter.computeUnusedImports(wc);
47.240 +// CompilationUnitTree cut = wc.getCompilationUnit();
47.241 +// // make the changes to the source
47.242 +// for (TreePathHandle handle : unusedImports) {
47.243 +// TreePath path = handle.resolve(wc);
47.244 +// assert path != null;
47.245 +// cut = wc.getTreeMaker().removeCompUnitImport(cut,
47.246 +// (ImportTree) path.getLeaf());
47.247 +// }
47.248 +//
47.249 +// if (!unusedImports.isEmpty()) {
47.250 +// wc.rewrite(wc.getCompilationUnit(), cut);
47.251 +// }
47.252 +// }
47.253 +// }
47.254 +
47.255 + public static boolean applyFixes(WorkingCopy copy, Map<Project, Set<String>> processedDependencyChanges, Collection<? extends ErrorDescription> hints, Map<FileObject, byte[]> resourceContentChanges, Collection<? super RefactoringElementImplementation> fileChanges, Collection<? super MessageImpl> problems) throws IllegalStateException, Exception {
47.256 + return applyFixes(copy, processedDependencyChanges, hints, resourceContentChanges, fileChanges, null, problems);
47.257 + }
47.258 +
47.259 + public static boolean applyFixes(WorkingCopy copy, Map<Project, Set<String>> processedDependencyChanges, Collection<? extends ErrorDescription> hints, Map<FileObject, byte[]> resourceContentChanges, Collection<? super RefactoringElementImplementation> fileChanges, Map<JavaFix, ModificationResult> changesPerFix, Collection<? super MessageImpl> problems) throws IllegalStateException, Exception {
47.260 + Set<JavaFix> fixes = new LinkedHashSet<JavaFix>();
47.261 + for (ErrorDescription ed : hints) {
47.262 + if (!ed.getFixes().isComputed()) {
47.263 + throw new IllegalStateException();//TODO: should be problem
47.264 + }
47.265 +
47.266 + Fix toApply = null;
47.267 +
47.268 + for (Fix f : ed.getFixes().getFixes()) {
47.269 + if (f instanceof SyntheticFix) continue;
47.270 + if (toApply == null) toApply = f;
47.271 + else problems.add(new MessageImpl(MessageKind.WARNING, "More than one fix for: " + ed.getDescription() + " at " + positionToString(ed) + ", only the first one will be used."));
47.272 + }
47.273 +
47.274 + if (toApply == null) {
47.275 + //TODO: currently giving a warning so that the hints can be augmented with "Options.QUERY", but that should be removed
47.276 + //if a non-query hint cannot produce any fix, it is likely Ok - if not, the hint should produce a warning itself
47.277 + boolean doWarning = false;
47.278 + assert doWarning = true;
47.279 + if (doWarning) {
47.280 + problems.add(new MessageImpl(MessageKind.WARNING, "No fix for: " + ed.getDescription() + " at " + positionToString(ed) + "."));
47.281 + }
47.282 + continue;
47.283 + }
47.284 +
47.285 + if (!(toApply instanceof JavaFixImpl)) {
47.286 + throw new IllegalStateException(toApply.getClass().getName());//XXX: hints need to provide JavaFixes
47.287 + }
47.288 +
47.289 +
47.290 + fixes.add(((JavaFixImpl) toApply).jf);
47.291 + }
47.292 + if (fixDependencies(copy.getFileObject(), fixes, processedDependencyChanges)) {
47.293 + return true;
47.294 + }
47.295 + for (JavaFix f : fixes) {
47.296 +// if (cancel.get()) return ;
47.297 +
47.298 + JavaFixImpl.Accessor.INSTANCE.process(f, copy, false, resourceContentChanges, fileChanges);
47.299 +
47.300 + if (changesPerFix != null) {
47.301 + ElementOverlay overlay = ElementOverlay.getOrCreateOverlay(); //XXX: will use the incorrect overlay?
47.302 + Constructor<WorkingCopy> wcConstr = WorkingCopy.class.getDeclaredConstructor(CompilationInfoImpl.class, ElementOverlay.class);
47.303 + wcConstr.setAccessible(true);
47.304 +
47.305 +// final WorkingCopy copy = new WorkingCopy(JavaSourceAccessor.getINSTANCE().getCompilationInfoImpl(parameter), overlay);
47.306 + WorkingCopy perFixCopy = wcConstr.newInstance(JavaSourceAccessor.getINSTANCE().getCompilationInfoImpl(copy), overlay);
47.307 + Method setJavaSource = CompilationInfo.class.getDeclaredMethod("setJavaSource", JavaSource.class);
47.308 + setJavaSource.setAccessible(true);
47.309 +
47.310 +// copy.setJavaSource(JavaSource.this);
47.311 + setJavaSource.invoke(perFixCopy, copy.getJavaSource());
47.312 +
47.313 + perFixCopy.toPhase(Phase.RESOLVED);
47.314 +
47.315 + final Map<FileObject, byte[]> perFixResourceContentChanges = new HashMap<FileObject, byte[]>();
47.316 +
47.317 + JavaFixImpl.Accessor.INSTANCE.process(f, perFixCopy, false, perFixResourceContentChanges, new ArrayList<RefactoringElementImplementation>());
47.318 +
47.319 + final JavacTaskImpl jt = JavaSourceAccessor.getINSTANCE().getJavacTask(perFixCopy);
47.320 + Log.instance(jt.getContext()).nerrors = 0;
47.321 + Method getChanges = WorkingCopy.class.getDeclaredMethod("getChanges", Map.class);
47.322 + getChanges.setAccessible(true);
47.323 +
47.324 + Map<FileObject, List<Difference>> changes = new HashMap<FileObject, List<Difference>>();
47.325 +
47.326 + changes.put(perFixCopy.getFileObject(), (List<ModificationResult.Difference>) getChanges.invoke(perFixCopy, new HashMap<Object, int[]>()));
47.327 +
47.328 + addResourceContentChanges(resourceContentChanges, changes);
47.329 +
47.330 + for (Iterator<Entry<FileObject, List<Difference>>> it = changes.entrySet().iterator(); it.hasNext();) {
47.331 + if (it.next().getValue().isEmpty()) it.remove();
47.332 + }
47.333 +
47.334 + if (!changes.isEmpty()) {
47.335 + ModificationResult perFixResult = JavaSourceAccessor.getINSTANCE().createModificationResult(changes, Collections.<Object, int[]>emptyMap());
47.336 +
47.337 + changesPerFix.put(f, perFixResult);
47.338 + }
47.339 + }
47.340 + }
47.341 + return false;
47.342 + }
47.343 +
47.344 + public static Collection<ModificationResult> applyFixes(final Map<FileObject, Collection<JavaFix>> toRun) {
47.345 + final Map<FileObject, List<ModificationResult.Difference>> result = new LinkedHashMap<FileObject, List<ModificationResult.Difference>>();
47.346 + final Map<FileObject, byte[]> resourceContentChanges = new HashMap<FileObject, byte[]>();
47.347 + Map<ClasspathInfo, Collection<FileObject>> cp2Files = BatchUtilities.sortFiles(toRun.keySet());
47.348 +
47.349 + for (Entry<ClasspathInfo, Collection<FileObject>> e : cp2Files.entrySet()) {
47.350 + try {
47.351 + ModificationResult mr = JavaSource.create(e.getKey(), e.getValue()).runModificationTask(new Task<WorkingCopy>() {
47.352 + @Override
47.353 + public void run(WorkingCopy parameter) throws Exception {
47.354 + if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0) return ;
47.355 +
47.356 + for (JavaFix jf : toRun.get(parameter.getFileObject())) {
47.357 + JavaFixImpl.Accessor.INSTANCE.process(jf, parameter, false, resourceContentChanges, new ArrayList<RefactoringElementImplementation>());
47.358 + }
47.359 + }
47.360 + });
47.361 +
47.362 + result.putAll(JavaSourceAccessor.getINSTANCE().getDiffsFromModificationResult(mr));
47.363 + } catch (IOException ex) {
47.364 + Exceptions.printStackTrace(ex);
47.365 + }
47.366 + }
47.367 +
47.368 + addResourceContentChanges(resourceContentChanges, result);
47.369 +
47.370 + return Collections.singletonList(JavaSourceAccessor.getINSTANCE().createModificationResult(result, Collections.<Object, int[]>emptyMap()));
47.371 + }
47.372 +
47.373 + public static Collection<FileObject> getSourceGroups(Iterable<? extends Project> prjs) {
47.374 + List<FileObject> result = new LinkedList<FileObject>();
47.375 +
47.376 + for (Project p : prjs) {
47.377 + Sources s = ProjectUtils.getSources(p);
47.378 +
47.379 + for (SourceGroup sg : s.getSourceGroups("java")) {
47.380 + result.add(sg.getRootFolder());
47.381 + }
47.382 + }
47.383 +
47.384 + return result;
47.385 + }
47.386 +
47.387 + public static Map<ClasspathInfo, Collection<FileObject>> sortFiles(Collection<? extends FileObject> from) {
47.388 + Map<CPCategorizer, Collection<FileObject>> m = new HashMap<CPCategorizer, Collection<FileObject>>();
47.389 +
47.390 + for (FileObject f : from) {
47.391 + CPCategorizer cpCategorizer = new CPCategorizer(f);
47.392 +
47.393 + Collection<FileObject> files = m.get(cpCategorizer);
47.394 +
47.395 + if (files == null) {
47.396 + m.put(cpCategorizer, files = new LinkedList<FileObject>());
47.397 + }
47.398 +
47.399 + files.add(f);
47.400 + }
47.401 +
47.402 + Map<ClasspathInfo, Collection<FileObject>> result = new IdentityHashMap<ClasspathInfo, Collection<FileObject>>();
47.403 +
47.404 + for (Entry<CPCategorizer, Collection<FileObject>> e : m.entrySet()) {
47.405 + result.put(ClasspathInfo.create(e.getKey().boot, e.getKey().compile, e.getKey().source), e.getValue());
47.406 + }
47.407 +
47.408 + return result;
47.409 + }
47.410 +
47.411 + private static final ClassPath getClassPath(FileObject forFO, String id) {
47.412 + ClassPath result = ClassPath.getClassPath(forFO, id);
47.413 +
47.414 + if (result == null) {
47.415 + if (ClassPath.BOOT.equals(id)) {
47.416 + result = JavaPlatformManager.getDefault().getDefaultPlatform().getBootstrapLibraries();
47.417 + } else {
47.418 + result = ClassPath.EMPTY;
47.419 + }
47.420 + }
47.421 +
47.422 + return result;
47.423 + }
47.424 +
47.425 + private static final class CPCategorizer {
47.426 + private final String cps;
47.427 + private final ClassPath boot;
47.428 + private final ClassPath compile;
47.429 + private final ClassPath source;
47.430 + private final FileObject sourceRoot;
47.431 +
47.432 + public CPCategorizer(FileObject file) {
47.433 + this.boot = getClassPath(file, ClassPath.BOOT);
47.434 + this.compile = getClassPath(file, ClassPath.COMPILE);
47.435 + this.source = getClassPath(file, ClassPath.SOURCE);
47.436 + this.sourceRoot = source != null ? source.findOwnerRoot(file) : null;
47.437 +
47.438 + StringBuilder cps = new StringBuilder();
47.439 +
47.440 + if (boot != null) cps.append(boot.toString(PathConversionMode.PRINT));
47.441 + if (compile != null) cps.append(compile.toString(PathConversionMode.PRINT));
47.442 + if (source != null) cps.append(source.toString(PathConversionMode.PRINT));
47.443 +
47.444 + this.cps = cps.toString();
47.445 + }
47.446 +
47.447 + @Override
47.448 + public int hashCode() {
47.449 + int hash = 5;
47.450 + hash = 53 * hash + this.cps.hashCode();
47.451 + hash = 53 * hash + (this.sourceRoot != null ? this.sourceRoot.hashCode() : 0);
47.452 + return hash;
47.453 + }
47.454 +
47.455 + @Override
47.456 + public boolean equals(Object obj) {
47.457 + if (obj == null) {
47.458 + return false;
47.459 + }
47.460 + if (getClass() != obj.getClass()) {
47.461 + return false;
47.462 + }
47.463 + final CPCategorizer other = (CPCategorizer) obj;
47.464 + if (!this.cps.equals(other.cps)) {
47.465 + return false;
47.466 + }
47.467 + if (this.sourceRoot != other.sourceRoot && (this.sourceRoot == null || !this.sourceRoot.equals(other.sourceRoot))) {
47.468 + return false;
47.469 + }
47.470 + return true;
47.471 + }
47.472 +
47.473 + }
47.474 +
47.475 + public static final String ENSURE_DEPENDENCY = "ensure-dependency";
47.476 +
47.477 + public static boolean fixDependencies(FileObject file, Iterable<? extends JavaFix> toProcess, Map<Project, Set<String>> alreadyProcessed) {
47.478 + boolean modified = false;
47.479 +// for (FileObject file : toProcess.keySet()) {
47.480 + for (JavaFix fix : toProcess) {
47.481 + String updateTo = Accessor.INSTANCE.getOptions(fix).get(ENSURE_DEPENDENCY);
47.482 +
47.483 + if (updateTo != null) {
47.484 + Project p = FileOwnerQuery.getOwner(file);
47.485 +
47.486 + if (p != null) {
47.487 + Set<String> seen = alreadyProcessed.get(p);
47.488 +
47.489 + if (seen == null) {
47.490 + alreadyProcessed.put(p, seen = new HashSet<String>());
47.491 + }
47.492 +
47.493 + if (seen.add(updateTo)) {
47.494 + for (ProjectDependencyUpgrader up : Lookup.getDefault().lookupAll(ProjectDependencyUpgrader.class)) {
47.495 + if (up.ensureDependency(p, updateTo, false)) { //XXX: should check whether the given project was actually modified
47.496 + modified = true;
47.497 + break;
47.498 + }
47.499 + }
47.500 + //TODO: fail if cannot update the dependency?
47.501 + }
47.502 + }
47.503 + }
47.504 + }
47.505 +
47.506 + return modified;
47.507 +// }
47.508 + }
47.509 +
47.510 + public static void recursive(FileObject root, FileObject file, Collection<FileObject> collected, ProgressHandleWrapper progress, int depth, Properties timeStamps, Set<String> removedFiles, boolean recursive) {
47.511 + if (!VisibilityQuery.getDefault().isVisible(file)) return;
47.512 +
47.513 + if (file.isData()) {
47.514 + if (timeStamps != null) {
47.515 + String relativePath = FileUtil.getRelativePath(root, file);
47.516 + String lastModified = Long.toHexString(file.lastModified().getTime());
47.517 +
47.518 + removedFiles.remove(relativePath);
47.519 +
47.520 + if (lastModified.equals(timeStamps.getProperty(relativePath))) {
47.521 + return;
47.522 + }
47.523 +
47.524 + timeStamps.setProperty(relativePath, lastModified);
47.525 + }
47.526 +
47.527 + if (/*???:*/"java".equals(file.getExt()) || "text/x-java".equals(FileUtil.getMIMEType(file, "text/x-java"))) {
47.528 + collected.add(file);
47.529 + }
47.530 + } else {
47.531 + FileObject[] children = file.getChildren();
47.532 +
47.533 + if (children.length == 0) return;
47.534 +
47.535 + ProgressHandleWrapper inner = depth < 2 ? progress.startNextPartWithEmbedding(ProgressHandleWrapper.prepareParts(children.length)) : null;
47.536 +
47.537 + if (inner == null && progress != null) {
47.538 + progress.startNextPart(children.length);
47.539 + } else {
47.540 + progress = null;
47.541 + }
47.542 +
47.543 + for (FileObject c : children) {
47.544 + if (recursive || c.isData())
47.545 + recursive(root, c, collected, inner, depth + 1, timeStamps, removedFiles, recursive);
47.546 +
47.547 + if (progress != null) progress.tick();
47.548 + }
47.549 + }
47.550 + }
47.551 +}
48.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
48.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/ProgressHandleWrapper.java Wed May 08 21:47:42 2013 +0200
48.3 @@ -0,0 +1,293 @@
48.4 +/*
48.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
48.6 + *
48.7 + * Copyright 2009-2011 Oracle and/or its affiliates. All rights reserved.
48.8 + *
48.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
48.10 + * Other names may be trademarks of their respective owners.
48.11 + *
48.12 + * The contents of this file are subject to the terms of either the GNU
48.13 + * General Public License Version 2 only ("GPL") or the Common
48.14 + * Development and Distribution License("CDDL") (collectively, the
48.15 + * "License"). You may not use this file except in compliance with the
48.16 + * License. You can obtain a copy of the License at
48.17 + * http://www.netbeans.org/cddl-gplv2.html
48.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
48.19 + * specific language governing permissions and limitations under the
48.20 + * License. When distributing the software, include this License Header
48.21 + * Notice in each file and include the License file at
48.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
48.23 + * particular file as subject to the "Classpath" exception as provided
48.24 + * by Oracle in the GPL Version 2 section of the License file that
48.25 + * accompanied this code. If applicable, add the following below the
48.26 + * License Header, with the fields enclosed by brackets [] replaced by
48.27 + * your own identifying information:
48.28 + * "Portions Copyrighted [year] [name of copyright owner]"
48.29 + *
48.30 + * If you wish your version of this file to be governed by only the CDDL
48.31 + * or only the GPL Version 2, indicate your decision by adding
48.32 + * "[Contributor] elects to include this software in this distribution
48.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
48.34 + * single choice of license, a recipient has the option to distribute
48.35 + * your version of this file under either the CDDL, the GPL Version 2 or
48.36 + * to extend the choice of license to its licensees as provided above.
48.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
48.38 + * Version 2 license, then the option applies only if the new code is
48.39 + * made subject to such option by the copyright holder.
48.40 + *
48.41 + * Contributor(s):
48.42 + *
48.43 + * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
48.44 + */
48.45 +package org.netbeans.modules.java.hints.spiimpl.batch;
48.46 +
48.47 +import java.util.Arrays;
48.48 +import java.util.logging.Level;
48.49 +import java.util.logging.Logger;
48.50 +import org.netbeans.api.progress.ProgressHandle;
48.51 +import org.netbeans.modules.analysis.spi.Analyzer.Context;
48.52 +import org.netbeans.modules.java.hints.spiimpl.Utilities;
48.53 +
48.54 +public final class ProgressHandleWrapper {
48.55 +
48.56 + private static final int TOTAL = 1000;
48.57 + private final ProgressHandleAbstraction handle;
48.58 + private final int[] parts;
48.59 + private int currentPart = -1;
48.60 + private int currentPartTotalWork;
48.61 + private int currentPartWorkDone;
48.62 + private long currentPartStartTime;
48.63 + private int currentOffset;
48.64 + private final long[] spentTime;
48.65 + private boolean debug;
48.66 +
48.67 + public ProgressHandleWrapper(int... parts) {
48.68 + this((ProgressHandleAbstraction) null, parts);
48.69 + }
48.70 +
48.71 + public ProgressHandleWrapper(ProgressHandle handle, int... parts) {
48.72 + this(new ProgressHandleBasedProgressHandleAbstraction(handle), parts);
48.73 + }
48.74 +
48.75 + public ProgressHandleWrapper(Context handle, int... parts) {
48.76 + this(new AnalysisContextBasedProgressHandleAbstraction(handle), parts);
48.77 + }
48.78 +
48.79 + public ProgressHandleWrapper(ProgressHandleAbstraction handle, int... parts) {
48.80 + this.handle = handle;
48.81 + if (handle == null) {
48.82 + this.parts = null;
48.83 + this.spentTime = null;
48.84 + } else {
48.85 + int total = 0;
48.86 + for (int i : parts) {
48.87 + total += i;
48.88 + }
48.89 + this.parts = new int[parts.length];
48.90 + for (int cntr = 0; cntr < parts.length; cntr++) {
48.91 + this.parts[cntr] = (TOTAL * parts[cntr]) / total;
48.92 + }
48.93 + this.spentTime = new long[parts.length];
48.94 + }
48.95 + }
48.96 +
48.97 + public void setDebug(boolean debug) {
48.98 + this.debug = debug;
48.99 + }
48.100 +
48.101 + public void startNextPart(int totalWork) {
48.102 + if (handle == null) {
48.103 + return;
48.104 + }
48.105 + if (currentPart == (-1)) {
48.106 + handle.start(TOTAL);
48.107 + } else {
48.108 + currentOffset += parts[currentPart];
48.109 + spentTime[currentPart] = System.currentTimeMillis() - currentPartStartTime;
48.110 + }
48.111 + currentPart++;
48.112 + currentPartTotalWork = totalWork;
48.113 + currentPartWorkDone = 0;
48.114 + currentPartStartTime = System.currentTimeMillis();
48.115 + currentPartWorkDoneUpdated();
48.116 + }
48.117 +
48.118 + public ProgressHandleWrapper startNextPartWithEmbedding(int... embeddedParts) {
48.119 +// startNextPart(TOTAL);
48.120 + return new ProgressHandleWrapper(new ProgressHandleWrapperBasedProgressHandleAbstraction(this), embeddedParts);
48.121 + }
48.122 +
48.123 + public void tick() {
48.124 + if (handle == null) {
48.125 + return;
48.126 + }
48.127 + currentPartWorkDone++;
48.128 + currentPartWorkDoneUpdated();
48.129 + }
48.130 +
48.131 + private void setCurrentPartWorkDone(int done) {
48.132 + if (handle == null) {
48.133 + return;
48.134 + }
48.135 + currentPartWorkDone = done;
48.136 + currentPartWorkDoneUpdated();
48.137 + }
48.138 +
48.139 + private void currentPartWorkDoneUpdated() {
48.140 + if (currentPartTotalWork > 0) {
48.141 + int parentProgress = currentOffset + (parts[currentPart] * currentPartWorkDone) / currentPartTotalWork;
48.142 + if (debug) {
48.143 + System.err.println("currentOffset=" + currentOffset);
48.144 + System.err.println("currentPart=" + currentPart);
48.145 + System.err.println("parts[currentPart]= " +parts[currentPart]);
48.146 + System.err.println("currentPartWorkDone=" + currentPartWorkDone);
48.147 + System.err.println("currentPartTotalWork= " +currentPartTotalWork);
48.148 + System.err.println("parentProgress=" + parentProgress);
48.149 + }
48.150 + handle.progress(parentProgress);
48.151 + } else {
48.152 + handle.progress(currentOffset + parts[currentPart]);
48.153 + }
48.154 + setAutomatedMessage();
48.155 + }
48.156 +
48.157 + public void setMessage(String message) {
48.158 + if (handle == null) {
48.159 + return;
48.160 + }
48.161 + handle.progress(message);
48.162 + }
48.163 +
48.164 + private void setAutomatedMessage() {
48.165 + if (handle == null || currentPart == (-1)) {
48.166 + return;
48.167 + }
48.168 + long spentTime = System.currentTimeMillis() - currentPartStartTime;
48.169 + double timePerUnit = ((double) spentTime) / currentPartWorkDone;
48.170 + String timeString;
48.171 + if (spentTime > 0) {
48.172 + double totalTime = currentPartTotalWork * timePerUnit;
48.173 + timeString = Utilities.toHumanReadableTime(spentTime) + "/" + Utilities.toHumanReadableTime(totalTime);
48.174 + } else {
48.175 + timeString = "No estimate";
48.176 + }
48.177 + handle.progress("Part " + (currentPart + 1) + "/" + parts.length + ", " + currentPartWorkDone + "/" + currentPartTotalWork + ", " + timeString);
48.178 + }
48.179 +
48.180 + public void finish() {
48.181 + if (handle == null) {
48.182 + return ;
48.183 + }
48.184 +
48.185 + handle.finish();
48.186 +
48.187 + if (currentPart < 0) return ;
48.188 +
48.189 + spentTime[currentPart] = System.currentTimeMillis() - currentPartStartTime;
48.190 +
48.191 + double total = 0.0;
48.192 +
48.193 + for (long t : spentTime) {
48.194 + total += t;
48.195 + }
48.196 +
48.197 + double[] actualSplit = new double[spentTime.length];
48.198 + int i = 0;
48.199 +
48.200 + for (long t : spentTime) {
48.201 + actualSplit[i++] = TOTAL * (t / total);
48.202 + }
48.203 +
48.204 + Logger.getLogger(ProgressHandleWrapper.class.getName()).log(Level.FINE, "Progress handle with split: {0}, actual times: {1}, actual split: {2}", new Object[] {Arrays.toString(parts), Arrays.toString(spentTime), Arrays.toString(actualSplit)});
48.205 + }
48.206 +
48.207 + public static int[] prepareParts(int count) {
48.208 + int[] result = new int[count];
48.209 +
48.210 + for (int cntr = 0; cntr < count; cntr++) {
48.211 + result[cntr] = 1;
48.212 + }
48.213 +
48.214 + return result;
48.215 + }
48.216 +
48.217 + public static interface ProgressHandleAbstraction {
48.218 +
48.219 + public void start(int totalWork);
48.220 +
48.221 + public void progress(int currentWorkDone);
48.222 +
48.223 + public void progress(String message);
48.224 +
48.225 + public void finish();
48.226 +
48.227 + }
48.228 +
48.229 + private static final class ProgressHandleBasedProgressHandleAbstraction implements ProgressHandleAbstraction {
48.230 + private final ProgressHandle delegate;
48.231 + public ProgressHandleBasedProgressHandleAbstraction(ProgressHandle delegate) {
48.232 + this.delegate = delegate;
48.233 + }
48.234 +
48.235 + public void start(int totalWork) {
48.236 + delegate.start(totalWork);
48.237 + }
48.238 +
48.239 + public void progress(int currentWorkDone) {
48.240 + delegate.progress(currentWorkDone);
48.241 + }
48.242 +
48.243 + public void progress(String message) {
48.244 + delegate.progress(message);
48.245 + }
48.246 +
48.247 + public void finish() {
48.248 + delegate.finish();
48.249 + }
48.250 + }
48.251 +
48.252 + private static final class AnalysisContextBasedProgressHandleAbstraction implements ProgressHandleAbstraction {
48.253 + private final Context delegate;
48.254 + AnalysisContextBasedProgressHandleAbstraction(Context delegate) {
48.255 + this.delegate = delegate;
48.256 + }
48.257 +
48.258 + public void start(int totalWork) {
48.259 + delegate.start(totalWork);
48.260 + }
48.261 +
48.262 + public void progress(int currentWorkDone) {
48.263 + delegate.progress(currentWorkDone);
48.264 + }
48.265 +
48.266 + public void progress(String message) {
48.267 + delegate.progress(message);
48.268 + }
48.269 +
48.270 + public void finish() {
48.271 + delegate.finish();
48.272 + }
48.273 + }
48.274 +
48.275 + private static final class ProgressHandleWrapperBasedProgressHandleAbstraction implements ProgressHandleAbstraction {
48.276 + private final ProgressHandleWrapper delegate;
48.277 + public ProgressHandleWrapperBasedProgressHandleAbstraction(ProgressHandleWrapper delegate) {
48.278 + this.delegate = delegate;
48.279 + }
48.280 +
48.281 + public void start(int totalWork) {
48.282 + delegate.startNextPart(totalWork);
48.283 + }
48.284 +
48.285 + public void progress(int currentWorkDone) {
48.286 + delegate.setCurrentPartWorkDone(currentWorkDone);
48.287 + }
48.288 +
48.289 + public void progress(String message) {
48.290 + delegate.setMessage(message);
48.291 + }
48.292 +
48.293 + public void finish() {}
48.294 + }
48.295 +
48.296 +}
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/Scopes.java Wed May 08 21:47:42 2013 +0200
49.3 @@ -0,0 +1,141 @@
49.4 +/*
49.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
49.6 + *
49.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
49.8 + *
49.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
49.10 + * Other names may be trademarks of their respective owners.
49.11 + *
49.12 + * The contents of this file are subject to the terms of either the GNU
49.13 + * General Public License Version 2 only ("GPL") or the Common
49.14 + * Development and Distribution License("CDDL") (collectively, the
49.15 + * "License"). You may not use this file except in compliance with the
49.16 + * License. You can obtain a copy of the License at
49.17 + * http://www.netbeans.org/cddl-gplv2.html
49.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
49.19 + * specific language governing permissions and limitations under the
49.20 + * License. When distributing the software, include this License Header
49.21 + * Notice in each file and include the License file at
49.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
49.23 + * particular file as subject to the "Classpath" exception as provided
49.24 + * by Oracle in the GPL Version 2 section of the License file that
49.25 + * accompanied this code. If applicable, add the following below the
49.26 + * License Header, with the fields enclosed by brackets [] replaced by
49.27 + * your own identifying information:
49.28 + * "Portions Copyrighted [year] [name of copyright owner]"
49.29 + *
49.30 + * If you wish your version of this file to be governed by only the CDDL
49.31 + * or only the GPL Version 2, indicate your decision by adding
49.32 + * "[Contributor] elects to include this software in this distribution
49.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
49.34 + * single choice of license, a recipient has the option to distribute
49.35 + * your version of this file under either the CDDL, the GPL Version 2 or
49.36 + * to extend the choice of license to its licensees as provided above.
49.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
49.38 + * Version 2 license, then the option applies only if the new code is
49.39 + * made subject to such option by the copyright holder.
49.40 + *
49.41 + * Contributor(s):
49.42 + *
49.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
49.44 + */
49.45 +package org.netbeans.modules.java.hints.spiimpl.batch;
49.46 +
49.47 +import java.util.Arrays;
49.48 +import java.util.Collection;
49.49 +import java.util.HashSet;
49.50 +import java.util.Set;
49.51 +import org.netbeans.api.java.classpath.ClassPath;
49.52 +import org.netbeans.api.java.classpath.GlobalPathRegistry;
49.53 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Folder;
49.54 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.IndexEnquirer;
49.55 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.MapIndices;
49.56 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Scope;
49.57 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
49.58 +import org.openide.filesystems.FileObject;
49.59 +import org.openide.util.Lookup;
49.60 +
49.61 +/**
49.62 + *
49.63 + * @author lahvac
49.64 + */
49.65 +public class Scopes {
49.66 +
49.67 + public static Scope allOpenedProjectsScope() {
49.68 + return new AllOpenedProjectsScope();
49.69 + }
49.70 +
49.71 + private static final class AllOpenedProjectsScope extends Scope {
49.72 +
49.73 + @Override
49.74 + public String getDisplayName() {
49.75 + return "All Opened Projects";
49.76 + }
49.77 +
49.78 + @Override
49.79 + public Collection<? extends Folder> getTodo() {
49.80 + Set<Folder> todo = new HashSet<Folder>();
49.81 +
49.82 + for (ClassPath source : GlobalPathRegistry.getDefault().getPaths(ClassPath.SOURCE)) {
49.83 + todo.addAll(Arrays.asList(Folder.convert(source.getRoots())));
49.84 + }
49.85 +
49.86 + return todo;
49.87 + }
49.88 +
49.89 + @Override
49.90 + public MapIndices getIndexMapper(Iterable<? extends HintDescription> hints) {
49.91 + return getDefaultIndicesMapper();
49.92 + }
49.93 + }
49.94 +
49.95 + public static Scope specifiedFoldersScope(Folder... roots) {
49.96 + return new SpecificFoldersScope(roots);
49.97 + }
49.98 +
49.99 + private static final class SpecificFoldersScope extends Scope {
49.100 +
49.101 + private final Collection<? extends Folder> roots;
49.102 +
49.103 + public SpecificFoldersScope(Folder... roots) {
49.104 + this.roots = Arrays.asList(roots);
49.105 + }
49.106 +
49.107 + @Override
49.108 + public String getDisplayName() {
49.109 + return "Specified Root";
49.110 + }
49.111 +
49.112 + @Override
49.113 + public Collection<? extends Folder> getTodo() {
49.114 + return roots;
49.115 + }
49.116 +
49.117 + @Override
49.118 + public MapIndices getIndexMapper(Iterable<? extends HintDescription> hints) {
49.119 + return getDefaultIndicesMapper();
49.120 + }
49.121 + }
49.122 +
49.123 + public static MapIndices getDefaultIndicesMapper() {
49.124 + return new MapIndices() {
49.125 + @Override
49.126 + public IndexEnquirer findIndex(FileObject root, ProgressHandleWrapper progress, boolean recursive) {
49.127 + IndexEnquirer e = findIndexEnquirer(root, progress, recursive);
49.128 +
49.129 + if (e != null) return e;
49.130 + else return new BatchSearch.FileSystemBasedIndexEnquirer(root, recursive);
49.131 + }
49.132 + };
49.133 + }
49.134 +
49.135 + public static IndexEnquirer findIndexEnquirer(FileObject root, ProgressHandleWrapper progress, boolean recursive) {
49.136 + for (MapIndices mi : Lookup.getDefault().lookupAll(MapIndices.class)) {
49.137 + IndexEnquirer r = mi.findIndex(root, progress, recursive);
49.138 +
49.139 + if (r != null) return r;
49.140 + }
49.141 +
49.142 + return null;
49.143 + }
49.144 +}
50.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
50.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/hints/HintsInvoker.java Wed May 08 21:47:42 2013 +0200
50.3 @@ -0,0 +1,862 @@
50.4 +/*
50.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
50.6 + *
50.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
50.8 + *
50.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
50.10 + * Other names may be trademarks of their respective owners.
50.11 + *
50.12 + * The contents of this file are subject to the terms of either the GNU
50.13 + * General Public License Version 2 only ("GPL") or the Common
50.14 + * Development and Distribution License("CDDL") (collectively, the
50.15 + * "License"). You may not use this file except in compliance with the
50.16 + * License. You can obtain a copy of the License at
50.17 + * http://www.netbeans.org/cddl-gplv2.html
50.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
50.19 + * specific language governing permissions and limitations under the
50.20 + * License. When distributing the software, include this License Header
50.21 + * Notice in each file and include the License file at
50.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
50.23 + * particular file as subject to the "Classpath" exception as provided
50.24 + * by Oracle in the GPL Version 2 section of the License file that
50.25 + * accompanied this code. If applicable, add the following below the
50.26 + * License Header, with the fields enclosed by brackets [] replaced by
50.27 + * your own identifying information:
50.28 + * "Portions Copyrighted [year] [name of copyright owner]"
50.29 + *
50.30 + * If you wish your version of this file to be governed by only the CDDL
50.31 + * or only the GPL Version 2, indicate your decision by adding
50.32 + * "[Contributor] elects to include this software in this distribution
50.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
50.34 + * single choice of license, a recipient has the option to distribute
50.35 + * your version of this file under either the CDDL, the GPL Version 2 or
50.36 + * to extend the choice of license to its licensees as provided above.
50.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
50.38 + * Version 2 license, then the option applies only if the new code is
50.39 + * made subject to such option by the copyright holder.
50.40 + *
50.41 + * Contributor(s):
50.42 + *
50.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
50.44 + */
50.45 +
50.46 +package org.netbeans.modules.java.hints.spiimpl.hints;
50.47 +
50.48 +import com.sun.source.tree.Tree;
50.49 +import java.util.Stack;
50.50 +import java.util.concurrent.atomic.AtomicBoolean;
50.51 +import javax.lang.model.element.AnnotationMirror;
50.52 +import javax.lang.model.element.AnnotationValue;
50.53 +import javax.lang.model.element.Element;
50.54 +import javax.lang.model.element.ExecutableElement;
50.55 +import javax.lang.model.element.TypeElement;
50.56 +import javax.swing.text.Document;
50.57 +import org.netbeans.api.java.source.support.CancellableTreePathScanner;
50.58 +import org.netbeans.editor.GuardedDocument;
50.59 +import org.netbeans.editor.MarkBlock;
50.60 +import org.netbeans.editor.MarkBlockChain;
50.61 +import org.openide.filesystems.FileObject;
50.62 +
50.63 +import com.sun.source.tree.Tree.Kind;
50.64 +import com.sun.source.util.TreePath;
50.65 +import com.sun.source.util.Trees;
50.66 +import java.io.IOException;
50.67 +import java.util.ArrayList;
50.68 +import java.util.Arrays;
50.69 +import java.util.Collection;
50.70 +import java.util.Collections;
50.71 +import java.util.Comparator;
50.72 +import java.util.EnumMap;
50.73 +import java.util.HashMap;
50.74 +import java.util.HashSet;
50.75 +import java.util.Iterator;
50.76 +import java.util.LinkedList;
50.77 +import java.util.List;
50.78 +import java.util.Map;
50.79 +import java.util.Map.Entry;
50.80 +import java.util.Set;
50.81 +import java.util.prefs.Preferences;
50.82 +import javax.annotation.processing.ProcessingEnvironment;
50.83 +import javax.lang.model.type.TypeKind;
50.84 +import javax.lang.model.type.TypeMirror;
50.85 +import org.netbeans.api.annotations.common.CheckForNull;
50.86 +import org.netbeans.api.java.source.CompilationInfo;
50.87 +import org.netbeans.modules.java.hints.spiimpl.Hacks;
50.88 +import org.netbeans.spi.java.hints.HintContext;
50.89 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
50.90 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
50.91 +import org.netbeans.modules.java.hints.providers.spi.Trigger;
50.92 +import org.netbeans.modules.java.hints.providers.spi.Trigger.Kinds;
50.93 +import org.netbeans.modules.java.hints.providers.spi.Trigger.PatternDescription;
50.94 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
50.95 +import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
50.96 +import org.netbeans.modules.java.hints.spiimpl.RulesManager;
50.97 +import org.netbeans.modules.java.hints.spiimpl.SPIAccessor;
50.98 +import org.netbeans.modules.java.hints.spiimpl.Utilities;
50.99 +import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch;
50.100 +import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch.BulkPattern;
50.101 +import org.netbeans.modules.java.hints.spiimpl.pm.PatternCompiler;
50.102 +import org.netbeans.spi.editor.hints.ErrorDescription;
50.103 +import org.netbeans.spi.editor.hints.Severity;
50.104 +import org.netbeans.spi.java.hints.Hint;
50.105 +import org.netbeans.api.java.source.matching.Matcher;
50.106 +import org.netbeans.api.java.source.matching.Occurrence;
50.107 +import org.netbeans.api.java.source.matching.Pattern;
50.108 +import org.openide.util.Exceptions;
50.109 +
50.110 +/**
50.111 + *
50.112 + * @author lahvac
50.113 + */
50.114 +public class HintsInvoker {
50.115 +
50.116 + private final Map<String, Long> timeLog = new HashMap<String, Long>();
50.117 +
50.118 + private final HintsSettings settings;
50.119 + private final int caret;
50.120 + private final int from;
50.121 + private final int to;
50.122 + private final boolean bulkMode;
50.123 + private final AtomicBoolean cancel;
50.124 +
50.125 + public HintsInvoker(HintsSettings settings, AtomicBoolean cancel) {
50.126 + this(settings, false, cancel);
50.127 + }
50.128 +
50.129 + public HintsInvoker(HintsSettings settings, boolean bulkMode, AtomicBoolean cancel) {
50.130 + this(settings, -1, -1, -1, bulkMode, cancel);
50.131 + }
50.132 +
50.133 + public HintsInvoker(HintsSettings settings, int caret, AtomicBoolean cancel) {
50.134 + this(settings, caret, -1, -1, false, cancel);
50.135 + }
50.136 +
50.137 + public HintsInvoker(HintsSettings settings, int from, int to, AtomicBoolean cancel) {
50.138 + this(settings, -1, from, to, false, cancel);
50.139 + }
50.140 +
50.141 + private HintsInvoker(HintsSettings settings, int caret, int from, int to, boolean bulkMode, AtomicBoolean cancel) {
50.142 + this.settings = settings;
50.143 + this.caret = caret;
50.144 + this.from = from;
50.145 + this.to = to;
50.146 + this.bulkMode = bulkMode;
50.147 + this.cancel = cancel;
50.148 + }
50.149 +
50.150 + @CheckForNull
50.151 + public List<ErrorDescription> computeHints(CompilationInfo info) {
50.152 + return computeHints(info, new TreePath(info.getCompilationUnit()));
50.153 + }
50.154 +
50.155 + private List<ErrorDescription> computeHints(CompilationInfo info, TreePath startAt) {
50.156 + List<HintDescription> descs = new LinkedList<HintDescription>();
50.157 + Map<HintMetadata, ? extends Collection<? extends HintDescription>> allHints = RulesManager.getInstance().readHints(info, null, cancel);
50.158 +
50.159 + for (Entry<HintMetadata, ? extends Collection<? extends HintDescription>> e : allHints.entrySet()) {
50.160 + HintMetadata m = e.getKey();
50.161 +
50.162 + if (!settings.isEnabled(m)) {
50.163 + continue;
50.164 + }
50.165 +
50.166 + if (caret != -1) {
50.167 + if (m.kind == Hint.Kind.ACTION) {
50.168 + descs.addAll(e.getValue());
50.169 + } else {
50.170 + if (settings.getSeverity(m) == Severity.HINT) {
50.171 + descs.addAll(e.getValue());
50.172 + }
50.173 + }
50.174 + } else {
50.175 + if (m.kind == Hint.Kind.INSPECTION) {
50.176 + if (settings.getSeverity(m) != Severity.HINT) {
50.177 + descs.addAll(e.getValue());
50.178 + }
50.179 + }
50.180 + }
50.181 + }
50.182 +
50.183 + List<ErrorDescription> errors = join(computeHints(info, startAt, descs, new LinkedList<MessageImpl>()));
50.184 +
50.185 + dumpTimeSpentInHints();
50.186 +
50.187 + return errors;
50.188 + }
50.189 +
50.190 + @CheckForNull
50.191 + public List<ErrorDescription> computeHints(CompilationInfo info,
50.192 + Iterable<? extends HintDescription> hints) {
50.193 + return computeHints(info, hints, new LinkedList<MessageImpl>());
50.194 + }
50.195 +
50.196 + @CheckForNull
50.197 + public List<ErrorDescription> computeHints(CompilationInfo info,
50.198 + Iterable<? extends HintDescription> hints,
50.199 + Collection<? super MessageImpl> problems) {
50.200 + return join(computeHints(info, new TreePath(info.getCompilationUnit()), hints, problems));
50.201 + }
50.202 +
50.203 + private static final Iterable<? extends Class<? extends Trigger>> TRIGGER_KINDS = Arrays.asList(Kinds.class, PatternDescription.class);
50.204 +
50.205 + @CheckForNull
50.206 + public Map<HintDescription, List<ErrorDescription>> computeHints(CompilationInfo info,
50.207 + TreePath startAt,
50.208 + Iterable<? extends HintDescription> hints,
50.209 + Collection<? super MessageImpl> problems) {
50.210 + return computeHints(info, startAt, true, hints, problems);
50.211 + }
50.212 +
50.213 + @CheckForNull
50.214 + public Map<HintDescription, List<ErrorDescription>> computeHints(CompilationInfo info,
50.215 + TreePath startAt,
50.216 + boolean recursive,
50.217 + Iterable<? extends HintDescription> hints,
50.218 + Collection<? super MessageImpl> problems) {
50.219 + Map<Class, List<HintDescription>> triggerKind2Hints = new HashMap<Class, List<HintDescription>>();
50.220 +
50.221 + for (Class<? extends Trigger> c : TRIGGER_KINDS) {
50.222 + triggerKind2Hints.put(c, new ArrayList<HintDescription>());
50.223 + }
50.224 +
50.225 + for (HintDescription hd : hints) {
50.226 + List<HintDescription> sorted = triggerKind2Hints.get(hd.getTrigger().getClass());
50.227 +
50.228 + sorted.add(hd);
50.229 + }
50.230 +
50.231 + if (caret != -1) {
50.232 + TreePath tp = info.getTreeUtilities().pathFor(caret);
50.233 + return computeSuggestions(info, tp, true, triggerKind2Hints, problems);
50.234 + } else {
50.235 + if (from != (-1) && to != (-1)) {
50.236 + return computeHintsInSpan(info, triggerKind2Hints, problems);
50.237 + } else if (!recursive) {
50.238 + return computeSuggestions(info, startAt, false, triggerKind2Hints, problems);
50.239 + } else {
50.240 + return computeHintsImpl(info, startAt, triggerKind2Hints, problems);
50.241 + }
50.242 + }
50.243 + }
50.244 +
50.245 + private Map<HintDescription, List<ErrorDescription>> computeHintsImpl(CompilationInfo info,
50.246 + TreePath startAt,
50.247 + Map<Class, List<HintDescription>> triggerKind2Hints,
50.248 + Collection<? super MessageImpl> problems) {
50.249 + Map<HintDescription, List<ErrorDescription>> errors = new HashMap<HintDescription, List<ErrorDescription>>();
50.250 + List<HintDescription> kindBasedHints = triggerKind2Hints.get(Kinds.class);
50.251 +
50.252 + timeLog.put("[C] Kind Based Hints", (long) kindBasedHints.size());
50.253 +
50.254 + if (!kindBasedHints.isEmpty()) {
50.255 + long kindStart = System.currentTimeMillis();
50.256 +
50.257 + new ScannerImpl(info, cancel, sortByKinds(kindBasedHints), problems).scan(startAt, errors);
50.258 +
50.259 + long kindEnd = System.currentTimeMillis();
50.260 +
50.261 + timeLog.put("Kind Based Hints", kindEnd - kindStart);
50.262 + }
50.263 +
50.264 + if (cancel.get()) return null;
50.265 +
50.266 + List<HintDescription> patternBasedHints = triggerKind2Hints.get(PatternDescription.class);
50.267 +
50.268 + timeLog.put("[C] Pattern Based Hints", (long) patternBasedHints.size());
50.269 +
50.270 + long patternStart = System.currentTimeMillis();
50.271 +
50.272 + Map<PatternDescription, List<HintDescription>> patternHints = sortByPatterns(patternBasedHints);
50.273 + Map<String, List<PatternDescription>> patternTests = computePatternTests(patternHints);
50.274 +
50.275 + long bulkPatternStart = System.currentTimeMillis();
50.276 +
50.277 + BulkPattern bulkPattern = BulkSearch.getDefault().create(info, cancel, patternTests.keySet());
50.278 +
50.279 + if (bulkPattern == null || cancel.get()) return null;
50.280 +
50.281 + long bulkPatternEnd = System.currentTimeMillis();
50.282 +
50.283 + timeLog.put("Bulk Pattern preparation", bulkPatternEnd - bulkPatternStart);
50.284 +
50.285 + long bulkStart = System.currentTimeMillis();
50.286 +
50.287 + Map<String, Collection<TreePath>> occurringPatterns = BulkSearch.getDefault().match(info, cancel, startAt, bulkPattern, timeLog);
50.288 +
50.289 + if (occurringPatterns == null || cancel.get()) return null;
50.290 +
50.291 + long bulkEnd = System.currentTimeMillis();
50.292 +
50.293 + timeLog.put("Bulk Search", bulkEnd - bulkStart);
50.294 +
50.295 + Map<HintDescription, List<ErrorDescription>> computedHints = doComputeHints(info, occurringPatterns, patternTests, patternHints, problems);
50.296 +
50.297 + if (computedHints == null || cancel.get()) return null;
50.298 +
50.299 + mergeAll(errors, computedHints);
50.300 +
50.301 + long patternEnd = System.currentTimeMillis();
50.302 +
50.303 + timeLog.put("Pattern Based Hints", patternEnd - patternStart);
50.304 +
50.305 + return errors;
50.306 + }
50.307 +
50.308 + private Map<HintDescription, List<ErrorDescription>> computeHintsInSpan(CompilationInfo info,
50.309 + Map<Class, List<HintDescription>> triggerKind2Hints,
50.310 + Collection<? super MessageImpl> problems) {
50.311 +
50.312 + TreePath path = info.getTreeUtilities().pathFor((from + to) / 2);
50.313 +
50.314 + while (path.getLeaf().getKind() != Kind.COMPILATION_UNIT) {
50.315 + int start = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), path.getLeaf());
50.316 + int end = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), path.getLeaf());
50.317 +
50.318 + if (start <= from && end >= to) {
50.319 + break;
50.320 + }
50.321 +
50.322 + path = path.getParentPath();
50.323 + }
50.324 +
50.325 + Map<HintDescription, List<ErrorDescription>> errors = new HashMap<HintDescription, List<ErrorDescription>>();
50.326 + List<HintDescription> kindBasedHints = triggerKind2Hints.get(Kinds.class);
50.327 +
50.328 + if (!kindBasedHints.isEmpty()) {
50.329 + long kindStart = System.currentTimeMillis();
50.330 +
50.331 + new ScannerImpl(info, cancel, sortByKinds(kindBasedHints), problems).scan(path, errors);
50.332 +
50.333 + long kindEnd = System.currentTimeMillis();
50.334 +
50.335 + timeLog.put("Kind Based Hints", kindEnd - kindStart);
50.336 + }
50.337 +
50.338 + List<HintDescription> patternBasedHints = triggerKind2Hints.get(PatternDescription.class);
50.339 +
50.340 + if (!patternBasedHints.isEmpty()) {
50.341 + long patternStart = System.currentTimeMillis();
50.342 +
50.343 + Map<PatternDescription, List<HintDescription>> patternHints = sortByPatterns(patternBasedHints);
50.344 + Map<String, List<PatternDescription>> patternTests = computePatternTests(patternHints);
50.345 +
50.346 + long bulkStart = System.currentTimeMillis();
50.347 +
50.348 + BulkPattern bulkPattern = BulkSearch.getDefault().create(info, cancel, patternTests.keySet());
50.349 +
50.350 + if (bulkPattern == null || cancel.get()) return null;
50.351 +
50.352 + Map<String, Collection<TreePath>> occurringPatterns = BulkSearch.getDefault().match(info, cancel, path, bulkPattern, timeLog);
50.353 +
50.354 + long bulkEnd = System.currentTimeMillis();
50.355 +
50.356 + timeLog.put("Bulk Search", bulkEnd - bulkStart);
50.357 +
50.358 + Map<HintDescription, List<ErrorDescription>> computedHints = doComputeHints(info, occurringPatterns, patternTests, patternHints, problems);
50.359 +
50.360 + if (computedHints == null || cancel.get()) return null;
50.361 +
50.362 + mergeAll(errors, computedHints);
50.363 +
50.364 + long patternEnd = System.currentTimeMillis();
50.365 +
50.366 + timeLog.put("Pattern Based Hints", patternEnd - patternStart);
50.367 + }
50.368 +
50.369 + if (path != null) {
50.370 + Map<HintDescription, List<ErrorDescription>> suggestions = computeSuggestions(info, path, true, triggerKind2Hints, problems);
50.371 +
50.372 + if (suggestions == null || cancel.get()) return null;
50.373 +
50.374 + mergeAll(errors, suggestions);
50.375 + }
50.376 +
50.377 + return errors;
50.378 + }
50.379 +
50.380 + private Map<HintDescription, List<ErrorDescription>> computeSuggestions(CompilationInfo info,
50.381 + TreePath workOn,
50.382 + boolean up,
50.383 + Map<Class, List<HintDescription>> triggerKind2Hints,
50.384 + Collection<? super MessageImpl> problems) {
50.385 + Map<HintDescription, List<ErrorDescription>> errors = new HashMap<HintDescription, List<ErrorDescription>>();
50.386 + List<HintDescription> kindBasedHints = triggerKind2Hints.get(Kinds.class);
50.387 +
50.388 + if (!kindBasedHints.isEmpty()) {
50.389 + long kindStart = System.currentTimeMillis();
50.390 +
50.391 + Map<Kind, List<HintDescription>> hints = sortByKinds(kindBasedHints);
50.392 + TreePath proc = workOn;
50.393 +
50.394 + while (proc != null) {
50.395 + new ScannerImpl(info, cancel, hints, problems).scanDoNotGoDeeper(proc, errors);
50.396 + if (!up) break;
50.397 + proc = proc.getParentPath();
50.398 + }
50.399 +
50.400 + long kindEnd = System.currentTimeMillis();
50.401 +
50.402 + timeLog.put("Kind Based Suggestions", kindEnd - kindStart);
50.403 + }
50.404 +
50.405 + if (cancel.get()) return null;
50.406 +
50.407 + List<HintDescription> patternBasedHints = triggerKind2Hints.get(PatternDescription.class);
50.408 +
50.409 + if (!patternBasedHints.isEmpty()) {
50.410 + long patternStart = System.currentTimeMillis();
50.411 +
50.412 + Map<PatternDescription, List<HintDescription>> patternHints = sortByPatterns(patternBasedHints);
50.413 + Map<String, List<PatternDescription>> patternTests = computePatternTests(patternHints);
50.414 +
50.415 + //pretend that all the patterns occur on all treepaths from the current path
50.416 + //up (probably faster than using BulkSearch over whole file)
50.417 + //TODO: what about machint trees under the current path?
50.418 + Set<TreePath> paths = new HashSet<TreePath>();
50.419 +
50.420 + TreePath tp = workOn;
50.421 +
50.422 + while (tp != null) {
50.423 + paths.add(tp);
50.424 + if (!up) break;
50.425 + tp = tp.getParentPath();
50.426 + }
50.427 +
50.428 + Map<String, Collection<TreePath>> occurringPatterns = new HashMap<String, Collection<TreePath>>();
50.429 +
50.430 + for (String p : patternTests.keySet()) {
50.431 + occurringPatterns.put(p, paths);
50.432 + }
50.433 +
50.434 +// long bulkStart = System.currentTimeMillis();
50.435 +//
50.436 +// BulkPattern bulkPattern = BulkSearch.getDefault().create(info, patternTests.keySet());
50.437 +// Map<String, Collection<TreePath>> occurringPatterns = BulkSearch.getDefault().match(info, new TreePath(info.getCompilationUnit()), bulkPattern, timeLog);
50.438 +//
50.439 +// long bulkEnd = System.currentTimeMillis();
50.440 +//
50.441 +// Set<Tree> acceptedLeafs = new HashSet<Tree>();
50.442 +//
50.443 +// TreePath tp = workOn;
50.444 +//
50.445 +// while (tp != null) {
50.446 +// acceptedLeafs.add(tp.getLeaf());
50.447 +// tp = tp.getParentPath();
50.448 +// }
50.449 +//
50.450 +// for (Entry<String, Collection<TreePath>> e : occurringPatterns.entrySet()) {
50.451 +// for (Iterator<TreePath> it = e.getValue().iterator(); it.hasNext(); ) {
50.452 +// if (!acceptedLeafs.contains(it.next().getLeaf())) {
50.453 +// it.remove();
50.454 +// }
50.455 +// }
50.456 +// }
50.457 +//
50.458 +// timeLog.put("Bulk Search", bulkEnd - bulkStart);
50.459 +
50.460 + Map<HintDescription, List<ErrorDescription>> computed = doComputeHints(info, occurringPatterns, patternTests, patternHints, problems);
50.461 +
50.462 + if (computed == null || cancel.get()) return null;
50.463 +
50.464 + mergeAll(errors, computed);
50.465 +
50.466 + long patternEnd = System.currentTimeMillis();
50.467 +
50.468 + timeLog.put("Pattern Based Hints", patternEnd - patternStart);
50.469 + }
50.470 +
50.471 + return errors;
50.472 + }
50.473 +
50.474 + public Map<HintDescription, List<ErrorDescription>> doComputeHints(CompilationInfo info, Map<String, Collection<TreePath>> occurringPatterns, Map<String, List<PatternDescription>> patterns, Map<PatternDescription, List<HintDescription>> patternHints) throws IllegalStateException {
50.475 + return doComputeHints(info, occurringPatterns, patterns, patternHints, new LinkedList<MessageImpl>());
50.476 + }
50.477 +
50.478 + private static Map<Kind, List<HintDescription>> sortByKinds(List<HintDescription> kindBasedHints) {
50.479 + Map<Kind, List<HintDescription>> result = new EnumMap<Kind, List<HintDescription>>(Kind.class);
50.480 +
50.481 + for (HintDescription hd : kindBasedHints) {
50.482 + for (Kind k : ((Kinds) hd.getTrigger()).getKinds()) {
50.483 + List<HintDescription> hints = result.get(k);
50.484 +
50.485 + if (hints == null) {
50.486 + result.put(k, hints = new ArrayList<HintDescription>());
50.487 + }
50.488 +
50.489 + hints.add(hd);
50.490 + }
50.491 + }
50.492 +
50.493 + return result;
50.494 + }
50.495 +
50.496 + private static Map<PatternDescription, List<HintDescription>> sortByPatterns(List<HintDescription> kindBasedHints) {
50.497 + Map<PatternDescription, List<HintDescription>> result = new HashMap<PatternDescription, List<HintDescription>>();
50.498 +
50.499 + for (HintDescription hd : kindBasedHints) {
50.500 + List<HintDescription> hints = result.get((PatternDescription) hd.getTrigger());
50.501 +
50.502 + if (hints == null) {
50.503 + result.put((PatternDescription) hd.getTrigger(), hints = new ArrayList<HintDescription>());
50.504 + }
50.505 +
50.506 + hints.add(hd);
50.507 + }
50.508 +
50.509 + return result;
50.510 + }
50.511 +
50.512 + public static Map<String, List<PatternDescription>> computePatternTests(Map<PatternDescription, List<HintDescription>> patternHints) {
50.513 + Map<String, List<PatternDescription>> patternTests = new HashMap<String, List<PatternDescription>>();
50.514 + for (Entry<PatternDescription, List<HintDescription>> e : patternHints.entrySet()) {
50.515 + String p = e.getKey().getPattern();
50.516 + List<PatternDescription> descs = patternTests.get(p);
50.517 + if (descs == null) {
50.518 + patternTests.put(p, descs = new LinkedList<PatternDescription>());
50.519 + }
50.520 + descs.add(e.getKey());
50.521 + }
50.522 + return patternTests;
50.523 + }
50.524 +
50.525 + private Map<HintDescription, List<ErrorDescription>> doComputeHints(CompilationInfo info, Map<String, Collection<TreePath>> occurringPatterns, Map<String, List<PatternDescription>> patterns, Map<PatternDescription, List<HintDescription>> patternHints, Collection<? super MessageImpl> problems) throws IllegalStateException {
50.526 + Map<HintDescription, List<ErrorDescription>> errors = new HashMap<HintDescription, List<ErrorDescription>>();
50.527 +
50.528 + for (Entry<String, Collection<TreePath>> occ : occurringPatterns.entrySet()) {
50.529 + PATTERN_LOOP: for (PatternDescription d : patterns.get(occ.getKey())) {
50.530 + if (cancel.get()) return null;
50.531 +
50.532 + Map<String, TypeMirror> constraints = new HashMap<String, TypeMirror>();
50.533 +
50.534 + for (Entry<String, String> e : d.getConstraints().entrySet()) {
50.535 + TypeMirror designedType = Hacks.parseFQNType(info, e.getValue());
50.536 +
50.537 + if (designedType == null || designedType.getKind() == TypeKind.ERROR) {
50.538 + //will not bind to anything anyway (#190449), skip pattern:
50.539 + continue PATTERN_LOOP;
50.540 + }
50.541 +
50.542 + constraints.put(e.getKey(), designedType);
50.543 + }
50.544 +
50.545 + Pattern pattern = PatternCompiler.compile(info, occ.getKey(), constraints, d.getImports());
50.546 +
50.547 + for (TreePath candidate : occ.getValue()) {
50.548 + if (cancel.get()) return null;
50.549 +
50.550 + Iterator<? extends Occurrence> verified = Matcher.create(info).setCancel(cancel).setSearchRoot(candidate).setTreeTopSearch().match(pattern).iterator();
50.551 +
50.552 + if (!verified.hasNext()) {
50.553 + continue;
50.554 + }
50.555 +
50.556 + Set<String> suppressedWarnings = new HashSet<String>(Utilities.findSuppressedWarnings(info, candidate));
50.557 + Occurrence verifiedVariables = verified.next();
50.558 +
50.559 + for (HintDescription hd : patternHints.get(d)) {
50.560 + HintMetadata hm = hd.getMetadata();
50.561 + HintContext c = SPIAccessor.getINSTANCE().createHintContext(info, settings, hm, candidate, verifiedVariables.getVariables(), verifiedVariables.getMultiVariables(), verifiedVariables.getVariables2Names(), constraints, problems, bulkMode, cancel, caret);
50.562 +
50.563 + if (!Collections.disjoint(suppressedWarnings, hm.suppressWarnings))
50.564 + continue;
50.565 +
50.566 + Collection<? extends ErrorDescription> workerErrors = runHint(hd, c);
50.567 +
50.568 + if (workerErrors != null) {
50.569 + merge(errors, hd, workerErrors);
50.570 + }
50.571 + }
50.572 + }
50.573 + }
50.574 + }
50.575 +
50.576 + return errors;
50.577 + }
50.578 +
50.579 +// public static void computeHints(URI file, ProcessingEnvironment env, CompilationUnitTree cut, RulesManager m) {
50.580 +// Map<Kind, HintDescription> hints = m.getKindBasedHints();
50.581 +//
50.582 +// if (hints.isEmpty()) {
50.583 +// return ;
50.584 +// }
50.585 +//
50.586 +// List<ErrorDescription> errors = new LinkedList<ErrorDescription>();
50.587 +//
50.588 +// File af = new File(file.getPath());
50.589 +// FileObject f = FileUtil.toFileObject(af);
50.590 +//
50.591 +// new ScannerImpl(f, env, hints).scan(cut, errors);
50.592 +//
50.593 +// for (ErrorDescription ed : errors) {
50.594 +// Diagnostic.Kind k;
50.595 +//
50.596 +// switch (ed.getSeverity()) {
50.597 +// case ERROR:
50.598 +// k = Diagnostic.Kind.ERROR;
50.599 +// break;
50.600 +// default:
50.601 +// k = Diagnostic.Kind.WARNING;
50.602 +// break;
50.603 +// }
50.604 +//
50.605 +// env.getMessager().printMessage(k, ed.getDescription());
50.606 +// }
50.607 +// }
50.608 +
50.609 + public Map<String, Long> getTimeLog() {
50.610 + return timeLog;
50.611 + }
50.612 +
50.613 + private final class ScannerImpl extends CancellableTreePathScanner<Void, Map<HintDescription, List<ErrorDescription>>> {
50.614 +
50.615 + private final Stack<Set<String>> suppresWarnings = new Stack<Set<String>>();
50.616 + private final CompilationInfo info;
50.617 + private final FileObject file;
50.618 + private final ProcessingEnvironment env;
50.619 + private final Map<Kind, List<HintDescription>> hints;
50.620 + private final Collection<? super MessageImpl> problems;
50.621 +
50.622 + public ScannerImpl(CompilationInfo info, AtomicBoolean cancel, Map<Kind, List<HintDescription>> hints, Collection<? super MessageImpl> problems) {
50.623 + super(cancel);
50.624 + this.info = info;
50.625 + this.file = null;
50.626 + this.env = null;
50.627 + this.hints = hints;
50.628 + this.problems = problems;
50.629 + }
50.630 +
50.631 + public ScannerImpl(FileObject file, ProcessingEnvironment env, Map<Kind, List<HintDescription>> hints, Collection<? super MessageImpl> problems) {
50.632 + super(new AtomicBoolean());
50.633 + this.info = null;
50.634 + this.file = file;
50.635 + this.env = env;
50.636 + this.hints = hints;
50.637 + this.problems = problems;
50.638 + }
50.639 +
50.640 + private void runAndAdd(TreePath path, List<HintDescription> rules, Map<HintDescription, List<ErrorDescription>> d) {
50.641 + if (rules != null && !isInGuarded(info, path)) {
50.642 + OUTER: for (HintDescription hd : rules) {
50.643 + if (isCanceled()) {
50.644 + return ;
50.645 + }
50.646 +
50.647 + HintMetadata hm = hd.getMetadata();
50.648 +
50.649 + for (String wname : hm.suppressWarnings) {
50.650 + if( !suppresWarnings.empty() && suppresWarnings.peek().contains(wname)) {
50.651 + continue OUTER;
50.652 + }
50.653 + }
50.654 +
50.655 + HintContext c = SPIAccessor.getINSTANCE().createHintContext(info, settings, hm, path, Collections.<String, TreePath>emptyMap(), Collections.<String, Collection<? extends TreePath>>emptyMap(), Collections.<String, String>emptyMap(), Collections.<String, TypeMirror>emptyMap(), new ArrayList<MessageImpl>(), bulkMode, cancel, caret);
50.656 + Collection<? extends ErrorDescription> errors = runHint(hd, c);
50.657 +
50.658 + if (errors != null) {
50.659 + merge(d, hd, errors);
50.660 + }
50.661 + }
50.662 + }
50.663 + }
50.664 +
50.665 + @Override
50.666 + public Void scan(Tree tree, Map<HintDescription, List<ErrorDescription>> p) {
50.667 + if (tree == null)
50.668 + return null;
50.669 +
50.670 + TreePath tp = new TreePath(getCurrentPath(), tree);
50.671 + Kind k = tree.getKind();
50.672 +
50.673 + boolean b = pushSuppressWarrnings(tp);
50.674 + try {
50.675 + runAndAdd(tp, hints.get(k), p);
50.676 +
50.677 + if (isCanceled()) {
50.678 + return null;
50.679 + }
50.680 +
50.681 + return super.scan(tree, p);
50.682 + } finally {
50.683 + if (b) {
50.684 + suppresWarnings.pop();
50.685 + }
50.686 + }
50.687 + }
50.688 +
50.689 + @Override
50.690 + public Void scan(TreePath path, Map<HintDescription, List<ErrorDescription>> p) {
50.691 + Kind k = path.getLeaf().getKind();
50.692 + boolean b = pushSuppressWarrnings(path);
50.693 + try {
50.694 + runAndAdd(path, hints.get(k), p);
50.695 +
50.696 + if (isCanceled()) {
50.697 + return null;
50.698 + }
50.699 +
50.700 + return super.scan(path, p);
50.701 + } finally {
50.702 + if (b) {
50.703 + suppresWarnings.pop();
50.704 + }
50.705 + }
50.706 + }
50.707 +
50.708 + public void scanDoNotGoDeeper(TreePath path, Map<HintDescription, List<ErrorDescription>> p) {
50.709 + Kind k = path.getLeaf().getKind();
50.710 + runAndAdd(path, hints.get(k), p);
50.711 + }
50.712 +
50.713 + private boolean pushSuppressWarrnings(TreePath path) {
50.714 + switch(path.getLeaf().getKind()) {
50.715 + case ANNOTATION_TYPE:
50.716 + case CLASS:
50.717 + case ENUM:
50.718 + case INTERFACE:
50.719 + case METHOD:
50.720 + case VARIABLE:
50.721 + Set<String> current = suppresWarnings.size() == 0 ? null : suppresWarnings.peek();
50.722 + Set<String> nju = current == null ? new HashSet<String>() : new HashSet<String>(current);
50.723 +
50.724 + Element e = getTrees().getElement(path);
50.725 +
50.726 + if ( e != null) {
50.727 + for (AnnotationMirror am : e.getAnnotationMirrors()) {
50.728 + String name = ((TypeElement)am.getAnnotationType().asElement()).getQualifiedName().toString();
50.729 + if ( "java.lang.SuppressWarnings".equals(name) ) { // NOI18N
50.730 + Map<? extends ExecutableElement, ? extends AnnotationValue> elementValues = am.getElementValues();
50.731 + for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : elementValues.entrySet()) {
50.732 + if( "value".equals(entry.getKey().getSimpleName().toString()) ) { // NOI18N
50.733 + Object value = entry.getValue().getValue();
50.734 + if ( value instanceof List) {
50.735 + for (Object av : (List)value) {
50.736 + if( av instanceof AnnotationValue ) {
50.737 + Object wname = ((AnnotationValue)av).getValue();
50.738 + if ( wname instanceof String ) {
50.739 + nju.add((String)wname);
50.740 + }
50.741 + }
50.742 + }
50.743 + }
50.744 + }
50.745 + }
50.746 + }
50.747 + }
50.748 + }
50.749 +
50.750 + suppresWarnings.push(nju);
50.751 + return true;
50.752 + }
50.753 + return false;
50.754 + }
50.755 +
50.756 + private Trees getTrees() {
50.757 + return info != null ? info.getTrees() : Trees.instance(env);
50.758 + }
50.759 + }
50.760 +
50.761 + static boolean isInGuarded(CompilationInfo info, TreePath tree) {
50.762 + if (info == null) {
50.763 + return false;
50.764 + }
50.765 +
50.766 + try {
50.767 + Document doc = info.getDocument();
50.768 +
50.769 + if (doc instanceof GuardedDocument) {
50.770 + int start = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), tree.getLeaf());
50.771 + int end = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), tree.getLeaf());
50.772 + GuardedDocument gdoc = (GuardedDocument) doc;
50.773 + MarkBlockChain guardedBlockChain = gdoc.getGuardedBlockChain();
50.774 + if (guardedBlockChain.compareBlock(start, end) == MarkBlock.INNER) {
50.775 + return true;
50.776 + }
50.777 + }
50.778 + } catch (IOException ex) {
50.779 + Exceptions.printStackTrace(ex);
50.780 + }
50.781 +
50.782 + return false;
50.783 + }
50.784 +
50.785 + private Collection<? extends ErrorDescription> runHint(HintDescription hd, HintContext ctx) {
50.786 + long start = System.nanoTime();
50.787 +
50.788 + try {
50.789 + return hd.getWorker().createErrors(ctx);
50.790 + } finally {
50.791 + long end = System.nanoTime();
50.792 + reportSpentTime(hd.getMetadata().id, end - start);
50.793 + }
50.794 + }
50.795 +
50.796 + public static <K, V> Map<K, List<V>> merge(Map<K, List<V>> to, K key, Collection<? extends V> value) {
50.797 + List<V> toColl = to.get(key);
50.798 +
50.799 + if (toColl == null) {
50.800 + to.put(key, toColl = new LinkedList<V>());
50.801 + }
50.802 +
50.803 + toColl.addAll(value);
50.804 +
50.805 + return to;
50.806 + }
50.807 +
50.808 + public static <K, V> Map<K, List<V>> mergeAll(Map<K, List<V>> to, Map<? extends K, ? extends Collection<? extends V>> what) {
50.809 + for (Entry<? extends K, ? extends Collection<? extends V>> e : what.entrySet()) {
50.810 + List<V> toColl = to.get(e.getKey());
50.811 +
50.812 + if (toColl == null) {
50.813 + to.put(e.getKey(), toColl = new LinkedList<V>());
50.814 + }
50.815 +
50.816 + toColl.addAll(e.getValue());
50.817 + }
50.818 +
50.819 + return to;
50.820 + }
50.821 +
50.822 + public static List<ErrorDescription> join(Map<?, ? extends List<? extends ErrorDescription>> errors) {
50.823 + if (errors == null) return null;
50.824 +
50.825 + List<ErrorDescription> result = new LinkedList<ErrorDescription>();
50.826 +
50.827 + for (Entry<?, ? extends Collection<? extends ErrorDescription>> e : errors.entrySet()) {
50.828 + result.addAll(e.getValue());
50.829 + }
50.830 +
50.831 + return result;
50.832 + }
50.833 +
50.834 + private static final boolean logTimeSpentInHints = Boolean.getBoolean("java.HintsInvoker.time.in.hints");
50.835 + private final Map<String, Long> hint2SpentTime = new HashMap<String, Long>();
50.836 +
50.837 + private void reportSpentTime(String id, long nanoTime) {
50.838 + if (!logTimeSpentInHints) return;
50.839 +
50.840 + Long prev = hint2SpentTime.get(id);
50.841 +
50.842 + if (prev == null) {
50.843 + prev = (long) 0;
50.844 + }
50.845 +
50.846 + hint2SpentTime.put(id, prev + nanoTime);
50.847 + }
50.848 +
50.849 + private void dumpTimeSpentInHints() {
50.850 + if (!logTimeSpentInHints) return;
50.851 +
50.852 + List<Entry<String, Long>> l = new ArrayList<Entry<String, Long>>(hint2SpentTime.entrySet());
50.853 +
50.854 + Collections.sort(l, new Comparator<Entry<String, Long>>() {
50.855 + @Override
50.856 + public int compare(Entry<String, Long> o1, Entry<String, Long> o2) {
50.857 + return (int) Math.signum(o1.getValue() - o2.getValue());
50.858 + }
50.859 + });
50.860 +
50.861 + for (Entry<String, Long> e : l) {
50.862 + System.err.println(e.getKey() + "=" + String.format("%3.2f", e.getValue() / 1000000.0));
50.863 + }
50.864 + }
50.865 +}
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/hints/HintsTask.java Wed May 08 21:47:42 2013 +0200
51.3 @@ -0,0 +1,254 @@
51.4 +/*
51.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
51.6 + *
51.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
51.8 + *
51.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
51.10 + * Other names may be trademarks of their respective owners.
51.11 + *
51.12 + * The contents of this file are subject to the terms of either the GNU
51.13 + * General Public License Version 2 only ("GPL") or the Common
51.14 + * Development and Distribution License("CDDL") (collectively, the
51.15 + * "License"). You may not use this file except in compliance with the
51.16 + * License. You can obtain a copy of the License at
51.17 + * http://www.netbeans.org/cddl-gplv2.html
51.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
51.19 + * specific language governing permissions and limitations under the
51.20 + * License. When distributing the software, include this License Header
51.21 + * Notice in each file and include the License file at
51.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
51.23 + * particular file as subject to the "Classpath" exception as provided
51.24 + * by Oracle in the GPL Version 2 section of the License file that
51.25 + * accompanied this code. If applicable, add the following below the
51.26 + * License Header, with the fields enclosed by brackets [] replaced by
51.27 + * your own identifying information:
51.28 + * "Portions Copyrighted [year] [name of copyright owner]"
51.29 + *
51.30 + * If you wish your version of this file to be governed by only the CDDL
51.31 + * or only the GPL Version 2, indicate your decision by adding
51.32 + * "[Contributor] elects to include this software in this distribution
51.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
51.34 + * single choice of license, a recipient has the option to distribute
51.35 + * your version of this file under either the CDDL, the GPL Version 2 or
51.36 + * to extend the choice of license to its licensees as provided above.
51.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
51.38 + * Version 2 license, then the option applies only if the new code is
51.39 + * made subject to such option by the copyright holder.
51.40 + *
51.41 + * Contributor(s):
51.42 + *
51.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
51.44 + */
51.45 +
51.46 +package org.netbeans.modules.java.hints.spiimpl.hints;
51.47 +
51.48 +import java.util.List;
51.49 +import java.util.Map.Entry;
51.50 +import java.util.concurrent.atomic.AtomicBoolean;
51.51 +import java.util.logging.Level;
51.52 +import java.util.logging.Logger;
51.53 +import javax.swing.event.ChangeEvent;
51.54 +import javax.swing.event.ChangeListener;
51.55 +import javax.swing.text.BadLocationException;
51.56 +import javax.swing.text.Document;
51.57 +import org.netbeans.api.editor.mimelookup.MimeLookup;
51.58 +import org.netbeans.api.editor.mimelookup.MimeRegistration;
51.59 +import org.netbeans.api.java.source.CancellableTask;
51.60 +import org.netbeans.api.java.source.CompilationInfo;
51.61 +import org.netbeans.api.java.source.JavaSource.Phase;
51.62 +import org.netbeans.api.java.source.JavaSource.Priority;
51.63 +import org.netbeans.api.java.source.JavaSourceTaskFactory;
51.64 +import org.netbeans.api.java.source.support.CaretAwareJavaSourceTaskFactory;
51.65 +import org.netbeans.api.java.source.support.EditorAwareJavaSourceTaskFactory;
51.66 +import org.netbeans.editor.BaseDocument;
51.67 +import org.netbeans.editor.Utilities;
51.68 +import org.netbeans.lib.editor.util.swing.DocumentUtilities;
51.69 +import org.netbeans.modules.java.hints.providers.spi.PositionRefresherHelper;
51.70 +import org.netbeans.modules.java.hints.providers.spi.PositionRefresherHelper.DocumentVersion;
51.71 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
51.72 +import org.netbeans.modules.parsing.spi.TaskIndexingMode;
51.73 +import org.netbeans.spi.editor.hints.Context;
51.74 +import org.netbeans.spi.editor.hints.ErrorDescription;
51.75 +import org.netbeans.spi.editor.hints.HintsController;
51.76 +import org.netbeans.spi.editor.hints.Severity;
51.77 +import org.netbeans.spi.editor.hints.settings.FileHintPreferences;
51.78 +import org.openide.filesystems.FileObject;
51.79 +import org.openide.util.WeakListeners;
51.80 +import org.openide.util.lookup.ServiceProvider;
51.81 +
51.82 +/**
51.83 + *
51.84 + * @author lahvac
51.85 + */
51.86 +public class HintsTask implements CancellableTask<CompilationInfo> {
51.87 +
51.88 + public static final String KEY_HINTS = HintsInvoker.class.getName() + "-hints";
51.89 + public static final String KEY_SUGGESTIONS = HintsInvoker.class.getName() + "-suggestions";
51.90 +
51.91 + private static final Logger TIMER = Logger.getLogger("TIMER");
51.92 + private static final Logger TIMER_EDITOR = Logger.getLogger("TIMER.editor");
51.93 + private static final Logger TIMER_CARET = Logger.getLogger("TIMER.caret");
51.94 +
51.95 + private final AtomicBoolean cancel = new AtomicBoolean();
51.96 +
51.97 + private final boolean caretAware;
51.98 +
51.99 + public HintsTask(boolean caretAware) {
51.100 + this.caretAware = caretAware;
51.101 + }
51.102 +
51.103 + public void run(CompilationInfo info) {
51.104 + cancel.set(false);
51.105 +
51.106 + if (org.netbeans.modules.java.hints.spiimpl.Utilities.disableErrors(info.getFileObject()).contains(Severity.VERIFIER)) {
51.107 + return;
51.108 + }
51.109 +
51.110 + Document doc = info.getSnapshot().getSource().getDocument(false);
51.111 + long version = doc != null ? DocumentUtilities.getDocumentVersion(doc) : 0;
51.112 + long startTime = System.currentTimeMillis();
51.113 +
51.114 + int caret = CaretAwareJavaSourceTaskFactory.getLastPosition(info.getFileObject());
51.115 + HintsSettings settings = HintsSettings.getSettingsFor(info.getFileObject());
51.116 + HintsInvoker inv = caretAware ? new HintsInvoker(settings, caret, cancel) : new HintsInvoker(settings, cancel);
51.117 + List<ErrorDescription> result = inv.computeHints(info);
51.118 +
51.119 + if (result == null || cancel.get()) {
51.120 + return;
51.121 + }
51.122 +
51.123 + HintsController.setErrors(info.getFileObject(), caretAware ? KEY_SUGGESTIONS : KEY_HINTS, result);
51.124 +
51.125 + if (caretAware) {
51.126 + SuggestionsPositionRefresherHelper.setVersion(doc, caret);
51.127 + } else {
51.128 + HintPositionRefresherHelper.setVersion(doc);
51.129 + }
51.130 +
51.131 + long endTime = System.currentTimeMillis();
51.132 +
51.133 + TIMER.log(Level.FINE, "Jackpot 3.0 Hints Task" + (caretAware ? " - Caret Aware" : ""), new Object[] {info.getFileObject(), endTime - startTime});
51.134 +
51.135 + Logger l = caretAware ? TIMER_CARET : TIMER_EDITOR;
51.136 +
51.137 + for (Entry<String, Long> e : inv.getTimeLog().entrySet()) {
51.138 + l.log(Level.FINE, e.getKey(), new Object[] {info.getFileObject(), e.getValue()});
51.139 + }
51.140 + }
51.141 +
51.142 + public void cancel() {
51.143 + cancel.set(true);
51.144 + }
51.145 +
51.146 +
51.147 + @ServiceProvider(service=JavaSourceTaskFactory.class)
51.148 + public static final class FactoryImpl extends EditorAwareJavaSourceTaskFactory implements ChangeListener {
51.149 +
51.150 + public FactoryImpl() {
51.151 + super(Phase.RESOLVED, Priority.LOW, TaskIndexingMode.ALLOWED_DURING_SCAN);
51.152 + FileHintPreferences.addChangeListener(WeakListeners.change(this, HintsSettings.class));
51.153 + }
51.154 +
51.155 + @Override
51.156 + protected CancellableTask<CompilationInfo> createTask(FileObject file) {
51.157 + return new HintsTask(false);
51.158 + }
51.159 +
51.160 + @Override
51.161 + public void stateChanged(ChangeEvent e) {
51.162 + for (FileObject file : getFileObjects()) {
51.163 + reschedule(file);
51.164 + }
51.165 + }
51.166 +
51.167 + }
51.168 +
51.169 + @ServiceProvider(service=JavaSourceTaskFactory.class)
51.170 + public static final class CaretFactoryImpl extends CaretAwareJavaSourceTaskFactory implements ChangeListener {
51.171 +
51.172 + public CaretFactoryImpl() {
51.173 + super(Phase.RESOLVED, Priority.LOW);
51.174 + FileHintPreferences.addChangeListener(WeakListeners.change(this, HintsSettings.class));
51.175 + }
51.176 +
51.177 + @Override
51.178 + protected CancellableTask<CompilationInfo> createTask(FileObject file) {
51.179 + return new HintsTask(true);
51.180 + }
51.181 +
51.182 + @Override
51.183 + public void stateChanged(ChangeEvent e) {
51.184 + for (FileObject file : getFileObjects()) {
51.185 + reschedule(file);
51.186 + }
51.187 + }
51.188 +
51.189 + }
51.190 +
51.191 + @MimeRegistration(mimeType="text/x-java", service=PositionRefresherHelper.class)
51.192 + public static final class HintPositionRefresherHelper extends PositionRefresherHelper<DocumentVersion> {
51.193 +
51.194 + public HintPositionRefresherHelper() {
51.195 + super(KEY_HINTS);
51.196 + }
51.197 +
51.198 + @Override
51.199 + protected boolean isUpToDate(Context context, Document doc, DocumentVersion oldVersion) {
51.200 + return true;
51.201 + }
51.202 +
51.203 + @Override
51.204 + public List<ErrorDescription> getErrorDescriptionsAt(CompilationInfo info, Context context, Document doc) throws BadLocationException {
51.205 + int rowStart = Utilities.getRowStart((BaseDocument) doc, context.getPosition());
51.206 + int rowEnd = Utilities.getRowEnd((BaseDocument) doc, context.getPosition());
51.207 +
51.208 + return new HintsInvoker(HintsSettings.getSettingsFor(info.getFileObject()), rowStart, rowEnd, context.getCancel()).computeHints(info);
51.209 + }
51.210 +
51.211 + private static void setVersion(Document doc) {
51.212 + for (PositionRefresherHelper h : MimeLookup.getLookup("text/x-java").lookupAll(PositionRefresherHelper.class)) {
51.213 + if (h instanceof HintPositionRefresherHelper) {
51.214 + ((HintPositionRefresherHelper) h).setVersion(doc, new DocumentVersion(doc));
51.215 + }
51.216 + }
51.217 + }
51.218 +
51.219 + }
51.220 +
51.221 + @MimeRegistration(mimeType="text/x-java", service=PositionRefresherHelper.class)
51.222 + public static final class SuggestionsPositionRefresherHelper extends PositionRefresherHelper<SuggestionsDocumentVersion> {
51.223 +
51.224 + public SuggestionsPositionRefresherHelper() {
51.225 + super(KEY_SUGGESTIONS);
51.226 + }
51.227 +
51.228 + @Override
51.229 + protected boolean isUpToDate(Context context, Document doc, SuggestionsDocumentVersion oldVersion) {
51.230 + return oldVersion.suggestionsCaret == context.getPosition();
51.231 + }
51.232 +
51.233 + @Override
51.234 + public List<ErrorDescription> getErrorDescriptionsAt(CompilationInfo info, Context context, Document doc) throws BadLocationException {
51.235 + return new HintsInvoker(HintsSettings.getSettingsFor(info.getFileObject()), context.getPosition(), context.getCancel()).computeHints(info);
51.236 + }
51.237 +
51.238 + private static void setVersion(Document doc, int caret) {
51.239 + for (PositionRefresherHelper h : MimeLookup.getLookup("text/x-java").lookupAll(PositionRefresherHelper.class)) {
51.240 + if (h instanceof SuggestionsPositionRefresherHelper) {
51.241 + ((SuggestionsPositionRefresherHelper) h).setVersion(doc, new SuggestionsDocumentVersion(doc, caret));
51.242 + }
51.243 + }
51.244 + }
51.245 + }
51.246 +
51.247 + private static class SuggestionsDocumentVersion extends DocumentVersion {
51.248 +
51.249 + private final int suggestionsCaret;
51.250 +
51.251 + public SuggestionsDocumentVersion(Document doc, int suggestionsCaret) {
51.252 + super(doc);
51.253 + this.suggestionsCaret = suggestionsCaret;
51.254 + }
51.255 + }
51.256 +
51.257 +}
52.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
52.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/ipi/upgrade/ProjectDependencyUpgrader.java Wed May 08 21:47:42 2013 +0200
52.3 @@ -0,0 +1,64 @@
52.4 +/*
52.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
52.6 + *
52.7 + * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
52.8 + *
52.9 + * The contents of this file are subject to the terms of either the GNU
52.10 + * General Public License Version 2 only ("GPL") or the Common
52.11 + * Development and Distribution License("CDDL") (collectively, the
52.12 + * "License"). You may not use this file except in compliance with the
52.13 + * License. You can obtain a copy of the License at
52.14 + * http://www.netbeans.org/cddl-gplv2.html
52.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
52.16 + * specific language governing permissions and limitations under the
52.17 + * License. When distributing the software, include this License Header
52.18 + * Notice in each file and include the License file at
52.19 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
52.20 + * particular file as subject to the "Classpath" exception as provided
52.21 + * by Sun in the GPL Version 2 section of the License file that
52.22 + * accompanied this code. If applicable, add the following below the
52.23 + * License Header, with the fields enclosed by brackets [] replaced by
52.24 + * your own identifying information:
52.25 + * "Portions Copyrighted [year] [name of copyright owner]"
52.26 + *
52.27 + * If you wish your version of this file to be governed by only the CDDL
52.28 + * or only the GPL Version 2, indicate your decision by adding
52.29 + * "[Contributor] elects to include this software in this distribution
52.30 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
52.31 + * single choice of license, a recipient has the option to distribute
52.32 + * your version of this file under either the CDDL, the GPL Version 2 or
52.33 + * to extend the choice of license to its licensees as provided above.
52.34 + * However, if you add GPL Version 2 code and therefore, elected the GPL
52.35 + * Version 2 license, then the option applies only if the new code is
52.36 + * made subject to such option by the copyright holder.
52.37 + *
52.38 + * Contributor(s):
52.39 + *
52.40 + * Portions Copyrighted 2010 Sun Microsystems, Inc.
52.41 + */
52.42 +package org.netbeans.modules.java.hints.spiimpl.ipi.upgrade;
52.43 +
52.44 +import org.netbeans.api.project.Project;
52.45 +import org.openide.DialogDisplayer;
52.46 +import org.openide.NotifyDescriptor;
52.47 +import org.openide.filesystems.FileObject;
52.48 +import org.openide.modules.SpecificationVersion;
52.49 +
52.50 +/**
52.51 + *
52.52 + * @author lahvac
52.53 + */
52.54 +public abstract class ProjectDependencyUpgrader {
52.55 +
52.56 + public abstract boolean ensureDependency(Project p, FileObject dep, SpecificationVersion spec, boolean canShowUI);
52.57 + public abstract boolean ensureDependency(Project p, String specification, boolean b);
52.58 +
52.59 + protected final boolean showDependencyUpgradeDialog(Project p, String dep, SpecificationVersion currentDependency, SpecificationVersion spec, boolean newDepenency, boolean canShowUI) {
52.60 + if (!canShowUI) return true;
52.61 +
52.62 + NotifyDescriptor nd = new NotifyDescriptor.Confirmation("New version: " + spec, "Update spec version.", NotifyDescriptor.YES_NO_OPTION);
52.63 +
52.64 + return DialogDisplayer.getDefault().notify(nd) == NotifyDescriptor.YES_OPTION;
52.65 + }
52.66 +
52.67 +}
53.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
53.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/options/HintsSettings.java Wed May 08 21:47:42 2013 +0200
53.3 @@ -0,0 +1,149 @@
53.4 +/*
53.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
53.6 + *
53.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
53.8 + *
53.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
53.10 + * Other names may be trademarks of their respective owners.
53.11 + *
53.12 + * The contents of this file are subject to the terms of either the GNU
53.13 + * General Public License Version 2 only ("GPL") or the Common
53.14 + * Development and Distribution License("CDDL") (collectively, the
53.15 + * "License"). You may not use this file except in compliance with the
53.16 + * License. You can obtain a copy of the License at
53.17 + * http://www.netbeans.org/cddl-gplv2.html
53.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
53.19 + * specific language governing permissions and limitations under the
53.20 + * License. When distributing the software, include this License Header
53.21 + * Notice in each file and include the License file at
53.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
53.23 + * particular file as subject to the "Classpath" exception as provided
53.24 + * by Oracle in the GPL Version 2 section of the License file that
53.25 + * accompanied this code. If applicable, add the following below the
53.26 + * License Header, with the fields enclosed by brackets [] replaced by
53.27 + * your own identifying information:
53.28 + * "Portions Copyrighted [year] [name of copyright owner]"
53.29 + *
53.30 + * Contributor(s):
53.31 + *
53.32 + * The Original Software is NetBeans. The Initial Developer of the Original
53.33 + * Software is Sun Microsystems, Inc. Portions Copyright 1997-2010 Sun
53.34 + * Microsystems, Inc. All Rights Reserved.
53.35 + *
53.36 + * If you wish your version of this file to be governed by only the CDDL
53.37 + * or only the GPL Version 2, indicate your decision by adding
53.38 + * "[Contributor] elects to include this software in this distribution
53.39 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
53.40 + * single choice of license, a recipient has the option to distribute
53.41 + * your version of this file under either the CDDL, the GPL Version 2 or
53.42 + * to extend the choice of license to its licensees as provided above.
53.43 + * However, if you add GPL Version 2 code and therefore, elected the GPL
53.44 + * Version 2 license, then the option applies only if the new code is
53.45 + * made subject to such option by the copyright holder.
53.46 + */
53.47 +package org.netbeans.modules.java.hints.spiimpl.options;
53.48 +
53.49 +import java.util.prefs.Preferences;
53.50 +import org.netbeans.api.editor.mimelookup.MimeRegistration;
53.51 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
53.52 +import org.netbeans.spi.editor.hints.Severity;
53.53 +import org.netbeans.spi.editor.hints.settings.FileHintPreferences;
53.54 +import org.netbeans.spi.editor.hints.settings.FileHintPreferences.GlobalHintPreferencesProvider;
53.55 +import org.openide.filesystems.FileObject;
53.56 +import org.openide.util.NbPreferences;
53.57 +
53.58 +/**
53.59 + *
53.60 + * @author Petr Hrebejk
53.61 + * @author Jan Lahoda
53.62 + */
53.63 +public abstract class HintsSettings {
53.64 +
53.65 + private static final String ENABLED_KEY = "enabled"; // NOI18N
53.66 + private static final String OLD_SEVERITY_KEY = "severity"; // NOI18N
53.67 + private static final String NEW_SEVERITY_KEY = "hintSeverity"; // NOI18N
53.68 +// protected static final String IN_TASK_LIST_KEY = "inTaskList"; // NOI18N
53.69 +
53.70 + public abstract boolean isEnabled(HintMetadata hint);
53.71 + public abstract void setEnabled(HintMetadata hint, boolean value);
53.72 + public abstract Preferences getHintPreferences(HintMetadata hint);
53.73 + public abstract Severity getSeverity(HintMetadata hint);
53.74 + public abstract void setSeverity(HintMetadata hint, Severity severity);
53.75 +// public abstract Iterable<? extends HintDescription> getEnabledHints();
53.76 +
53.77 + private static final class PreferencesBasedHintsSettings extends HintsSettings {
53.78 +
53.79 + private final Preferences preferences;
53.80 + private final boolean useDefaultEnabled;
53.81 + private final Severity overrideSeverity;
53.82 +
53.83 + public PreferencesBasedHintsSettings(Preferences preferences, boolean useDefaultEnabled, Severity overrideSeverity) {
53.84 + this.preferences = preferences;
53.85 + this.useDefaultEnabled = useDefaultEnabled;
53.86 + this.overrideSeverity = overrideSeverity;
53.87 + }
53.88 +
53.89 + @Override
53.90 + public boolean isEnabled(HintMetadata hint) {
53.91 + return getHintPreferences(hint).getBoolean(ENABLED_KEY, useDefaultEnabled && hint.enabled);
53.92 + }
53.93 +
53.94 + @Override
53.95 + public void setEnabled(HintMetadata hint, boolean value) {
53.96 + getHintPreferences(hint).putBoolean(ENABLED_KEY, value);
53.97 + }
53.98 +
53.99 + @Override
53.100 + public Preferences getHintPreferences(HintMetadata hint) {
53.101 + return preferences.node(hint.id);
53.102 + }
53.103 +
53.104 + @Override
53.105 + public Severity getSeverity(HintMetadata hint) {
53.106 + Preferences prefs = getHintPreferences(hint);
53.107 + String s = prefs.get(NEW_SEVERITY_KEY, null);
53.108 + if (s != null) return Severity.valueOf(s);
53.109 +
53.110 + s = prefs.get(OLD_SEVERITY_KEY, null);
53.111 +
53.112 + if (s == null) return overrideSeverity != null ? overrideSeverity : hint != null ? hint.severity : null;
53.113 +
53.114 + if ("ERROR".equals(s)) return Severity.ERROR;
53.115 + else if ("WARNING".equals(s)) return Severity.VERIFIER;
53.116 + else if ("CURRENT_LINE_WARNING".equals(s)) return Severity.HINT;
53.117 +
53.118 + return overrideSeverity != null ? overrideSeverity : hint != null ? hint.severity : null;
53.119 + }
53.120 +
53.121 + @Override
53.122 + public void setSeverity(HintMetadata hint, Severity severity) {
53.123 + getHintPreferences(hint).put(NEW_SEVERITY_KEY, severity.name());
53.124 + }
53.125 + }
53.126 +
53.127 + public static HintsSettings createPreferencesBasedHintsSettings(Preferences preferences, boolean useDefaultEnabled, Severity overrideSeverity) {
53.128 + return new PreferencesBasedHintsSettings(preferences, useDefaultEnabled, overrideSeverity);
53.129 + }
53.130 +
53.131 + public static HintsSettings getSettingsFor(FileObject file) {
53.132 + return createPreferencesBasedHintsSettings(FileHintPreferences.getFilePreferences(file, "text/x-java"), true, null);
53.133 + }
53.134 +
53.135 + public static HintsSettings getGlobalSettings() {
53.136 + return GLOBAL_SETTINGS;
53.137 + }
53.138 +
53.139 + private static final String DEFAULT_PROFILE = "default"; // NOI18N
53.140 + private static final String PREFERENCES_LOCATION = "org/netbeans/modules/java/hints";
53.141 + private static final HintsSettings GLOBAL_SETTINGS = createPreferencesBasedHintsSettings(NbPreferences.root().node(PREFERENCES_LOCATION).node(DEFAULT_PROFILE), true, null);
53.142 +
53.143 + @MimeRegistration(mimeType="text/x-java", service=GlobalHintPreferencesProvider.class)
53.144 + public static class GlobalSettingsProvider implements GlobalHintPreferencesProvider {
53.145 +
53.146 + @Override
53.147 + public Preferences getGlobalPreferences() {
53.148 + return NbPreferences.root().node(PREFERENCES_LOCATION).node(DEFAULT_PROFILE);
53.149 + }
53.150 +
53.151 + }
53.152 +}
54.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
54.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/pm/BulkSearch.java Wed May 08 21:47:42 2013 +0200
54.3 @@ -0,0 +1,190 @@
54.4 +/*
54.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
54.6 + *
54.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
54.8 + *
54.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
54.10 + * Other names may be trademarks of their respective owners.
54.11 + *
54.12 + * The contents of this file are subject to the terms of either the GNU
54.13 + * General Public License Version 2 only ("GPL") or the Common
54.14 + * Development and Distribution License("CDDL") (collectively, the
54.15 + * "License"). You may not use this file except in compliance with the
54.16 + * License. You can obtain a copy of the License at
54.17 + * http://www.netbeans.org/cddl-gplv2.html
54.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
54.19 + * specific language governing permissions and limitations under the
54.20 + * License. When distributing the software, include this License Header
54.21 + * Notice in each file and include the License file at
54.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
54.23 + * particular file as subject to the "Classpath" exception as provided
54.24 + * by Oracle in the GPL Version 2 section of the License file that
54.25 + * accompanied this code. If applicable, add the following below the
54.26 + * License Header, with the fields enclosed by brackets [] replaced by
54.27 + * your own identifying information:
54.28 + * "Portions Copyrighted [year] [name of copyright owner]"
54.29 + *
54.30 + * If you wish your version of this file to be governed by only the CDDL
54.31 + * or only the GPL Version 2, indicate your decision by adding
54.32 + * "[Contributor] elects to include this software in this distribution
54.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
54.34 + * single choice of license, a recipient has the option to distribute
54.35 + * your version of this file under either the CDDL, the GPL Version 2 or
54.36 + * to extend the choice of license to its licensees as provided above.
54.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
54.38 + * Version 2 license, then the option applies only if the new code is
54.39 + * made subject to such option by the copyright holder.
54.40 + *
54.41 + * Contributor(s):
54.42 + *
54.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
54.44 + */
54.45 +
54.46 +package org.netbeans.modules.java.hints.spiimpl.pm;
54.47 +
54.48 +import com.sun.source.tree.Tree;
54.49 +import com.sun.source.util.TreePath;
54.50 +import java.io.InputStream;
54.51 +import java.io.OutputStream;
54.52 +import java.util.Arrays;
54.53 +import java.util.Collection;
54.54 +import java.util.LinkedList;
54.55 +import java.util.List;
54.56 +import java.util.Map;
54.57 +import java.util.Set;
54.58 +import java.util.concurrent.atomic.AtomicBoolean;
54.59 +import org.netbeans.api.annotations.common.CheckForNull;
54.60 +import org.netbeans.api.java.source.CompilationInfo;
54.61 +import org.netbeans.modules.java.hints.spiimpl.Utilities;
54.62 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.AdditionalQueryConstraints;
54.63 +
54.64 +/**
54.65 + *
54.66 + * @author lahvac
54.67 + */
54.68 +public abstract class BulkSearch {
54.69 +
54.70 + private static final BulkSearch INSTANCE = new NFABasedBulkSearch();
54.71 +// private static final BulkSearch INSTANCE = new REBasedBulkSearch();
54.72 +
54.73 + public static BulkSearch getDefault() {
54.74 + return INSTANCE;
54.75 + }
54.76 +
54.77 + private final boolean requiresLightweightVerification;
54.78 +
54.79 + protected BulkSearch(boolean requiresLightweightVerification) {
54.80 + this.requiresLightweightVerification = requiresLightweightVerification;
54.81 + }
54.82 +
54.83 + public final Map<String, Collection<TreePath>> match(CompilationInfo info, AtomicBoolean cancel, TreePath toSearch, BulkPattern pattern) {
54.84 + return match(info, cancel, toSearch, pattern, null);
54.85 + }
54.86 +
54.87 + public final boolean requiresLightweightVerification() {
54.88 + return requiresLightweightVerification;
54.89 + }
54.90 +
54.91 + @CheckForNull
54.92 + public abstract Map<String, Collection<TreePath>> match(CompilationInfo info, AtomicBoolean cancel, TreePath toSearch, BulkPattern pattern, Map<String, Long> timeLog);
54.93 +
54.94 + public abstract boolean matches(InputStream encoded, AtomicBoolean cancel, BulkPattern pattern);
54.95 +
54.96 + @CheckForNull
54.97 + public abstract Map<String, Integer> matchesWithFrequencies(InputStream encoded, BulkPattern pattern, AtomicBoolean cancel);
54.98 +
54.99 + public abstract boolean matches(CompilationInfo info, AtomicBoolean cancel, TreePath toSearch, BulkPattern pattern);
54.100 +
54.101 + public abstract void encode(Tree tree, EncodingContext ctx, AtomicBoolean cancel);
54.102 +
54.103 + @CheckForNull
54.104 + public final BulkPattern create(CompilationInfo info, AtomicBoolean cancel, String... code) {
54.105 + return create(info, cancel, Arrays.asList(code));
54.106 + }
54.107 +
54.108 + @CheckForNull
54.109 + public final BulkPattern create(CompilationInfo info, AtomicBoolean cancel, Collection<? extends String> code) {
54.110 + List<Tree> patterns = new LinkedList<Tree>();
54.111 + List<AdditionalQueryConstraints> additionalConstraints = new LinkedList<AdditionalQueryConstraints>();
54.112 +
54.113 + for (String c : code) {
54.114 + patterns.add(Utilities.parseAndAttribute(info, c, null));
54.115 + additionalConstraints.add(AdditionalQueryConstraints.empty());
54.116 + }
54.117 +
54.118 + return create(code, patterns, additionalConstraints, cancel);
54.119 + }
54.120 +
54.121 + @CheckForNull
54.122 + public abstract BulkPattern create(Collection<? extends String> code, Collection<? extends Tree> patterns, Collection<? extends AdditionalQueryConstraints> additionalConstraints, AtomicBoolean cancel);
54.123 +
54.124 + public static abstract class BulkPattern {
54.125 +
54.126 + private final List<? extends String> patterns;
54.127 + private final List<? extends Set<? extends String>> identifiers;
54.128 + private final List<List<List<String>>> requiredContent;
54.129 + private final List<AdditionalQueryConstraints> additionalConstraints;
54.130 +
54.131 + public BulkPattern(List<? extends String> patterns, List<? extends Set<? extends String>> identifiers, List<List<List<String>>> requiredContent, List<AdditionalQueryConstraints> additionalConstraints) {
54.132 + this.patterns = patterns;
54.133 + this.identifiers = identifiers;//TODO: immutable, maybe clone
54.134 + this.requiredContent = requiredContent;
54.135 + this.additionalConstraints = additionalConstraints;
54.136 + }
54.137 +
54.138 + public List<? extends String> getPatterns() {
54.139 + return patterns;
54.140 + }
54.141 +
54.142 + public List<? extends Set<? extends String>> getIdentifiers() {
54.143 + return identifiers;
54.144 + }
54.145 +
54.146 + public List<List<List<String>>> getRequiredContent() {
54.147 + return requiredContent;
54.148 + }
54.149 +
54.150 + public List<AdditionalQueryConstraints> getAdditionalConstraints() {
54.151 + return additionalConstraints;
54.152 + }
54.153 +
54.154 + }
54.155 +
54.156 + public static final class EncodingContext {
54.157 +
54.158 + private final OutputStream out;
54.159 + private final boolean forDuplicates;
54.160 + private Set<? extends String> identifiers;
54.161 + private List<String> content;
54.162 +
54.163 + public EncodingContext(OutputStream out, boolean forDuplicates) {
54.164 + this.out = out;
54.165 + this.forDuplicates = forDuplicates;
54.166 + }
54.167 +
54.168 + public Set<? extends String> getIdentifiers() {
54.169 + return identifiers;
54.170 + }
54.171 +
54.172 + public OutputStream getOut() {
54.173 + return out;
54.174 + }
54.175 +
54.176 + public boolean isForDuplicates() {
54.177 + return forDuplicates;
54.178 + }
54.179 +
54.180 + public void setIdentifiers(Set<? extends String> identifiers) {
54.181 + this.identifiers = identifiers;
54.182 + }
54.183 +
54.184 + public void setContent(List<String> content) {
54.185 + this.content = content;
54.186 + }
54.187 +
54.188 + public List<String> getContent() {
54.189 + return content;
54.190 + }
54.191 +
54.192 + }
54.193 +}
55.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
55.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/pm/CopyFinderBasedBulkSearch.java Wed May 08 21:47:42 2013 +0200
55.3 @@ -0,0 +1,141 @@
55.4 +/*
55.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
55.6 + *
55.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
55.8 + *
55.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
55.10 + * Other names may be trademarks of their respective owners.
55.11 + *
55.12 + * The contents of this file are subject to the terms of either the GNU
55.13 + * General Public License Version 2 only ("GPL") or the Common
55.14 + * Development and Distribution License("CDDL") (collectively, the
55.15 + * "License"). You may not use this file except in compliance with the
55.16 + * License. You can obtain a copy of the License at
55.17 + * http://www.netbeans.org/cddl-gplv2.html
55.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
55.19 + * specific language governing permissions and limitations under the
55.20 + * License. When distributing the software, include this License Header
55.21 + * Notice in each file and include the License file at
55.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
55.23 + * particular file as subject to the "Classpath" exception as provided
55.24 + * by Oracle in the GPL Version 2 section of the License file that
55.25 + * accompanied this code. If applicable, add the following below the
55.26 + * License Header, with the fields enclosed by brackets [] replaced by
55.27 + * your own identifying information:
55.28 + * "Portions Copyrighted [year] [name of copyright owner]"
55.29 + *
55.30 + * If you wish your version of this file to be governed by only the CDDL
55.31 + * or only the GPL Version 2, indicate your decision by adding
55.32 + * "[Contributor] elects to include this software in this distribution
55.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
55.34 + * single choice of license, a recipient has the option to distribute
55.35 + * your version of this file under either the CDDL, the GPL Version 2 or
55.36 + * to extend the choice of license to its licensees as provided above.
55.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
55.38 + * Version 2 license, then the option applies only if the new code is
55.39 + * made subject to such option by the copyright holder.
55.40 + *
55.41 + * Contributor(s):
55.42 + *
55.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
55.44 + */
55.45 +
55.46 +package org.netbeans.modules.java.hints.spiimpl.pm;
55.47 +
55.48 +import com.sun.source.tree.Tree;
55.49 +import com.sun.source.util.TreePath;
55.50 +import java.io.InputStream;
55.51 +import java.util.Collection;
55.52 +import java.util.Collections;
55.53 +import java.util.HashMap;
55.54 +import java.util.Iterator;
55.55 +import java.util.LinkedList;
55.56 +import java.util.Map;
55.57 +import java.util.Map.Entry;
55.58 +import java.util.concurrent.atomic.AtomicBoolean;
55.59 +import javax.lang.model.type.TypeMirror;
55.60 +import org.netbeans.api.java.source.CompilationInfo;
55.61 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.AdditionalQueryConstraints;
55.62 +import org.netbeans.api.java.source.matching.Matcher;
55.63 +import org.netbeans.api.java.source.matching.Occurrence;
55.64 +import org.netbeans.api.java.source.matching.Pattern;
55.65 +import org.openide.util.Parameters;
55.66 +
55.67 +/**
55.68 + *
55.69 + * @author lahvac
55.70 + */
55.71 +public class CopyFinderBasedBulkSearch extends BulkSearch {
55.72 +
55.73 + public CopyFinderBasedBulkSearch() {
55.74 + super(false);
55.75 + }
55.76 +
55.77 + @Override
55.78 + public Map<String, Collection<TreePath>> match(CompilationInfo info, AtomicBoolean cancel, TreePath toSearch, BulkPattern pattern, Map<String, Long> timeLog) {
55.79 + Parameters.notNull("info", info);
55.80 + Map<String, Collection<TreePath>> result = new HashMap<String, Collection<TreePath>>();
55.81 + TreePath topLevel = new TreePath(info.getCompilationUnit());
55.82 +
55.83 + for (Entry<Tree, String> e : ((BulkPatternImpl) pattern).pattern2Code.entrySet()) {
55.84 + for (Occurrence od : Matcher.create(info).setCancel(new AtomicBoolean()).setUntypedMatching().setCancel(cancel).match(Pattern.createPatternWithFreeVariables(new TreePath(topLevel, e.getKey()), Collections.<String, TypeMirror>emptyMap()))) {
55.85 + Collection<TreePath> c = result.get(e.getValue());
55.86 +
55.87 + if (c == null) {
55.88 + result.put(e.getValue(), c = new LinkedList<TreePath>());
55.89 + }
55.90 +
55.91 + c.add(od.getOccurrenceRoot());
55.92 + }
55.93 + }
55.94 +
55.95 + return result;
55.96 + }
55.97 +
55.98 + @Override
55.99 + public boolean matches(CompilationInfo info, AtomicBoolean cancel, TreePath toSearch, BulkPattern pattern) {
55.100 + //XXX: performance
55.101 + return !match(info, cancel, toSearch, pattern).isEmpty();
55.102 + }
55.103 +
55.104 + @Override
55.105 + public BulkPattern create(Collection<? extends String> code, Collection<? extends Tree> patterns, Collection<? extends AdditionalQueryConstraints> additionalConstraints, AtomicBoolean cancel) {
55.106 + Map<Tree, String> pattern2Code = new HashMap<Tree, String>();
55.107 +
55.108 + Iterator<? extends String> itCode = code.iterator();
55.109 + Iterator<? extends Tree> itPatt = patterns.iterator();
55.110 +
55.111 + while (itCode.hasNext() && itPatt.hasNext()) {
55.112 + pattern2Code.put(itPatt.next(), itCode.next());
55.113 + }
55.114 +
55.115 + return new BulkPatternImpl(additionalConstraints, pattern2Code);
55.116 + }
55.117 +
55.118 + @Override
55.119 + public boolean matches(InputStream encoded, AtomicBoolean cancel, BulkPattern pattern) {
55.120 + throw new UnsupportedOperationException("Not supported yet.");
55.121 + }
55.122 +
55.123 + @Override
55.124 + public void encode(Tree tree, EncodingContext ctx, AtomicBoolean cancel) {
55.125 + throw new UnsupportedOperationException("Not supported yet.");
55.126 + }
55.127 +
55.128 + @Override
55.129 + public Map<String, Integer> matchesWithFrequencies(InputStream encoded, BulkPattern pattern, AtomicBoolean cancel) {
55.130 + throw new UnsupportedOperationException("Not supported yet.");
55.131 + }
55.132 +
55.133 + private static final class BulkPatternImpl extends BulkPattern {
55.134 +
55.135 + private final Map<Tree, String> pattern2Code;
55.136 +
55.137 + public BulkPatternImpl(Collection<? extends AdditionalQueryConstraints> additionalConstraints, Map<Tree, String> pattern2Code) {
55.138 + super(new LinkedList<String>(pattern2Code.values()), null, null, new LinkedList<AdditionalQueryConstraints>(additionalConstraints));
55.139 + this.pattern2Code = pattern2Code;
55.140 + }
55.141 +
55.142 + }
55.143 +
55.144 +}
56.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
56.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/pm/NFA.java Wed May 08 21:47:42 2013 +0200
56.3 @@ -0,0 +1,216 @@
56.4 +/*
56.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
56.6 + *
56.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
56.8 + *
56.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
56.10 + * Other names may be trademarks of their respective owners.
56.11 + *
56.12 + * The contents of this file are subject to the terms of either the GNU
56.13 + * General Public License Version 2 only ("GPL") or the Common
56.14 + * Development and Distribution License("CDDL") (collectively, the
56.15 + * "License"). You may not use this file except in compliance with the
56.16 + * License. You can obtain a copy of the License at
56.17 + * http://www.netbeans.org/cddl-gplv2.html
56.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
56.19 + * specific language governing permissions and limitations under the
56.20 + * License. When distributing the software, include this License Header
56.21 + * Notice in each file and include the License file at
56.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
56.23 + * particular file as subject to the "Classpath" exception as provided
56.24 + * by Oracle in the GPL Version 2 section of the License file that
56.25 + * accompanied this code. If applicable, add the following below the
56.26 + * License Header, with the fields enclosed by brackets [] replaced by
56.27 + * your own identifying information:
56.28 + * "Portions Copyrighted [year] [name of copyright owner]"
56.29 + *
56.30 + * If you wish your version of this file to be governed by only the CDDL
56.31 + * or only the GPL Version 2, indicate your decision by adding
56.32 + * "[Contributor] elects to include this software in this distribution
56.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
56.34 + * single choice of license, a recipient has the option to distribute
56.35 + * your version of this file under either the CDDL, the GPL Version 2 or
56.36 + * to extend the choice of license to its licensees as provided above.
56.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
56.38 + * Version 2 license, then the option applies only if the new code is
56.39 + * made subject to such option by the copyright holder.
56.40 + *
56.41 + * Contributor(s):
56.42 + *
56.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
56.44 + */
56.45 +
56.46 +package org.netbeans.modules.java.hints.spiimpl.pm;
56.47 +
56.48 +import java.util.BitSet;
56.49 +import java.util.HashSet;
56.50 +import java.util.Map;
56.51 +import java.util.Set;
56.52 +
56.53 +/**
56.54 + *
56.55 + * @author lahvac
56.56 + */
56.57 +public class NFA<I, R> {
56.58 +
56.59 + /*XXX: private*/ final int stateCount;
56.60 + private final int startingState;
56.61 + private final Set<I> inputs;
56.62 + private final Map<Key<I>, State> transitionTable;
56.63 + private final Map<Integer, R> finalStates;
56.64 +
56.65 + private final State startingStateObject;
56.66 +
56.67 + private NFA(int startingState, int stateCount, Set<I> inputs, Map<Key<I>, State> transitionTable, Map<Integer, R> finalStates) {
56.68 + this.startingState = startingState;
56.69 + this.stateCount = stateCount;
56.70 + this.inputs = inputs;
56.71 + this.transitionTable = transitionTable;
56.72 + this.finalStates = finalStates;
56.73 +
56.74 + startingStateObject = State.create().mutableOr(startingState);
56.75 + }
56.76 +
56.77 + public State getStartingState() {
56.78 + return startingStateObject;
56.79 + }
56.80 +
56.81 + public State transition(final State active, final I input) {
56.82 + State result = null;
56.83 +
56.84 +// for (int i : active) {
56.85 + for (int i = active.nextSetBit(0); i >= 0; i = active.nextSetBit(i+1)) {
56.86 + State target = transitionTable.get(Key.create(i, input));
56.87 +
56.88 + if (target != null) {
56.89 + if (result == null) {
56.90 + result = State.create();
56.91 + }
56.92 +
56.93 + result.mutableOr(target);
56.94 + }
56.95 + }
56.96 +
56.97 + State r;
56.98 +
56.99 + //XXX:
56.100 + if (result == null) {
56.101 + r = startingStateObject;
56.102 + } else {
56.103 + r = result.mutableOr(startingState);//???
56.104 + }
56.105 +
56.106 + return r;
56.107 + }
56.108 +
56.109 + public Set<R> getResults(State bs) {
56.110 + Set<R> result = new HashSet<R>();
56.111 +
56.112 + for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) {
56.113 + if (finalStates.get(i) != null) {
56.114 + result.add(finalStates.get(i));
56.115 + }
56.116 + }
56.117 +
56.118 + return result;
56.119 + }
56.120 +
56.121 + public static <I, R> NFA<I, R> create(int startingState, int stateCount, Set<I> inputs, Map<Key<I>, State> transitionTable, Map<Integer, R> finalStates) {
56.122 + return new NFA<I, R>(startingState, stateCount, inputs, transitionTable, finalStates);
56.123 + }
56.124 +
56.125 + public State join(State s1, State s2) {
56.126 + State bs = State.create();
56.127 +
56.128 + bs.mutableOr(s1);
56.129 + bs.mutableOr(s2);
56.130 +
56.131 + return bs;
56.132 + }
56.133 +
56.134 + public static final class Key<I> {
56.135 + private final int state;
56.136 + private final I input;
56.137 +
56.138 + private Key(int state, I input) {
56.139 + this.state = state;
56.140 + this.input = input;
56.141 + }
56.142 +
56.143 + public static <I> Key<I> create(int state, I input) {
56.144 + return new Key<I>(state, input);
56.145 + }
56.146 +
56.147 + @Override
56.148 + public boolean equals(Object obj) {
56.149 + if (obj == null) {
56.150 + return false;
56.151 + }
56.152 + if (getClass() != obj.getClass()) {
56.153 + return false;
56.154 + }
56.155 + final Key<?> other = (Key<?>) obj;
56.156 + if (this.state != other.state) {
56.157 + return false;
56.158 + }
56.159 + if (this.input != other.input && (this.input == null || !this.input.equals(other.input))) {
56.160 + return false;
56.161 + }
56.162 + return true;
56.163 + }
56.164 +
56.165 + @Override
56.166 + public int hashCode() {
56.167 + int hash = 3;
56.168 + hash = 83 * hash + this.state;
56.169 + hash = 83 * hash + (this.input != null ? this.input.hashCode() : 0);
56.170 + return hash;
56.171 + }
56.172 +
56.173 + @Override
56.174 + public String toString() {
56.175 + return "[" + state + ", " + input + "]";
56.176 + }
56.177 +
56.178 + }
56.179 +
56.180 +// public static final class State extends HashSet<Integer> {
56.181 +// private State() {
56.182 +// }
56.183 +//
56.184 +// public static State create() {
56.185 +// return new State();
56.186 +// }
56.187 +//
56.188 +// public State mutableOr(int state) {
56.189 +// add(state);
56.190 +// return this;
56.191 +// }
56.192 +//
56.193 +// public State mutableOr(State or) {
56.194 +// addAll(or);
56.195 +// return this;
56.196 +// }
56.197 +//
56.198 +// }
56.199 +
56.200 + public static final class State extends BitSet {
56.201 + private State() {}
56.202 +
56.203 + public static State create() {
56.204 + return new State();
56.205 + }
56.206 +
56.207 + public State mutableOr(int state) {
56.208 + set(state);
56.209 + return this;
56.210 + }
56.211 +
56.212 + public State mutableOr(State or) {
56.213 + or(or);
56.214 + return this;
56.215 + }
56.216 +
56.217 + }
56.218 +
56.219 +}
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/pm/NFABasedBulkSearch.java Wed May 08 21:47:42 2013 +0200
57.3 @@ -0,0 +1,826 @@
57.4 +/*
57.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
57.6 + *
57.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
57.8 + *
57.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
57.10 + * Other names may be trademarks of their respective owners.
57.11 + *
57.12 + * The contents of this file are subject to the terms of either the GNU
57.13 + * General Public License Version 2 only ("GPL") or the Common
57.14 + * Development and Distribution License("CDDL") (collectively, the
57.15 + * "License"). You may not use this file except in compliance with the
57.16 + * License. You can obtain a copy of the License at
57.17 + * http://www.netbeans.org/cddl-gplv2.html
57.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
57.19 + * specific language governing permissions and limitations under the
57.20 + * License. When distributing the software, include this License Header
57.21 + * Notice in each file and include the License file at
57.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
57.23 + * particular file as subject to the "Classpath" exception as provided
57.24 + * by Oracle in the GPL Version 2 section of the License file that
57.25 + * accompanied this code. If applicable, add the following below the
57.26 + * License Header, with the fields enclosed by brackets [] replaced by
57.27 + * your own identifying information:
57.28 + * "Portions Copyrighted [year] [name of copyright owner]"
57.29 + *
57.30 + * If you wish your version of this file to be governed by only the CDDL
57.31 + * or only the GPL Version 2, indicate your decision by adding
57.32 + * "[Contributor] elects to include this software in this distribution
57.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
57.34 + * single choice of license, a recipient has the option to distribute
57.35 + * your version of this file under either the CDDL, the GPL Version 2 or
57.36 + * to extend the choice of license to its licensees as provided above.
57.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
57.38 + * Version 2 license, then the option applies only if the new code is
57.39 + * made subject to such option by the copyright holder.
57.40 + *
57.41 + * Contributor(s):
57.42 + *
57.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
57.44 + */
57.45 +
57.46 +package org.netbeans.modules.java.hints.spiimpl.pm;
57.47 +
57.48 +import com.sun.source.tree.AnnotationTree;
57.49 +import com.sun.source.tree.BlockTree;
57.50 +import com.sun.source.tree.ClassTree;
57.51 +import com.sun.source.tree.IdentifierTree;
57.52 +import com.sun.source.tree.LiteralTree;
57.53 +import com.sun.source.tree.MemberSelectTree;
57.54 +import com.sun.source.tree.MethodTree;
57.55 +import com.sun.source.tree.ModifiersTree;
57.56 +import com.sun.source.tree.StatementTree;
57.57 +import com.sun.source.tree.Tree;
57.58 +import com.sun.source.tree.Tree.Kind;
57.59 +import com.sun.source.tree.VariableTree;
57.60 +import com.sun.source.util.TreePath;
57.61 +import com.sun.source.util.TreeScanner;
57.62 +import java.io.ByteArrayOutputStream;
57.63 +import java.io.IOException;
57.64 +import java.io.InputStream;
57.65 +import java.io.UnsupportedEncodingException;
57.66 +import java.util.ArrayList;
57.67 +import java.util.Collection;
57.68 +import java.util.Collections;
57.69 +import java.util.EnumMap;
57.70 +import java.util.EnumSet;
57.71 +import java.util.HashMap;
57.72 +import java.util.HashSet;
57.73 +import java.util.Iterator;
57.74 +import java.util.LinkedHashMap;
57.75 +import java.util.LinkedList;
57.76 +import java.util.List;
57.77 +import java.util.Map;
57.78 +import java.util.Map.Entry;
57.79 +import java.util.Set;
57.80 +import java.util.Stack;
57.81 +import java.util.concurrent.atomic.AtomicBoolean;
57.82 +import javax.lang.model.element.Name;
57.83 +import org.netbeans.api.java.source.CompilationInfo;
57.84 +import org.netbeans.api.java.source.support.CancellableTreeScanner;
57.85 +import org.netbeans.modules.java.hints.spiimpl.Utilities;
57.86 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.AdditionalQueryConstraints;
57.87 +import org.openide.util.Exceptions;
57.88 +
57.89 +/**
57.90 + *
57.91 + * @author lahvac
57.92 + */
57.93 +public class NFABasedBulkSearch extends BulkSearch {
57.94 +
57.95 + public NFABasedBulkSearch() {
57.96 + super(false);
57.97 + }
57.98 +
57.99 + @Override
57.100 + public Map<String, Collection<TreePath>> match(CompilationInfo info, final AtomicBoolean cancel, TreePath tree, BulkPattern patternIn, Map<String, Long> timeLog) {
57.101 + BulkPatternImpl pattern = (BulkPatternImpl) patternIn;
57.102 +
57.103 + final Map<Res, Collection<TreePath>> occurringPatterns = new HashMap<Res, Collection<TreePath>>();
57.104 + final NFA<Input, Res> nfa = pattern.toNFA();
57.105 + final Set<String> identifiers = new HashSet<String>();
57.106 +
57.107 + new CollectIdentifiers<Void, TreePath>(identifiers, cancel) {
57.108 + private NFA.State active = nfa.getStartingState();
57.109 + @Override
57.110 + public Void scan(Tree node, TreePath p) {
57.111 + if (node == null) {
57.112 + return null;
57.113 + }
57.114 +
57.115 + TreePath currentPath = new TreePath(p, node);
57.116 + boolean[] goDeeper = new boolean[1];
57.117 + final NFA.State newActiveAfterVariable = nfa.transition(active, new Input(Kind.IDENTIFIER, "$", false));
57.118 + Input normalizedInput = normalizeInput(node, goDeeper, null);
57.119 + boolean ignoreKind = normalizedInput.kind == Kind.IDENTIFIER || normalizedInput.kind == Kind.MEMBER_SELECT;
57.120 +
57.121 + NFA.State newActiveBefore = nfa.transition(active, normalizedInput);
57.122 +
57.123 + if (normalizedInput.name != null && !ignoreKind) {
57.124 + newActiveBefore = nfa.join(newActiveBefore, nfa.transition(active, new Input(normalizedInput.kind, "$", false)));
57.125 + }
57.126 +
57.127 + active = newActiveBefore;
57.128 +
57.129 + if (goDeeper[0]) {
57.130 + super.scan(node, currentPath);
57.131 + } else {
57.132 + new CollectIdentifiers<Void, Void>(identifiers, cancel).scan(node, null);
57.133 + }
57.134 +
57.135 + if (cancel.get()) return null;
57.136 +
57.137 + NFA.State newActiveAfter = nfa.transition(active, UP);
57.138 +
57.139 + active = nfa.join(newActiveAfter, nfa.transition(newActiveAfterVariable, UP));
57.140 +
57.141 + for (Res r : nfa.getResults(active)) {
57.142 + addOccurrence(r, currentPath);
57.143 + }
57.144 +
57.145 + return null;
57.146 + }
57.147 +
57.148 + @Override
57.149 + public Void scan(Iterable<? extends Tree> nodes, TreePath p) {
57.150 + active = nfa.transition(active, new Input(Kind.IDENTIFIER, "(", false));
57.151 + try {
57.152 + return super.scan(nodes, p);
57.153 + } finally {
57.154 + active = nfa.transition(active, UP);
57.155 + }
57.156 + }
57.157 +
57.158 + private void addOccurrence(Res r, TreePath currentPath) {
57.159 + Collection<TreePath> occurrences = occurringPatterns.get(r);
57.160 + if (occurrences == null) {
57.161 + occurringPatterns.put(r, occurrences = new LinkedList<TreePath>());
57.162 + }
57.163 + occurrences.add(currentPath);
57.164 + }
57.165 + }.scan(tree, tree.getParentPath());
57.166 +
57.167 + if (cancel.get()) return null;
57.168 +
57.169 + Map<String, Collection<TreePath>> result = new HashMap<String, Collection<TreePath>>();
57.170 +
57.171 + for (Entry<Res, Collection<TreePath>> e : occurringPatterns.entrySet()) {
57.172 + if (cancel.get()) return null;
57.173 + if (!identifiers.containsAll(pattern.getIdentifiers().get(e.getKey().patternIndex))) {
57.174 + continue;
57.175 + }
57.176 +
57.177 + result.put(e.getKey().pattern, e.getValue());
57.178 + }
57.179 +
57.180 + return result;
57.181 + }
57.182 +
57.183 + @Override
57.184 + public BulkPattern create(Collection<? extends String> code, Collection<? extends Tree> patterns, Collection<? extends AdditionalQueryConstraints> additionalConstraints, final AtomicBoolean cancel) {
57.185 + int startState = 0;
57.186 + final int[] nextState = new int[] {1};
57.187 + final Map<NFA.Key<Input>, NFA.State> transitionTable = new LinkedHashMap<NFA.Key<Input>, NFA.State>();
57.188 + Map<Integer, Res> finalStates = new HashMap<Integer, Res>();
57.189 + List<Set<? extends String>> identifiers = new LinkedList<Set<? extends String>>();
57.190 + List<List<List<String>>> requiredContent = new ArrayList<List<List<String>>>();
57.191 + Iterator<? extends String> codeIt = code.iterator();
57.192 + int patternIndex = 0;
57.193 +
57.194 + for (final Tree pattern : patterns) {
57.195 + final int[] currentState = new int[] {startState};
57.196 + final Set<String> patternIdentifiers = new HashSet<String>();
57.197 + final List<List<String>> content = new ArrayList<List<String>>();
57.198 +
57.199 + identifiers.add(patternIdentifiers);
57.200 + requiredContent.add(content);
57.201 +
57.202 + class Scanner extends CollectIdentifiers<Void, Void> {
57.203 + public Scanner() {
57.204 + super(patternIdentifiers, cancel);
57.205 + }
57.206 + private boolean auxPath;
57.207 + private List<String> currentContent;
57.208 + {
57.209 + content.add(currentContent = new ArrayList<String>());
57.210 + }
57.211 + @Override
57.212 + public Void scan(Tree t, Void v) {
57.213 + if (t == null) {
57.214 + return null;
57.215 + }
57.216 +
57.217 + if (Utilities.isMultistatementWildcardTree(t) || multiModifiers(t)) {
57.218 + int target = nextState[0]++;
57.219 +
57.220 + setBit(transitionTable, NFA.Key.create(currentState[0], new Input(Kind.IDENTIFIER, "$", false)), target);
57.221 + setBit(transitionTable, NFA.Key.create(target, UP), currentState[0]);
57.222 +
57.223 + content.add(currentContent = new ArrayList<String>());
57.224 +
57.225 + return null;
57.226 + }
57.227 +
57.228 + if (t.getKind() == Kind.BLOCK) {
57.229 + StatementTree singletonStatement = null;
57.230 + BlockTree bt = (BlockTree) t;
57.231 +
57.232 + if (!bt.isStatic()) {
57.233 + switch (bt.getStatements().size()) {
57.234 + case 1:
57.235 + singletonStatement = bt.getStatements().get(0);
57.236 + break;
57.237 + case 2:
57.238 + if (Utilities.isMultistatementWildcardTree(bt.getStatements().get(0))) {
57.239 + singletonStatement = bt.getStatements().get(1);
57.240 + } else {
57.241 + if (Utilities.isMultistatementWildcardTree(bt.getStatements().get(1))) {
57.242 + singletonStatement = bt.getStatements().get(0);
57.243 + }
57.244 + }
57.245 + break;
57.246 + case 3:
57.247 + if (Utilities.isMultistatementWildcardTree(bt.getStatements().get(0)) && Utilities.isMultistatementWildcardTree(bt.getStatements().get(2))) {
57.248 + singletonStatement = bt.getStatements().get(1);
57.249 + }
57.250 + break;
57.251 + }
57.252 + }
57.253 +
57.254 + if (singletonStatement != null) {
57.255 + int backup = currentState[0];
57.256 +
57.257 + boolean oldAuxPath = auxPath;
57.258 +
57.259 + auxPath = true;
57.260 +
57.261 + scan(singletonStatement, null);
57.262 +
57.263 + auxPath = oldAuxPath;
57.264 +
57.265 + int target = currentState[0];
57.266 +
57.267 + setBit(transitionTable, NFA.Key.create(backup, new Input(Kind.BLOCK, null, false)), currentState[0] = nextState[0]++);
57.268 + setBit(transitionTable, NFA.Key.create(currentState[0], new Input(Kind.IDENTIFIER, "(", false)), currentState[0] = nextState[0]++);
57.269 +
57.270 + for (StatementTree st : bt.getStatements()) {
57.271 + scan(st, null);
57.272 + }
57.273 +
57.274 + setBit(transitionTable, NFA.Key.create(currentState[0], UP), currentState[0] = nextState[0]++);
57.275 + setBit(transitionTable, NFA.Key.create(currentState[0], UP), target);
57.276 + currentState[0] = target;
57.277 +
57.278 + return null;
57.279 + }
57.280 + }
57.281 +
57.282 + boolean[] goDeeper = new boolean[1];
57.283 + Input[] bypass = new Input[1];
57.284 + Input i = normalizeInput(t, goDeeper, bypass);
57.285 +
57.286 + if (!TO_IGNORE.contains(i.kind) && !auxPath) {
57.287 + currentContent.add(kind2EncodedString.get(i.kind));
57.288 + }
57.289 +
57.290 + if (i.name != null && !auxPath) {
57.291 + if (!"$".equals(i.name)) {
57.292 + if (isIdentifierAcceptable(i.name)) {
57.293 + currentContent.add(i.name);
57.294 + }
57.295 + if (Utilities.isPureMemberSelect(t, false)) {
57.296 + content.add(currentContent = new ArrayList<String>());
57.297 + }
57.298 + } else {
57.299 + content.add(currentContent = new ArrayList<String>());
57.300 + }
57.301 + }
57.302 +
57.303 + int backup = currentState[0];
57.304 +
57.305 + handleTree(i, goDeeper, t, bypass);
57.306 +
57.307 + boolean oldAuxPath = auxPath;
57.308 +
57.309 + auxPath = true;
57.310 +
57.311 + if (StatementTree.class.isAssignableFrom(t.getKind().asInterface()) && t != pattern) {
57.312 + int target = currentState[0];
57.313 +
57.314 + setBit(transitionTable, NFA.Key.create(backup, new Input(Kind.BLOCK, null, false)), currentState[0] = nextState[0]++);
57.315 + setBit(transitionTable, NFA.Key.create(currentState[0], new Input(Kind.IDENTIFIER, "(", false)), currentState[0] = nextState[0]++);
57.316 + handleTree(i, goDeeper, t, bypass);
57.317 + setBit(transitionTable, NFA.Key.create(currentState[0], UP), currentState[0] = nextState[0]++);
57.318 + setBit(transitionTable, NFA.Key.create(currentState[0], UP), target);
57.319 + currentState[0] = target;
57.320 + }
57.321 +
57.322 + auxPath = oldAuxPath;
57.323 +
57.324 + return null;
57.325 + }
57.326 +
57.327 + @Override
57.328 + public Void scan(Iterable<? extends Tree> nodes, Void p) {
57.329 + setBit(transitionTable, NFA.Key.create(currentState[0], new Input(Kind.IDENTIFIER, "(", false)), currentState[0] = nextState[0]++);
57.330 + try {
57.331 + return super.scan(nodes, p);
57.332 + } finally {
57.333 + setBit(transitionTable, NFA.Key.create(currentState[0], UP), currentState[0] = nextState[0]++);
57.334 + }
57.335 + }
57.336 +
57.337 + private void handleTree(Input i, boolean[] goDeeper, Tree t, Input[] bypass) {
57.338 + int backup = currentState[0];
57.339 + int target = nextState[0]++;
57.340 +
57.341 + setBit(transitionTable, NFA.Key.create(backup, i), currentState[0] = nextState[0]++);
57.342 +
57.343 + if (goDeeper[0]) {
57.344 + super.scan(t, null);
57.345 + } else {
57.346 + new CollectIdentifiers<Void, Void>(patternIdentifiers, cancel).scan(t, null);
57.347 + int aux = nextState[0]++;
57.348 + setBit(transitionTable, NFA.Key.create(backup, new Input(Kind.MEMBER_SELECT, i.name, false)), aux);
57.349 + setBit(transitionTable, NFA.Key.create(aux, new Input(Kind.IDENTIFIER, "$", false)), aux = nextState[0]++);
57.350 + setBit(transitionTable, NFA.Key.create(aux, UP), aux = nextState[0]++);
57.351 + setBit(transitionTable, NFA.Key.create(aux, UP), target);
57.352 + }
57.353 +
57.354 + setBit(transitionTable, NFA.Key.create(currentState[0], UP), target);
57.355 +
57.356 + if (bypass[0] != null) {
57.357 + int intermediate = nextState[0]++;
57.358 +
57.359 + setBit(transitionTable, NFA.Key.create(backup, bypass[0]), intermediate);
57.360 + setBit(transitionTable, NFA.Key.create(intermediate, UP), target);
57.361 + }
57.362 +
57.363 + currentState[0] = target;
57.364 + }
57.365 + }
57.366 +
57.367 + Scanner s = new Scanner();
57.368 +
57.369 + s.scan(pattern, null);
57.370 +
57.371 + finalStates.put(currentState[0], new Res(codeIt.next(), patternIndex++));
57.372 + }
57.373 +
57.374 + if (cancel.get()) return null;
57.375 +
57.376 + NFA<Input, Res> nfa = NFA.<Input, Res>create(startState, nextState[0], null, transitionTable, finalStates);
57.377 +
57.378 + return new BulkPatternImpl(new LinkedList<String>(code), identifiers, requiredContent, new LinkedList<AdditionalQueryConstraints>(additionalConstraints), nfa);
57.379 + }
57.380 +
57.381 + private static void setBit(Map<NFA.Key<Input>, NFA.State> transitionTable, NFA.Key<Input> input, int state) {
57.382 + NFA.State target = transitionTable.get(input);
57.383 +
57.384 + if (target == null) {
57.385 + transitionTable.put(input, target = NFA.State.create());
57.386 + }
57.387 +
57.388 + target.mutableOr(state);
57.389 + }
57.390 +
57.391 + private static Input normalizeInput(Tree t, boolean[] goDeeper, Input[] bypass) {
57.392 + if (t.getKind() == Kind.IDENTIFIER && ((IdentifierTree) t).getName().toString().startsWith("$")) {
57.393 + goDeeper[0] = false;
57.394 + return new Input(Kind.IDENTIFIER, "$", false);
57.395 + }
57.396 +
57.397 + if (Utilities.getWildcardTreeName(t) != null) {
57.398 + goDeeper[0] = false;
57.399 + return new Input(Kind.IDENTIFIER, "$", false);
57.400 + }
57.401 +
57.402 + if (t.getKind() == Kind.IDENTIFIER) {
57.403 + goDeeper[0] = false;
57.404 + String name = ((IdentifierTree) t).getName().toString();
57.405 + return new Input(Kind.IDENTIFIER, name, false);
57.406 + }
57.407 +
57.408 + if (t.getKind() == Kind.MEMBER_SELECT) {
57.409 + String name = ((MemberSelectTree) t).getIdentifier().toString();
57.410 + if (name.startsWith("$")) {
57.411 + goDeeper[0] = false;//???
57.412 + return new Input(Kind.IDENTIFIER, "$", false);
57.413 + }
57.414 + if (bypass != null && Utilities.isPureMemberSelect(t, true)) {
57.415 + bypass[0] = new Input(Kind.IDENTIFIER, name, false);
57.416 + }
57.417 + goDeeper[0] = true;
57.418 + return new Input(Kind.MEMBER_SELECT, name, false);
57.419 + }
57.420 +
57.421 + goDeeper[0] = true;
57.422 +
57.423 + String name;
57.424 +
57.425 + switch (t.getKind()) {
57.426 + case CLASS: name = ((ClassTree)t).getSimpleName().toString(); break;
57.427 + case VARIABLE: name = ((VariableTree)t).getName().toString(); break;
57.428 + case METHOD: name = ((MethodTree)t).getName().toString(); break;
57.429 + case BOOLEAN_LITERAL: name = ((LiteralTree) t).getValue().toString(); break;
57.430 + default: name = null;
57.431 + }
57.432 +
57.433 + if (name != null) {
57.434 + if (!name.isEmpty() && name.charAt(0) == '$') {
57.435 + name = "$";
57.436 + }
57.437 + }
57.438 + return new Input(t.getKind(), name, false);
57.439 + }
57.440 +
57.441 + private boolean multiModifiers(Tree t) {
57.442 + if (t.getKind() != Kind.MODIFIERS) return false;
57.443 +
57.444 + List<AnnotationTree> annotations = new ArrayList<AnnotationTree>(((ModifiersTree) t).getAnnotations());
57.445 +
57.446 + return !annotations.isEmpty() && annotations.get(0).getAnnotationType().getKind() == Kind.IDENTIFIER;
57.447 + }
57.448 +
57.449 + @Override
57.450 + public boolean matches(CompilationInfo info, AtomicBoolean cancel, TreePath tree, BulkPattern pattern) {
57.451 + //XXX: performance
57.452 + return !match(info, cancel, tree, pattern).isEmpty();
57.453 + }
57.454 +
57.455 + private static final Set<Kind> TO_IGNORE = EnumSet.of(Kind.BLOCK, Kind.IDENTIFIER, Kind.MEMBER_SELECT);
57.456 +
57.457 + @Override
57.458 + public void encode(Tree tree, final EncodingContext ctx, AtomicBoolean cancel) {
57.459 + final Set<String> identifiers = new HashSet<String>();
57.460 + final List<String> content = new ArrayList<String>();
57.461 + if (!ctx.isForDuplicates()) {
57.462 + new CollectIdentifiers<Void, Void>(identifiers, cancel).scan(tree, null);
57.463 + try {
57.464 + int size = identifiers.size();
57.465 + ctx.getOut().write((size >> 24) & 0xFF);
57.466 + ctx.getOut().write((size >> 16) & 0xFF);
57.467 + ctx.getOut().write((size >> 8) & 0xFF);
57.468 + ctx.getOut().write((size >> 0) & 0xFF);
57.469 + for (String ident : identifiers) {
57.470 + ctx.getOut().write(ident.getBytes("UTF-8"));//XXX: might probably contain ';'
57.471 + ctx.getOut().write(';');
57.472 + }
57.473 + } catch (IOException ex) {
57.474 + throw new IllegalStateException(ex);
57.475 + }
57.476 + }
57.477 + if (cancel.get());
57.478 + new CollectIdentifiers<Void, Void>(new HashSet<String>(), cancel) {
57.479 + private boolean encode = true;
57.480 + @Override
57.481 + public Void scan(Tree t, Void v) {
57.482 + if (t == null) return null;
57.483 +
57.484 + if (t instanceof StatementTree && Utilities.isMultistatementWildcardTree((StatementTree) t)) {
57.485 + return null;
57.486 + }
57.487 +
57.488 + boolean[] goDeeper = new boolean[1];
57.489 +
57.490 + Input i = normalizeInput(t, goDeeper, null);
57.491 + try {
57.492 + ctx.getOut().write('(');
57.493 + ctx.getOut().write(kind2Encoded.get(i.kind));
57.494 + if (!TO_IGNORE.contains(i.kind)) {
57.495 + content.add(kind2EncodedString.get(i.kind));
57.496 + }
57.497 + if (i.name != null) {
57.498 + if (encode) {
57.499 + ctx.getOut().write('$');
57.500 + ctx.getOut().write(i.name.getBytes("UTF-8"));
57.501 + ctx.getOut().write(';');
57.502 + }
57.503 + if (isIdentifierAcceptable(i.name)) content.add(i.name);
57.504 + }
57.505 +
57.506 + boolean oldEncode = encode;
57.507 +
57.508 + encode &= goDeeper[0];
57.509 + super.scan(t, v);
57.510 + encode = oldEncode;
57.511 +
57.512 + ctx.getOut().write(')');
57.513 + } catch (IOException ex) {
57.514 + //XXX
57.515 + Exceptions.printStackTrace(ex);
57.516 + }
57.517 +
57.518 + return null;
57.519 + }
57.520 + @Override
57.521 + public Void scan(Iterable<? extends Tree> nodes, Void p) {
57.522 + try {
57.523 + ctx.getOut().write('(');
57.524 + ctx.getOut().write(kind2Encoded.get(Kind.IDENTIFIER));
57.525 + ctx.getOut().write('$');
57.526 + ctx.getOut().write('(');
57.527 + ctx.getOut().write(';');
57.528 + super.scan(nodes, p);
57.529 + ctx.getOut().write(')');
57.530 + } catch (IOException ex) {
57.531 + //XXX
57.532 + Exceptions.printStackTrace(ex);
57.533 + }
57.534 + return null;
57.535 + }
57.536 + }.scan(tree, null);
57.537 +
57.538 + ctx.setIdentifiers(identifiers);
57.539 + ctx.setContent(content);
57.540 + if (cancel.get());
57.541 + }
57.542 +
57.543 + @Override
57.544 + public boolean matches(InputStream encoded, AtomicBoolean cancel, BulkPattern patternIn) {
57.545 + try {
57.546 + return !matchesImpl(encoded, cancel, patternIn, false).isEmpty();
57.547 + } catch (IOException ex) {
57.548 + Exceptions.printStackTrace(ex);
57.549 + return false;
57.550 + }
57.551 + }
57.552 +
57.553 + @Override
57.554 + public Map<String, Integer> matchesWithFrequencies(InputStream encoded, BulkPattern patternIn, AtomicBoolean cancel) {
57.555 + try {
57.556 + return matchesImpl(encoded, cancel, patternIn, true);
57.557 + } catch (IOException ex) {
57.558 + Exceptions.printStackTrace(ex);
57.559 + return Collections.emptyMap();
57.560 + }
57.561 + }
57.562 +
57.563 + public Map<String, Integer> matchesImpl(InputStream encoded, AtomicBoolean cancel, BulkPattern patternIn, boolean withFrequencies) throws IOException {
57.564 + BulkPatternImpl pattern = (BulkPatternImpl) patternIn;
57.565 + final NFA<Input, Res> nfa = pattern.toNFA();
57.566 + Stack<NFA.State> skips = new Stack<NFA.State>();
57.567 + NFA.State active = nfa.getStartingState();
57.568 + int identSize = 0;
57.569 +
57.570 + identSize = encoded.read();
57.571 + identSize = (identSize << 8) + encoded.read();
57.572 + identSize = (identSize << 8) + encoded.read();
57.573 + identSize = (identSize << 8) + encoded.read();
57.574 +
57.575 + Set<String> identifiers = new HashSet<String>(2 * identSize);
57.576 +
57.577 + while (identSize-- > 0) {
57.578 + if (cancel.get()) return null;
57.579 + int read = encoded.read();
57.580 +
57.581 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
57.582 +
57.583 + //read name:
57.584 + while (read != ';') {
57.585 + baos.write(read);
57.586 + read = encoded.read();
57.587 + }
57.588 +
57.589 + identifiers.add(new String(baos.toByteArray(), "UTF-8"));
57.590 + }
57.591 +
57.592 + Map<String, Integer> patternsAndFrequencies = new HashMap<String, Integer>();
57.593 + int read = encoded.read();
57.594 +
57.595 + while (read != (-1)) {
57.596 + if (cancel.get()) return null;
57.597 + if (read == '(') {
57.598 + read = encoded.read(); //kind
57.599 +
57.600 + Kind k = encoded2Kind.get((read << 8) + encoded.read());
57.601 +
57.602 + read = encoded.read();
57.603 +
57.604 + String name;
57.605 +
57.606 + if (read == '$') {
57.607 + //XXX:
57.608 + read = encoded.read();
57.609 +
57.610 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
57.611 +
57.612 + //read name:
57.613 + while (read != ';') {
57.614 + baos.write(read);
57.615 + read = encoded.read();
57.616 + }
57.617 +
57.618 + read = encoded.read();
57.619 + name = new String(baos.toByteArray(), "UTF-8");
57.620 + } else {
57.621 + name = null;
57.622 + }
57.623 +
57.624 + final NFA.State newActiveAfterVariable = nfa.transition(active, new Input(Kind.IDENTIFIER, "$", false));
57.625 + Input normalizedInput = new Input(k, name, false);
57.626 + boolean ignoreKind = normalizedInput.kind == Kind.IDENTIFIER || normalizedInput.kind == Kind.MEMBER_SELECT;
57.627 +
57.628 + NFA.State newActive = nfa.transition(active, normalizedInput);
57.629 +
57.630 + if (normalizedInput.name != null && !ignoreKind) {
57.631 + newActive = nfa.join(newActive, nfa.transition(active, new Input(k, "$", false)));
57.632 + }
57.633 +
57.634 + active = newActive;
57.635 +
57.636 + skips.push(newActiveAfterVariable);
57.637 + } else {
57.638 + NFA.State newActiveAfterVariable = skips.pop();
57.639 + NFA.State newActive = nfa.transition(active, UP);
57.640 + NFA.State s2 = nfa.transition(newActiveAfterVariable, UP);
57.641 +
57.642 + active = nfa.join(newActive, s2);
57.643 +
57.644 + for (Res res : nfa.getResults(active)) {
57.645 + if (identifiers.containsAll(pattern.getIdentifiers().get(res.patternIndex))) {
57.646 + if (!withFrequencies) {
57.647 + patternsAndFrequencies.put(res.pattern, 1);
57.648 + return patternsAndFrequencies;
57.649 + }
57.650 +
57.651 + Integer freqs = patternsAndFrequencies.get(res.pattern);
57.652 +
57.653 + if (freqs == null) freqs = 0;
57.654 +
57.655 + patternsAndFrequencies.put(res.pattern, freqs + 1);
57.656 + }
57.657 + }
57.658 +
57.659 + read = encoded.read();
57.660 + }
57.661 + }
57.662 +
57.663 + return patternsAndFrequencies;
57.664 + }
57.665 +
57.666 + private static final Map<Kind, byte[]> kind2Encoded;
57.667 + private static final Map<Kind, String> kind2EncodedString;
57.668 + private static final Map<Integer, Kind> encoded2Kind;
57.669 +
57.670 + static {
57.671 + kind2Encoded = new EnumMap<Kind, byte[]>(Kind.class);
57.672 + kind2EncodedString = new EnumMap<Kind, String>(Kind.class);
57.673 + encoded2Kind = new HashMap<Integer, Kind>();
57.674 +
57.675 + for (Kind k : Kind.values()) {
57.676 + String enc = Integer.toHexString(k.ordinal());
57.677 +
57.678 + if (enc.length() < 2) {
57.679 + enc = "0" + enc;
57.680 + }
57.681 +
57.682 + try {
57.683 + final byte[] bytes = enc.getBytes("UTF-8");
57.684 +
57.685 + assert bytes.length == 2;
57.686 +
57.687 + kind2Encoded.put(k, bytes);
57.688 + kind2EncodedString.put(k, enc);
57.689 +
57.690 + encoded2Kind.put((bytes[0] << 8) + bytes[1], k);
57.691 + } catch (UnsupportedEncodingException ex) {
57.692 + throw new IllegalStateException(ex);
57.693 + }
57.694 + }
57.695 + }
57.696 +
57.697 + public static class BulkPatternImpl extends BulkPattern {
57.698 +
57.699 + private final NFA<Input, Res> nfa;
57.700 +
57.701 + private BulkPatternImpl(List<? extends String> patterns, List<? extends Set<? extends String>> identifiers, List<List<List<String>>> requiredContent, List<AdditionalQueryConstraints> additionalConstraints, NFA<Input, Res> nfa) {
57.702 + super(patterns, identifiers, requiredContent, additionalConstraints);
57.703 + this.nfa = nfa;
57.704 + }
57.705 +
57.706 + NFA<Input, Res> toNFA() {
57.707 + return nfa;
57.708 + }
57.709 +
57.710 + }
57.711 +
57.712 + private static final class Res {
57.713 + private final String pattern;
57.714 + private final int patternIndex;
57.715 +
57.716 + public Res(String pattern, int patternIndex) {
57.717 + this.pattern = pattern;
57.718 + this.patternIndex = patternIndex;
57.719 + }
57.720 +
57.721 + }
57.722 +
57.723 + private static final class Input {
57.724 + private final Kind kind;
57.725 + private final String name;
57.726 + private final boolean end;
57.727 +
57.728 + private Input(Kind kind, String name, boolean end) {
57.729 + this.kind = kind;
57.730 + this.name = name;
57.731 + this.end = end;
57.732 + }
57.733 +
57.734 + @Override
57.735 + public boolean equals(Object obj) {
57.736 + if (obj == null) {
57.737 + return false;
57.738 + }
57.739 + if (getClass() != obj.getClass()) {
57.740 + return false;
57.741 + }
57.742 + final Input other = (Input) obj;
57.743 + if (this.kind != other.kind) {
57.744 + return false;
57.745 + }
57.746 + if ((this.name == null) ? (other.name != null) : !this.name.equals(other.name)) {
57.747 + return false;
57.748 + }
57.749 + if (this.end != other.end) {
57.750 + return false;
57.751 + }
57.752 + return true;
57.753 + }
57.754 +
57.755 + @Override
57.756 + public int hashCode() {
57.757 + int hash = 7;
57.758 + hash = 47 * hash + (this.kind != null ? this.kind.hashCode() : 17);
57.759 + hash = 47 * hash + (this.name != null ? this.name.hashCode() : 0);
57.760 + hash = 47 * hash + (this.end ? 1 : 0);
57.761 + return hash;
57.762 + }
57.763 +
57.764 + @Override
57.765 + public String toString() {
57.766 + return kind + ", " + name + ", " + end;
57.767 + }
57.768 +
57.769 + }
57.770 +
57.771 + private static final Input UP = new Input(null, null, true);
57.772 +
57.773 + private static boolean isIdentifierAcceptable(CharSequence content) {
57.774 + if (content.length() == 0) return false;
57.775 + if (content.charAt(0) == '$' || content.charAt(0) == '<') return false;
57.776 + String stringValue = content.toString();
57.777 + if (stringValue.contentEquals("java") || "lang".equals(stringValue)) return false;
57.778 + return true;
57.779 + }
57.780 +
57.781 + private static class CollectIdentifiers<R, P> extends CancellableTreeScanner<R, P> {
57.782 +
57.783 + private final Set<String> identifiers;
57.784 +
57.785 + public CollectIdentifiers(Set<String> identifiers, AtomicBoolean cancel) {
57.786 + super(cancel);
57.787 + this.identifiers = identifiers;
57.788 + }
57.789 +
57.790 + private void addIdentifier(Name ident) {
57.791 + if (!isIdentifierAcceptable(ident)) return;
57.792 + identifiers.add(ident.toString());
57.793 + }
57.794 +
57.795 + @Override
57.796 + public R visitMemberSelect(MemberSelectTree node, P p) {
57.797 + addIdentifier(node.getIdentifier());
57.798 + return super.visitMemberSelect(node, p);
57.799 + }
57.800 +
57.801 + @Override
57.802 + public R visitIdentifier(IdentifierTree node, P p) {
57.803 + addIdentifier(node.getName());
57.804 + return super.visitIdentifier(node, p);
57.805 + }
57.806 +
57.807 + @Override
57.808 + public R visitClass(ClassTree node, P p) {
57.809 + if (node.getSimpleName().length() == 0) {
57.810 + return scan(Utilities.filterHidden(null, node.getMembers()), p);
57.811 + }
57.812 + addIdentifier(node.getSimpleName());
57.813 + return super.visitClass(node, p);
57.814 + }
57.815 +
57.816 + @Override
57.817 + public R visitMethod(MethodTree node, P p) {
57.818 + addIdentifier(node.getName());
57.819 + return super.visitMethod(node, p);
57.820 + }
57.821 +
57.822 + @Override
57.823 + public R visitVariable(VariableTree node, P p) {
57.824 + addIdentifier(node.getName());
57.825 + return super.visitVariable(node, p);
57.826 + }
57.827 +
57.828 + }
57.829 +}
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/pm/PatternCompiler.java Wed May 08 21:47:42 2013 +0200
58.3 @@ -0,0 +1,72 @@
58.4 +/*
58.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
58.6 + *
58.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
58.8 + *
58.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
58.10 + * Other names may be trademarks of their respective owners.
58.11 + *
58.12 + * The contents of this file are subject to the terms of either the GNU
58.13 + * General Public License Version 2 only ("GPL") or the Common
58.14 + * Development and Distribution License("CDDL") (collectively, the
58.15 + * "License"). You may not use this file except in compliance with the
58.16 + * License. You can obtain a copy of the License at
58.17 + * http://www.netbeans.org/cddl-gplv2.html
58.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
58.19 + * specific language governing permissions and limitations under the
58.20 + * License. When distributing the software, include this License Header
58.21 + * Notice in each file and include the License file at
58.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
58.23 + * particular file as subject to the "Classpath" exception as provided
58.24 + * by Oracle in the GPL Version 2 section of the License file that
58.25 + * accompanied this code. If applicable, add the following below the
58.26 + * License Header, with the fields enclosed by brackets [] replaced by
58.27 + * your own identifying information:
58.28 + * "Portions Copyrighted [year] [name of copyright owner]"
58.29 + *
58.30 + * If you wish your version of this file to be governed by only the CDDL
58.31 + * or only the GPL Version 2, indicate your decision by adding
58.32 + * "[Contributor] elects to include this software in this distribution
58.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
58.34 + * single choice of license, a recipient has the option to distribute
58.35 + * your version of this file under either the CDDL, the GPL Version 2 or
58.36 + * to extend the choice of license to its licensees as provided above.
58.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
58.38 + * Version 2 license, then the option applies only if the new code is
58.39 + * made subject to such option by the copyright holder.
58.40 + *
58.41 + * Contributor(s):
58.42 + *
58.43 + * Portions Copyrighted 2008-2009 Sun Microsystems, Inc.
58.44 + */
58.45 +
58.46 +package org.netbeans.modules.java.hints.spiimpl.pm;
58.47 +
58.48 +import com.sun.source.tree.Scope;
58.49 +import com.sun.source.tree.Tree;
58.50 +import com.sun.source.util.TreePath;
58.51 +import java.util.Map;
58.52 +import javax.lang.model.type.TypeMirror;
58.53 +import org.netbeans.api.java.source.CompilationInfo;
58.54 +import org.netbeans.modules.java.hints.spiimpl.Utilities;
58.55 +import org.netbeans.api.java.source.matching.Pattern;
58.56 +
58.57 +/**XXX: cancelability!
58.58 + *
58.59 + * @author Jan Lahoda
58.60 + */
58.61 +public class PatternCompiler {
58.62 +
58.63 + public static Pattern compile(CompilationInfo info, String pattern, Map<String, TypeMirror> constraints, Iterable<? extends String> imports) {
58.64 + Scope scope = Utilities.constructScope(info, constraints, imports);
58.65 +
58.66 + if (scope == null) {
58.67 + return null; //TODO: can happen?
58.68 + }
58.69 +
58.70 + Tree patternTree = Utilities.parseAndAttribute(info, pattern, scope);
58.71 +
58.72 + return Pattern.createPatternWithFreeVariables(new TreePath(new TreePath(info.getCompilationUnit()), patternTree), constraints);
58.73 + }
58.74 +
58.75 +}
59.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
59.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/processor/Bundle.properties Wed May 08 21:47:42 2013 +0200
59.3 @@ -0,0 +1,3 @@
59.4 +OpenIDE-Module-Name=Java Hints Annotation Processor
59.5 +OpenIDE-Module-Display-Category=Java
59.6 +OpenIDE-Module-Short-Description=Java Hints Annotation Processor
60.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
60.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/processor/JavaHintsAnnotationProcessor.java Wed May 08 21:47:42 2013 +0200
60.3 @@ -0,0 +1,635 @@
60.4 +/*
60.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
60.6 + *
60.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
60.8 + *
60.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
60.10 + * Other names may be trademarks of their respective owners.
60.11 + *
60.12 + * The contents of this file are subject to the terms of either the GNU
60.13 + * General Public License Version 2 only ("GPL") or the Common
60.14 + * Development and Distribution License("CDDL") (collectively, the
60.15 + * "License"). You may not use this file except in compliance with the
60.16 + * License. You can obtain a copy of the License at
60.17 + * http://www.netbeans.org/cddl-gplv2.html
60.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
60.19 + * specific language governing permissions and limitations under the
60.20 + * License. When distributing the software, include this License Header
60.21 + * Notice in each file and include the License file at
60.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
60.23 + * particular file as subject to the "Classpath" exception as provided
60.24 + * by Oracle in the GPL Version 2 section of the License file that
60.25 + * accompanied this code. If applicable, add the following below the
60.26 + * License Header, with the fields enclosed by brackets [] replaced by
60.27 + * your own identifying information:
60.28 + * "Portions Copyrighted [year] [name of copyright owner]"
60.29 + *
60.30 + * If you wish your version of this file to be governed by only the CDDL
60.31 + * or only the GPL Version 2, indicate your decision by adding
60.32 + * "[Contributor] elects to include this software in this distribution
60.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
60.34 + * single choice of license, a recipient has the option to distribute
60.35 + * your version of this file under either the CDDL, the GPL Version 2 or
60.36 + * to extend the choice of license to its licensees as provided above.
60.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
60.38 + * Version 2 license, then the option applies only if the new code is
60.39 + * made subject to such option by the copyright holder.
60.40 + *
60.41 + * Contributor(s):
60.42 + *
60.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
60.44 + */
60.45 +
60.46 +package org.netbeans.modules.java.hints.spiimpl.processor;
60.47 +
60.48 +import java.lang.reflect.Array;
60.49 +import java.util.Map.Entry;
60.50 +import java.util.*;
60.51 +import java.util.AbstractMap.SimpleEntry;
60.52 +import java.util.logging.Logger;
60.53 +import java.util.regex.Matcher;
60.54 +import java.util.regex.Pattern;
60.55 +import javax.annotation.processing.Processor;
60.56 +import javax.annotation.processing.RoundEnvironment;
60.57 +import javax.annotation.processing.SupportedAnnotationTypes;
60.58 +import javax.annotation.processing.SupportedSourceVersion;
60.59 +import javax.lang.model.SourceVersion;
60.60 +import javax.lang.model.element.*;
60.61 +import javax.lang.model.type.DeclaredType;
60.62 +import javax.lang.model.type.TypeMirror;
60.63 +import javax.lang.model.util.AbstractAnnotationValueVisitor6;
60.64 +import javax.lang.model.util.ElementFilter;
60.65 +import javax.lang.model.util.ElementScanner6;
60.66 +import javax.lang.model.util.Elements;
60.67 +import javax.lang.model.util.Types;
60.68 +import javax.tools.Diagnostic.Kind;
60.69 +import org.openide.filesystems.annotations.LayerBuilder;
60.70 +import org.openide.filesystems.annotations.LayerBuilder.File;
60.71 +import org.openide.filesystems.annotations.LayerGeneratingProcessor;
60.72 +import org.openide.filesystems.annotations.LayerGenerationException;
60.73 +import org.openide.util.NbCollections;
60.74 +import org.openide.util.lookup.ServiceProvider;
60.75 +
60.76 +/**Inspired by https://sezpoz.dev.java.net/.
60.77 + *
60.78 + * @author lahvac
60.79 + */
60.80 +@SupportedSourceVersion(SourceVersion.RELEASE_6)
60.81 +@SupportedAnnotationTypes("org.netbeans.spi.java.hints.*")
60.82 +@ServiceProvider(service=Processor.class, position=100)
60.83 +public class JavaHintsAnnotationProcessor extends LayerGeneratingProcessor {
60.84 +
60.85 + private static final Logger LOG = Logger.getLogger(JavaHintsAnnotationProcessor.class.getName());
60.86 +
60.87 + @Override
60.88 + protected boolean handleProcess(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) throws LayerGenerationException {
60.89 + if (!roundEnv.processingOver()) {
60.90 + generateTypeList("org.netbeans.spi.java.hints.Hint", roundEnv);
60.91 + }
60.92 +
60.93 + return false;
60.94 + }
60.95 +
60.96 + private static final String[] TRIGGERS = new String[] {
60.97 + "org.netbeans.spi.java.hints.TriggerTreeKind",
60.98 + "org.netbeans.spi.java.hints.TriggerPattern",
60.99 + "org.netbeans.spi.java.hints.TriggerPatterns",
60.100 + };
60.101 +
60.102 + private static final String[] OPTIONS = new String[] {
60.103 + "org.netbeans.spi.java.hints.BooleanOption"
60.104 + };
60.105 +
60.106 + private void generateTypeList(String annotationName, RoundEnvironment roundEnv) throws LayerGenerationException {
60.107 + TypeElement hint = processingEnv.getElementUtils().getTypeElement(annotationName);
60.108 +
60.109 + if (hint == null) return ;
60.110 +
60.111 + for (Element annotated : roundEnv.getElementsAnnotatedWith(hint)) {
60.112 + if (!verifyHintAnnotationAcceptable(annotated)) continue;
60.113 + if (!annotated.getKind().isClass() && !annotated.getKind().isInterface()) {
60.114 + if (annotated.getKind() != ElementKind.METHOD) {
60.115 + //the compiler should have already warned about this
60.116 + continue;
60.117 + }
60.118 +
60.119 + annotated = annotated.getEnclosingElement();
60.120 + } else {
60.121 + if (!annotated.getKind().isClass()) {
60.122 + //the compiler should have already warned about this
60.123 + continue;
60.124 + }
60.125 + }
60.126 +
60.127 + if (!annotated.getKind().isClass()) {
60.128 + processingEnv.getMessager().printMessage(Kind.ERROR, "Internal error - cannot find class containing the hint", annotated);
60.129 + continue;
60.130 + }
60.131 +
60.132 + TypeElement clazz = (TypeElement) annotated;
60.133 + String classFolder = "org-netbeans-modules-java-hints/code-hints/" + getFQN(clazz).replace('.', '-') + ".class";
60.134 +
60.135 + {
60.136 + LayerBuilder builder = layer(clazz);
60.137 + File clazzFolder = builder.folder(classFolder);
60.138 +
60.139 + for (AnnotationMirror am : clazz.getAnnotationMirrors()) {
60.140 + dumpAnnotation(builder, clazzFolder, clazz, am, true);
60.141 + }
60.142 +
60.143 + clazzFolder.write();
60.144 + }
60.145 +
60.146 + for (ExecutableElement ee : ElementFilter.methodsIn(clazz.getEnclosedElements())) {
60.147 + if (!ee.getAnnotationMirrors().isEmpty()) {
60.148 + LayerBuilder builder = layer(ee);
60.149 + File methodFolder = builder.folder(classFolder + "/" + ee.getSimpleName() + ".method");
60.150 +
60.151 + for (AnnotationMirror am : ee.getAnnotationMirrors()) {
60.152 + dumpAnnotation(builder, methodFolder, ee, am, true);
60.153 + }
60.154 +
60.155 + methodFolder.write();
60.156 + }
60.157 + }
60.158 +
60.159 + for (VariableElement var : ElementFilter.fieldsIn(clazz.getEnclosedElements())) {
60.160 + if (!var.getAnnotationMirrors().isEmpty()) {
60.161 + LayerBuilder builder = layer(var);
60.162 + File fieldFolder = builder.folder(classFolder + "/" + var.getSimpleName() + ".field");
60.163 +
60.164 + for (AnnotationMirror am : var.getAnnotationMirrors()) {
60.165 + dumpAnnotation(builder, fieldFolder, var, am, true);
60.166 + }
60.167 +
60.168 + if (var.getConstantValue() instanceof String) {
60.169 + fieldFolder.stringvalue("constantValue", (String) var.getConstantValue());
60.170 + }
60.171 +
60.172 + fieldFolder.write();
60.173 + }
60.174 + }
60.175 +
60.176 + new ElementScanner6<Void, Void>() {
60.177 + @Override public Void scan(Element e, Void p) {
60.178 + AnnotationMirror hintMirror = findAnnotation(e.getAnnotationMirrors(), "org.netbeans.spi.java.hints.Hint");
60.179 +
60.180 + if (hintMirror != null) {
60.181 + String qualifiedName;
60.182 + switch (e.getKind()) {
60.183 + case METHOD: case CONSTRUCTOR:
60.184 + qualifiedName = e.getEnclosingElement().asType().toString() + "." + e.getSimpleName().toString() + e.asType().toString();
60.185 + break;
60.186 + case FIELD: case ENUM_CONSTANT:
60.187 + qualifiedName = e.getEnclosingElement().asType().toString() + "." + e.getSimpleName().toString();
60.188 + break;
60.189 + case ANNOTATION_TYPE: case CLASS:
60.190 + case ENUM: case INTERFACE:
60.191 + default:
60.192 + qualifiedName = e.asType().toString();
60.193 + break;
60.194 + }
60.195 +
60.196 + try {
60.197 + File keywordsFile = layer(e)
60.198 + .file("OptionsDialog/Keywords/".concat(qualifiedName))
60.199 + .stringvalue("location", "Editor")
60.200 + .bundlevalue("tabTitle", "org.netbeans.modules.options.editor.Bundle", "CTL_Hints_DisplayName");
60.201 +
60.202 + String displayName = getAttributeValue(hintMirror, "displayName", String.class);
60.203 +
60.204 + if (displayName != null)
60.205 + keywordsFile = keywordsFile.bundlevalue("keywords-1", displayName);
60.206 +
60.207 + String description = getAttributeValue(hintMirror, "description", String.class);
60.208 +
60.209 + if (description != null)
60.210 + keywordsFile = keywordsFile.bundlevalue("keywords-2", description);
60.211 +
60.212 + int i = 3;
60.213 +
60.214 + for (String sw : getAttributeValue(hintMirror, "suppressWarnings", String[].class)) {
60.215 + keywordsFile = keywordsFile.stringvalue("keywords-" + i++, sw);
60.216 + }
60.217 +
60.218 + keywordsFile.write();
60.219 + } catch (LayerGenerationException ex) {
60.220 + JavaHintsAnnotationProcessor.<RuntimeException>rethrowAsRuntime(ex);
60.221 + }
60.222 + }
60.223 +
60.224 + return super.scan(e, p);
60.225 + }
60.226 + }.scan(annotated, null);
60.227 + }
60.228 +
60.229 + for (String ann : TRIGGERS) {
60.230 + TypeElement annRes = processingEnv.getElementUtils().getTypeElement(ann);
60.231 +
60.232 + if (annRes == null) continue;
60.233 +
60.234 + for (ExecutableElement method : ElementFilter.methodsIn(roundEnv.getElementsAnnotatedWith(annRes))) {
60.235 + verifyHintMethod(method);
60.236 + verifyTriggerAnnotations(method);
60.237 + }
60.238 + }
60.239 +
60.240 + for (String ann : OPTIONS) {
60.241 + TypeElement annRes = processingEnv.getElementUtils().getTypeElement(ann);
60.242 +
60.243 + if (annRes == null) continue;
60.244 +
60.245 + for (VariableElement var : ElementFilter.fieldsIn(roundEnv.getElementsAnnotatedWith(annRes))) {
60.246 + verifyOptionField(var);
60.247 + }
60.248 + }
60.249 +
60.250 + }
60.251 +
60.252 + private void dumpAnnotation(LayerBuilder builder, File folder, Element errElement, AnnotationMirror annotation, boolean topLevel) {
60.253 + String fqn = getFQN(((TypeElement) annotation.getAnnotationType().asElement())).replace('.', '-');
60.254 + if (topLevel && !fqn.startsWith("org-netbeans-spi-java-hints")) return ;
60.255 + final File annotationFolder = builder.folder(folder.getPath() + "/" + fqn + ".annotation");
60.256 +
60.257 + for (Entry<? extends ExecutableElement, ? extends AnnotationValue> e : annotation.getElementValues().entrySet()) {
60.258 + final String attrName = e.getKey().getSimpleName().toString();
60.259 + e.getValue().accept(new DumpAnnotationValue(builder, annotationFolder, attrName, errElement, annotation, e.getValue()), null);
60.260 + }
60.261 +
60.262 + annotationFolder.write();
60.263 + }
60.264 +
60.265 + private String getFQN(TypeElement clazz) {
60.266 + return processingEnv.getElementUtils().getBinaryName(clazz).toString();
60.267 + }
60.268 +
60.269 + static final String ERR_RETURN_TYPE = "The return type must be either org.netbeans.spi.editor.hints.ErrorDescription or java.util.List<org.netbeans.spi.editor.hints.ErrorDescription>";
60.270 + static final String ERR_PARAMETERS = "The method must have exactly one parameter of type org.netbeans.spi.java.hints.HintContext";
60.271 + static final String ERR_MUST_BE_STATIC = "The method must be static";
60.272 + static final String ERR_OPTION_TYPE = "The option field must be of type java.lang.String";
60.273 + static final String ERR_OPTION_MUST_BE_STATIC_FINAL = "The option field must be static final";
60.274 + static final String WARN_BUNDLE_KEY_NOT_FOUND = "Bundle key %s not found";
60.275 +
60.276 + private static AnnotationMirror findAnnotation(Iterable<? extends AnnotationMirror> annotations, String annotationFQN) {
60.277 + for (AnnotationMirror am : annotations) {
60.278 + if (((TypeElement) am.getAnnotationType().asElement()).getQualifiedName().contentEquals(annotationFQN)) {
60.279 + return am;
60.280 + }
60.281 + }
60.282 +
60.283 + return null;
60.284 + }
60.285 +
60.286 + private <T> T getAttributeValue(AnnotationMirror annotation, String attribute, Class<T> clazz) {
60.287 + if (clazz.isArray()) {
60.288 + Iterable<?> attributes = getAttributeValueInternal(annotation, attribute, Iterable.class);
60.289 +
60.290 + Collection<Object> coll = new ArrayList<Object>();
60.291 + Class<?> componentType = clazz.getComponentType();
60.292 +
60.293 + for (Object attr : attributes) {
60.294 + if (attr instanceof AnnotationValue) {
60.295 + attr = ((AnnotationValue) attr).getValue();
60.296 + }
60.297 +
60.298 + if (componentType.isAssignableFrom(attr.getClass())) {
60.299 + coll.add(componentType.cast(attr));
60.300 + }
60.301 + }
60.302 +
60.303 + return clazz.cast(coll.toArray((Object[]) Array.newInstance(clazz.getComponentType(), 0)));
60.304 + } else {
60.305 + return getAttributeValueInternal(annotation, attribute, clazz);
60.306 + }
60.307 + }
60.308 +
60.309 + private <T> T getAttributeValueInternal(AnnotationMirror annotation, String attribute, Class<T> clazz) {
60.310 + for (Entry<? extends ExecutableElement, ? extends AnnotationValue> e : processingEnv.getElementUtils().getElementValuesWithDefaults(annotation).entrySet()) {
60.311 + if (e.getKey().getSimpleName().contentEquals(attribute)) {
60.312 + Object value = e.getValue().getValue();
60.313 +
60.314 + if (clazz.isAssignableFrom(value.getClass())) {
60.315 + return clazz.cast(value);
60.316 + }
60.317 +
60.318 + return null;
60.319 + }
60.320 + }
60.321 +
60.322 + return null;
60.323 + }
60.324 +
60.325 + private AnnotationValue getAttributeValueDescription(AnnotationMirror annotation, String attribute) {
60.326 + for (Entry<? extends ExecutableElement, ? extends AnnotationValue> e : processingEnv.getElementUtils().getElementValuesWithDefaults(annotation).entrySet()) {
60.327 + if (e.getKey().getSimpleName().contentEquals(attribute)) {
60.328 + return e.getValue();
60.329 + }
60.330 + }
60.331 +
60.332 + return null;
60.333 + }
60.334 +
60.335 + private boolean verifyHintAnnotationAcceptable(Element hint) {
60.336 + AnnotationMirror hintMirror = findAnnotation(hint.getAnnotationMirrors(), "org.netbeans.spi.java.hints.Hint");
60.337 +
60.338 + if (hintMirror == null) return false;
60.339 +
60.340 + String id = getAttributeValue(hintMirror, "id", String.class);
60.341 +
60.342 + if (id == null || id.isEmpty()) {
60.343 + switch (hint.getKind()) {
60.344 + case CLASS:
60.345 + case METHOD:
60.346 + break; //OK
60.347 + default:
60.348 + //compiler should have already warned about this
60.349 + return false;
60.350 + }
60.351 + }
60.352 +
60.353 + TypeMirror customizerProviderType = getAttributeValue(hintMirror, "customizerProvider", TypeMirror.class);
60.354 +
60.355 + if (customizerProviderType != null) {
60.356 + Element customizerProvider = processingEnv.getTypeUtils().asElement(customizerProviderType);
60.357 +
60.358 + if (customizerProvider != null) {
60.359 + if (customizerProvider.getKind() != ElementKind.CLASS) {
60.360 + TypeElement customizerProviderInterface = processingEnv.getElementUtils().getTypeElement("org.netbeans.spi.java.hints.CustomizerProvider");
60.361 +
60.362 + if (customizerProviderInterface != null && !customizerProviderInterface.equals(customizerProvider)) {
60.363 + processingEnv.getMessager().printMessage(Kind.ERROR, "Customizer provider must be a concrete class", hint, hintMirror, getAttributeValueDescription(hintMirror, "customizerProvider"));
60.364 + }
60.365 + } else {
60.366 + TypeElement customizerProviderClazz = (TypeElement) customizerProvider;
60.367 +
60.368 + if (!customizerProviderClazz.getModifiers().contains(Modifier.PUBLIC)) {
60.369 + processingEnv.getMessager().printMessage(Kind.ERROR, "Customizer provider must be public", hint, hintMirror, getAttributeValueDescription(hintMirror, "customizerProvider"));
60.370 + }
60.371 +
60.372 + if ( customizerProviderClazz.getEnclosingElement().getKind() != ElementKind.PACKAGE
60.373 + && !customizerProviderClazz.getModifiers().contains(Modifier.STATIC)) {
60.374 + processingEnv.getMessager().printMessage(Kind.ERROR, "Customizer provider must be non-static innerclass", hint, hintMirror, getAttributeValueDescription(hintMirror, "customizerProvider"));
60.375 + }
60.376 +
60.377 + boolean foundDefaultConstructor = false;
60.378 +
60.379 + for (ExecutableElement ee : ElementFilter.constructorsIn(customizerProviderClazz.getEnclosedElements())) {
60.380 + if (ee.getParameters().isEmpty()) {
60.381 + foundDefaultConstructor = true;
60.382 + if (!ee.getModifiers().contains(Modifier.PUBLIC)) {
60.383 + processingEnv.getMessager().printMessage(Kind.ERROR, "Customizer provider must provide a public default constructor", hint, hintMirror, getAttributeValueDescription(hintMirror, "customizerProvider"));
60.384 + }
60.385 + break;
60.386 + }
60.387 + }
60.388 +
60.389 + if (!foundDefaultConstructor) {
60.390 + processingEnv.getMessager().printMessage(Kind.ERROR, "Customizer provider must provide a public default constructor", hint, hintMirror, getAttributeValueDescription(hintMirror, "customizerProvider"));
60.391 + }
60.392 + }
60.393 + }
60.394 + }
60.395 +
60.396 + return true;
60.397 + }
60.398 +
60.399 + private boolean verifyHintMethod(ExecutableElement method) {
60.400 + StringBuilder error = new StringBuilder();
60.401 + Elements elements = processingEnv.getElementUtils();
60.402 + TypeElement errDesc = elements.getTypeElement("org.netbeans.spi.editor.hints.ErrorDescription");
60.403 + TypeElement jlIterable = elements.getTypeElement("java.lang.Iterable");
60.404 + TypeElement hintCtx = elements.getTypeElement("org.netbeans.spi.java.hints.HintContext");
60.405 +
60.406 + if (errDesc == null || jlIterable == null || hintCtx == null) {
60.407 + return true;
60.408 + }
60.409 +
60.410 + Types types = processingEnv.getTypeUtils();
60.411 + TypeMirror errDescType = errDesc.asType(); //no type params, no need to erasure
60.412 + TypeMirror jlIterableErrDesc = types.getDeclaredType(jlIterable, errDescType);
60.413 + TypeMirror ret = method.getReturnType();
60.414 +
60.415 + if (!types.isSameType(ret, errDescType) && !types.isAssignable(ret, jlIterableErrDesc)) {
60.416 + error.append(ERR_RETURN_TYPE);
60.417 + error.append("\n");
60.418 + }
60.419 +
60.420 + if (method.getParameters().size() != 1 || !types.isSameType(method.getParameters().get(0).asType(), hintCtx.asType())) {
60.421 + error.append(ERR_PARAMETERS);
60.422 + error.append("\n");
60.423 + }
60.424 +
60.425 + if (!method.getModifiers().contains(Modifier.STATIC)) {
60.426 + error.append(ERR_MUST_BE_STATIC);
60.427 + error.append("\n");
60.428 + }
60.429 +
60.430 + if (error.length() == 0) {
60.431 + return true;
60.432 + }
60.433 +
60.434 + if (error.charAt(error.length() - 1) == '\n') {
60.435 + error.delete(error.length() - 1, error.length());
60.436 + }
60.437 +
60.438 + processingEnv.getMessager().printMessage(Kind.ERROR, error.toString(), method);
60.439 +
60.440 + return false;
60.441 + }
60.442 +
60.443 + private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\$[a-zA-Z0-9_]+");
60.444 + private boolean verifyTriggerAnnotations(ExecutableElement method) {
60.445 + List<AnnotationMirror> patternAnnotations = new ArrayList<AnnotationMirror>();
60.446 + AnnotationMirror am = findAnnotation(method.getAnnotationMirrors(), "org.netbeans.spi.java.hints.TriggerPattern");
60.447 +
60.448 + if (am != null) {
60.449 + patternAnnotations.add(am);
60.450 + }
60.451 +
60.452 + am = findAnnotation(method.getAnnotationMirrors(), "org.netbeans.spi.java.hints.TriggerPatterns");
60.453 +
60.454 + if (am != null) {
60.455 + patternAnnotations.addAll(Arrays.asList(getAttributeValue(am, "value", AnnotationMirror[].class)));
60.456 + }
60.457 +
60.458 + for (AnnotationMirror patternDescription : patternAnnotations) {
60.459 + String pattern = getAttributeValue(patternDescription, "value", String.class);
60.460 +
60.461 + if (pattern == null) continue;
60.462 +
60.463 + Set<String> variables = new HashSet<String>();
60.464 + Matcher m = VARIABLE_PATTERN.matcher(pattern);
60.465 +
60.466 + while (m.find()) {
60.467 + variables.add(m.group(0));
60.468 + }
60.469 +
60.470 + for (AnnotationMirror constraint : getAttributeValue(patternDescription, "constraints", AnnotationMirror[].class)) {
60.471 + String variable = getAttributeValue(constraint, "variable", String.class);
60.472 + String type = getAttributeValue(constraint, "type", String.class);
60.473 +
60.474 + if (variable == null || type == null) continue;
60.475 +
60.476 + if (!variables.contains(variable)) {
60.477 + processingEnv.getMessager().printMessage(Kind.WARNING, "Variable " + variable + " not used in the pattern", method, constraint, getAttributeValueDescription(constraint, "variable"));
60.478 + }
60.479 + }
60.480 + }
60.481 +
60.482 + return false;
60.483 + }
60.484 +
60.485 + private boolean verifyOptionField(VariableElement field) {
60.486 + StringBuilder error = new StringBuilder();
60.487 + Elements elements = processingEnv.getElementUtils();
60.488 + TypeElement jlString = elements.getTypeElement("java.lang.String");
60.489 +
60.490 + if (jlString == null) {
60.491 + return true;
60.492 + }
60.493 +
60.494 + Types types = processingEnv.getTypeUtils();
60.495 + TypeMirror jlStringType = jlString.asType(); //no type params, no need to erasure
60.496 +
60.497 + if (!types.isSameType(field.asType(), jlStringType)) {
60.498 + error.append(ERR_RETURN_TYPE);
60.499 + error.append("\n");
60.500 + }
60.501 +
60.502 + if (!field.getModifiers().contains(Modifier.STATIC) || !field.getModifiers().contains(Modifier.FINAL)) {
60.503 + error.append(ERR_OPTION_MUST_BE_STATIC_FINAL);
60.504 + error.append("\n");
60.505 + }
60.506 +
60.507 + Object key = field.getConstantValue();
60.508 +
60.509 + if (key == null) {
60.510 + error.append("Option field not a compile-time constant");
60.511 + error.append("\n");
60.512 + }
60.513 +
60.514 + if (error.length() == 0) {
60.515 + return true;
60.516 + }
60.517 +
60.518 + if (error.charAt(error.length() - 1) == '\n') {
60.519 + error.delete(error.length() - 1, error.length());
60.520 + }
60.521 +
60.522 + processingEnv.getMessager().printMessage(Kind.ERROR, error.toString(), field);
60.523 +
60.524 + return false;
60.525 + }
60.526 +
60.527 + private class DumpAnnotationValue extends AbstractAnnotationValueVisitor6<Void, Void> {
60.528 +
60.529 + private final LayerBuilder builder;
60.530 + private final File annotationFolder;
60.531 + private final String attrName;
60.532 + private final Element errElement;
60.533 + private final AnnotationMirror errAnnotationMirror;
60.534 + private final AnnotationValue errAnnotationValue;
60.535 +
60.536 + public DumpAnnotationValue(LayerBuilder builder, File annotationFolder, String attrName, Element errElement, AnnotationMirror errAnnotationMirror, AnnotationValue errAnnotationValue) {
60.537 + this.builder = builder;
60.538 + this.annotationFolder = annotationFolder;
60.539 + this.attrName = attrName;
60.540 + this.errElement = errElement;
60.541 + this.errAnnotationMirror = errAnnotationMirror;
60.542 + this.errAnnotationValue = errAnnotationValue;
60.543 + }
60.544 +
60.545 + public Void visitBoolean(boolean b, Void p) {
60.546 + annotationFolder.boolvalue(attrName, b);
60.547 + return null;
60.548 + }
60.549 +
60.550 + public Void visitByte(byte b, Void p) {
60.551 + annotationFolder.bytevalue(attrName, b);
60.552 + return null;
60.553 + }
60.554 +
60.555 + public Void visitChar(char c, Void p) {
60.556 + annotationFolder.charvalue(attrName, c);
60.557 + return null;
60.558 + }
60.559 +
60.560 + public Void visitDouble(double d, Void p) {
60.561 + annotationFolder.doublevalue(attrName, d);
60.562 + return null;
60.563 + }
60.564 +
60.565 + public Void visitFloat(float f, Void p) {
60.566 + annotationFolder.floatvalue(attrName, f);
60.567 + return null;
60.568 + }
60.569 +
60.570 + public Void visitInt(int i, Void p) {
60.571 + annotationFolder.intvalue(attrName, i);
60.572 + return null;
60.573 + }
60.574 +
60.575 + public Void visitLong(long i, Void p) {
60.576 + annotationFolder.longvalue(attrName, i);
60.577 + return null;
60.578 + }
60.579 +
60.580 + public Void visitShort(short s, Void p) {
60.581 + annotationFolder.shortvalue(attrName, s);
60.582 + return null;
60.583 + }
60.584 +
60.585 + public Void visitString(String s, Void p) {
60.586 + if ("displayName".equals(attrName) || "description".equals(attrName) || "tooltip".equals(attrName)) {
60.587 + try {
60.588 + annotationFolder.bundlevalue(attrName, s);
60.589 + } catch (LayerGenerationException ex) {
60.590 + processingEnv.getMessager().printMessage(Kind.ERROR, ex.getLocalizedMessage(), errElement, errAnnotationMirror, errAnnotationValue);
60.591 + }
60.592 + } else {
60.593 + annotationFolder.stringvalue(attrName, s);
60.594 + }
60.595 + return null;
60.596 + }
60.597 +
60.598 + public Void visitType(TypeMirror t, Void p) {
60.599 + annotationFolder.stringvalue(attrName, getFQN(((TypeElement) ((DeclaredType) t).asElement())));
60.600 + return null;
60.601 + }
60.602 +
60.603 + public Void visitEnumConstant(VariableElement c, Void p) {
60.604 + TypeElement owner = (TypeElement) c.getEnclosingElement();
60.605 + annotationFolder.stringvalue(attrName, getFQN(owner) + "." + c.getSimpleName());
60.606 + return null;
60.607 + }
60.608 +
60.609 + public Void visitAnnotation(AnnotationMirror a, Void p) {
60.610 + File f = builder.folder(annotationFolder.getPath() + "/" + attrName);
60.611 +
60.612 + dumpAnnotation(builder, f, errElement, a, false);
60.613 +
60.614 + f.write();
60.615 + return null;
60.616 + }
60.617 +
60.618 + public Void visitArray(List<? extends AnnotationValue> vals, Void p) {
60.619 + File arr = builder.folder(annotationFolder.getPath() + "/" + attrName);
60.620 + int c = 0;
60.621 +
60.622 + for (AnnotationValue av : vals) {
60.623 + av.accept(new DumpAnnotationValue(builder, arr, "item" + c, errElement, errAnnotationMirror, av), null);
60.624 + c++;
60.625 + }
60.626 +
60.627 + arr.write();
60.628 +
60.629 + return null;
60.630 + }
60.631 + }
60.632 +
60.633 + @SuppressWarnings("unchecked")
60.634 + private static <T extends Throwable> void rethrowAsRuntime(Throwable t) throws T {
60.635 + throw (T) t;
60.636 + }
60.637 +
60.638 +}
61.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
61.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/BooleanOption.java Wed May 08 21:47:42 2013 +0200
61.3 @@ -0,0 +1,87 @@
61.4 +/*
61.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
61.6 + *
61.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
61.8 + *
61.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
61.10 + * Other names may be trademarks of their respective owners.
61.11 + *
61.12 + * The contents of this file are subject to the terms of either the GNU
61.13 + * General Public License Version 2 only ("GPL") or the Common
61.14 + * Development and Distribution License("CDDL") (collectively, the
61.15 + * "License"). You may not use this file except in compliance with the
61.16 + * License. You can obtain a copy of the License at
61.17 + * http://www.netbeans.org/cddl-gplv2.html
61.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
61.19 + * specific language governing permissions and limitations under the
61.20 + * License. When distributing the software, include this License Header
61.21 + * Notice in each file and include the License file at
61.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
61.23 + * particular file as subject to the "Classpath" exception as provided
61.24 + * by Oracle in the GPL Version 2 section of the License file that
61.25 + * accompanied this code. If applicable, add the following below the
61.26 + * License Header, with the fields enclosed by brackets [] replaced by
61.27 + * your own identifying information:
61.28 + * "Portions Copyrighted [year] [name of copyright owner]"
61.29 + *
61.30 + * If you wish your version of this file to be governed by only the CDDL
61.31 + * or only the GPL Version 2, indicate your decision by adding
61.32 + * "[Contributor] elects to include this software in this distribution
61.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
61.34 + * single choice of license, a recipient has the option to distribute
61.35 + * your version of this file under either the CDDL, the GPL Version 2 or
61.36 + * to extend the choice of license to its licensees as provided above.
61.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
61.38 + * Version 2 license, then the option applies only if the new code is
61.39 + * made subject to such option by the copyright holder.
61.40 + *
61.41 + * Contributor(s):
61.42 + *
61.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
61.44 + */
61.45 +package org.netbeans.spi.java.hints;
61.46 +
61.47 +import java.lang.annotation.ElementType;
61.48 +import java.lang.annotation.Retention;
61.49 +import java.lang.annotation.RetentionPolicy;
61.50 +import java.lang.annotation.Target;
61.51 +import java.util.prefs.Preferences;
61.52 +
61.53 +/**Specify an option that affects the way the hint works.
61.54 + *
61.55 + * Only {@code static final String} compile-time constant can be marked with this
61.56 + * annotation. The value of the constant will be used as the key to the hint's {@link Preferences}.
61.57 + *
61.58 + * For hints that consist of a class, all options that are directly enclosed in the class
61.59 + * will be used in their source order.
61.60 + *
61.61 + * For hints that consist of a single method, use {@link UseOptions} to specify which options
61.62 + * from the enclosing class should be used. The order of the options will be the order in which
61.63 + * they appear in the source code of the enclosing class.
61.64 + *
61.65 + * The customizer will be generated automatically when {@link BooleanOption} is used.
61.66 + *
61.67 + * Two keys need to be defined in the corresponding {@code Bundle.properties}:
61.68 + * {@code LBL_<class-fqn>.<field_name>}, which will be used as the display name of
61.69 + * the corresponding checkbox in the customizer, and {@code TP_<class-fqn>.<field_name>}
61.70 + * which will be used as the tooltip of the checkbox.
61.71 + *
61.72 + * @author lahvac
61.73 + */
61.74 +@Retention(RetentionPolicy.SOURCE)
61.75 +@Target(ElementType.FIELD)
61.76 +public @interface BooleanOption {
61.77 +
61.78 + /**The options' display name. Will be used as the display name of the
61.79 + * checkbox in the customizer.
61.80 + */
61.81 + public String displayName();
61.82 + /**The tooltip of the checkbox in the customizer.
61.83 + */
61.84 + public String tooltip();
61.85 +
61.86 + /**The default value of the option.
61.87 + */
61.88 + public boolean defaultValue();
61.89 +
61.90 +}
62.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
62.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/Bundle.properties Wed May 08 21:47:42 2013 +0200
62.3 @@ -0,0 +1,7 @@
62.4 +#{0}: hint/suggestion name
62.5 +FIX_DisableHint=Disable "{0}" Hint
62.6 +FIX_ConfigureHint=Configure "{0}" Hint
62.7 +FIX_DisableSuggestion=Disable "{0}" Suggestion
62.8 +FIX_ConfigureSuggestion=Configure "{0}" Suggestion
62.9 +#{0}: Key of the warning
62.10 +LBL_FIX_Suppress_Waning=Suppress Warning - {0}
63.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
63.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/ConstraintVariableType.java Wed May 08 21:47:42 2013 +0200
63.3 @@ -0,0 +1,73 @@
63.4 +/*
63.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
63.6 + *
63.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
63.8 + *
63.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
63.10 + * Other names may be trademarks of their respective owners.
63.11 + *
63.12 + * The contents of this file are subject to the terms of either the GNU
63.13 + * General Public License Version 2 only ("GPL") or the Common
63.14 + * Development and Distribution License("CDDL") (collectively, the
63.15 + * "License"). You may not use this file except in compliance with the
63.16 + * License. You can obtain a copy of the License at
63.17 + * http://www.netbeans.org/cddl-gplv2.html
63.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
63.19 + * specific language governing permissions and limitations under the
63.20 + * License. When distributing the software, include this License Header
63.21 + * Notice in each file and include the License file at
63.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
63.23 + * particular file as subject to the "Classpath" exception as provided
63.24 + * by Oracle in the GPL Version 2 section of the License file that
63.25 + * accompanied this code. If applicable, add the following below the
63.26 + * License Header, with the fields enclosed by brackets [] replaced by
63.27 + * your own identifying information:
63.28 + * "Portions Copyrighted [year] [name of copyright owner]"
63.29 + *
63.30 + * If you wish your version of this file to be governed by only the CDDL
63.31 + * or only the GPL Version 2, indicate your decision by adding
63.32 + * "[Contributor] elects to include this software in this distribution
63.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
63.34 + * single choice of license, a recipient has the option to distribute
63.35 + * your version of this file under either the CDDL, the GPL Version 2 or
63.36 + * to extend the choice of license to its licensees as provided above.
63.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
63.38 + * Version 2 license, then the option applies only if the new code is
63.39 + * made subject to such option by the copyright holder.
63.40 + *
63.41 + * Contributor(s):
63.42 + *
63.43 + * Portions Copyrighted 2008-2009 Sun Microsystems, Inc.
63.44 + */
63.45 +
63.46 +package org.netbeans.spi.java.hints;
63.47 +
63.48 +import java.lang.annotation.Target;
63.49 +
63.50 +/**Specifies a type of a variable. During the matching process, only those
63.51 + * sections of the source code that have the given type are considered.
63.52 + *
63.53 + * @author Jan Lahoda
63.54 + */
63.55 +@Target({})
63.56 +public @interface ConstraintVariableType {
63.57 +
63.58 + /**Variable name, must start with the dollar sign (<code>$</code>).
63.59 + * Variable<code>$this</code> is automatically bound to the current class.
63.60 + */
63.61 + public String variable();
63.62 +
63.63 + /**The required type of the section of source code. The value must be a type
63.64 + * per JLS 4.1, i.e. a primitive type (JLS 4.2), or a reference type (JLS 4.3).
63.65 + * All elements of the type must be resolvable when written to any Java file,
63.66 + * they may not contain e.g. references to type variables, simple names, etc.
63.67 + *
63.68 + * The type may include any actual type arguments, including wildcard.
63.69 + *
63.70 + * While matching, the type of the tree that corresponds to the variable in
63.71 + * the actual occurrence candidate is accepted if it is assignable into the
63.72 + * variable defined by the attribute.
63.73 + */
63.74 + public String type();
63.75 +
63.76 +}
64.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
64.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/CustomizerProvider.java Wed May 08 21:47:42 2013 +0200
64.3 @@ -0,0 +1,66 @@
64.4 +/*
64.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
64.6 + *
64.7 + * Copyright 2010-2012 Oracle and/or its affiliates. All rights reserved.
64.8 + *
64.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
64.10 + * Other names may be trademarks of their respective owners.
64.11 + *
64.12 + * The contents of this file are subject to the terms of either the GNU
64.13 + * General Public License Version 2 only ("GPL") or the Common
64.14 + * Development and Distribution License("CDDL") (collectively, the
64.15 + * "License"). You may not use this file except in compliance with the
64.16 + * License. You can obtain a copy of the License at
64.17 + * http://www.netbeans.org/cddl-gplv2.html
64.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
64.19 + * specific language governing permissions and limitations under the
64.20 + * License. When distributing the software, include this License Header
64.21 + * Notice in each file and include the License file at
64.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
64.23 + * particular file as subject to the "Classpath" exception as provided
64.24 + * by Oracle in the GPL Version 2 section of the License file that
64.25 + * accompanied this code. If applicable, add the following below the
64.26 + * License Header, with the fields enclosed by brackets [] replaced by
64.27 + * your own identifying information:
64.28 + * "Portions Copyrighted [year] [name of copyright owner]"
64.29 + *
64.30 + * If you wish your version of this file to be governed by only the CDDL
64.31 + * or only the GPL Version 2, indicate your decision by adding
64.32 + * "[Contributor] elects to include this software in this distribution
64.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
64.34 + * single choice of license, a recipient has the option to distribute
64.35 + * your version of this file under either the CDDL, the GPL Version 2 or
64.36 + * to extend the choice of license to its licensees as provided above.
64.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
64.38 + * Version 2 license, then the option applies only if the new code is
64.39 + * made subject to such option by the copyright holder.
64.40 + *
64.41 + * Contributor(s):
64.42 + *
64.43 + * Portions Copyrighted 2010-2012 Sun Microsystems, Inc.
64.44 + */
64.45 +
64.46 +package org.netbeans.spi.java.hints;
64.47 +
64.48 +import java.util.prefs.Preferences;
64.49 +import javax.swing.JComponent;
64.50 +import org.netbeans.api.annotations.common.NonNull;
64.51 +
64.52 +/**A factory for hint customizer.
64.53 + *
64.54 + * @author lahvac
64.55 + */
64.56 +public interface CustomizerProvider {
64.57 +
64.58 + /**Create a customizer component. The hint settings are in the given
64.59 + * {@link Preferences}. The customizer can write into the provided {@link Preferences}
64.60 + * immediately, the values will be persisted or rolled-back automatically
64.61 + * based on the user's gesture.
64.62 + *
64.63 + * @param prefs the hints preferences from which the data to show should be read,
64.64 + * and to which the new settings should be written
64.65 + * @return a customizer component
64.66 + */
64.67 + public @NonNull JComponent getCustomizer(@NonNull Preferences prefs);
64.68 +
64.69 +}
65.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
65.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/ErrorDescriptionFactory.java Wed May 08 21:47:42 2013 +0200
65.3 @@ -0,0 +1,619 @@
65.4 +/*
65.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
65.6 + *
65.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
65.8 + *
65.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
65.10 + * Other names may be trademarks of their respective owners.
65.11 + *
65.12 + * The contents of this file are subject to the terms of either the GNU
65.13 + * General Public License Version 2 only ("GPL") or the Common
65.14 + * Development and Distribution License("CDDL") (collectively, the
65.15 + * "License"). You may not use this file except in compliance with the
65.16 + * License. You can obtain a copy of the License at
65.17 + * http://www.netbeans.org/cddl-gplv2.html
65.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
65.19 + * specific language governing permissions and limitations under the
65.20 + * License. When distributing the software, include this License Header
65.21 + * Notice in each file and include the License file at
65.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
65.23 + * particular file as subject to the "Classpath" exception as provided
65.24 + * by Oracle in the GPL Version 2 section of the License file that
65.25 + * accompanied this code. If applicable, add the following below the
65.26 + * License Header, with the fields enclosed by brackets [] replaced by
65.27 + * your own identifying information:
65.28 + * "Portions Copyrighted [year] [name of copyright owner]"
65.29 + *
65.30 + * If you wish your version of this file to be governed by only the CDDL
65.31 + * or only the GPL Version 2, indicate your decision by adding
65.32 + * "[Contributor] elects to include this software in this distribution
65.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
65.34 + * single choice of license, a recipient has the option to distribute
65.35 + * your version of this file under either the CDDL, the GPL Version 2 or
65.36 + * to extend the choice of license to its licensees as provided above.
65.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
65.38 + * Version 2 license, then the option applies only if the new code is
65.39 + * made subject to such option by the copyright holder.
65.40 + *
65.41 + * Contributor(s):
65.42 + *
65.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
65.44 + */
65.45 +
65.46 +package org.netbeans.spi.java.hints;
65.47 +
65.48 +import com.sun.source.tree.BlockTree;
65.49 +import com.sun.source.tree.ClassTree;
65.50 +import com.sun.source.tree.LiteralTree;
65.51 +import com.sun.source.tree.MemberSelectTree;
65.52 +import com.sun.source.tree.MethodInvocationTree;
65.53 +import com.sun.source.tree.MethodTree;
65.54 +import com.sun.source.tree.ModifiersTree;
65.55 +import com.sun.source.tree.StatementTree;
65.56 +import com.sun.source.tree.Tree;
65.57 +import com.sun.source.tree.Tree.Kind;
65.58 +import com.sun.source.tree.VariableTree;
65.59 +import com.sun.source.util.TreePath;
65.60 +import java.io.IOException;
65.61 +import java.util.Arrays;
65.62 +import java.util.Collection;
65.63 +import java.util.Collections;
65.64 +import java.util.EnumSet;
65.65 +import java.util.LinkedHashSet;
65.66 +import java.util.LinkedList;
65.67 +import java.util.List;
65.68 +import java.util.Set;
65.69 +import javax.lang.model.SourceVersion;
65.70 +import javax.lang.model.element.TypeElement;
65.71 +import javax.swing.SwingUtilities;
65.72 +import org.netbeans.api.annotations.common.NonNull;
65.73 +import org.netbeans.api.java.source.CompilationInfo;
65.74 +import org.netbeans.api.java.source.GeneratorUtilities;
65.75 +import org.netbeans.api.java.source.JavaSource;
65.76 +import org.netbeans.api.java.source.JavaSource.Phase;
65.77 +import org.netbeans.api.java.source.Task;
65.78 +import org.netbeans.api.java.source.TreePathHandle;
65.79 +import org.netbeans.api.java.source.WorkingCopy;
65.80 +import org.netbeans.api.lexer.TokenSequence;
65.81 +import org.netbeans.api.options.OptionsDisplayer;
65.82 +import org.netbeans.modules.analysis.api.CodeAnalysis;
65.83 +import org.netbeans.modules.analysis.spi.Analyzer.WarningDescription;
65.84 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
65.85 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata.Options;
65.86 +import org.netbeans.modules.java.hints.spiimpl.Hacks.InspectAndTransformOpener;
65.87 +import org.netbeans.modules.java.hints.spiimpl.SPIAccessor;
65.88 +import org.netbeans.modules.java.hints.spiimpl.SyntheticFix;
65.89 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
65.90 +import org.netbeans.spi.editor.hints.ChangeInfo;
65.91 +import org.netbeans.spi.editor.hints.EnhancedFix;
65.92 +import org.netbeans.spi.editor.hints.ErrorDescription;
65.93 +import org.netbeans.spi.editor.hints.Fix;
65.94 +import org.netbeans.spi.editor.hints.LazyFixList;
65.95 +import org.openide.filesystems.FileObject;
65.96 +import org.openide.util.Lookup;
65.97 +import org.openide.util.NbBundle;
65.98 +import org.openide.util.NbBundle.Messages;
65.99 +import org.openide.util.Parameters;
65.100 +
65.101 +/**
65.102 + *
65.103 + * @author Jan Lahoda
65.104 + */
65.105 +public class ErrorDescriptionFactory {
65.106 +
65.107 + private ErrorDescriptionFactory() {
65.108 + }
65.109 +
65.110 +// public static ErrorDescription forTree(HintContext context, String text, Fix... fixes) {
65.111 +// return forTree(context, context.getContext(), text, fixes);
65.112 +// }
65.113 +
65.114 + public static ErrorDescription forTree(HintContext context, TreePath tree, String text, Fix... fixes) {
65.115 + return forTree(context, tree.getLeaf(), text, fixes);
65.116 + }
65.117 +
65.118 + public static ErrorDescription forTree(HintContext context, Tree tree, String text, Fix... fixes) {
65.119 + int start;
65.120 + int end;
65.121 +
65.122 + if (context.getHintMetadata().kind == Hint.Kind.INSPECTION) {
65.123 + start = (int) context.getInfo().getTrees().getSourcePositions().getStartPosition(context.getInfo().getCompilationUnit(), tree);
65.124 + end = (int) context.getInfo().getTrees().getSourcePositions().getEndPosition(context.getInfo().getCompilationUnit(), tree);
65.125 + } else {
65.126 + start = end = context.getCaretLocation();
65.127 + }
65.128 +
65.129 + if (start != (-1) && end != (-1)) {
65.130 + LazyFixList fixesForED = org.netbeans.spi.editor.hints.ErrorDescriptionFactory.lazyListForFixes(resolveDefaultFixes(context, fixes));
65.131 + return org.netbeans.spi.editor.hints.ErrorDescriptionFactory.createErrorDescription("text/x-java:" + context.getHintMetadata().id, context.getSeverity(), text, context.getHintMetadata().description, fixesForED, context.getInfo().getFileObject(), start, end);
65.132 + }
65.133 +
65.134 + return null;
65.135 + }
65.136 +
65.137 + /**Create a new {@link ErrorDescription}. Severity is automatically inferred from the {@link HintContext},
65.138 + * and the {@link ErrorDescription} is created to be consistent with {@link ErrorDescription}s created
65.139 + * by the other factory methods in this class.
65.140 + *
65.141 + * @param context from which the {@link Severity} and other properties are inferred.
65.142 + * @param start start of the warning
65.143 + * @param end end of the warning
65.144 + * @param text the warning text
65.145 + * @param fixes one or more {@link Fix}es to show shown to the user.
65.146 + * @return a standard {@link ErrorDescription} for use in Java source
65.147 + * @since 1.9
65.148 + */
65.149 + public static ErrorDescription forSpan(HintContext context, int start, int end, String text, Fix... fixes) {
65.150 + if (context.getHintMetadata().kind != Hint.Kind.INSPECTION) {
65.151 + start = end = context.getCaretLocation();
65.152 + }
65.153 +
65.154 + if (start != (-1) && end != (-1)) {
65.155 + LazyFixList fixesForED = org.netbeans.spi.editor.hints.ErrorDescriptionFactory.lazyListForFixes(resolveDefaultFixes(context, fixes));
65.156 + return org.netbeans.spi.editor.hints.ErrorDescriptionFactory.createErrorDescription("text/x-java:" + context.getHintMetadata().id, context.getSeverity(), text, context.getHintMetadata().description, fixesForED, context.getInfo().getFileObject(), start, end);
65.157 + }
65.158 +
65.159 + return null;
65.160 + }
65.161 +
65.162 + public static ErrorDescription forName(HintContext context, TreePath tree, String text, Fix... fixes) {
65.163 + return forName(context, tree.getLeaf(), text, fixes);
65.164 + }
65.165 +
65.166 + public static ErrorDescription forName(HintContext context, Tree tree, String text, Fix... fixes) {
65.167 + int[] span;
65.168 +
65.169 + if (context.getHintMetadata().kind == Hint.Kind.INSPECTION) {
65.170 + span = computeNameSpan(tree, context);
65.171 + } else {
65.172 + span = new int[] {context.getCaretLocation(), context.getCaretLocation()};
65.173 + }
65.174 +
65.175 + if (span != null && span[0] != (-1) && span[1] != (-1)) {
65.176 + LazyFixList fixesForED = org.netbeans.spi.editor.hints.ErrorDescriptionFactory.lazyListForFixes(resolveDefaultFixes(context, fixes));
65.177 + return org.netbeans.spi.editor.hints.ErrorDescriptionFactory.createErrorDescription("text/x-java:" + context.getHintMetadata().id, context.getSeverity(), text, context.getHintMetadata().description, fixesForED, context.getInfo().getFileObject(), span[0], span[1]);
65.178 + }
65.179 +
65.180 + return null;
65.181 + }
65.182 +
65.183 + private static int[] computeNameSpan(Tree tree, HintContext context) {
65.184 + switch (tree.getKind()) {
65.185 + case METHOD:
65.186 + return context.getInfo().getTreeUtilities().findNameSpan((MethodTree) tree);
65.187 + case ANNOTATION_TYPE:
65.188 + case CLASS:
65.189 + case ENUM:
65.190 + case INTERFACE:
65.191 + return context.getInfo().getTreeUtilities().findNameSpan((ClassTree) tree);
65.192 + case VARIABLE:
65.193 + return context.getInfo().getTreeUtilities().findNameSpan((VariableTree) tree);
65.194 + case MEMBER_SELECT:
65.195 + //XXX:
65.196 + MemberSelectTree mst = (MemberSelectTree) tree;
65.197 + int[] span = context.getInfo().getTreeUtilities().findNameSpan(mst);
65.198 +
65.199 + if (span == null) {
65.200 + int end = (int) context.getInfo().getTrees().getSourcePositions().getEndPosition(context.getInfo().getCompilationUnit(), tree);
65.201 + span = new int[] {end - mst.getIdentifier().length(), end};
65.202 + }
65.203 + return span;
65.204 + case METHOD_INVOCATION:
65.205 + return computeNameSpan(((MethodInvocationTree) tree).getMethodSelect(), context);
65.206 + case BLOCK:
65.207 + Collection<? extends TreePath> prefix = context.getMultiVariables().get("$$1$");
65.208 +
65.209 + if (prefix != null) {
65.210 + BlockTree bt = (BlockTree) tree;
65.211 +
65.212 + if (bt.getStatements().size() > prefix.size()) {
65.213 + return computeNameSpan(bt.getStatements().get(prefix.size()), context);
65.214 + }
65.215 + }
65.216 + default:
65.217 + int start = (int) context.getInfo().getTrees().getSourcePositions().getStartPosition(context.getInfo().getCompilationUnit(), tree);
65.218 + if ( StatementTree.class.isAssignableFrom(tree.getKind().asInterface())
65.219 + && tree.getKind() != Kind.EXPRESSION_STATEMENT
65.220 + && tree.getKind() != Kind.BLOCK) {
65.221 + TokenSequence<?> ts = context.getInfo().getTokenHierarchy().tokenSequence();
65.222 + ts.move(start);
65.223 + if (ts.moveNext()) {
65.224 + return new int[] {ts.offset(), ts.offset() + ts.token().length()};
65.225 + }
65.226 + }
65.227 + return new int[] {
65.228 + start,
65.229 + (int) context.getInfo().getTrees().getSourcePositions().getEndPosition(context.getInfo().getCompilationUnit(), tree),
65.230 + };
65.231 + }
65.232 + }
65.233 +
65.234 + static List<Fix> resolveDefaultFixes(HintContext ctx, Fix... provided) {
65.235 + List<Fix> auxiliaryFixes = new LinkedList<Fix>();
65.236 + HintMetadata hm = SPIAccessor.getINSTANCE().getHintMetadata(ctx);
65.237 +
65.238 + if (hm != null) {
65.239 + Set<String> suppressWarningsKeys = new LinkedHashSet<String>();
65.240 +
65.241 + for (String key : hm.suppressWarnings) {
65.242 + if (key == null || key.length() == 0) {
65.243 + break;
65.244 + }
65.245 +
65.246 + suppressWarningsKeys.add(key);
65.247 + }
65.248 +
65.249 +
65.250 + auxiliaryFixes.add(new DisableConfigure(hm, true, SPIAccessor.getINSTANCE().getHintSettings(ctx)));
65.251 + auxiliaryFixes.add(new DisableConfigure(hm, false, null));
65.252 +
65.253 + if (hm.kind == Hint.Kind.INSPECTION) {
65.254 + auxiliaryFixes.add(new InspectFix(hm, false));
65.255 + if (!hm.options.contains(Options.QUERY)) {
65.256 + auxiliaryFixes.add(new InspectFix(hm, true));
65.257 + }
65.258 + }
65.259 +
65.260 + if (!suppressWarningsKeys.isEmpty()) {
65.261 + auxiliaryFixes.addAll(createSuppressWarnings(ctx.getInfo(), ctx.getPath(), suppressWarningsKeys.toArray(new String[0])));
65.262 + }
65.263 +
65.264 + List<Fix> result = new LinkedList<Fix>();
65.265 +
65.266 + for (Fix f : provided != null ? provided : new Fix[0]) {
65.267 + if (f == null) continue;
65.268 +
65.269 + result.add(org.netbeans.spi.editor.hints.ErrorDescriptionFactory.attachSubfixes(f, auxiliaryFixes));
65.270 + }
65.271 +
65.272 + if (result.isEmpty()) {
65.273 + result.add(org.netbeans.spi.editor.hints.ErrorDescriptionFactory.attachSubfixes(new TopLevelConfigureFix(hm), auxiliaryFixes));
65.274 + }
65.275 +
65.276 + return result;
65.277 + }
65.278 +
65.279 + return Arrays.asList(provided);
65.280 + }
65.281 +
65.282 + private static class DisableConfigure implements Fix, SyntheticFix {
65.283 + private final @NonNull HintMetadata metadata;
65.284 + private final boolean disable;
65.285 + private final HintsSettings hintsSettings;
65.286 +
65.287 + DisableConfigure(@NonNull HintMetadata metadata, boolean disable, HintsSettings hintsSettings) {
65.288 + this.metadata = metadata;
65.289 + this.disable = disable;
65.290 + this.hintsSettings = hintsSettings;
65.291 + }
65.292 +
65.293 + @Override
65.294 + public String getText() {
65.295 + String displayName = metadata.displayName;
65.296 + String key;
65.297 + switch (metadata.kind) {
65.298 + case INSPECTION:
65.299 + key = disable ? "FIX_DisableHint" : "FIX_ConfigureHint";
65.300 + break;
65.301 + case ACTION:
65.302 + key = disable ? "FIX_DisableSuggestion" : "FIX_ConfigureSuggestion";
65.303 + break;
65.304 + default:
65.305 + throw new IllegalStateException();
65.306 + }
65.307 +
65.308 + return NbBundle.getMessage(ErrorDescriptionFactory.class, key, displayName);
65.309 + }
65.310 +
65.311 + @Override
65.312 + public ChangeInfo implement() throws Exception {
65.313 + if (disable) {
65.314 + hintsSettings.setEnabled(metadata, false);
65.315 + //XXX: re-run hints task
65.316 + } else {
65.317 + OptionsDisplayer.getDefault().open("Editor/Hints/text/x-java/" + metadata.id);
65.318 + }
65.319 +
65.320 + return null;
65.321 + }
65.322 +
65.323 + @Override
65.324 + public boolean equals(Object obj) {
65.325 + if (obj == null) {
65.326 + return false;
65.327 + }
65.328 + if (this.getClass() != obj.getClass()) {
65.329 + return false;
65.330 + }
65.331 + final DisableConfigure other = (DisableConfigure) obj;
65.332 + if (this.metadata != other.metadata && (this.metadata == null || !this.metadata.equals(other.metadata))) {
65.333 + return false;
65.334 + }
65.335 + if (this.disable != other.disable) {
65.336 + return false;
65.337 + }
65.338 + return true;
65.339 + }
65.340 +
65.341 + @Override
65.342 + public int hashCode() {
65.343 + int hash = 7;
65.344 + hash = 43 * hash + (this.metadata != null ? this.metadata.hashCode() : 0);
65.345 + hash = 43 * hash + (this.disable ? 1 : 0);
65.346 + return hash;
65.347 + }
65.348 +
65.349 +
65.350 + }
65.351 +
65.352 + private static final class TopLevelConfigureFix extends DisableConfigure implements EnhancedFix {
65.353 +
65.354 + public TopLevelConfigureFix(@NonNull HintMetadata metadata) {
65.355 + super(metadata, false, null);
65.356 + }
65.357 +
65.358 + @Override
65.359 + public CharSequence getSortText() {
65.360 + return "\uFFFFzz";
65.361 + }
65.362 +
65.363 + }
65.364 +
65.365 + private static class InspectFix implements Fix, SyntheticFix {
65.366 + private final @NonNull HintMetadata metadata;
65.367 + private final boolean transform;
65.368 +
65.369 + InspectFix(@NonNull HintMetadata metadata, boolean transform) {
65.370 + this.metadata = metadata;
65.371 + this.transform = transform;
65.372 + }
65.373 +
65.374 + @Override
65.375 + @Messages({
65.376 + "DN_InspectAndTransform=Run Inspect&Transform on...",
65.377 + "DN_Inspect=Run Inspect on..."
65.378 + })
65.379 + public String getText() {
65.380 + return transform ? Bundle.DN_InspectAndTransform() : Bundle.DN_Inspect();
65.381 + }
65.382 +
65.383 + @Override
65.384 + public ChangeInfo implement() throws Exception {
65.385 + SwingUtilities.invokeLater(new Runnable() {
65.386 + @Override
65.387 + public void run() {
65.388 + if (transform) {
65.389 + final InspectAndTransformOpener o = Lookup.getDefault().lookup(InspectAndTransformOpener.class);
65.390 +
65.391 + if (o != null) {
65.392 + o.openIAT(metadata);
65.393 + } else {
65.394 + //warn
65.395 + }
65.396 + } else {
65.397 + CodeAnalysis.open(WarningDescription.create("text/x-java:" + metadata.id, null, null, null));
65.398 + }
65.399 + }
65.400 + });
65.401 +
65.402 + return null;
65.403 + }
65.404 +
65.405 + @Override
65.406 + public boolean equals(Object obj) {
65.407 + if (obj == null) {
65.408 + return false;
65.409 + }
65.410 + if (this.getClass() != obj.getClass()) {
65.411 + return false;
65.412 + }
65.413 + final InspectFix other = (InspectFix) obj;
65.414 + if (this.metadata != other.metadata && (this.metadata == null || !this.metadata.equals(other.metadata))) {
65.415 + return false;
65.416 + }
65.417 + if (this.transform != other.transform) {
65.418 + return false;
65.419 + }
65.420 + return true;
65.421 + }
65.422 +
65.423 + @Override
65.424 + public int hashCode() {
65.425 + int hash = 7;
65.426 + hash = 43 * hash + (this.metadata != null ? this.metadata.hashCode() : 0);
65.427 + hash = 43 * hash + (this.transform ? 1 : 0);
65.428 + return hash;
65.429 + }
65.430 +
65.431 +
65.432 + }
65.433 +
65.434 + /** Creates a fix, which when invoked adds @SuppresWarnings(keys) to
65.435 + * nearest declaration.
65.436 + * @param compilationInfo CompilationInfo to work on
65.437 + * @param treePath TreePath to a tree. The method will find nearest outer
65.438 + * declaration. (type, method, field or local variable)
65.439 + * @param keys keys to be contained in the SuppresWarnings annotation. E.g.
65.440 + * @SuppresWarnings( "key" ) or @SuppresWarnings( {"key1", "key2", ..., "keyN" } ).
65.441 + * @throws IllegalArgumentException if keys are null or empty or id no suitable element
65.442 + * to put the annotation on is found (e.g. if TreePath to CompilationUnit is given")
65.443 + */
65.444 + static Fix createSuppressWarningsFix(CompilationInfo compilationInfo, TreePath treePath, String... keys ) {
65.445 + Parameters.notNull("compilationInfo", compilationInfo);
65.446 + Parameters.notNull("treePath", treePath);
65.447 + Parameters.notNull("keys", keys);
65.448 +
65.449 + if (keys.length == 0) {
65.450 + throw new IllegalArgumentException("key must not be empty"); // NOI18N
65.451 + }
65.452 +
65.453 + if (!isSuppressWarningsSupported(compilationInfo)) {
65.454 + return null;
65.455 + }
65.456 +
65.457 + while (treePath.getLeaf().getKind() != Kind.COMPILATION_UNIT && !DECLARATION.contains(treePath.getLeaf().getKind())) {
65.458 + treePath = treePath.getParentPath();
65.459 + }
65.460 +
65.461 + if (treePath.getLeaf().getKind() != Kind.COMPILATION_UNIT) {
65.462 + return new FixImpl(TreePathHandle.create(treePath, compilationInfo), compilationInfo.getFileObject(), keys);
65.463 + } else {
65.464 + return null;
65.465 + }
65.466 + }
65.467 +
65.468 + /** Creates a fix, which when invoked adds @SuppresWarnings(keys) to
65.469 + * nearest declaration.
65.470 + * @param compilationInfo CompilationInfo to work on
65.471 + * @param treePath TreePath to a tree. The method will find nearest outer
65.472 + * declaration. (type, method, field or local variable)
65.473 + * @param keys keys to be contained in the SuppresWarnings annotation. E.g.
65.474 + * @SuppresWarnings( "key" ) or @SuppresWarnings( {"key1", "key2", ..., "keyN" } ).
65.475 + * @throws IllegalArgumentException if keys are null or empty or id no suitable element
65.476 + * to put the annotation on is found (e.g. if TreePath to CompilationUnit is given")
65.477 + */
65.478 + static List<Fix> createSuppressWarnings(CompilationInfo compilationInfo, TreePath treePath, String... keys ) {
65.479 + Parameters.notNull("compilationInfo", compilationInfo);
65.480 + Parameters.notNull("treePath", treePath);
65.481 + Parameters.notNull("keys", keys);
65.482 +
65.483 + if (keys.length == 0) {
65.484 + throw new IllegalArgumentException("key must not be empty"); // NOI18N
65.485 + }
65.486 +
65.487 + Fix f = createSuppressWarningsFix(compilationInfo, treePath, keys);
65.488 +
65.489 + if (f != null) {
65.490 + return Collections.<Fix>singletonList(f);
65.491 + } else {
65.492 + return Collections.emptyList();
65.493 + }
65.494 + }
65.495 +
65.496 + private static boolean isSuppressWarningsSupported(CompilationInfo info) {
65.497 + //cannot suppress if there is no SuppressWarnings annotation in the platform:
65.498 + if (info.getElements().getTypeElement("java.lang.SuppressWarnings") == null)
65.499 + return false;
65.500 +
65.501 + return info.getSourceVersion().compareTo(SourceVersion.RELEASE_5) >= 0;
65.502 + }
65.503 +
65.504 + private static final Set<Kind> DECLARATION = EnumSet.of(Kind.ANNOTATION_TYPE, Kind.CLASS, Kind.ENUM, Kind.INTERFACE, Kind.METHOD, Kind.VARIABLE);
65.505 +
65.506 + private static final class FixImpl implements Fix, SyntheticFix {
65.507 +
65.508 + private String keys[];
65.509 + private TreePathHandle handle;
65.510 + private FileObject file;
65.511 +
65.512 + public FixImpl(TreePathHandle handle, FileObject file, String... keys) {
65.513 + this.keys = keys;
65.514 + this.handle = handle;
65.515 + this.file = file;
65.516 + }
65.517 +
65.518 + public String getText() {
65.519 + StringBuilder keyNames = new StringBuilder();
65.520 + for (int i = 0; i < keys.length; i++) {
65.521 + String string = keys[i];
65.522 + keyNames.append(string);
65.523 + if ( i < keys.length - 1) {
65.524 + keyNames.append(", "); // NOI18N
65.525 + }
65.526 + }
65.527 +
65.528 + return NbBundle.getMessage(ErrorDescriptionFactory.class, "LBL_FIX_Suppress_Waning", keyNames.toString() ); // NOI18N
65.529 + }
65.530 +
65.531 + public ChangeInfo implement() throws IOException {
65.532 + JavaSource js = JavaSource.forFileObject(file);
65.533 +
65.534 + js.runModificationTask(new Task<WorkingCopy>() {
65.535 + public void run(WorkingCopy copy) throws IOException {
65.536 + copy.toPhase(Phase.RESOLVED); //XXX: performance
65.537 + TreePath path = handle.resolve(copy);
65.538 +
65.539 + while (path != null && path.getLeaf().getKind() != Kind.COMPILATION_UNIT && !DECLARATION.contains(path.getLeaf().getKind())) {
65.540 + path = path.getParentPath();
65.541 + }
65.542 +
65.543 + if (path.getLeaf().getKind() == Kind.COMPILATION_UNIT) {
65.544 + return ;
65.545 + }
65.546 +
65.547 + Tree top = path.getLeaf();
65.548 + ModifiersTree modifiers = null;
65.549 +
65.550 + switch (top.getKind()) {
65.551 + case ANNOTATION_TYPE:
65.552 + case CLASS:
65.553 + case ENUM:
65.554 + case INTERFACE:
65.555 + modifiers = ((ClassTree) top).getModifiers();
65.556 + break;
65.557 + case METHOD:
65.558 + modifiers = ((MethodTree) top).getModifiers();
65.559 + break;
65.560 + case VARIABLE:
65.561 + modifiers = ((VariableTree) top).getModifiers();
65.562 + break;
65.563 + default: assert false : "Unhandled Tree.Kind"; // NOI18N
65.564 + }
65.565 +
65.566 + if (modifiers == null) {
65.567 + return ;
65.568 + }
65.569 +
65.570 + TypeElement el = copy.getElements().getTypeElement("java.lang.SuppressWarnings"); // NOI18N
65.571 +
65.572 + if (el == null) {
65.573 + return ;
65.574 + }
65.575 +
65.576 + LiteralTree[] keyLiterals = new LiteralTree[keys.length];
65.577 +
65.578 + for (int i = 0; i < keys.length; i++) {
65.579 + keyLiterals[i] = copy.getTreeMaker().
65.580 + Literal(keys[i]);
65.581 + }
65.582 +
65.583 + ModifiersTree nueMods = GeneratorUtilities.get(copy).appendToAnnotationValue(modifiers, el, "value", keyLiterals);
65.584 +
65.585 + copy.rewrite(modifiers, nueMods);
65.586 + }
65.587 + }).commit();
65.588 +
65.589 + return null;
65.590 + }
65.591 +
65.592 + @Override
65.593 + public boolean equals(Object obj) {
65.594 + if (obj == null) {
65.595 + return false;
65.596 + }
65.597 + if (getClass() != obj.getClass()) {
65.598 + return false;
65.599 + }
65.600 + final FixImpl other = (FixImpl) obj;
65.601 + if (!Arrays.deepEquals(this.keys, other.keys)) {
65.602 + return false;
65.603 + }
65.604 + if (this.handle != other.handle && (this.handle == null || !this.handle.equals(other.handle))) {
65.605 + return false;
65.606 + }
65.607 + if (this.file != other.file && (this.file == null || !this.file.equals(other.file))) {
65.608 + return false;
65.609 + }
65.610 + return true;
65.611 + }
65.612 +
65.613 + @Override
65.614 + public int hashCode() {
65.615 + int hash = 5;
65.616 + hash = 79 * hash + Arrays.deepHashCode(this.keys);
65.617 + hash = 79 * hash + (this.handle != null ? this.handle.hashCode() : 0);
65.618 + hash = 79 * hash + (this.file != null ? this.file.hashCode() : 0);
65.619 + return hash;
65.620 + }
65.621 + }
65.622 +}
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/Hint.java Wed May 08 21:47:42 2013 +0200
66.3 @@ -0,0 +1,128 @@
66.4 +/*
66.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
66.6 + *
66.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
66.8 + *
66.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
66.10 + * Other names may be trademarks of their respective owners.
66.11 + *
66.12 + * The contents of this file are subject to the terms of either the GNU
66.13 + * General Public License Version 2 only ("GPL") or the Common
66.14 + * Development and Distribution License("CDDL") (collectively, the
66.15 + * "License"). You may not use this file except in compliance with the
66.16 + * License. You can obtain a copy of the License at
66.17 + * http://www.netbeans.org/cddl-gplv2.html
66.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
66.19 + * specific language governing permissions and limitations under the
66.20 + * License. When distributing the software, include this License Header
66.21 + * Notice in each file and include the License file at
66.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
66.23 + * particular file as subject to the "Classpath" exception as provided
66.24 + * by Oracle in the GPL Version 2 section of the License file that
66.25 + * accompanied this code. If applicable, add the following below the
66.26 + * License Header, with the fields enclosed by brackets [] replaced by
66.27 + * your own identifying information:
66.28 + * "Portions Copyrighted [year] [name of copyright owner]"
66.29 + *
66.30 + * If you wish your version of this file to be governed by only the CDDL
66.31 + * or only the GPL Version 2, indicate your decision by adding
66.32 + * "[Contributor] elects to include this software in this distribution
66.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
66.34 + * single choice of license, a recipient has the option to distribute
66.35 + * your version of this file under either the CDDL, the GPL Version 2 or
66.36 + * to extend the choice of license to its licensees as provided above.
66.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
66.38 + * Version 2 license, then the option applies only if the new code is
66.39 + * made subject to such option by the copyright holder.
66.40 + *
66.41 + * Contributor(s):
66.42 + *
66.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
66.44 + */
66.45 +
66.46 +package org.netbeans.spi.java.hints;
66.47 +
66.48 +import java.lang.annotation.ElementType;
66.49 +import java.lang.annotation.Retention;
66.50 +import java.lang.annotation.RetentionPolicy;
66.51 +import java.lang.annotation.Target;
66.52 +import org.netbeans.spi.editor.hints.Severity;
66.53 +
66.54 +/** Description of a hint.
66.55 + * When applied to a class, any enclosed method marked with a trigger
66.56 + * will be considered to be part of this hint. When applied to a method, only this specific
66.57 + * method will be considered to the part of the hint.
66.58 + * Currently recognized triggers include {@link TriggerPattern} and {@link TriggerTreeKind}.
66.59 + * @author lahvac, Petr Hrebejk
66.60 + */
66.61 +@Target({ElementType.TYPE, ElementType.METHOD})
66.62 +@Retention(RetentionPolicy.SOURCE)
66.63 +public @interface Hint {
66.64 + /**Manually specify the hint's id. Use only reorganizing code to keep compatibility with settings
66.65 + * from previous version. Id will be generated automatically is not specified.
66.66 + */
66.67 + public String id() default "";
66.68 + /** The hint's display name.
66.69 + */
66.70 + public String displayName();
66.71 + /** The hint's long description.
66.72 + */
66.73 + public String description();
66.74 + /**Category where the hint belongs.
66.75 + */
66.76 + public String category();
66.77 + /**Should the hint be enabled by default?*/
66.78 + public boolean enabled() default true;
66.79 + /**Default severity of the hint. {@link Severity#HINT} will typically be shown
66.80 + * only on the line with the caret.*/
66.81 + public Severity severity() default Severity.VERIFIER;
66.82 + /**Suppress warnings keys that should automatically suppress the hint.*/
66.83 + public String[] suppressWarnings() default {};
66.84 + /**A customizer that allows to customize hint's preferences.
66.85 + */
66.86 + public Class<? extends CustomizerProvider> customizerProvider() default CustomizerProvider.class;
66.87 + /**Whether the hint should be considered an {@link Kind#INSPECTION inspection}, i.e. it detects a code smell,
66.88 + * or otherwise leads to improving the code, or a {@link Kind#SUGGESTION}, which is simply
66.89 + * an offer to do automatically do something for the user.
66.90 + */
66.91 + public Kind hintKind() default Kind.INSPECTION;
66.92 + /**Specify various options for the hint*/
66.93 + public Options[] options() default {};
66.94 +
66.95 + /**Whether the hint should be considered a {@link Kind#HINT hint}, e.g. it
66.96 + * detects a code smell, or otherwise leads to improving the code, or a {@link Kind#ACTION},
66.97 + * which is simply an offer to do automatically do something for the user.
66.98 + */
66.99 + public enum Kind {
66.100 + /**The hint represents a code-smell detector, or alike. It marks code that
66.101 + * is not correct (in some sense).
66.102 + */
66.103 + INSPECTION,
66.104 +
66.105 + /**The hint represents an offer to the user to automatically alter the code.
66.106 + * The transformation is not intended to improve the code, only allow the
66.107 + * user to do some kind of code transformation quickly.
66.108 + *
66.109 + * The only meaningful severity for suggestions if {@link Severity#CURRENT_LINE_WARNING}.
66.110 + */
66.111 + ACTION;
66.112 + }
66.113 +
66.114 + /**Various options to altering the behavior of the hint.
66.115 + */
66.116 + public enum Options {
66.117 + /**The hint does not produce any automatic transformations that could be run
66.118 + * inside the Inspect&Refactor dialog.
66.119 + */
66.120 + QUERY,
66.121 + /**The hint cannot be run inside the Inspect&Refactor dialog.
66.122 + */
66.123 + NO_BATCH,
66.124 + /**
66.125 + * The hint requires heavyweight processing so it should be run explicitly only by Inspect, Refactor (or similar)
66.126 + * features
66.127 + */
66.128 + HEAVY;
66.129 + }
66.130 +
66.131 +}
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/HintContext.java Wed May 08 21:47:42 2013 +0200
67.3 @@ -0,0 +1,197 @@
67.4 +/*
67.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
67.6 + *
67.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
67.8 + *
67.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
67.10 + * Other names may be trademarks of their respective owners.
67.11 + *
67.12 + * The contents of this file are subject to the terms of either the GNU
67.13 + * General Public License Version 2 only ("GPL") or the Common
67.14 + * Development and Distribution License("CDDL") (collectively, the
67.15 + * "License"). You may not use this file except in compliance with the
67.16 + * License. You can obtain a copy of the License at
67.17 + * http://www.netbeans.org/cddl-gplv2.html
67.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
67.19 + * specific language governing permissions and limitations under the
67.20 + * License. When distributing the software, include this License Header
67.21 + * Notice in each file and include the License file at
67.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
67.23 + * particular file as subject to the "Classpath" exception as provided
67.24 + * by Oracle in the GPL Version 2 section of the License file that
67.25 + * accompanied this code. If applicable, add the following below the
67.26 + * License Header, with the fields enclosed by brackets [] replaced by
67.27 + * your own identifying information:
67.28 + * "Portions Copyrighted [year] [name of copyright owner]"
67.29 + *
67.30 + * If you wish your version of this file to be governed by only the CDDL
67.31 + * or only the GPL Version 2, indicate your decision by adding
67.32 + * "[Contributor] elects to include this software in this distribution
67.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
67.34 + * single choice of license, a recipient has the option to distribute
67.35 + * your version of this file under either the CDDL, the GPL Version 2 or
67.36 + * to extend the choice of license to its licensees as provided above.
67.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
67.38 + * Version 2 license, then the option applies only if the new code is
67.39 + * made subject to such option by the copyright holder.
67.40 + *
67.41 + * Contributor(s):
67.42 + *
67.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
67.44 + */
67.45 +
67.46 +package org.netbeans.spi.java.hints;
67.47 +
67.48 +import com.sun.source.util.TreePath;
67.49 +import java.util.Collection;
67.50 +import java.util.Collections;
67.51 +import java.util.HashMap;
67.52 +import java.util.LinkedList;
67.53 +import java.util.Map;
67.54 +import java.util.concurrent.atomic.AtomicBoolean;
67.55 +import java.util.prefs.Preferences;
67.56 +import javax.lang.model.type.TypeMirror;
67.57 +import org.netbeans.api.java.source.CompilationInfo;
67.58 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
67.59 +import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
67.60 +import org.netbeans.modules.java.hints.spiimpl.SPIAccessor;
67.61 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
67.62 +import org.netbeans.spi.editor.hints.Severity;
67.63 +import org.netbeans.spi.java.hints.Hint.Kind;
67.64 +
67.65 +/**
67.66 + *
67.67 + * @author Jan Lahoda
67.68 + */
67.69 +public class HintContext {
67.70 +
67.71 + private final CompilationInfo info;
67.72 + private final HintsSettings settings;
67.73 + private final Preferences preferences;
67.74 + private final Severity severity;
67.75 + private final HintMetadata metadata;
67.76 + private final TreePath path;
67.77 + private final Map<String, TreePath> variables;
67.78 + private final Map<String, Collection<? extends TreePath>> multiVariables;
67.79 + private final Map<String, String> variableNames;
67.80 + private final Collection<? super MessageImpl> messages;
67.81 + private final Map<String, TypeMirror> constraints;
67.82 + private final boolean bulkMode;
67.83 + private final AtomicBoolean cancel;
67.84 + private final int caret;
67.85 +
67.86 + private HintContext(CompilationInfo info, HintsSettings settings, HintMetadata metadata, TreePath path, Map<String, TreePath> variables, Map<String, Collection<? extends TreePath>> multiVariables, Map<String, String> variableNames, Map<String, TypeMirror> constraints, Collection<? super MessageImpl> problems, boolean bulkMode, AtomicBoolean cancel, int caret) {
67.87 + this.info = info;
67.88 + this.settings = settings;
67.89 + this.preferences = metadata != null ? settings.getHintPreferences(metadata) : null;
67.90 + this.severity = preferences != null ? settings.getSeverity(metadata) : Severity.ERROR;
67.91 + this.metadata = metadata;
67.92 + this.path = path;
67.93 +
67.94 + variables = new HashMap<String, TreePath>(variables);
67.95 + variables.put("$_", path);
67.96 +
67.97 + this.variables = variables;
67.98 + this.multiVariables = multiVariables;
67.99 + this.variableNames = variableNames;
67.100 + this.messages = problems;
67.101 + this.constraints = constraints;
67.102 + this.bulkMode = bulkMode;
67.103 + this.cancel = cancel;
67.104 + this.caret = caret;
67.105 + }
67.106 +
67.107 + public CompilationInfo getInfo() {
67.108 + return info;
67.109 + }
67.110 +
67.111 + public Preferences getPreferences() {
67.112 + return preferences;
67.113 + }
67.114 +
67.115 + public Severity getSeverity() {
67.116 + return severity;
67.117 + }
67.118 +
67.119 + public TreePath getPath() {
67.120 + return path;
67.121 + }
67.122 +
67.123 + public Map<String, TreePath> getVariables() {
67.124 + return variables;
67.125 + }
67.126 +
67.127 + public Map<String, Collection<? extends TreePath>> getMultiVariables() {
67.128 + return multiVariables;
67.129 + }
67.130 +
67.131 + public Map<String, String> getVariableNames() {
67.132 + return variableNames;
67.133 + }
67.134 +
67.135 + HintMetadata getHintMetadata() {
67.136 + return metadata;
67.137 + }
67.138 +
67.139 + //TODO: not sure it should be here:
67.140 + public Map<String, TypeMirror> getConstraints() {
67.141 + return constraints;
67.142 + }
67.143 +
67.144 + /**
67.145 + * Will be used only for refactoring(s), will be ignored for hints.
67.146 + *
67.147 + * @param kind
67.148 + * @param text
67.149 + */
67.150 + public void reportMessage(MessageKind kind, String text) {
67.151 + messages.add(new MessageImpl(kind, text));
67.152 + }
67.153 +
67.154 + /**Returns {@code true} if the hint is being run in over many files, {@code false}
67.155 + * if only the file opened in the editor is being inspected.
67.156 + *
67.157 + * @return {@code true} if the hint is being run in over many files.
67.158 + */
67.159 + public boolean isBulkMode() {
67.160 + return bulkMode;
67.161 + }
67.162 +
67.163 + /**Returns {@code true} if the computation has been canceled.
67.164 + *
67.165 + * @return {@code true} if the computation has been canceled.
67.166 + */
67.167 + public boolean isCanceled() {
67.168 + return cancel.get();
67.169 + }
67.170 +
67.171 + /**For suggestions, returns the caret location for the editor
67.172 + * for which the suggestion is being computed. Returns -1 for hints.
67.173 + *
67.174 + * @return for suggestions, returns the caret location, -1 otherwise
67.175 + */
67.176 + public int getCaretLocation() {
67.177 + return metadata.kind == Kind.ACTION ? caret : -1;
67.178 + }
67.179 +
67.180 + public enum MessageKind {
67.181 + WARNING, ERROR;
67.182 + }
67.183 +
67.184 + static {
67.185 + SPIAccessor.setINSTANCE(new SPIAccessor() {
67.186 + @Override public HintContext createHintContext(CompilationInfo info, HintsSettings settings, HintMetadata metadata, TreePath path, Map<String, TreePath> variables, Map<String, Collection<? extends TreePath>> multiVariables, Map<String, String> variableNames, Map<String, TypeMirror> constraints, Collection<? super MessageImpl> problems, boolean bulkMode, AtomicBoolean cancel, int caret) {
67.187 + return new HintContext(info, settings, metadata, path, variables, multiVariables, variableNames, constraints, problems, bulkMode, cancel, caret);
67.188 + }
67.189 + @Override public HintContext createHintContext(CompilationInfo info, HintsSettings settings, HintMetadata metadata, TreePath path, Map<String, TreePath> variables, Map<String, Collection<? extends TreePath>> multiVariables, Map<String, String> variableNames) {
67.190 + return new HintContext(info, settings, metadata, path, variables, multiVariables, variableNames, Collections.<String, TypeMirror>emptyMap(), new LinkedList<MessageImpl>(), false, new AtomicBoolean(), -1);
67.191 + }
67.192 + @Override public HintMetadata getHintMetadata(HintContext ctx) {
67.193 + return ctx.getHintMetadata();
67.194 + }
67.195 + @Override public HintsSettings getHintSettings(HintContext ctx) {
67.196 + return ctx.settings;
67.197 + }
67.198 + });
67.199 + }
67.200 +}
68.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
68.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/HintSeverity.java Wed May 08 21:47:42 2013 +0200
68.3 @@ -0,0 +1,69 @@
68.4 +/*
68.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
68.6 + *
68.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
68.8 + *
68.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
68.10 + * Other names may be trademarks of their respective owners.
68.11 + *
68.12 + * The contents of this file are subject to the terms of either the GNU
68.13 + * General Public License Version 2 only ("GPL") or the Common
68.14 + * Development and Distribution License("CDDL") (collectively, the
68.15 + * "License"). You may not use this file except in compliance with the
68.16 + * License. You can obtain a copy of the License at
68.17 + * http://www.netbeans.org/cddl-gplv2.html
68.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
68.19 + * specific language governing permissions and limitations under the
68.20 + * License. When distributing the software, include this License Header
68.21 + * Notice in each file and include the License file at
68.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
68.23 + * particular file as subject to the "Classpath" exception as provided
68.24 + * by Oracle in the GPL Version 2 section of the License file that
68.25 + * accompanied this code. If applicable, add the following below the
68.26 + * License Header, with the fields enclosed by brackets [] replaced by
68.27 + * your own identifying information:
68.28 + * "Portions Copyrighted [year] [name of copyright owner]"
68.29 + *
68.30 + * If you wish your version of this file to be governed by only the CDDL
68.31 + * or only the GPL Version 2, indicate your decision by adding
68.32 + * "[Contributor] elects to include this software in this distribution
68.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
68.34 + * single choice of license, a recipient has the option to distribute
68.35 + * your version of this file under either the CDDL, the GPL Version 2 or
68.36 + * to extend the choice of license to its licensees as provided above.
68.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
68.38 + * Version 2 license, then the option applies only if the new code is
68.39 + * made subject to such option by the copyright holder.
68.40 + *
68.41 + * Contributor(s):
68.42 + *
68.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
68.44 + */
68.45 +package org.netbeans.spi.java.hints;
68.46 +
68.47 +import org.netbeans.spi.editor.hints.Severity;
68.48 +
68.49 +/** Severity of hint
68.50 + * <li><code>ERROR</code> - will show up as error
68.51 + * <li><code>WARNING</code> - will show up as warning
68.52 + * <li><code>CURRENT_LINE_WARNING</code> - will only show up when the caret is placed in the erroneous element
68.53 + * @author Petr Hrebejk
68.54 + */
68.55 +public enum HintSeverity {
68.56 + ERROR,
68.57 + WARNING,
68.58 + CURRENT_LINE_WARNING;
68.59 +
68.60 + public Severity toEditorSeverity() {
68.61 + switch ( this ) {
68.62 + case ERROR:
68.63 + return Severity.ERROR;
68.64 + case WARNING:
68.65 + return Severity.VERIFIER;
68.66 + case CURRENT_LINE_WARNING:
68.67 + return Severity.HINT;
68.68 + default:
68.69 + return null;
68.70 + }
68.71 + }
68.72 +}
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/IntegerOption.java Wed May 08 21:47:42 2013 +0200
69.3 @@ -0,0 +1,99 @@
69.4 +/*
69.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
69.6 + *
69.7 + * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
69.8 + *
69.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
69.10 + * Other names may be trademarks of their respective owners.
69.11 + *
69.12 + * The contents of this file are subject to the terms of either the GNU
69.13 + * General Public License Version 2 only ("GPL") or the Common
69.14 + * Development and Distribution License("CDDL") (collectively, the
69.15 + * "License"). You may not use this file except in compliance with the
69.16 + * License. You can obtain a copy of the License at
69.17 + * http://www.netbeans.org/cddl-gplv2.html
69.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
69.19 + * specific language governing permissions and limitations under the
69.20 + * License. When distributing the software, include this License Header
69.21 + * Notice in each file and include the License file at
69.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
69.23 + * particular file as subject to the "Classpath" exception as provided
69.24 + * by Oracle in the GPL Version 2 section of the License file that
69.25 + * accompanied this code. If applicable, add the following below the
69.26 + * License Header, with the fields enclosed by brackets [] replaced by
69.27 + * your own identifying information:
69.28 + * "Portions Copyrighted [year] [name of copyright owner]"
69.29 + *
69.30 + * If you wish your version of this file to be governed by only the CDDL
69.31 + * or only the GPL Version 2, indicate your decision by adding
69.32 + * "[Contributor] elects to include this software in this distribution
69.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
69.34 + * single choice of license, a recipient has the option to distribute
69.35 + * your version of this file under either the CDDL, the GPL Version 2 or
69.36 + * to extend the choice of license to its licensees as provided above.
69.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
69.38 + * Version 2 license, then the option applies only if the new code is
69.39 + * made subject to such option by the copyright holder.
69.40 + *
69.41 + * Contributor(s):
69.42 + *
69.43 + * Portions Copyrighted 2013 Sun Microsystems, Inc.
69.44 + */
69.45 +package org.netbeans.spi.java.hints;
69.46 +
69.47 +import java.lang.annotation.Documented;
69.48 +import java.lang.annotation.ElementType;
69.49 +import java.lang.annotation.Retention;
69.50 +import java.lang.annotation.RetentionPolicy;
69.51 +import java.lang.annotation.Target;
69.52 +
69.53 +/**
69.54 + * Declares an int-value option that affects hint processing.
69.55 + * If the Hint mixes integer and boolean options, the integer options
69.56 + * come first, boolean second in the UI.
69.57 + *
69.58 + * @author sdedic
69.59 + */
69.60 +@Retention(RetentionPolicy.SOURCE)
69.61 +@Target(ElementType.FIELD)
69.62 +@Documented
69.63 +public @interface IntegerOption {
69.64 + /**
69.65 + * @return Display name of the option
69.66 + */
69.67 + public String displayName();
69.68 +
69.69 + /**
69.70 + * @return tooltip for mouse hover over the option
69.71 + */
69.72 + public String tooltip() default "";
69.73 +
69.74 + /**
69.75 + * @return default value for the option
69.76 + */
69.77 + public int defaultValue() default 0;
69.78 +
69.79 + /**
69.80 + * Minimum value for the option. If Integer.MIN_VALUE (the default),
69.81 + * no minimum will be enforced.
69.82 + *
69.83 + * @return minimum value.
69.84 + */
69.85 + public int minValue() default 0;
69.86 +
69.87 + /**
69.88 + * Maximum value for the option. If Integer.MAX_VALUE (the default),
69.89 + * no maximum will be enforced. Please do choose a reasonable maximum value,
69.90 + * as the UI may size the input box to accommodate all digits of the maximum
69.91 + * permitted value, and the input box may seem unreasonably large.
69.92 + *
69.93 + * @return maximum value
69.94 + */
69.95 + public int maxValue() default Integer.MAX_VALUE;
69.96 +
69.97 + /**
69.98 + * If non-zero, a spinner will be created with the specified step. If zero (the default),
69.99 + * a plain input will be presented. Negative values are not accepted at the moment and are reserved.
69.100 + */
69.101 + public int step() default 0;
69.102 +}
70.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
70.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/JavaFix.java Wed May 08 21:47:42 2013 +0200
70.3 @@ -0,0 +1,328 @@
70.4 +/*
70.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
70.6 + *
70.7 + * Copyright 2008-2012 Oracle and/or its affiliates. All rights reserved.
70.8 + *
70.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
70.10 + * Other names may be trademarks of their respective owners.
70.11 + *
70.12 + * The contents of this file are subject to the terms of either the GNU
70.13 + * General Public License Version 2 only ("GPL") or the Common
70.14 + * Development and Distribution License("CDDL") (collectively, the
70.15 + * "License"). You may not use this file except in compliance with the
70.16 + * License. You can obtain a copy of the License at
70.17 + * http://www.netbeans.org/cddl-gplv2.html
70.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
70.19 + * specific language governing permissions and limitations under the
70.20 + * License. When distributing the software, include this License Header
70.21 + * Notice in each file and include the License file at
70.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
70.23 + * particular file as subject to the "Classpath" exception as provided
70.24 + * by Oracle in the GPL Version 2 section of the License file that
70.25 + * accompanied this code. If applicable, add the following below the
70.26 + * License Header, with the fields enclosed by brackets [] replaced by
70.27 + * your own identifying information:
70.28 + * "Portions Copyrighted [year] [name of copyright owner]"
70.29 + *
70.30 + * If you wish your version of this file to be governed by only the CDDL
70.31 + * or only the GPL Version 2, indicate your decision by adding
70.32 + * "[Contributor] elects to include this software in this distribution
70.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
70.34 + * single choice of license, a recipient has the option to distribute
70.35 + * your version of this file under either the CDDL, the GPL Version 2 or
70.36 + * to extend the choice of license to its licensees as provided above.
70.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
70.38 + * Version 2 license, then the option applies only if the new code is
70.39 + * made subject to such option by the copyright holder.
70.40 + *
70.41 + * Contributor(s):
70.42 + *
70.43 + * Portions Copyrighted 2008-2012 Sun Microsystems, Inc.
70.44 + */
70.45 +
70.46 +package org.netbeans.spi.java.hints;
70.47 +
70.48 +import com.sun.source.util.TreePath;
70.49 +import java.io.ByteArrayInputStream;
70.50 +import java.io.ByteArrayOutputStream;
70.51 +import java.io.IOException;
70.52 +import java.io.InputStream;
70.53 +import java.io.OutputStream;
70.54 +import java.nio.ByteBuffer;
70.55 +import java.util.Collection;
70.56 +import java.util.Collections;
70.57 +import java.util.HashMap;
70.58 +import java.util.List;
70.59 +import java.util.Map;
70.60 +import java.util.logging.Level;
70.61 +import java.util.logging.Logger;
70.62 +import javax.lang.model.type.TypeMirror;
70.63 +import javax.swing.text.BadLocationException;
70.64 +import javax.swing.text.Document;
70.65 +import org.netbeans.api.annotations.common.CheckForNull;
70.66 +import org.netbeans.api.annotations.common.NonNull;
70.67 +import org.netbeans.api.java.source.CompilationInfo;
70.68 +import org.netbeans.api.java.source.TreePathHandle;
70.69 +import org.netbeans.api.java.source.WorkingCopy;
70.70 +import org.netbeans.api.queries.FileEncodingQuery;
70.71 +import org.netbeans.modules.java.hints.spiimpl.JavaFixImpl;
70.72 +import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
70.73 +import org.netbeans.spi.editor.hints.ChangeInfo;
70.74 +import org.netbeans.spi.editor.hints.Fix;
70.75 +import org.openide.cookies.EditorCookie;
70.76 +import org.openide.filesystems.FileObject;
70.77 +import org.openide.loaders.DataObject;
70.78 +import org.openide.loaders.DataObjectNotFoundException;
70.79 +import org.openide.util.Exceptions;
70.80 +import org.openide.util.Parameters;
70.81 +
70.82 +/**A base class for fixes that modify Java source code. Using this class
70.83 + * as a base class makes creating the fix somewhat simpler, but also supports
70.84 + * running the hint in the Inspect&Transform dialog. The fix can be converted
70.85 + * to {@link Fix} by means of the {@link #toEditorFix() } method.
70.86 + *
70.87 + * @see JavaFixUtilities for various predefined fixes.
70.88 + * @author Jan Lahoda
70.89 + */
70.90 +public abstract class JavaFix {
70.91 +
70.92 + private final TreePathHandle handle;
70.93 + private final Map<String, String> options;
70.94 +
70.95 + /**Create JavaFix with the given base {@link TreePath}. The base {@link TreePath}
70.96 + * will be passed back to the real implementation of the fix.
70.97 + *
70.98 + * @param info a {@link CompilationInfo} from which the given {@link TreePath} originates
70.99 + * @param tp a {@link TreePath} that will be passed back to the
70.100 + * {@link #performRewrite(org.netbeans.spi.java.hints.JavaFix.TransformationContext) } method
70.101 + */
70.102 + protected JavaFix(@NonNull CompilationInfo info, @NonNull TreePath tp) {
70.103 + this(info, tp, Collections.<String, String>emptyMap());
70.104 + }
70.105 +
70.106 + JavaFix(CompilationInfo info, TreePath tp, Map<String, String> options) {
70.107 + this.handle = TreePathHandle.create(tp, info);
70.108 + this.options = Collections.unmodifiableMap(new HashMap<String, String>(options));
70.109 + }
70.110 +
70.111 + /**Create JavaFix with the given base {@link TreePathHandle}. The base {@link TreePathHandle}
70.112 + * will be resolved and passed back to the real implementation of the fix.
70.113 + *
70.114 + * @param handle a {@link TreePathHandle} that will be resolved and passed back to the
70.115 + * {@link #performRewrite(org.netbeans.spi.java.hints.JavaFix.TransformationContext) } method
70.116 + */
70.117 + protected JavaFix(@NonNull TreePathHandle handle) {
70.118 + this(handle, Collections.<String, String>emptyMap());
70.119 + }
70.120 +
70.121 + JavaFix(TreePathHandle handle, Map<String, String> options) {
70.122 + this.handle = handle;
70.123 + this.options = Collections.unmodifiableMap(new HashMap<String, String>(options));
70.124 + }
70.125 +
70.126 + /**The display text of the fix.
70.127 + *
70.128 + * @return the display text of the fix.
70.129 + */
70.130 + protected abstract @NonNull String getText();
70.131 +
70.132 + /**Do the transformations needed to implement the hint's function.
70.133 + *
70.134 + * @param ctx a context over which the fix should operate
70.135 + * @throws Exception if something goes wrong while performing the transformation
70.136 + * - will be logged by the infrastructure
70.137 + */
70.138 + protected abstract void performRewrite(@NonNull TransformationContext ctx) throws Exception;
70.139 +
70.140 + /**Convert this {@link JavaFix} into the Editor Hints {@link Fix}.
70.141 + *
70.142 + * @return a {@link Fix}, that when invoked, will invoke {@link #performRewrite(org.netbeans.spi.java.hints.JavaFix.TransformationContext) }
70.143 + * method on this {@link JavaFix}.
70.144 + */
70.145 + public final Fix toEditorFix() {
70.146 + return new JavaFixImpl(this);
70.147 + }
70.148 +
70.149 + static {
70.150 + JavaFixImpl.Accessor.INSTANCE = new JavaFixImpl.Accessor() {
70.151 + @Override
70.152 + public String getText(JavaFix jf) {
70.153 + return jf.getText();
70.154 + }
70.155 + @Override
70.156 + public ChangeInfo process(JavaFix jf, WorkingCopy wc, boolean canShowUI, Map<FileObject, byte[]> resourceContent, Collection<? super RefactoringElementImplementation> fileChanges) throws Exception {
70.157 + TreePath tp = jf.handle.resolve(wc);
70.158 +
70.159 + if (tp == null) {
70.160 + Logger.getLogger(JavaFix.class.getName()).log(Level.SEVERE, "Cannot resolve handle={0}", jf.handle);
70.161 + return null;
70.162 + }
70.163 +
70.164 + jf.performRewrite(new TransformationContext(wc, tp, canShowUI, resourceContent, fileChanges));
70.165 +
70.166 + return null;
70.167 + }
70.168 + @Override
70.169 + public FileObject getFile(JavaFix jf) {
70.170 + return jf.handle.getFileObject();
70.171 + }
70.172 + @Override
70.173 + public Map<String, String> getOptions(JavaFix jf) {
70.174 + return jf.options;
70.175 + }
70.176 +
70.177 + @Override
70.178 + public Fix rewriteFix(CompilationInfo info, String displayName, TreePath what, String to, Map<String, TreePath> parameters, Map<String, Collection<? extends TreePath>> parametersMulti, Map<String, String> parameterNames, Map<String, TypeMirror> constraints, Map<String, String> options, String... imports) {
70.179 + return JavaFixUtilities.rewriteFix(info, displayName, what, to, parameters, parametersMulti, parameterNames, constraints, options, imports);
70.180 + }
70.181 +
70.182 + @Override
70.183 + public Fix createSuppressWarningsFix(CompilationInfo compilationInfo, TreePath treePath, String... keys) {
70.184 + return ErrorDescriptionFactory.createSuppressWarningsFix(compilationInfo, treePath, keys);
70.185 + }
70.186 +
70.187 + @Override
70.188 + public List<Fix> createSuppressWarnings(CompilationInfo compilationInfo, TreePath treePath, String... keys) {
70.189 + return ErrorDescriptionFactory.createSuppressWarnings(compilationInfo, treePath, keys);
70.190 + }
70.191 +
70.192 + @Override
70.193 + public List<Fix> resolveDefaultFixes(HintContext ctx, Fix... provided) {
70.194 + return ErrorDescriptionFactory.resolveDefaultFixes(ctx, provided);
70.195 + }
70.196 + };
70.197 + }
70.198 +
70.199 + /**A context that contains a reference to a {@link WorkingCopy} through which
70.200 + * modifications of Java source code can be made.
70.201 + *
70.202 + */
70.203 + public static final class TransformationContext {
70.204 + private final WorkingCopy workingCopy;
70.205 + private final TreePath path;
70.206 + private final boolean canShowUI;
70.207 + private final Map<FileObject, byte[]> resourceContentChanges;
70.208 + private final Collection<? super RefactoringElementImplementation> fileChanges;
70.209 + TransformationContext(WorkingCopy workingCopy, TreePath path, boolean canShowUI, Map<FileObject, byte[]> resourceContentChanges, Collection<? super RefactoringElementImplementation> fileChanges) {
70.210 + this.workingCopy = workingCopy;
70.211 + this.path = path;
70.212 + this.canShowUI = canShowUI;
70.213 + this.resourceContentChanges = resourceContentChanges;
70.214 + this.fileChanges = fileChanges;
70.215 + }
70.216 +
70.217 + boolean isCanShowUI() {
70.218 + return canShowUI;
70.219 + }
70.220 +
70.221 + /**Returns the {@link TreePath} that was passed to a {@link JavaFix} constructor.
70.222 + *
70.223 + * @return the {@link TreePath} that was passed to a {@link JavaFix} constructor.
70.224 + */
70.225 + public @NonNull TreePath getPath() {
70.226 + return path;
70.227 + }
70.228 +
70.229 + /**A {@link WorkingCopy} over which the transformation should operate.
70.230 + * @return {@link WorkingCopy} over which the transformation should operate.
70.231 + */
70.232 + public @NonNull WorkingCopy getWorkingCopy() {
70.233 + return workingCopy;
70.234 + }
70.235 +
70.236 + /**Allows access to non-Java resources. The content of this InputStream will
70.237 + * include all changes done through {@link #getResourceOutput(org.openide.filesystems.FileObject) }
70.238 + * before calling this method.
70.239 + *
70.240 + * @param file whose content should be returned
70.241 + * @return the file's content
70.242 + * @throws IOException if something goes wrong while opening the file
70.243 + * @throws IllegalArgumentException if {@code file} parameter is null, or
70.244 + * if it represents a Java file
70.245 + */
70.246 + public @NonNull InputStream getResourceContent(@NonNull FileObject file) throws IOException, IllegalArgumentException {
70.247 + Parameters.notNull("file", file);
70.248 + if ("text/x-java".equals(file.getMIMEType("text/x-java")))
70.249 + throw new IllegalArgumentException("Cannot access Java files");
70.250 +
70.251 + byte[] newContent = resourceContentChanges != null ? resourceContentChanges.get(file) : null;
70.252 +
70.253 + if (newContent == null) {
70.254 + final Document doc = getDocument(file);
70.255 +
70.256 + if (doc != null) {
70.257 + final String[] result = new String[1];
70.258 +
70.259 + doc.render(new Runnable() {
70.260 + @Override public void run() {
70.261 + try {
70.262 + result[0] = doc.getText(0, doc.getLength());
70.263 + } catch (BadLocationException ex) {
70.264 + Exceptions.printStackTrace(ex);
70.265 + }
70.266 + }
70.267 + });
70.268 +
70.269 + if (result[0] != null) {
70.270 + ByteBuffer encoded = FileEncodingQuery.getEncoding(file).encode(result[0]);
70.271 + byte[] encodedBytes = new byte[encoded.remaining()];
70.272 +
70.273 + encoded.get(encodedBytes);
70.274 +
70.275 + return new ByteArrayInputStream(encodedBytes);
70.276 + }
70.277 + }
70.278 +
70.279 + return file.getInputStream();
70.280 + } else {
70.281 + return new ByteArrayInputStream(newContent);
70.282 + }
70.283 + }
70.284 +
70.285 + /**Record a changed version of a file. The changes will be applied altogether with
70.286 + * changes to the Java file. In Inspect&Transform, changes done through this
70.287 + * method will be part of the preview.
70.288 + *
70.289 + * @param file whose content should be changed
70.290 + * @return an {@link java.io.OutputStream} into which the new content of the file should be written
70.291 + * @throws IOException if something goes wrong while opening the file
70.292 + * @throws IllegalArgumentException if {@code file} parameter is null, or
70.293 + * if it represents a Java file
70.294 + */
70.295 + public @NonNull OutputStream getResourceOutput(@NonNull final FileObject file) throws IOException {
70.296 + Parameters.notNull("file", file);
70.297 + if ("text/x-java".equals(file.getMIMEType("text/x-java")))
70.298 + throw new IllegalArgumentException("Cannot access Java files");
70.299 + if (resourceContentChanges == null) return file.getOutputStream();
70.300 +
70.301 + return new ByteArrayOutputStream() {
70.302 + @Override public void close() throws IOException {
70.303 + super.close();
70.304 + resourceContentChanges.put(file, toByteArray());
70.305 + }
70.306 + };
70.307 + }
70.308 +
70.309 + Collection<? super RefactoringElementImplementation> getFileChanges() {
70.310 + return fileChanges;
70.311 + }
70.312 +
70.313 + private @CheckForNull Document getDocument(@NonNull FileObject file) {
70.314 + try {
70.315 + DataObject od = DataObject.find(file);
70.316 + EditorCookie ec = od.getLookup().lookup(EditorCookie.class);
70.317 +
70.318 + if (ec == null) return null;
70.319 +
70.320 + return ec.getDocument();
70.321 + } catch (DataObjectNotFoundException ex) {
70.322 + LOG.log(Level.FINE, null, ex);
70.323 + return null;
70.324 + }
70.325 + }
70.326 +
70.327 + }
70.328 +
70.329 + private static final Logger LOG = Logger.getLogger(JavaFix.class.getName());
70.330 +
70.331 +}
71.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
71.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/JavaFixUtilities.java Wed May 08 21:47:42 2013 +0200
71.3 @@ -0,0 +1,1631 @@
71.4 +/*
71.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
71.6 + *
71.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
71.8 + *
71.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
71.10 + * Other names may be trademarks of their respective owners.
71.11 + *
71.12 + * The contents of this file are subject to the terms of either the GNU
71.13 + * General Public License Version 2 only ("GPL") or the Common
71.14 + * Development and Distribution License("CDDL") (collectively, the
71.15 + * "License"). You may not use this file except in compliance with the
71.16 + * License. You can obtain a copy of the License at
71.17 + * http://www.netbeans.org/cddl-gplv2.html
71.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
71.19 + * specific language governing permissions and limitations under the
71.20 + * License. When distributing the software, include this License Header
71.21 + * Notice in each file and include the License file at
71.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
71.23 + * particular file as subject to the "Classpath" exception as provided
71.24 + * by Oracle in the GPL Version 2 section of the License file that
71.25 + * accompanied this code. If applicable, add the following below the
71.26 + * License Header, with the fields enclosed by brackets [] replaced by
71.27 + * your own identifying information:
71.28 + * "Portions Copyrighted [year] [name of copyright owner]"
71.29 + *
71.30 + * If you wish your version of this file to be governed by only the CDDL
71.31 + * or only the GPL Version 2, indicate your decision by adding
71.32 + * "[Contributor] elects to include this software in this distribution
71.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
71.34 + * single choice of license, a recipient has the option to distribute
71.35 + * your version of this file under either the CDDL, the GPL Version 2 or
71.36 + * to extend the choice of license to its licensees as provided above.
71.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
71.38 + * Version 2 license, then the option applies only if the new code is
71.39 + * made subject to such option by the copyright holder.
71.40 + *
71.41 + * Contributor(s):
71.42 + *
71.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
71.44 + */
71.45 +package org.netbeans.spi.java.hints;
71.46 +
71.47 +import com.sun.javadoc.Doc;
71.48 +import com.sun.javadoc.Tag;
71.49 +import com.sun.source.tree.AnnotationTree;
71.50 +import com.sun.source.tree.AssignmentTree;
71.51 +import com.sun.source.tree.BinaryTree;
71.52 +import com.sun.source.tree.BlockTree;
71.53 +import com.sun.source.tree.CaseTree;
71.54 +import com.sun.source.tree.CatchTree;
71.55 +import com.sun.source.tree.ClassTree;
71.56 +import com.sun.source.tree.CompilationUnitTree;
71.57 +import com.sun.source.tree.CompoundAssignmentTree;
71.58 +import com.sun.source.tree.ExpressionStatementTree;
71.59 +import com.sun.source.tree.ExpressionTree;
71.60 +import com.sun.source.tree.IdentifierTree;
71.61 +import com.sun.source.tree.IfTree;
71.62 +import com.sun.source.tree.LambdaExpressionTree;
71.63 +import com.sun.source.tree.LiteralTree;
71.64 +import com.sun.source.tree.MemberSelectTree;
71.65 +import com.sun.source.tree.MethodInvocationTree;
71.66 +import com.sun.source.tree.MethodTree;
71.67 +import com.sun.source.tree.ModifiersTree;
71.68 +import com.sun.source.tree.NewArrayTree;
71.69 +import com.sun.source.tree.NewClassTree;
71.70 +import com.sun.source.tree.ParameterizedTypeTree;
71.71 +import com.sun.source.tree.ParenthesizedTree;
71.72 +import com.sun.source.tree.Scope;
71.73 +import com.sun.source.tree.StatementTree;
71.74 +import com.sun.source.tree.SwitchTree;
71.75 +import com.sun.source.tree.Tree;
71.76 +import com.sun.source.tree.Tree.Kind;
71.77 +import com.sun.source.tree.TryTree;
71.78 +import com.sun.source.tree.TypeParameterTree;
71.79 +import com.sun.source.tree.UnaryTree;
71.80 +import com.sun.source.tree.UnionTypeTree;
71.81 +import com.sun.source.tree.VariableTree;
71.82 +import com.sun.source.util.SourcePositions;
71.83 +import com.sun.source.util.TreePath;
71.84 +import com.sun.source.util.TreePathScanner;
71.85 +import com.sun.source.util.TreeScanner;
71.86 +import java.io.IOException;
71.87 +import java.util.ArrayList;
71.88 +import java.util.Arrays;
71.89 +import java.util.Collection;
71.90 +import java.util.Collections;
71.91 +import java.util.EnumMap;
71.92 +import java.util.EnumSet;
71.93 +import java.util.HashMap;
71.94 +import java.util.IdentityHashMap;
71.95 +import java.util.Iterator;
71.96 +import java.util.LinkedList;
71.97 +import java.util.List;
71.98 +import java.util.Map;
71.99 +import java.util.Map.Entry;
71.100 +import java.util.Set;
71.101 +import java.util.concurrent.Callable;
71.102 +import java.util.logging.Level;
71.103 +import java.util.logging.Logger;
71.104 +import java.util.regex.Matcher;
71.105 +import javax.lang.model.element.Element;
71.106 +import javax.lang.model.element.ElementKind;
71.107 +import javax.lang.model.element.Modifier;
71.108 +import javax.lang.model.element.TypeElement;
71.109 +import javax.lang.model.type.TypeKind;
71.110 +import javax.lang.model.type.TypeMirror;
71.111 +import org.netbeans.api.java.classpath.ClassPath;
71.112 +import org.netbeans.api.java.classpath.ClassPath.PathConversionMode;
71.113 +import org.netbeans.api.java.queries.SourceForBinaryQuery;
71.114 +import org.netbeans.api.java.source.ClasspathInfo;
71.115 +import org.netbeans.api.java.source.ClasspathInfo.PathKind;
71.116 +import org.netbeans.api.java.source.CompilationInfo;
71.117 +import org.netbeans.api.java.source.SourceUtils;
71.118 +import org.netbeans.api.java.source.TreeMaker;
71.119 +import org.netbeans.api.java.source.TreePathHandle;
71.120 +import org.netbeans.api.java.source.TypeMirrorHandle;
71.121 +import org.netbeans.api.java.source.WorkingCopy;
71.122 +import org.netbeans.api.java.source.matching.Occurrence;
71.123 +import org.netbeans.api.java.source.matching.Pattern;
71.124 +import org.netbeans.api.project.FileOwnerQuery;
71.125 +import org.netbeans.api.project.Project;
71.126 +import org.netbeans.modules.java.hints.spiimpl.Hacks;
71.127 +import org.netbeans.modules.java.hints.spiimpl.Utilities;
71.128 +import org.netbeans.modules.java.hints.spiimpl.ipi.upgrade.ProjectDependencyUpgrader;
71.129 +import org.netbeans.modules.refactoring.spi.SimpleRefactoringElementImplementation;
71.130 +import org.netbeans.spi.editor.hints.Fix;
71.131 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
71.132 +import org.netbeans.spi.java.hints.JavaFix.TransformationContext;
71.133 +import org.openide.filesystems.FileObject;
71.134 +import org.openide.filesystems.FileUtil;
71.135 +import org.openide.loaders.DataFolder;
71.136 +import org.openide.loaders.DataObject;
71.137 +import org.openide.loaders.DataObjectNotFoundException;
71.138 +import org.openide.modules.SpecificationVersion;
71.139 +import org.openide.text.PositionBounds;
71.140 +import org.openide.util.Exceptions;
71.141 +import org.openide.util.Lookup;
71.142 +import org.openide.util.NbBundle.Messages;
71.143 +import org.openide.util.NbCollections;
71.144 +
71.145 +/**Factory methods for various predefined {@link JavaFix} implementations.
71.146 + *
71.147 + * @author lahvac
71.148 + */
71.149 +public class JavaFixUtilities {
71.150 +
71.151 + /**Prepare a fix that will replace the given tree node ({@code what}) with the
71.152 + * given code. Any variables in the {@code to} pattern will be replaced with their
71.153 + * values from {@link HintContext#getVariables() }, {@link HintContext#getMultiVariables() }
71.154 + * and {@link HintContext#getVariableNames() }.
71.155 + *
71.156 + * @param ctx basic context for which the fix should be created
71.157 + * @param displayName the display name of the fix
71.158 + * @param what the tree node that should be replaced
71.159 + * @param to the new code that should replaced the {@code what} tree node
71.160 + * @return an editor fix that performs the required transformation
71.161 + */
71.162 + public static Fix rewriteFix(HintContext ctx, String displayName, TreePath what, final String to) {
71.163 + return rewriteFix(ctx.getInfo(), displayName, what, to, ctx.getVariables(), ctx.getMultiVariables(), ctx.getVariableNames(), ctx.getConstraints(), Collections.<String, String>emptyMap());
71.164 + }
71.165 +
71.166 + static Fix rewriteFix(CompilationInfo info, String displayName, TreePath what, final String to, Map<String, TreePath> parameters, Map<String, Collection<? extends TreePath>> parametersMulti, final Map<String, String> parameterNames, Map<String, TypeMirror> constraints, Map<String, String> options, String... imports) {
71.167 + final Map<String, TreePathHandle> params = new HashMap<String, TreePathHandle>();
71.168 + final Map<String, Object> extraParamsData = new HashMap<String, Object>();
71.169 +
71.170 + for (Entry<String, TreePath> e : parameters.entrySet()) {
71.171 + params.put(e.getKey(), TreePathHandle.create(e.getValue(), info));
71.172 + if (e.getValue() instanceof Callable) {
71.173 + try {
71.174 + extraParamsData.put(e.getKey(), ((Callable) e.getValue()).call());
71.175 + } catch (Exception ex) {
71.176 + Exceptions.printStackTrace(ex);
71.177 + }
71.178 + }
71.179 + }
71.180 +
71.181 + final Map<String, Collection<TreePathHandle>> paramsMulti = new HashMap<String, Collection<TreePathHandle>>();
71.182 +
71.183 + for (Entry<String, Collection<? extends TreePath>> e : parametersMulti.entrySet()) {
71.184 + Collection<TreePathHandle> tph = new LinkedList<TreePathHandle>();
71.185 +
71.186 + for (TreePath tp : e.getValue()) {
71.187 + tph.add(TreePathHandle.create(tp, info));
71.188 + }
71.189 +
71.190 + paramsMulti.put(e.getKey(), tph);
71.191 + }
71.192 +
71.193 + final Map<String, TypeMirrorHandle<?>> constraintsHandles = new HashMap<String, TypeMirrorHandle<?>>();
71.194 +
71.195 + for (Entry<String, TypeMirror> c : constraints.entrySet()) {
71.196 + constraintsHandles.put(c.getKey(), TypeMirrorHandle.create(c.getValue()));
71.197 + }
71.198 +
71.199 + if (displayName == null) {
71.200 + displayName = defaultFixDisplayName(info, parameters, to);
71.201 + }
71.202 +
71.203 + return new JavaFixRealImpl(info, what, options, displayName, to, params, extraParamsData, paramsMulti, parameterNames, constraintsHandles, Arrays.asList(imports)).toEditorFix();
71.204 + }
71.205 +
71.206 + /**Creates a fix that removes the given code corresponding to the given tree
71.207 + * node from the source code.
71.208 + *
71.209 + * @param ctx basic context for which the fix should be created
71.210 + * @param displayName the display name of the fix
71.211 + * @param what the tree node that should be removed
71.212 + * @return an editor fix that removes the give tree from the source code
71.213 + */
71.214 + public static Fix removeFromParent(HintContext ctx, String displayName, TreePath what) {
71.215 + return new RemoveFromParent(displayName, ctx.getInfo(), what).toEditorFix();
71.216 + }
71.217 +
71.218 + private static String defaultFixDisplayName(CompilationInfo info, Map<String, TreePath> variables, String replaceTarget) {
71.219 + Map<String, String> stringsForVariables = new HashMap<String, String>();
71.220 +
71.221 + for (Entry<String, TreePath> e : variables.entrySet()) {
71.222 + Tree t = e.getValue().getLeaf();
71.223 + SourcePositions sp = info.getTrees().getSourcePositions();
71.224 + int startPos = (int) sp.getStartPosition(info.getCompilationUnit(), t);
71.225 + int endPos = (int) sp.getEndPosition(info.getCompilationUnit(), t);
71.226 +
71.227 + if (startPos >= 0 && endPos >= 0) {
71.228 + stringsForVariables.put(e.getKey(), info.getText().substring(startPos, endPos));
71.229 + } else {
71.230 + stringsForVariables.put(e.getKey(), "");
71.231 + }
71.232 + }
71.233 +
71.234 + if (!stringsForVariables.containsKey("$this")) {
71.235 + //XXX: is this correct?
71.236 + stringsForVariables.put("$this", "this");
71.237 + }
71.238 +
71.239 + for (Entry<String, String> e : stringsForVariables.entrySet()) {
71.240 + String quotedVariable = java.util.regex.Pattern.quote(e.getKey());
71.241 + String quotedTarget = Matcher.quoteReplacement(e.getValue());
71.242 + replaceTarget = replaceTarget.replaceAll(quotedVariable, quotedTarget);
71.243 + }
71.244 +
71.245 + return "Rewrite to " + replaceTarget;
71.246 + }
71.247 +
71.248 + private static void checkDependency(CompilationInfo copy, Element e, boolean canShowUI) {
71.249 + SpecificationVersion sv = computeSpecVersion(copy, e);
71.250 +
71.251 + while (sv == null && e.getKind() != ElementKind.PACKAGE) {
71.252 + e = e.getEnclosingElement();
71.253 + sv = computeSpecVersion(copy, e);
71.254 + }
71.255 +
71.256 + if (sv == null) {
71.257 + return ;
71.258 + }
71.259 +
71.260 + Project currentProject = FileOwnerQuery.getOwner(copy.getFileObject());
71.261 +
71.262 + if (currentProject == null) {
71.263 + return ;
71.264 + }
71.265 +
71.266 + FileObject file = getFile(copy, e);
71.267 +
71.268 + if (file == null) {
71.269 + return ;
71.270 + }
71.271 +
71.272 + FileObject root = findRootForFile(file, copy.getClasspathInfo());
71.273 +
71.274 + if (root == null) {
71.275 + return ;
71.276 + }
71.277 +
71.278 + Project referedProject = FileOwnerQuery.getOwner(file);
71.279 +
71.280 + if (referedProject != null && currentProject.getProjectDirectory().equals(referedProject.getProjectDirectory())) {
71.281 + return ;
71.282 + }
71.283 +
71.284 + for (ProjectDependencyUpgrader pdu : Lookup.getDefault().lookupAll(ProjectDependencyUpgrader.class)) {
71.285 + if (pdu.ensureDependency(currentProject, root, sv, canShowUI)) {
71.286 + return ;
71.287 + }
71.288 + }
71.289 + }
71.290 +
71.291 + private static java.util.regex.Pattern SPEC_VERSION = java.util.regex.Pattern.compile("[0-9]+(\\.[0-9]+)+");
71.292 +
71.293 + static SpecificationVersion computeSpecVersion(CompilationInfo info, Element el) {
71.294 + if (!Utilities.isJavadocSupported(info)) return null;
71.295 +
71.296 + Doc javaDoc = info.getElementUtilities().javaDocFor(el);
71.297 +
71.298 + if (javaDoc == null) return null;
71.299 +
71.300 + for (Tag since : javaDoc.tags("@since")) {
71.301 + String text = since.text();
71.302 +
71.303 + Matcher m = SPEC_VERSION.matcher(text);
71.304 +
71.305 + if (!m.find()) {
71.306 + continue;
71.307 + }
71.308 +
71.309 + return new SpecificationVersion(m.group()/*ver.toString()*/);
71.310 + }
71.311 +
71.312 + return null;
71.313 + }
71.314 +
71.315 + @SuppressWarnings("deprecation")
71.316 + private static FileObject getFile(CompilationInfo copy, Element e) {
71.317 + return SourceUtils.getFile(e, copy.getClasspathInfo());
71.318 + }
71.319 +
71.320 + private static FileObject findRootForFile(final FileObject file, final ClasspathInfo cpInfo) {
71.321 + ClassPath cp = ClassPathSupport.createProxyClassPath(
71.322 + new ClassPath[] {
71.323 + cpInfo.getClassPath(ClasspathInfo.PathKind.SOURCE),
71.324 + cpInfo.getClassPath(ClasspathInfo.PathKind.BOOT),
71.325 + cpInfo.getClassPath(ClasspathInfo.PathKind.COMPILE),
71.326 + });
71.327 +
71.328 + FileObject root = cp.findOwnerRoot(file);
71.329 +
71.330 + if (root != null) {
71.331 + return root;
71.332 + }
71.333 +
71.334 + for (ClassPath.Entry e : cp.entries()) {
71.335 + FileObject[] sourceRoots = SourceForBinaryQuery.findSourceRoots(e.getURL()).getRoots();
71.336 +
71.337 + if (sourceRoots.length == 0) continue;
71.338 +
71.339 + ClassPath sourcePath = ClassPathSupport.createClassPath(sourceRoots);
71.340 +
71.341 + root = sourcePath.findOwnerRoot(file);
71.342 +
71.343 + if (root != null) {
71.344 + return root;
71.345 + }
71.346 + }
71.347 + return null;
71.348 + }
71.349 +
71.350 + private static boolean isStaticElement(Element el) {
71.351 + if (el == null) return false;
71.352 +
71.353 + if (el.asType() == null || el.asType().getKind() == TypeKind.ERROR) {
71.354 + return false;
71.355 + }
71.356 +
71.357 + if (el.getModifiers().contains(Modifier.STATIC)) {
71.358 + //XXX:
71.359 + if (!el.getKind().isClass() && !el.getKind().isInterface()) {
71.360 + return false;
71.361 + }
71.362 +
71.363 + return true;
71.364 + }
71.365 +
71.366 + if (el.getKind().isClass() || el.getKind().isInterface()) {
71.367 + return el.getEnclosingElement().getKind() == ElementKind.PACKAGE;
71.368 + }
71.369 +
71.370 + return false;
71.371 + }
71.372 +
71.373 + private static class JavaFixRealImpl extends JavaFix {
71.374 + private final String displayName;
71.375 + private final Map<String, TreePathHandle> params;
71.376 + private final Map<String, Object> extraParamsData;
71.377 + private final Map<String, Collection<TreePathHandle>> paramsMulti;
71.378 + private final Map<String, String> parameterNames;
71.379 + private final Map<String, TypeMirrorHandle<?>> constraintsHandles;
71.380 + private final Iterable<? extends String> imports;
71.381 + private final String to;
71.382 +
71.383 + public JavaFixRealImpl(CompilationInfo info, TreePath what, Map<String, String> options, String displayName, String to, Map<String, TreePathHandle> params, Map<String, Object> extraParamsData, Map<String, Collection<TreePathHandle>> paramsMulti, final Map<String, String> parameterNames, Map<String, TypeMirrorHandle<?>> constraintsHandles, Iterable<? extends String> imports) {
71.384 + super(info, what, options);
71.385 +
71.386 + this.displayName = displayName;
71.387 + this.to = to;
71.388 + this.params = params;
71.389 + this.extraParamsData = extraParamsData;
71.390 + this.paramsMulti = paramsMulti;
71.391 + this.parameterNames = parameterNames;
71.392 + this.constraintsHandles = constraintsHandles;
71.393 + this.imports = imports;
71.394 + }
71.395 +
71.396 + @Override
71.397 + protected String getText() {
71.398 + return displayName;
71.399 + }
71.400 +
71.401 + @Override
71.402 + protected void performRewrite(TransformationContext ctx) {
71.403 + final WorkingCopy wc = ctx.getWorkingCopy();
71.404 + TreePath tp = ctx.getPath();
71.405 + final Map<String, TreePath> parameters = new HashMap<String, TreePath>();
71.406 +
71.407 + for (Entry<String, TreePathHandle> e : params.entrySet()) {
71.408 + TreePath p = e.getValue().resolve(wc);
71.409 +
71.410 + if (p == null) {
71.411 + Logger.getLogger(JavaFix.class.getName()).log(Level.SEVERE, "Cannot resolve handle={0}", e.getValue());
71.412 + }
71.413 +
71.414 + parameters.put(e.getKey(), p);
71.415 + }
71.416 +
71.417 + final Map<String, Collection<TreePath>> parametersMulti = new HashMap<String, Collection<TreePath>>();
71.418 +
71.419 + for (Entry<String, Collection<TreePathHandle>> e : paramsMulti.entrySet()) {
71.420 + Collection<TreePath> tps = new LinkedList<TreePath>();
71.421 +
71.422 + for (TreePathHandle tph : e.getValue()) {
71.423 + TreePath p = tph.resolve(wc);
71.424 +
71.425 + if (p == null) {
71.426 + Logger.getLogger(JavaFix.class.getName()).log(Level.SEVERE, "Cannot resolve handle={0}", e.getValue());
71.427 + }
71.428 +
71.429 + tps.add(p);
71.430 + }
71.431 +
71.432 + parametersMulti.put(e.getKey(), tps);
71.433 + }
71.434 +
71.435 + Map<String, TypeMirror> constraints = new HashMap<String, TypeMirror>();
71.436 +
71.437 + for (Entry<String, TypeMirrorHandle<?>> c : constraintsHandles.entrySet()) {
71.438 + constraints.put(c.getKey(), c.getValue().resolve(wc));
71.439 + }
71.440 +
71.441 + Scope scope = Utilities.constructScope(wc, constraints, imports);
71.442 +
71.443 + assert scope != null;
71.444 +
71.445 + Tree parsed = Utilities.parseAndAttribute(wc, to, scope);
71.446 +
71.447 + if (parsed.getKind() == Kind.EXPRESSION_STATEMENT && ExpressionTree.class.isAssignableFrom(tp.getLeaf().getKind().asInterface())) {
71.448 + parsed = ((ExpressionStatementTree) parsed).getExpression();
71.449 + }
71.450 +
71.451 + Map<Tree, Tree> rewriteFromTo = new IdentityHashMap<Tree, Tree>();
71.452 + Tree original;
71.453 +
71.454 + if (Utilities.isFakeBlock(parsed)) {
71.455 + TreePath parent = tp.getParentPath();
71.456 + List<? extends StatementTree> statements = ((BlockTree) parsed).getStatements();
71.457 +
71.458 + if (tp.getLeaf().getKind() == Kind.BLOCK) {
71.459 + BlockTree real = (BlockTree) tp.getLeaf();
71.460 + rewriteFromTo.put(original = real, wc.getTreeMaker().Block(statements, real.isStatic()));
71.461 + } else {
71.462 + statements = statements.subList(1, statements.size() - 1);
71.463 +
71.464 + if (parent.getLeaf().getKind() == Kind.BLOCK) {
71.465 + List<StatementTree> newStatements = new LinkedList<StatementTree>();
71.466 +
71.467 + for (StatementTree st : ((BlockTree) parent.getLeaf()).getStatements()) {
71.468 + if (st == tp.getLeaf()) {
71.469 + newStatements.addAll(statements);
71.470 + } else {
71.471 + newStatements.add(st);
71.472 + }
71.473 + }
71.474 +
71.475 + rewriteFromTo.put(original = parent.getLeaf(), wc.getTreeMaker().Block(newStatements, ((BlockTree) parent.getLeaf()).isStatic()));
71.476 + } else {
71.477 + rewriteFromTo.put(original = tp.getLeaf(), wc.getTreeMaker().Block(statements, false));
71.478 + }
71.479 + }
71.480 + } else if (Utilities.isFakeClass(parsed)) {
71.481 + TreePath parent = tp.getParentPath();
71.482 + List<? extends Tree> members = ((ClassTree) parsed).getMembers();
71.483 +
71.484 + members = members.subList(1, members.size());
71.485 +
71.486 + assert parent.getLeaf().getKind() == Kind.CLASS;
71.487 +
71.488 + List<Tree> newMembers = new LinkedList<Tree>();
71.489 +
71.490 + ClassTree ct = (ClassTree) parent.getLeaf();
71.491 +
71.492 + for (Tree t : ct.getMembers()) {
71.493 + if (t == tp.getLeaf()) {
71.494 + newMembers.addAll(members);
71.495 + } else {
71.496 + newMembers.add(t);
71.497 + }
71.498 + }
71.499 +
71.500 + rewriteFromTo.put(original = parent.getLeaf(), wc.getTreeMaker().Class(ct.getModifiers(), ct.getSimpleName(), ct.getTypeParameters(), ct.getExtendsClause(), ct.getImplementsClause(), newMembers));
71.501 + } else if (tp.getLeaf().getKind() == Kind.BLOCK && parametersMulti.containsKey("$$1$") && parsed.getKind() != Kind.BLOCK && StatementTree.class.isAssignableFrom(parsed.getKind().asInterface())) {
71.502 + List<StatementTree> newStatements = new LinkedList<StatementTree>();
71.503 +
71.504 + newStatements.add(wc.getTreeMaker().ExpressionStatement(wc.getTreeMaker().Identifier("$$1$")));
71.505 + newStatements.add((StatementTree) parsed);
71.506 + newStatements.add(wc.getTreeMaker().ExpressionStatement(wc.getTreeMaker().Identifier("$$2$")));
71.507 +
71.508 + parsed = wc.getTreeMaker().Block(newStatements, ((BlockTree) tp.getLeaf()).isStatic());
71.509 +
71.510 + rewriteFromTo.put(original = tp.getLeaf(), parsed);
71.511 + } else {
71.512 + while ( tp.getParentPath().getLeaf().getKind() == Kind.PARENTHESIZED
71.513 + && tp.getLeaf().getKind() != parsed.getKind()
71.514 + && tp.getParentPath() != null
71.515 + && tp.getParentPath().getParentPath() != null
71.516 + && !requiresParenthesis(parsed, tp.getParentPath().getLeaf(), tp.getParentPath().getParentPath().getLeaf())
71.517 + && requiresParenthesis(tp.getLeaf(), tp.getParentPath().getLeaf(), tp.getParentPath().getParentPath().getLeaf()))
71.518 + tp = tp.getParentPath();
71.519 + rewriteFromTo.put(original = tp.getLeaf(), parsed);
71.520 + }
71.521 +
71.522 + //prevent generating QualIdents inside import clauses - might be better to solve that inside ImportAnalysis2,
71.523 + //but that seems not to be straightforward:
71.524 + boolean inImport = parsed.getKind() == Kind.IMPORT;
71.525 + boolean inPackage = false;
71.526 + TreePath w = tp;
71.527 +
71.528 + while (!inImport && w != null) {
71.529 + inImport |= w.getLeaf().getKind() == Kind.IMPORT;
71.530 + inPackage |= w.getParentPath() != null && w.getParentPath().getLeaf().getKind() == Kind.COMPILATION_UNIT && ((CompilationUnitTree) w.getParentPath().getLeaf()).getPackageName() == w.getLeaf();
71.531 + w = w.getParentPath();
71.532 + }
71.533 +
71.534 + final Set<Tree> originalTrees = Collections.newSetFromMap(new IdentityHashMap<Tree, Boolean>());
71.535 +
71.536 + new TreeScanner<Void, Void>() {
71.537 + @Override public Void scan(Tree tree, Void p) {
71.538 + originalTrees.add(tree);
71.539 + return super.scan(tree, p);
71.540 + }
71.541 + }.scan(original, null);
71.542 +
71.543 + new ReplaceParameters(wc, ctx.isCanShowUI(), inImport, parameters, extraParamsData, parametersMulti, parameterNames, rewriteFromTo, originalTrees).scan(new TreePath(tp.getParentPath(), rewriteFromTo.get(original)), null);
71.544 +
71.545 + if (inPackage) {
71.546 + String newPackage = wc.getTreeUtilities().translate(wc.getCompilationUnit().getPackageName(), new IdentityHashMap<Tree, Tree>(rewriteFromTo))./*XXX: not correct*/toString();
71.547 +
71.548 + ClassPath source = wc.getClasspathInfo().getClassPath(PathKind.SOURCE);
71.549 + FileObject ownerRoot = source.findOwnerRoot(wc.getFileObject());
71.550 +
71.551 + if (ownerRoot != null) {
71.552 + ctx.getFileChanges().add(new MoveFile(wc.getFileObject(), ownerRoot, newPackage.replace('.', '/')));
71.553 + } else {
71.554 + Logger.getLogger(JavaFix.class.getName()).log(Level.WARNING, "{0} not on its source path ({1})", new Object[] {FileUtil.getFileDisplayName(wc.getFileObject()), source.toString(PathConversionMode.PRINT)});
71.555 + }
71.556 + }
71.557 +
71.558 + for (Entry<Tree, Tree> e : rewriteFromTo.entrySet()) {
71.559 + wc.rewrite(e.getKey(), e.getValue());
71.560 + }
71.561 + }
71.562 + }
71.563 +
71.564 + private static final Set<Kind> NUMBER_LITERAL_KINDS = EnumSet.of(Kind.FLOAT_LITERAL, Kind.DOUBLE_LITERAL, Kind.INT_LITERAL, Kind.LONG_LITERAL);
71.565 +
71.566 + private static class ReplaceParameters extends TreePathScanner<Number, Void> {
71.567 +
71.568 + private final CompilationInfo info;
71.569 + private final TreeMaker make;
71.570 + private final boolean canShowUI;
71.571 + private final boolean inImport;
71.572 + private final Map<String, TreePath> parameters;
71.573 + private final Map<String, Object> extraParamsData;
71.574 + private final Map<String, Collection<TreePath>> parametersMulti;
71.575 + private final Map<String, String> parameterNames;
71.576 + private final Map<Tree, Tree> rewriteFromTo;
71.577 + private final Set<Tree> originalTrees;
71.578 +
71.579 + public ReplaceParameters(WorkingCopy wc, boolean canShowUI, boolean inImport, Map<String, TreePath> parameters, Map<String, Object> extraParamsData, Map<String, Collection<TreePath>> parametersMulti, Map<String, String> parameterNames, Map<Tree, Tree> rewriteFromTo, Set<Tree> originalTrees) {
71.580 + this.parameters = parameters;
71.581 + this.info = wc;
71.582 + this.make = wc.getTreeMaker();
71.583 + this.canShowUI = canShowUI;
71.584 + this.inImport = inImport;
71.585 + this.extraParamsData = extraParamsData;
71.586 + this.parametersMulti = parametersMulti;
71.587 + this.parameterNames = parameterNames;
71.588 + this.rewriteFromTo = rewriteFromTo;
71.589 + this.originalTrees = originalTrees;
71.590 + }
71.591 +
71.592 + @Override
71.593 + public Number visitIdentifier(IdentifierTree node, Void p) {
71.594 + String name = node.getName().toString();
71.595 + Tree newNode = handleIdentifier(name, node);
71.596 +
71.597 + if (newNode != null) {
71.598 + rewrite(node, newNode);
71.599 + if (NUMBER_LITERAL_KINDS.contains(newNode.getKind())) {
71.600 + return (Number) ((LiteralTree) newNode).getValue();
71.601 + }
71.602 + }
71.603 +
71.604 + Element e = info.getTrees().getElement(getCurrentPath());
71.605 +
71.606 + if (e != null && isStaticElement(e) && !inImport) {
71.607 + rewrite(node, make.QualIdent(e));
71.608 + }
71.609 +
71.610 + return super.visitIdentifier(node, p);
71.611 + }
71.612 +
71.613 + @Override
71.614 + public Number visitTypeParameter(TypeParameterTree node, Void p) {
71.615 + String name = node.getName().toString();
71.616 + Tree newNode = handleIdentifier(name, node);
71.617 +
71.618 + if (newNode != null) {
71.619 + rewrite(node, newNode);
71.620 + if (NUMBER_LITERAL_KINDS.contains(newNode.getKind())) {
71.621 + return (Number) ((LiteralTree) newNode).getValue();
71.622 + }
71.623 + }
71.624 +
71.625 + return super.visitTypeParameter(node, p);
71.626 + }
71.627 +
71.628 + private Tree handleIdentifier(String name, Tree node) {
71.629 + TreePath tp = parameters.get(name);
71.630 +
71.631 + if (tp != null) {
71.632 + if (tp.getLeaf() instanceof Hacks.RenameTree) {
71.633 + Hacks.RenameTree rt = (Hacks.RenameTree) tp.getLeaf();
71.634 + return make.setLabel(rt.originalTree, rt.newName);
71.635 + }
71.636 + if (!parameterNames.containsKey(name)) {
71.637 + Tree target = tp.getLeaf();
71.638 + if (NUMBER_LITERAL_KINDS.contains(target.getKind())) {
71.639 + return target;
71.640 + }
71.641 + //TODO: might also remove parenthesis, but needs to ensure the diff will still be minimal
71.642 +// while (target.getKind() == Kind.PARENTHESIZED
71.643 +// && !requiresParenthesis(((ParenthesizedTree) target).getExpression(), getCurrentPath().getParentPath().getLeaf())) {
71.644 +// target = ((ParenthesizedTree) target).getExpression();
71.645 +// }
71.646 + if ( getCurrentPath().getParentPath() != null
71.647 + && getCurrentPath().getParentPath().getLeaf().getKind() == Kind.LOGICAL_COMPLEMENT
71.648 + && ( tp.getParentPath() == null
71.649 + || tp.getParentPath().getLeaf().getKind() != Kind.LOGICAL_COMPLEMENT)) {
71.650 + Tree negated = negate((ExpressionTree) tp.getLeaf(), getCurrentPath().getParentPath().getParentPath().getLeaf(), true);
71.651 +
71.652 + if (negated != null) {
71.653 + rewrite(getCurrentPath().getParentPath().getLeaf(), negated);
71.654 + }
71.655 + }
71.656 + if (requiresParenthesis(target, node, getCurrentPath().getParentPath().getLeaf())) {
71.657 + target = make.Parenthesized((ExpressionTree) target);
71.658 + }
71.659 + return target;
71.660 + }
71.661 + }
71.662 +
71.663 + String variableName = parameterNames.get(name);
71.664 +
71.665 + if (variableName != null) {
71.666 + return make.Identifier(variableName);
71.667 + }
71.668 +
71.669 + return null;
71.670 + }
71.671 +
71.672 + @Override
71.673 + public Number visitMemberSelect(MemberSelectTree node, Void p) {
71.674 + Element e = info.getTrees().getElement(getCurrentPath());
71.675 +
71.676 + if (e != null && (e.getKind() != ElementKind.CLASS || ((TypeElement) e).asType().getKind() != TypeKind.ERROR)) {
71.677 + //check correct dependency:
71.678 + checkDependency(info, e, canShowUI);
71.679 +
71.680 + if (isStaticElement(e) && !inImport) {
71.681 + rewrite(node, make.QualIdent(e));
71.682 +
71.683 + return null;
71.684 + }
71.685 + }
71.686 +
71.687 + MemberSelectTree nue = node;
71.688 + String selectedName = node.getIdentifier().toString();
71.689 +
71.690 + if (selectedName.startsWith("$") && parameterNames.get(selectedName) != null) {
71.691 + nue = make.MemberSelect(node.getExpression(), parameterNames.get(selectedName));
71.692 + }
71.693 +
71.694 + if (nue.getExpression().getKind() == Kind.IDENTIFIER) {
71.695 + String name = ((IdentifierTree) nue.getExpression()).getName().toString();
71.696 +
71.697 + if (name.startsWith("$") && parameters.get(name) == null) {
71.698 + //XXX: unbound variable, use identifier instead of member select - may cause problems?
71.699 + rewrite(node, make.Identifier(nue.getIdentifier()));
71.700 + return null;
71.701 + }
71.702 + }
71.703 +
71.704 + if (nue != node) {
71.705 + rewrite(node, nue);
71.706 + }
71.707 +
71.708 + return super.visitMemberSelect(node, p);
71.709 + }
71.710 +
71.711 + @Override
71.712 + public Number visitVariable(VariableTree node, Void p) {
71.713 + String name = node.getName().toString();
71.714 +
71.715 + if (name.startsWith("$")) {
71.716 + String nueName = parameterNames.get(name);
71.717 +
71.718 + if (nueName != null) {
71.719 + name = nueName;
71.720 + }
71.721 + }
71.722 +
71.723 + VariableTree nue = make.Variable(node.getModifiers(), name, node.getType(), resolveOptionalValue(node.getInitializer()));
71.724 +
71.725 + rewrite(node, nue);
71.726 +
71.727 + return super.visitVariable(nue, p);
71.728 + }
71.729 +
71.730 + @Override
71.731 + public Number visitIf(IfTree node, Void p) {
71.732 + IfTree nue = make.If(node.getCondition(), node.getThenStatement(), resolveOptionalValue(node.getElseStatement()));
71.733 +
71.734 + rewrite(node, nue);
71.735 +
71.736 + return super.visitIf(nue, p);
71.737 + }
71.738 +
71.739 + @Override
71.740 + public Number visitMethod(MethodTree node, Void p) {
71.741 + String name = node.getName().toString();
71.742 + String newName = name;
71.743 +
71.744 + if (name.startsWith("$")) {
71.745 + if (parameterNames.containsKey(name)) {
71.746 + newName = parameterNames.get(name);
71.747 + }
71.748 + }
71.749 +
71.750 + List<? extends TypeParameterTree> typeParams = resolveMultiParameters(node.getTypeParameters());
71.751 + List<? extends VariableTree> params = resolveMultiParameters(node.getParameters());
71.752 + List<? extends ExpressionTree> thrown = resolveMultiParameters(node.getThrows());
71.753 +
71.754 + MethodTree nue = make.Method(node.getModifiers(), newName, node.getReturnType(), typeParams, params, thrown, node.getBody(), (ExpressionTree) node.getDefaultValue());
71.755 +
71.756 + rewrite(node, nue);
71.757 +
71.758 + return super.visitMethod(nue, p);
71.759 + }
71.760 +
71.761 + @Override
71.762 + public Number visitClass(ClassTree node, Void p) {
71.763 + String name = node.getSimpleName().toString();
71.764 + String newName = name;
71.765 +
71.766 + if (name.startsWith("$")) {
71.767 + if (parameterNames.containsKey(name)) {
71.768 + newName = parameterNames.get(name);
71.769 + }
71.770 + }
71.771 +
71.772 + List<? extends TypeParameterTree> typeParams = resolveMultiParameters(node.getTypeParameters());
71.773 + List<? extends Tree> implementsClauses = resolveMultiParameters(node.getImplementsClause());
71.774 + List<? extends Tree> members = resolveMultiParameters(Utilities.filterHidden(getCurrentPath(), node.getMembers()));
71.775 + Tree extend = resolveOptionalValue(node.getExtendsClause());
71.776 + ClassTree nue = make.Class(node.getModifiers(), newName, typeParams, extend, implementsClauses, members);
71.777 +
71.778 + rewrite(node, nue);
71.779 +
71.780 + return super.visitClass(nue, p);
71.781 + }
71.782 +
71.783 + @Override
71.784 + public Number visitExpressionStatement(ExpressionStatementTree node, Void p) {
71.785 + CharSequence name = Utilities.getWildcardTreeName(node);
71.786 +
71.787 + if (name != null) {
71.788 + TreePath tp = parameters.get(name.toString());
71.789 +
71.790 + if (tp != null) {
71.791 + rewrite(node, tp.getLeaf());
71.792 + return null;
71.793 + }
71.794 + }
71.795 +
71.796 + return super.visitExpressionStatement(node, p);
71.797 + }
71.798 +
71.799 + @Override
71.800 + public Number visitLiteral(LiteralTree node, Void p) {
71.801 + if (node.getValue() instanceof Number) {
71.802 + return (Number) node.getValue();
71.803 + }
71.804 +
71.805 + return super.visitLiteral(node, p);
71.806 + }
71.807 +
71.808 + @Override
71.809 + public Number visitBinary(BinaryTree node, Void p) {
71.810 + Number left = scan(node.getLeftOperand(), p);
71.811 + Number right = scan(node.getRightOperand(), p);
71.812 +
71.813 + if (left != null && right != null) {
71.814 + Number result = null;
71.815 + switch (node.getKind()) {
71.816 + case MULTIPLY:
71.817 + if (left instanceof Double || right instanceof Double) {
71.818 + result = left.doubleValue() * right.doubleValue();
71.819 + } else if (left instanceof Float || right instanceof Float) {
71.820 + result = left.floatValue() * right.floatValue();
71.821 + } else if (left instanceof Long || right instanceof Long) {
71.822 + result = left.longValue() * right.longValue();
71.823 + } else if (left instanceof Integer || right instanceof Integer) {
71.824 + result = left.intValue() * right.intValue();
71.825 + } else {
71.826 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.827 + }
71.828 + break;
71.829 +
71.830 + case DIVIDE:
71.831 + if (left instanceof Double || right instanceof Double) {
71.832 + result = left.doubleValue() / right.doubleValue();
71.833 + } else if (left instanceof Float || right instanceof Float) {
71.834 + result = left.floatValue() / right.floatValue();
71.835 + } else if (left instanceof Long || right instanceof Long) {
71.836 + result = left.longValue() / right.longValue();
71.837 + } else if (left instanceof Integer || right instanceof Integer) {
71.838 + result = left.intValue() / right.intValue();
71.839 + } else {
71.840 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.841 + }
71.842 + break;
71.843 +
71.844 + case REMAINDER:
71.845 + if (left instanceof Double || right instanceof Double) {
71.846 + result = left.doubleValue() % right.doubleValue();
71.847 + } else if (left instanceof Float || right instanceof Float) {
71.848 + result = left.floatValue() % right.floatValue();
71.849 + } else if (left instanceof Long || right instanceof Long) {
71.850 + result = left.longValue() % right.longValue();
71.851 + } else if (left instanceof Integer || right instanceof Integer) {
71.852 + result = left.intValue() % right.intValue();
71.853 + } else {
71.854 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.855 + }
71.856 + break;
71.857 +
71.858 + case PLUS:
71.859 + if (left instanceof Double || right instanceof Double) {
71.860 + result = left.doubleValue() + right.doubleValue();
71.861 + } else if (left instanceof Float || right instanceof Float) {
71.862 + result = left.floatValue() + right.floatValue();
71.863 + } else if (left instanceof Long || right instanceof Long) {
71.864 + result = left.longValue() + right.longValue();
71.865 + } else if (left instanceof Integer || right instanceof Integer) {
71.866 + result = left.intValue() + right.intValue();
71.867 + } else {
71.868 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.869 + }
71.870 + break;
71.871 +
71.872 + case MINUS:
71.873 + if (left instanceof Double || right instanceof Double) {
71.874 + result = left.doubleValue() - right.doubleValue();
71.875 + } else if (left instanceof Float || right instanceof Float) {
71.876 + result = left.floatValue() - right.floatValue();
71.877 + } else if (left instanceof Long || right instanceof Long) {
71.878 + result = left.longValue() - right.longValue();
71.879 + } else if (left instanceof Integer || right instanceof Integer) {
71.880 + result = left.intValue() - right.intValue();
71.881 + } else {
71.882 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.883 + }
71.884 + break;
71.885 +
71.886 + case LEFT_SHIFT:
71.887 + if (left instanceof Long || right instanceof Long) {
71.888 + result = left.longValue() << right.longValue();
71.889 + } else if (left instanceof Integer || right instanceof Integer) {
71.890 + result = left.intValue() << right.intValue();
71.891 + } else {
71.892 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.893 + }
71.894 + break;
71.895 +
71.896 + case RIGHT_SHIFT:
71.897 + if (left instanceof Long || right instanceof Long) {
71.898 + result = left.longValue() >> right.longValue();
71.899 + } else if (left instanceof Integer || right instanceof Integer) {
71.900 + result = left.intValue() >> right.intValue();
71.901 + } else {
71.902 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.903 + }
71.904 + break;
71.905 +
71.906 + case UNSIGNED_RIGHT_SHIFT:
71.907 + if (left instanceof Long || right instanceof Long) {
71.908 + result = left.longValue() >>> right.longValue();
71.909 + } else if (left instanceof Integer || right instanceof Integer) {
71.910 + result = left.intValue() >>> right.intValue();
71.911 + } else {
71.912 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.913 + }
71.914 + break;
71.915 +
71.916 + case AND:
71.917 + if (left instanceof Long || right instanceof Long) {
71.918 + result = left.longValue() & right.longValue();
71.919 + } else if (left instanceof Integer || right instanceof Integer) {
71.920 + result = left.intValue() & right.intValue();
71.921 + } else {
71.922 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.923 + }
71.924 + break;
71.925 +
71.926 + case XOR:
71.927 + if (left instanceof Long || right instanceof Long) {
71.928 + result = left.longValue() ^ right.longValue();
71.929 + } else if (left instanceof Integer || right instanceof Integer) {
71.930 + result = left.intValue() ^ right.intValue();
71.931 + } else {
71.932 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.933 + }
71.934 + break;
71.935 +
71.936 + case OR:
71.937 + if (left instanceof Long || right instanceof Long) {
71.938 + result = left.longValue() | right.longValue();
71.939 + } else if (left instanceof Integer || right instanceof Integer) {
71.940 + result = left.intValue() | right.intValue();
71.941 + } else {
71.942 + throw new IllegalStateException("left=" + left.getClass() + ", right=" + right.getClass());
71.943 + }
71.944 + break;
71.945 + }
71.946 +
71.947 + if (result != null) {
71.948 + rewrite(node, make.Literal(result));
71.949 +
71.950 + return result;
71.951 + }
71.952 + }
71.953 +
71.954 + return null;
71.955 + }
71.956 +
71.957 + @Override
71.958 + public Number visitUnary(UnaryTree node, Void p) {
71.959 + Number op = scan(node.getExpression(), p);
71.960 +
71.961 + if (op != null) {
71.962 + Number result = null;
71.963 + switch (node.getKind()) {
71.964 + case UNARY_MINUS:
71.965 + if (op instanceof Double) {
71.966 + result = -op.doubleValue();
71.967 + } else if (op instanceof Float) {
71.968 + result = -op.floatValue();
71.969 + } else if (op instanceof Long) {
71.970 + result = -op.longValue();
71.971 + } else if (op instanceof Integer) {
71.972 + result = -op.intValue();
71.973 + } else {
71.974 + throw new IllegalStateException("op=" + op.getClass());
71.975 + }
71.976 + break;
71.977 + case UNARY_PLUS:
71.978 + result = op;
71.979 + break;
71.980 + }
71.981 +
71.982 + if (result != null) {
71.983 + rewrite(node, make.Literal(result));
71.984 +
71.985 + return result;
71.986 + }
71.987 + }
71.988 +
71.989 + return super.visitUnary(node, p);
71.990 + }
71.991 +
71.992 + @Override
71.993 + public Number visitBlock(BlockTree node, Void p) {
71.994 + List<? extends StatementTree> nueStatement = resolveMultiParameters(node.getStatements());
71.995 + BlockTree nue = make.Block(nueStatement, node.isStatic());
71.996 +
71.997 + rewrite(node, nue);
71.998 +
71.999 + return super.visitBlock(nue, p);
71.1000 + }
71.1001 +
71.1002 + @Override
71.1003 + public Number visitCase(CaseTree node, Void p) {
71.1004 + List<? extends StatementTree> statements = (List<? extends StatementTree>) resolveMultiParameters(node.getStatements());
71.1005 + CaseTree nue = make.Case(node.getExpression(), statements);
71.1006 +
71.1007 + rewrite(node, nue);
71.1008 + return super.visitCase(node, p);
71.1009 + }
71.1010 +
71.1011 + @Override
71.1012 + public Number visitMethodInvocation(MethodInvocationTree node, Void p) {
71.1013 + List<? extends ExpressionTree> typeArgs = (List<? extends ExpressionTree>) resolveMultiParameters(node.getTypeArguments());
71.1014 + List<? extends ExpressionTree> args = resolveMultiParameters(node.getArguments());
71.1015 + MethodInvocationTree nue = make.MethodInvocation(typeArgs, node.getMethodSelect(), args);
71.1016 +
71.1017 + rewrite(node, nue);
71.1018 +
71.1019 + return super.visitMethodInvocation(nue, p);
71.1020 + }
71.1021 +
71.1022 + @Override
71.1023 + public Number visitNewClass(NewClassTree node, Void p) {
71.1024 + List<? extends ExpressionTree> typeArgs = (List<? extends ExpressionTree>) resolveMultiParameters(node.getTypeArguments());
71.1025 + List<? extends ExpressionTree> args = resolveMultiParameters(node.getArguments());
71.1026 + NewClassTree nue = make.NewClass(node.getEnclosingExpression(), typeArgs, node.getIdentifier(), args, node.getClassBody());
71.1027 +
71.1028 + rewrite(node, nue);
71.1029 + return super.visitNewClass(nue, p);
71.1030 + }
71.1031 +
71.1032 + @Override
71.1033 + public Number visitParameterizedType(ParameterizedTypeTree node, Void p) {
71.1034 + List<? extends ExpressionTree> typeArgs = (List<? extends ExpressionTree>) resolveMultiParameters(node.getTypeArguments());
71.1035 + ParameterizedTypeTree nue = make.ParameterizedType(node.getType(), typeArgs);
71.1036 +
71.1037 + rewrite(node, nue);
71.1038 + return super.visitParameterizedType(node, p);
71.1039 + }
71.1040 +
71.1041 + @Override
71.1042 + public Number visitSwitch(SwitchTree node, Void p) {
71.1043 + List<? extends CaseTree> cases = (List<? extends CaseTree>) resolveMultiParameters(node.getCases());
71.1044 + SwitchTree nue = make.Switch(node.getExpression(), cases);
71.1045 +
71.1046 + rewrite(node, nue);
71.1047 + return super.visitSwitch(node, p);
71.1048 + }
71.1049 +
71.1050 + @Override
71.1051 + public Number visitTry(TryTree node, Void p) {
71.1052 + List<? extends Tree> resources = (List<? extends Tree>) resolveMultiParameters(node.getResources());
71.1053 + List<? extends CatchTree> catches = (List<? extends CatchTree>) resolveMultiParameters(node.getCatches());
71.1054 + TryTree nue = make.Try(resources, node.getBlock(), catches, node.getFinallyBlock());
71.1055 +
71.1056 + rewrite(node, nue);
71.1057 + return super.visitTry(node, p);
71.1058 + }
71.1059 +
71.1060 + @Override
71.1061 + public Number visitModifiers(ModifiersTree node, Void p) {
71.1062 + List<AnnotationTree> annotations = new ArrayList<AnnotationTree>(node.getAnnotations());
71.1063 + IdentifierTree ident = !annotations.isEmpty() && annotations.get(0).getAnnotationType().getKind() == Kind.IDENTIFIER ? (IdentifierTree) annotations.get(0).getAnnotationType() : null;
71.1064 +
71.1065 + if (ident != null) {
71.1066 + annotations.remove(0);
71.1067 +
71.1068 + String name = ident.getName().toString();
71.1069 + TreePath orig = parameters.get(name);
71.1070 + ModifiersTree nue;
71.1071 +
71.1072 + if (orig != null && orig.getLeaf().getKind() == Kind.MODIFIERS) {
71.1073 + ModifiersTree origMods = (ModifiersTree) orig.getLeaf();
71.1074 + Object actualContent = extraParamsData.get(name);
71.1075 + Set<Modifier> actualFlags = EnumSet.noneOf(Modifier.class);
71.1076 + boolean[] actualAnnotationsMask = new boolean[0];
71.1077 +
71.1078 + if (actualContent instanceof Object[] && ((Object[]) actualContent)[0] instanceof Set) {
71.1079 + actualFlags.addAll(NbCollections.checkedSetByFilter((Set) ((Object[]) actualContent)[0], Modifier.class, false));
71.1080 + }
71.1081 +
71.1082 + if (actualContent instanceof Object[] && ((Object[]) actualContent)[1] instanceof boolean[]) {
71.1083 + actualAnnotationsMask = (boolean[]) ((Object[]) actualContent)[1];
71.1084 + }
71.1085 +
71.1086 + nue = origMods;
71.1087 +
71.1088 + for (Modifier m : origMods.getFlags()) {
71.1089 + if (actualFlags.contains(m)) continue;
71.1090 + nue = make.removeModifiersModifier(nue, m);
71.1091 + }
71.1092 +
71.1093 + for (Modifier m : node.getFlags()) {
71.1094 + nue = make.addModifiersModifier(nue, m);
71.1095 + }
71.1096 +
71.1097 + int ai = 0;
71.1098 +
71.1099 + OUTER: for (AnnotationTree a : origMods.getAnnotations()) {
71.1100 + if (actualAnnotationsMask.length <= ai || actualAnnotationsMask[ai++]) continue;
71.1101 + for (Iterator<AnnotationTree> it = annotations.iterator(); it.hasNext();) {
71.1102 + AnnotationTree toCheck = it.next();
71.1103 + Collection<? extends Occurrence> match = org.netbeans.api.java.source.matching.Matcher.create(info).setTreeTopSearch().setSearchRoot(new TreePath(getCurrentPath(), a)).match(Pattern.createSimplePattern(new TreePath(getCurrentPath(), toCheck)));
71.1104 +
71.1105 + if (!match.isEmpty()) {
71.1106 + //should be kept:
71.1107 + it.remove();
71.1108 + break OUTER;
71.1109 + }
71.1110 + }
71.1111 +
71.1112 + nue = make.removeModifiersAnnotation(nue, a);
71.1113 + }
71.1114 +
71.1115 + for (AnnotationTree a : annotations) {
71.1116 + nue = make.addModifiersAnnotation(nue, a);
71.1117 + scan(a, p);
71.1118 + }
71.1119 + } else {
71.1120 + nue = make.removeModifiersAnnotation(node, 0);
71.1121 + }
71.1122 +
71.1123 + rewrite(node, nue);
71.1124 +
71.1125 + return null;
71.1126 + }
71.1127 +
71.1128 + return super.visitModifiers(node, p);
71.1129 + }
71.1130 +
71.1131 + @Override
71.1132 + public Number visitNewArray(NewArrayTree node, Void p) {
71.1133 + List<? extends ExpressionTree> dimensions = (List<? extends ExpressionTree>) resolveMultiParameters(node.getDimensions());
71.1134 + List<? extends ExpressionTree> initializers = (List<? extends ExpressionTree>) resolveMultiParameters(node.getInitializers());
71.1135 + NewArrayTree nue = make.NewArray(node.getType(), dimensions, initializers);
71.1136 +
71.1137 + rewrite(node, nue);
71.1138 + return super.visitNewArray(node, p);
71.1139 + }
71.1140 +
71.1141 + @Override
71.1142 + public Number visitLambdaExpression(LambdaExpressionTree node, Void p) {
71.1143 + List<? extends VariableTree> args = resolveMultiParameters(node.getParameters());
71.1144 + LambdaExpressionTree nue = make.LambdaExpression(args, node.getBody());
71.1145 +
71.1146 + rewrite(node, nue);
71.1147 +
71.1148 + return super.visitLambdaExpression(node, p);
71.1149 + }
71.1150 +
71.1151 + private <T extends Tree> List<T> resolveMultiParameters(List<T> list) {
71.1152 + if (list == null) return null;
71.1153 + if (!Utilities.containsMultistatementTrees(list)) return list;
71.1154 +
71.1155 + List<T> result = new LinkedList<T>();
71.1156 +
71.1157 + for (T t : list) {
71.1158 + if (Utilities.isMultistatementWildcardTree(t)) {
71.1159 + Collection<TreePath> embedded = parametersMulti.get(Utilities.getWildcardTreeName(t).toString());
71.1160 +
71.1161 + if (embedded != null) {
71.1162 + for (TreePath tp : embedded) {
71.1163 + result.add((T) tp.getLeaf());
71.1164 + }
71.1165 + }
71.1166 + } else {
71.1167 + result.add(t);
71.1168 + }
71.1169 + }
71.1170 +
71.1171 + return result;
71.1172 + }
71.1173 +
71.1174 + private <T extends Tree> T resolveOptionalValue(T in) {
71.1175 + if (in != null && Utilities.isMultistatementWildcardTree(in)) {
71.1176 + TreePath out = parameters.get(Utilities.getWildcardTreeName(in).toString());
71.1177 + if (out != null) return (T) out.getLeaf();
71.1178 + return null;
71.1179 + }
71.1180 +
71.1181 + return in;
71.1182 + }
71.1183 +
71.1184 + private ExpressionTree negate(ExpressionTree original, Tree parent, boolean nullOnPlainNeg) {
71.1185 + ExpressionTree newTree;
71.1186 + switch (original.getKind()) {
71.1187 + case PARENTHESIZED:
71.1188 + ExpressionTree expr = ((ParenthesizedTree) original).getExpression();
71.1189 + return negate(expr, original, nullOnPlainNeg);
71.1190 + case LOGICAL_COMPLEMENT:
71.1191 + newTree = ((UnaryTree) original).getExpression();
71.1192 + while (newTree.getKind() == Kind.PARENTHESIZED && !JavaFixUtilities.requiresParenthesis(((ParenthesizedTree) newTree).getExpression(), original, parent)) {
71.1193 + newTree = ((ParenthesizedTree) newTree).getExpression();
71.1194 + }
71.1195 + break;
71.1196 + case NOT_EQUAL_TO:
71.1197 + newTree = negateBinaryOperator(original, Kind.EQUAL_TO, false);
71.1198 + break;
71.1199 + case EQUAL_TO:
71.1200 + newTree = negateBinaryOperator(original, Kind.NOT_EQUAL_TO, false);
71.1201 + break;
71.1202 + case BOOLEAN_LITERAL:
71.1203 + newTree = make.Literal(!(Boolean) ((LiteralTree) original).getValue());
71.1204 + break;
71.1205 + case CONDITIONAL_AND:
71.1206 + newTree = negateBinaryOperator(original, Kind.CONDITIONAL_OR, true);
71.1207 + break;
71.1208 + case CONDITIONAL_OR:
71.1209 + newTree = negateBinaryOperator(original, Kind.CONDITIONAL_AND, true);
71.1210 + break;
71.1211 + case LESS_THAN:
71.1212 + newTree = negateBinaryOperator(original, Kind.GREATER_THAN_EQUAL, false);
71.1213 + break;
71.1214 + case LESS_THAN_EQUAL:
71.1215 + newTree = negateBinaryOperator(original, Kind.GREATER_THAN, false);
71.1216 + break;
71.1217 + case GREATER_THAN:
71.1218 + newTree = negateBinaryOperator(original, Kind.LESS_THAN_EQUAL, false);
71.1219 + break;
71.1220 + case GREATER_THAN_EQUAL:
71.1221 + newTree = negateBinaryOperator(original, Kind.LESS_THAN, false);
71.1222 + break;
71.1223 + default:
71.1224 + if (nullOnPlainNeg)
71.1225 + return null;
71.1226 + newTree = make.Unary(Kind.LOGICAL_COMPLEMENT, original);
71.1227 + }
71.1228 +
71.1229 + if (JavaFixUtilities.requiresParenthesis(newTree, original, parent)) {
71.1230 + newTree = make.Parenthesized(newTree);
71.1231 + }
71.1232 +
71.1233 + return newTree;
71.1234 + }
71.1235 +
71.1236 + private ExpressionTree negateBinaryOperator(Tree original, Kind newKind, boolean negateOperands) {
71.1237 + BinaryTree bt = (BinaryTree) original;
71.1238 + if (negateOperands) {
71.1239 + ExpressionTree lo = negate(bt.getLeftOperand(), original, false);
71.1240 + ExpressionTree ro = negate(bt.getRightOperand(), original, false);
71.1241 + return make.Binary(newKind,
71.1242 + lo != null ? lo : bt.getLeftOperand(),
71.1243 + ro != null ? ro : bt.getRightOperand());
71.1244 + }
71.1245 + return make.Binary(newKind,
71.1246 + bt.getLeftOperand(),
71.1247 + bt.getRightOperand());
71.1248 + }
71.1249 +
71.1250 + private void rewrite(Tree from, Tree to) {
71.1251 + if (originalTrees.contains(from)) return ;
71.1252 + rewriteFromTo.put(from, to);
71.1253 + }
71.1254 + }
71.1255 +
71.1256 + private static final Map<Kind, Integer> OPERATOR_PRIORITIES;
71.1257 +
71.1258 + static {
71.1259 + OPERATOR_PRIORITIES = new EnumMap<Kind, Integer>(Kind.class);
71.1260 +
71.1261 + OPERATOR_PRIORITIES.put(Kind.IDENTIFIER, 0);
71.1262 +
71.1263 + for (Kind k : Kind.values()) {
71.1264 + if (k.asInterface() == LiteralTree.class) {
71.1265 + OPERATOR_PRIORITIES.put(k, 0);
71.1266 + }
71.1267 + }
71.1268 +
71.1269 + OPERATOR_PRIORITIES.put(Kind.ARRAY_ACCESS, 1);
71.1270 + OPERATOR_PRIORITIES.put(Kind.METHOD_INVOCATION, 1);
71.1271 + OPERATOR_PRIORITIES.put(Kind.MEMBER_SELECT, 1);
71.1272 + OPERATOR_PRIORITIES.put(Kind.POSTFIX_DECREMENT, 1);
71.1273 + OPERATOR_PRIORITIES.put(Kind.POSTFIX_INCREMENT, 1);
71.1274 + OPERATOR_PRIORITIES.put(Kind.NEW_ARRAY, 1);
71.1275 + OPERATOR_PRIORITIES.put(Kind.NEW_CLASS, 1);
71.1276 +
71.1277 + OPERATOR_PRIORITIES.put(Kind.BITWISE_COMPLEMENT, 2);
71.1278 + OPERATOR_PRIORITIES.put(Kind.LOGICAL_COMPLEMENT, 2);
71.1279 + OPERATOR_PRIORITIES.put(Kind.PREFIX_DECREMENT, 2);
71.1280 + OPERATOR_PRIORITIES.put(Kind.PREFIX_INCREMENT, 2);
71.1281 + OPERATOR_PRIORITIES.put(Kind.UNARY_MINUS, 2);
71.1282 + OPERATOR_PRIORITIES.put(Kind.UNARY_PLUS, 2);
71.1283 +
71.1284 + OPERATOR_PRIORITIES.put(Kind.TYPE_CAST, 3);
71.1285 +
71.1286 + OPERATOR_PRIORITIES.put(Kind.DIVIDE, 4);
71.1287 + OPERATOR_PRIORITIES.put(Kind.MULTIPLY, 4);
71.1288 + OPERATOR_PRIORITIES.put(Kind.REMAINDER, 4);
71.1289 +
71.1290 + OPERATOR_PRIORITIES.put(Kind.MINUS, 5);
71.1291 + OPERATOR_PRIORITIES.put(Kind.PLUS, 5);
71.1292 +
71.1293 + OPERATOR_PRIORITIES.put(Kind.LEFT_SHIFT, 6);
71.1294 + OPERATOR_PRIORITIES.put(Kind.RIGHT_SHIFT, 6);
71.1295 + OPERATOR_PRIORITIES.put(Kind.UNSIGNED_RIGHT_SHIFT, 6);
71.1296 +
71.1297 + OPERATOR_PRIORITIES.put(Kind.INSTANCE_OF, 7);
71.1298 + OPERATOR_PRIORITIES.put(Kind.GREATER_THAN, 7);
71.1299 + OPERATOR_PRIORITIES.put(Kind.GREATER_THAN_EQUAL, 7);
71.1300 + OPERATOR_PRIORITIES.put(Kind.LESS_THAN, 7);
71.1301 + OPERATOR_PRIORITIES.put(Kind.LESS_THAN_EQUAL, 7);
71.1302 +
71.1303 + OPERATOR_PRIORITIES.put(Kind.EQUAL_TO, 8);
71.1304 + OPERATOR_PRIORITIES.put(Kind.NOT_EQUAL_TO, 8);
71.1305 +
71.1306 + OPERATOR_PRIORITIES.put(Kind.AND, 9);
71.1307 + OPERATOR_PRIORITIES.put(Kind.OR, 11);
71.1308 + OPERATOR_PRIORITIES.put(Kind.XOR, 10);
71.1309 +
71.1310 + OPERATOR_PRIORITIES.put(Kind.CONDITIONAL_AND, 12);
71.1311 + OPERATOR_PRIORITIES.put(Kind.CONDITIONAL_OR, 13);
71.1312 +
71.1313 + OPERATOR_PRIORITIES.put(Kind.CONDITIONAL_EXPRESSION, 14);
71.1314 +
71.1315 + OPERATOR_PRIORITIES.put(Kind.AND_ASSIGNMENT, 15);
71.1316 + OPERATOR_PRIORITIES.put(Kind.ASSIGNMENT, 15);
71.1317 + OPERATOR_PRIORITIES.put(Kind.DIVIDE_ASSIGNMENT, 15);
71.1318 + OPERATOR_PRIORITIES.put(Kind.LEFT_SHIFT_ASSIGNMENT, 15);
71.1319 + OPERATOR_PRIORITIES.put(Kind.MINUS_ASSIGNMENT, 15);
71.1320 + OPERATOR_PRIORITIES.put(Kind.MULTIPLY_ASSIGNMENT, 15);
71.1321 + OPERATOR_PRIORITIES.put(Kind.OR_ASSIGNMENT, 15);
71.1322 + OPERATOR_PRIORITIES.put(Kind.PLUS_ASSIGNMENT, 15);
71.1323 + OPERATOR_PRIORITIES.put(Kind.REMAINDER_ASSIGNMENT, 15);
71.1324 + OPERATOR_PRIORITIES.put(Kind.RIGHT_SHIFT_ASSIGNMENT, 15);
71.1325 + OPERATOR_PRIORITIES.put(Kind.UNSIGNED_RIGHT_SHIFT_ASSIGNMENT, 15);
71.1326 + OPERATOR_PRIORITIES.put(Kind.XOR_ASSIGNMENT, 15);
71.1327 + }
71.1328 +
71.1329 + /**Checks whether putting {@code inner} tree into {@code outter} tree,
71.1330 + * when {@code original} is being replaced with {@code inner} requires parentheses.
71.1331 + *
71.1332 + * @param inner the new tree node that will be placed under {@code outter}
71.1333 + * @param original the tree node that is being replaced with {@code inner}
71.1334 + * @param outter the future parent node of {@code inner}
71.1335 + * @return true if and only if inner needs to be wrapped using {@link TreeMaker#Parenthesized(com.sun.source.tree.ExpressionTree) }
71.1336 + * to keep the original meaning.
71.1337 + */
71.1338 + public static boolean requiresParenthesis(Tree inner, Tree original, Tree outter) {
71.1339 + if (!ExpressionTree.class.isAssignableFrom(inner.getKind().asInterface())) return false;
71.1340 + if (!ExpressionTree.class.isAssignableFrom(outter.getKind().asInterface())) return false;
71.1341 +
71.1342 + if (outter.getKind() == Kind.PARENTHESIZED || inner.getKind() == Kind.PARENTHESIZED) return false;
71.1343 +
71.1344 + if (outter.getKind() == Kind.METHOD_INVOCATION) {
71.1345 + if (((MethodInvocationTree) outter).getArguments().contains(original)) return false;
71.1346 + }
71.1347 +
71.1348 + if (outter.getKind() == Kind.NEW_CLASS) {
71.1349 + if (((NewClassTree) outter).getArguments().contains(original)) return false;
71.1350 + }
71.1351 +
71.1352 + Integer innerPriority = OPERATOR_PRIORITIES.get(inner.getKind());
71.1353 + Integer outterPriority = OPERATOR_PRIORITIES.get(outter.getKind());
71.1354 +
71.1355 + if (innerPriority == null || outterPriority == null) {
71.1356 + Logger.getLogger(JavaFix.class.getName()).log(Level.WARNING, "Unknown tree kind(s): {0}/{1}", new Object[] {inner.getKind(), outter.getKind()});
71.1357 + return true;
71.1358 + }
71.1359 +
71.1360 + if (innerPriority > outterPriority) {
71.1361 + return true;
71.1362 + }
71.1363 +
71.1364 + if (innerPriority < outterPriority) {
71.1365 + return false;
71.1366 + }
71.1367 +
71.1368 + //associativity
71.1369 + if (BinaryTree.class.isAssignableFrom(outter.getKind().asInterface())) {
71.1370 + BinaryTree ot = (BinaryTree) outter;
71.1371 +
71.1372 + //TODO: for + it might be possible to skip the parenthesis:
71.1373 + return ot.getRightOperand() == original;
71.1374 + }
71.1375 +
71.1376 + if (CompoundAssignmentTree.class.isAssignableFrom(outter.getKind().asInterface())) {
71.1377 + CompoundAssignmentTree ot = (CompoundAssignmentTree) outter;
71.1378 +
71.1379 + return ot.getVariable() == original;
71.1380 + }
71.1381 +
71.1382 + if (AssignmentTree.class.isAssignableFrom(outter.getKind().asInterface())) {
71.1383 + AssignmentTree ot = (AssignmentTree) outter;
71.1384 +
71.1385 + return ot.getVariable() == original;
71.1386 + }
71.1387 +
71.1388 + return false;
71.1389 + }
71.1390 +
71.1391 + private static final class RemoveFromParent extends JavaFix {
71.1392 +
71.1393 + private final String displayName;
71.1394 +
71.1395 + public RemoveFromParent(String displayName, CompilationInfo info, TreePath toRemove) {
71.1396 + super(info, toRemove);
71.1397 + this.displayName = displayName;
71.1398 + }
71.1399 +
71.1400 + @Override
71.1401 + protected String getText() {
71.1402 + return displayName;
71.1403 + }
71.1404 +
71.1405 + @Override
71.1406 + protected void performRewrite(TransformationContext ctx) {
71.1407 + WorkingCopy wc = ctx.getWorkingCopy();
71.1408 + TreePath tp = ctx.getPath();
71.1409 +
71.1410 + doRemoveFromParent(wc, tp);
71.1411 + }
71.1412 +
71.1413 + private void doRemoveFromParent(WorkingCopy wc, TreePath what) {
71.1414 + TreeMaker make = wc.getTreeMaker();
71.1415 + Tree leaf = what.getLeaf();
71.1416 + Tree parentLeaf = what.getParentPath().getLeaf();
71.1417 +
71.1418 + switch (parentLeaf.getKind()) {
71.1419 + case ANNOTATION:
71.1420 + AnnotationTree at = (AnnotationTree) parentLeaf;
71.1421 + AnnotationTree newAnnot;
71.1422 +
71.1423 + newAnnot = make.removeAnnotationAttrValue(at, (ExpressionTree) leaf);
71.1424 +
71.1425 + wc.rewrite(at, newAnnot);
71.1426 + break;
71.1427 + case BLOCK:
71.1428 + BlockTree bt = (BlockTree) parentLeaf;
71.1429 +
71.1430 + wc.rewrite(bt, make.removeBlockStatement(bt, (StatementTree) leaf));
71.1431 + break;
71.1432 + case CASE:
71.1433 + CaseTree caseTree = (CaseTree) parentLeaf;
71.1434 +
71.1435 + wc.rewrite(caseTree, make.removeCaseStatement(caseTree, (StatementTree) leaf));
71.1436 + break;
71.1437 + case CLASS:
71.1438 + ClassTree classTree = (ClassTree) parentLeaf;
71.1439 + ClassTree nueClassTree;
71.1440 +
71.1441 + if (classTree.getTypeParameters().contains(leaf)) {
71.1442 + nueClassTree = make.removeClassTypeParameter(classTree, (TypeParameterTree) leaf);
71.1443 + } else if (classTree.getExtendsClause() == leaf) {
71.1444 + nueClassTree = make.Class(classTree.getModifiers(), classTree.getSimpleName(), classTree.getTypeParameters(), null, classTree.getImplementsClause(), classTree.getMembers());
71.1445 + } else if (classTree.getImplementsClause().contains(leaf)) {
71.1446 + nueClassTree = make.removeClassImplementsClause(classTree, leaf);
71.1447 + } else if (classTree.getMembers().contains(leaf)) {
71.1448 + nueClassTree = make.removeClassMember(classTree, leaf);
71.1449 + } else {
71.1450 + throw new UnsupportedOperationException();
71.1451 + }
71.1452 +
71.1453 + wc.rewrite(classTree, nueClassTree);
71.1454 + break;
71.1455 + case UNION_TYPE:
71.1456 + UnionTypeTree disjunct = (UnionTypeTree) parentLeaf;
71.1457 + List<? extends Tree> alternatives = new LinkedList<Tree>(disjunct.getTypeAlternatives());
71.1458 +
71.1459 + alternatives.remove(leaf);
71.1460 +
71.1461 + wc.rewrite(disjunct, make.UnionType(alternatives));
71.1462 + break;
71.1463 + case METHOD:
71.1464 + MethodTree mTree = (MethodTree) parentLeaf;
71.1465 + MethodTree newMethod;
71.1466 +
71.1467 + if (mTree.getTypeParameters().contains(leaf)) {
71.1468 + newMethod = make.removeMethodTypeParameter(mTree, (TypeParameterTree) leaf);
71.1469 + } else if (mTree.getParameters().contains(leaf)) {
71.1470 + newMethod = make.removeMethodParameter(mTree, (VariableTree) leaf);
71.1471 + } else if (mTree.getThrows().contains(leaf)) {
71.1472 + newMethod = make.removeMethodThrows(mTree, (ExpressionTree) leaf);
71.1473 + } else {
71.1474 + throw new UnsupportedOperationException();
71.1475 + }
71.1476 +
71.1477 + wc.rewrite(mTree, newMethod);
71.1478 + break;
71.1479 + case METHOD_INVOCATION:
71.1480 + MethodInvocationTree iTree = (MethodInvocationTree) parentLeaf;
71.1481 + MethodInvocationTree newInvocation;
71.1482 +
71.1483 + if (iTree.getTypeArguments().contains(leaf)) {
71.1484 + newInvocation = make.removeMethodInvocationTypeArgument(iTree, (ExpressionTree) leaf);
71.1485 + } else if (iTree.getArguments().contains(leaf)) {
71.1486 + newInvocation = make.removeMethodInvocationArgument(iTree, (ExpressionTree) leaf);
71.1487 + } else {
71.1488 + throw new UnsupportedOperationException();
71.1489 + }
71.1490 +
71.1491 + wc.rewrite(iTree, newInvocation);
71.1492 + break;
71.1493 + case MODIFIERS:
71.1494 + ModifiersTree modsTree = (ModifiersTree) parentLeaf;
71.1495 +
71.1496 + wc.rewrite(modsTree, make.removeModifiersAnnotation(modsTree, (AnnotationTree) leaf));
71.1497 + break;
71.1498 + case NEW_CLASS:
71.1499 + NewClassTree newCTree = (NewClassTree) parentLeaf;
71.1500 + NewClassTree newNCT;
71.1501 +
71.1502 + if (newCTree.getTypeArguments().contains(leaf)) {
71.1503 + newNCT = make.removeNewClassTypeArgument(newCTree, (ExpressionTree) leaf);
71.1504 + } else if (newCTree.getArguments().contains(leaf)) {
71.1505 + newNCT = make.removeNewClassArgument(newCTree, (ExpressionTree) leaf);
71.1506 + } else {
71.1507 + throw new UnsupportedOperationException();
71.1508 + }
71.1509 +
71.1510 + wc.rewrite(newCTree, newNCT);
71.1511 + break;
71.1512 + case PARAMETERIZED_TYPE:
71.1513 + ParameterizedTypeTree parTree = (ParameterizedTypeTree) parentLeaf;
71.1514 +
71.1515 + wc.rewrite(parTree, make.removeParameterizedTypeTypeArgument(parTree, (ExpressionTree) leaf));
71.1516 + break;
71.1517 + case SWITCH:
71.1518 + SwitchTree switchTree = (SwitchTree) parentLeaf;
71.1519 + SwitchTree newSwitch;
71.1520 +
71.1521 + if (switchTree.getCases().contains(leaf)) {
71.1522 + newSwitch = make.removeSwitchCase(switchTree, (CaseTree) leaf);
71.1523 + } else {
71.1524 + throw new UnsupportedOperationException();
71.1525 + }
71.1526 +
71.1527 + wc.rewrite(switchTree, newSwitch);
71.1528 + break;
71.1529 + case TRY:
71.1530 + TryTree tryTree = (TryTree) parentLeaf;
71.1531 + TryTree newTry;
71.1532 +
71.1533 + if (tryTree.getResources().contains(leaf)) {
71.1534 + LinkedList<Tree> resources = new LinkedList<Tree>(tryTree.getResources());
71.1535 +
71.1536 + resources.remove(leaf);
71.1537 +
71.1538 + newTry = make.Try(resources, tryTree.getBlock(), tryTree.getCatches(), tryTree.getFinallyBlock());
71.1539 + } else if (tryTree.getCatches().contains(leaf)) {
71.1540 + newTry = make.removeTryCatch(tryTree, (CatchTree) leaf);
71.1541 + } else {
71.1542 + throw new UnsupportedOperationException();
71.1543 + }
71.1544 +
71.1545 + wc.rewrite(tryTree, newTry);
71.1546 + break;
71.1547 + case EXPRESSION_STATEMENT:
71.1548 + doRemoveFromParent(wc, what.getParentPath());
71.1549 + break;
71.1550 + default:
71.1551 + wc.rewrite(what.getLeaf(), make.Block(Collections.<StatementTree>emptyList(), false));
71.1552 + break;
71.1553 + }
71.1554 + }
71.1555 +
71.1556 + }
71.1557 +
71.1558 + //TODO: from FileMovePlugin
71.1559 + private static class MoveFile extends SimpleRefactoringElementImplementation {
71.1560 +
71.1561 + private FileObject toMove;
71.1562 + private final FileObject sourceRoot;
71.1563 + private final String targetFolderName;
71.1564 +
71.1565 + public MoveFile(FileObject toMove, FileObject sourceRoot, String targetFolderName) {
71.1566 + this.toMove = toMove;
71.1567 + this.sourceRoot = sourceRoot;
71.1568 + this.targetFolderName = targetFolderName;
71.1569 + }
71.1570 +
71.1571 + @Override
71.1572 + @Messages({"#{0} - original file name", "TXT_MoveFile=Move {0}"})
71.1573 + public String getText() {
71.1574 + return Bundle.TXT_MoveFile(toMove.getNameExt());
71.1575 + }
71.1576 +
71.1577 + @Override
71.1578 + public String getDisplayText() {
71.1579 + return getText();
71.1580 + }
71.1581 +
71.1582 + DataFolder sourceFolder;
71.1583 + DataObject source;
71.1584 + @Override
71.1585 + public void performChange() {
71.1586 + try {
71.1587 + FileObject target = FileUtil.createFolder(sourceRoot, targetFolderName);
71.1588 + DataFolder targetFolder = DataFolder.findFolder(target);
71.1589 + if (!toMove.isValid()) {
71.1590 + String path = FileUtil.getFileDisplayName(toMove);
71.1591 + Logger.getLogger(JavaFix.class.getName()).fine("Invalid FileObject " + path + "trying to recreate...");
71.1592 + toMove = FileUtil.toFileObject(FileUtil.toFile(toMove));
71.1593 + if (toMove==null) {
71.1594 + Logger.getLogger(JavaFix.class.getName()).severe("Invalid FileObject " + path + "\n. File not found.");
71.1595 + return;
71.1596 + }
71.1597 + }
71.1598 + source = DataObject.find(toMove);
71.1599 + sourceFolder = source.getFolder();
71.1600 + source.move(targetFolder);
71.1601 + } catch (DataObjectNotFoundException ex) {
71.1602 + ex.printStackTrace();
71.1603 + } catch (IOException ex) {
71.1604 + ex.printStackTrace();
71.1605 + }
71.1606 + }
71.1607 +
71.1608 + @Override
71.1609 + public void undoChange() {
71.1610 + try {
71.1611 + source.move(sourceFolder);
71.1612 + } catch (DataObjectNotFoundException ex) {
71.1613 + ex.printStackTrace();
71.1614 + } catch (IOException ex) {
71.1615 + ex.printStackTrace();
71.1616 + }
71.1617 + }
71.1618 +
71.1619 + @Override
71.1620 + public Lookup getLookup() {
71.1621 + return Lookup.EMPTY;
71.1622 + }
71.1623 +
71.1624 + @Override
71.1625 + public FileObject getParentFile() {
71.1626 + return toMove;
71.1627 + }
71.1628 +
71.1629 + @Override
71.1630 + public PositionBounds getPosition() {
71.1631 + return null;
71.1632 + }
71.1633 + }
71.1634 +}
72.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
72.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/MatcherUtilities.java Wed May 08 21:47:42 2013 +0200
72.3 @@ -0,0 +1,157 @@
72.4 +/*
72.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
72.6 + *
72.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
72.8 + *
72.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
72.10 + * Other names may be trademarks of their respective owners.
72.11 + *
72.12 + * The contents of this file are subject to the terms of either the GNU
72.13 + * General Public License Version 2 only ("GPL") or the Common
72.14 + * Development and Distribution License("CDDL") (collectively, the
72.15 + * "License"). You may not use this file except in compliance with the
72.16 + * License. You can obtain a copy of the License at
72.17 + * http://www.netbeans.org/cddl-gplv2.html
72.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
72.19 + * specific language governing permissions and limitations under the
72.20 + * License. When distributing the software, include this License Header
72.21 + * Notice in each file and include the License file at
72.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
72.23 + * particular file as subject to the "Classpath" exception as provided
72.24 + * by Oracle in the GPL Version 2 section of the License file that
72.25 + * accompanied this code. If applicable, add the following below the
72.26 + * License Header, with the fields enclosed by brackets [] replaced by
72.27 + * your own identifying information:
72.28 + * "Portions Copyrighted [year] [name of copyright owner]"
72.29 + *
72.30 + * If you wish your version of this file to be governed by only the CDDL
72.31 + * or only the GPL Version 2, indicate your decision by adding
72.32 + * "[Contributor] elects to include this software in this distribution
72.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
72.34 + * single choice of license, a recipient has the option to distribute
72.35 + * your version of this file under either the CDDL, the GPL Version 2 or
72.36 + * to extend the choice of license to its licensees as provided above.
72.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
72.38 + * Version 2 license, then the option applies only if the new code is
72.39 + * made subject to such option by the copyright holder.
72.40 + *
72.41 + * Contributor(s):
72.42 + *
72.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
72.44 + */
72.45 +
72.46 +package org.netbeans.spi.java.hints;
72.47 +
72.48 +import com.sun.source.tree.BlockTree;
72.49 +import com.sun.source.tree.Scope;
72.50 +import com.sun.source.tree.StatementTree;
72.51 +import com.sun.source.tree.Tree;
72.52 +import com.sun.source.util.TreePath;
72.53 +import java.util.Collection;
72.54 +import java.util.Collections;
72.55 +import java.util.HashMap;
72.56 +import java.util.Iterator;
72.57 +import java.util.List;
72.58 +import java.util.Map;
72.59 +import java.util.concurrent.atomic.AtomicBoolean;
72.60 +import javax.lang.model.type.TypeMirror;
72.61 +import org.netbeans.api.annotations.common.NonNull;
72.62 +import org.netbeans.modules.java.hints.spiimpl.Utilities;
72.63 +import org.netbeans.modules.java.hints.spiimpl.pm.PatternCompiler;
72.64 +import org.netbeans.api.java.source.matching.Matcher;
72.65 +import org.netbeans.api.java.source.matching.Occurrence;
72.66 +import org.netbeans.api.java.source.matching.Pattern;
72.67 +
72.68 +/**XXX: cancelability
72.69 + * TODO: needed?
72.70 + *
72.71 + * @author lahvac
72.72 + */
72.73 +public class MatcherUtilities {
72.74 +
72.75 + public static boolean matches(@NonNull HintContext ctx, @NonNull TreePath variable, @NonNull String pattern) {
72.76 + return matches(ctx, variable, pattern, null, null, null);
72.77 + }
72.78 +
72.79 + public static boolean matches(@NonNull HintContext ctx, @NonNull TreePath variable, @NonNull String pattern, boolean fillInVariablesHack) {
72.80 + return matches(ctx, variable, pattern, ctx.getVariables(), ctx.getMultiVariables(), ctx.getVariableNames());
72.81 + }
72.82 +
72.83 + public static boolean matches(@NonNull HintContext ctx, @NonNull TreePath variable, @NonNull String pattern, Map<String, TreePath> outVariables, Map<String, Collection<? extends TreePath>> outMultiVariables, Map<String, String> outVariables2Names) {
72.84 + Pattern p = PatternCompiler.compile(ctx.getInfo(), pattern, Collections.<String, TypeMirror>emptyMap(), Collections.<String>emptyList());
72.85 + Map<String, TreePath> variables = new HashMap<String, TreePath>(ctx.getVariables());
72.86 + Map<String, Collection<? extends TreePath>> multiVariables = new HashMap<String, Collection<? extends TreePath>>(ctx.getMultiVariables());
72.87 + Map<String, String> variables2Names = new HashMap<String, String>(ctx.getVariableNames());
72.88 + Iterable<? extends Occurrence> occurrences = Matcher.create(ctx.getInfo()).setCancel(new AtomicBoolean()).setPresetVariable(variables, multiVariables, variables2Names).setSearchRoot(variable).setTreeTopSearch().match(p);
72.89 +
72.90 + if (occurrences.iterator().hasNext()) {
72.91 + Occurrence od = occurrences.iterator().next();
72.92 + outVariables(outVariables, od.getVariables(), ctx.getVariables());
72.93 + outVariables(outMultiVariables, od.getMultiVariables(), ctx.getMultiVariables());
72.94 + outVariables(outVariables2Names, od.getVariables2Names(), ctx.getVariableNames());
72.95 +
72.96 + return true;
72.97 + }
72.98 +
72.99 + return false;
72.100 + }
72.101 +
72.102 + public static boolean matches(@NonNull HintContext ctx, @NonNull Collection<? extends TreePath> variable, @NonNull String pattern, Map<String, TreePath> outVariables, Map<String, Collection<? extends TreePath>> outMultiVariables, Map<String, String> outVariables2Names) {
72.103 + Scope s = Utilities.constructScope(ctx.getInfo(), Collections.<String, TypeMirror>emptyMap());
72.104 + Tree patternTree = Utilities.parseAndAttribute(ctx.getInfo(), pattern, s);
72.105 + List<? extends Tree> patternTrees;
72.106 +
72.107 + if (Utilities.isFakeBlock(patternTree)) {
72.108 + List<? extends StatementTree> statements = ((BlockTree) patternTree).getStatements();
72.109 +
72.110 + patternTrees = statements.subList(1, statements.size() - 1);
72.111 + } else {
72.112 + patternTrees = Collections.singletonList(patternTree);
72.113 + }
72.114 +
72.115 + if (variable.size() != patternTrees.size()) return false;
72.116 +
72.117 + Map<String, TreePath> variables = new HashMap<String, TreePath>(ctx.getVariables());
72.118 + Map<String, Collection<? extends TreePath>> multiVariables = new HashMap<String, Collection<? extends TreePath>>(ctx.getMultiVariables());
72.119 + Map<String, String> variables2Names = new HashMap<String, String>(ctx.getVariableNames());
72.120 + Iterator<? extends TreePath> variableIt = variable.iterator();
72.121 + Iterator<? extends Tree> patternTreesIt = patternTrees.iterator();
72.122 +
72.123 + while (variableIt.hasNext() && patternTreesIt.hasNext()) {
72.124 + TreePath patternTreePath = new TreePath(new TreePath(ctx.getInfo().getCompilationUnit()), patternTreesIt.next());
72.125 + Pattern p = Pattern.createPatternWithFreeVariables(patternTreePath, Collections.<String, TypeMirror>emptyMap());
72.126 + Iterable<? extends Occurrence> occurrences = Matcher.create(ctx.getInfo()).setCancel(new AtomicBoolean()).setPresetVariable(variables, multiVariables, variables2Names).setSearchRoot(variableIt.next()).setTreeTopSearch().match(p);
72.127 +
72.128 + if (!occurrences.iterator().hasNext()) {
72.129 + return false;
72.130 + }
72.131 +
72.132 + Occurrence od = occurrences.iterator().next();
72.133 +
72.134 + variables = od.getVariables();
72.135 + multiVariables = od.getMultiVariables();
72.136 + variables2Names = od.getVariables2Names();
72.137 + }
72.138 +
72.139 + if (variableIt.hasNext() == patternTreesIt.hasNext()) {
72.140 + outVariables(outVariables, variables, ctx.getVariables());
72.141 + outVariables(outMultiVariables, multiVariables, ctx.getMultiVariables());
72.142 + outVariables(outVariables2Names, variables2Names, ctx.getVariableNames());
72.143 +
72.144 + return true;
72.145 + }
72.146 +
72.147 + return false;
72.148 + }
72.149 +
72.150 + private static <T> void outVariables(Map<String, T> outMap, Map<String, T> currentValues, Map<String, T> origValues) {
72.151 + if (outMap == null) return;
72.152 +
72.153 + for (String key : origValues.keySet()) {
72.154 + currentValues.remove(key);
72.155 + }
72.156 +
72.157 + outMap.putAll(currentValues);
72.158 + }
72.159 +
72.160 +}
73.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
73.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/TriggerPattern.java Wed May 08 21:47:42 2013 +0200
73.3 @@ -0,0 +1,93 @@
73.4 +/*
73.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
73.6 + *
73.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
73.8 + *
73.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
73.10 + * Other names may be trademarks of their respective owners.
73.11 + *
73.12 + * The contents of this file are subject to the terms of either the GNU
73.13 + * General Public License Version 2 only ("GPL") or the Common
73.14 + * Development and Distribution License("CDDL") (collectively, the
73.15 + * "License"). You may not use this file except in compliance with the
73.16 + * License. You can obtain a copy of the License at
73.17 + * http://www.netbeans.org/cddl-gplv2.html
73.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
73.19 + * specific language governing permissions and limitations under the
73.20 + * License. When distributing the software, include this License Header
73.21 + * Notice in each file and include the License file at
73.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
73.23 + * particular file as subject to the "Classpath" exception as provided
73.24 + * by Oracle in the GPL Version 2 section of the License file that
73.25 + * accompanied this code. If applicable, add the following below the
73.26 + * License Header, with the fields enclosed by brackets [] replaced by
73.27 + * your own identifying information:
73.28 + * "Portions Copyrighted [year] [name of copyright owner]"
73.29 + *
73.30 + * If you wish your version of this file to be governed by only the CDDL
73.31 + * or only the GPL Version 2, indicate your decision by adding
73.32 + * "[Contributor] elects to include this software in this distribution
73.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
73.34 + * single choice of license, a recipient has the option to distribute
73.35 + * your version of this file under either the CDDL, the GPL Version 2 or
73.36 + * to extend the choice of license to its licensees as provided above.
73.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
73.38 + * Version 2 license, then the option applies only if the new code is
73.39 + * made subject to such option by the copyright holder.
73.40 + *
73.41 + * Contributor(s):
73.42 + *
73.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
73.44 + */
73.45 +
73.46 +package org.netbeans.spi.java.hints;
73.47 +
73.48 +import java.lang.annotation.ElementType;
73.49 +import java.lang.annotation.Retention;
73.50 +import java.lang.annotation.RetentionPolicy;
73.51 +import java.lang.annotation.Target;
73.52 +import org.netbeans.spi.editor.hints.ErrorDescription;
73.53 +
73.54 +/**Find parts of the source code that satisfy the given pattern, and invoke the method
73.55 + * that is annotated with this annotation.
73.56 + *
73.57 + * The method must be {@code public static}, the return type must either be assignable to
73.58 + * {@link ErrorDescription} or to {@link Iterable}{@code <? extends }{@link ErrorDescription}{@code >}.
73.59 + * Its sole parameter must be {@link HintContext}.
73.60 + *
73.61 + * @author lahvac
73.62 + */
73.63 +@Retention(RetentionPolicy.SOURCE)
73.64 +@Target(ElementType.METHOD)
73.65 +public @interface TriggerPattern {
73.66 +
73.67 + /**
73.68 + * Pattern to match on.
73.69 + * The pattern consists of:
73.70 + * <ul>
73.71 + * <li>a single Java expression</li>
73.72 + * <li>a single Java statement</li>
73.73 + * <li>multiple Java statements</li>
73.74 + * <li>a Java field, method or class</li>
73.75 + * </ul>
73.76 + *
73.77 + * Variables (identifiers starting with {@code $}) can be used to replace part of the pattern.
73.78 + * During matching, the actual part of the AST that corresponds to the variable in the pattern
73.79 + * will be "bound" to the variable. Variables whose names that do not end with a {@code $} ("single" variables)
73.80 + * will be bound to exactly one AST node, whereas variables whose names end with a {@code $} ("multi" variables)
73.81 + * will be bound to any number of consecutive AST nodes (with the same AST node as a parent).
73.82 + *
73.83 + * The actual AST nodes that were bound to single variables are available through {@link HintContext#getVariables() },
73.84 + * nodes bound to multi variables are available through {@link HintContext#getMultiVariables() }.
73.85 + *
73.86 + * For variables that represent an expression, a type constraint can be specified using the
73.87 + * {@link #constraints() } attribute.
73.88 + *
73.89 + * All classes should be referred to using FQNs.
73.90 + */
73.91 + public String value();
73.92 + /**Expected types for variables from the {@link #value() pattern}.
73.93 + */
73.94 + public ConstraintVariableType[] constraints() default {};
73.95 +
73.96 +}
74.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
74.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/TriggerPatterns.java Wed May 08 21:47:42 2013 +0200
74.3 @@ -0,0 +1,60 @@
74.4 +/*
74.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
74.6 + *
74.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
74.8 + *
74.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
74.10 + * Other names may be trademarks of their respective owners.
74.11 + *
74.12 + * The contents of this file are subject to the terms of either the GNU
74.13 + * General Public License Version 2 only ("GPL") or the Common
74.14 + * Development and Distribution License("CDDL") (collectively, the
74.15 + * "License"). You may not use this file except in compliance with the
74.16 + * License. You can obtain a copy of the License at
74.17 + * http://www.netbeans.org/cddl-gplv2.html
74.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
74.19 + * specific language governing permissions and limitations under the
74.20 + * License. When distributing the software, include this License Header
74.21 + * Notice in each file and include the License file at
74.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
74.23 + * particular file as subject to the "Classpath" exception as provided
74.24 + * by Oracle in the GPL Version 2 section of the License file that
74.25 + * accompanied this code. If applicable, add the following below the
74.26 + * License Header, with the fields enclosed by brackets [] replaced by
74.27 + * your own identifying information:
74.28 + * "Portions Copyrighted [year] [name of copyright owner]"
74.29 + *
74.30 + * If you wish your version of this file to be governed by only the CDDL
74.31 + * or only the GPL Version 2, indicate your decision by adding
74.32 + * "[Contributor] elects to include this software in this distribution
74.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
74.34 + * single choice of license, a recipient has the option to distribute
74.35 + * your version of this file under either the CDDL, the GPL Version 2 or
74.36 + * to extend the choice of license to its licensees as provided above.
74.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
74.38 + * Version 2 license, then the option applies only if the new code is
74.39 + * made subject to such option by the copyright holder.
74.40 + *
74.41 + * Contributor(s):
74.42 + *
74.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
74.44 + */
74.45 +
74.46 +package org.netbeans.spi.java.hints;
74.47 +
74.48 +import java.lang.annotation.ElementType;
74.49 +import java.lang.annotation.Retention;
74.50 +import java.lang.annotation.RetentionPolicy;
74.51 +import java.lang.annotation.Target;
74.52 +
74.53 +/**Multiple {@link TriggerPattern}s.
74.54 + *
74.55 + * @author lahvac
74.56 + */
74.57 +@Retention(RetentionPolicy.SOURCE)
74.58 +@Target(ElementType.METHOD)
74.59 +public @interface TriggerPatterns {
74.60 +
74.61 + public TriggerPattern[] value();
74.62 +
74.63 +}
75.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
75.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/TriggerTreeKind.java Wed May 08 21:47:42 2013 +0200
75.3 @@ -0,0 +1,66 @@
75.4 +/*
75.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
75.6 + *
75.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
75.8 + *
75.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
75.10 + * Other names may be trademarks of their respective owners.
75.11 + *
75.12 + * The contents of this file are subject to the terms of either the GNU
75.13 + * General Public License Version 2 only ("GPL") or the Common
75.14 + * Development and Distribution License("CDDL") (collectively, the
75.15 + * "License"). You may not use this file except in compliance with the
75.16 + * License. You can obtain a copy of the License at
75.17 + * http://www.netbeans.org/cddl-gplv2.html
75.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
75.19 + * specific language governing permissions and limitations under the
75.20 + * License. When distributing the software, include this License Header
75.21 + * Notice in each file and include the License file at
75.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
75.23 + * particular file as subject to the "Classpath" exception as provided
75.24 + * by Oracle in the GPL Version 2 section of the License file that
75.25 + * accompanied this code. If applicable, add the following below the
75.26 + * License Header, with the fields enclosed by brackets [] replaced by
75.27 + * your own identifying information:
75.28 + * "Portions Copyrighted [year] [name of copyright owner]"
75.29 + *
75.30 + * If you wish your version of this file to be governed by only the CDDL
75.31 + * or only the GPL Version 2, indicate your decision by adding
75.32 + * "[Contributor] elects to include this software in this distribution
75.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
75.34 + * single choice of license, a recipient has the option to distribute
75.35 + * your version of this file under either the CDDL, the GPL Version 2 or
75.36 + * to extend the choice of license to its licensees as provided above.
75.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
75.38 + * Version 2 license, then the option applies only if the new code is
75.39 + * made subject to such option by the copyright holder.
75.40 + *
75.41 + * Contributor(s):
75.42 + *
75.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
75.44 + */
75.45 +
75.46 +package org.netbeans.spi.java.hints;
75.47 +
75.48 +import com.sun.source.tree.Tree.Kind;
75.49 +import com.sun.source.util.TreePath;
75.50 +import java.lang.annotation.ElementType;
75.51 +import java.lang.annotation.Retention;
75.52 +import java.lang.annotation.RetentionPolicy;
75.53 +import java.lang.annotation.Target;
75.54 +
75.55 +/**Invoke the method for {@link TreePath}s of the given kind.
75.56 + *
75.57 + * The method must be {@code public static}, the return type must either be assignable to
75.58 + * {@link ErrorDescription} or to {@link Iterable}{@code <? extends }{@link ErrorDescription}{@code >}.
75.59 + * Its sole parameter must be {@link HintContext}.
75.60 + *
75.61 + * @author lahvac
75.62 + */
75.63 +@Retention(RetentionPolicy.SOURCE)
75.64 +@Target(ElementType.METHOD)
75.65 +public @interface TriggerTreeKind {
75.66 +
75.67 + public Kind[] value();
75.68 +
75.69 +}
76.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
76.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/UseOptions.java Wed May 08 21:47:42 2013 +0200
76.3 @@ -0,0 +1,64 @@
76.4 +/*
76.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
76.6 + *
76.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
76.8 + *
76.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
76.10 + * Other names may be trademarks of their respective owners.
76.11 + *
76.12 + * The contents of this file are subject to the terms of either the GNU
76.13 + * General Public License Version 2 only ("GPL") or the Common
76.14 + * Development and Distribution License("CDDL") (collectively, the
76.15 + * "License"). You may not use this file except in compliance with the
76.16 + * License. You can obtain a copy of the License at
76.17 + * http://www.netbeans.org/cddl-gplv2.html
76.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
76.19 + * specific language governing permissions and limitations under the
76.20 + * License. When distributing the software, include this License Header
76.21 + * Notice in each file and include the License file at
76.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
76.23 + * particular file as subject to the "Classpath" exception as provided
76.24 + * by Oracle in the GPL Version 2 section of the License file that
76.25 + * accompanied this code. If applicable, add the following below the
76.26 + * License Header, with the fields enclosed by brackets [] replaced by
76.27 + * your own identifying information:
76.28 + * "Portions Copyrighted [year] [name of copyright owner]"
76.29 + *
76.30 + * If you wish your version of this file to be governed by only the CDDL
76.31 + * or only the GPL Version 2, indicate your decision by adding
76.32 + * "[Contributor] elects to include this software in this distribution
76.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
76.34 + * single choice of license, a recipient has the option to distribute
76.35 + * your version of this file under either the CDDL, the GPL Version 2 or
76.36 + * to extend the choice of license to its licensees as provided above.
76.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
76.38 + * Version 2 license, then the option applies only if the new code is
76.39 + * made subject to such option by the copyright holder.
76.40 + *
76.41 + * Contributor(s):
76.42 + *
76.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
76.44 + */
76.45 +package org.netbeans.spi.java.hints;
76.46 +
76.47 +import java.lang.annotation.ElementType;
76.48 +import java.lang.annotation.Retention;
76.49 +import java.lang.annotation.RetentionPolicy;
76.50 +import java.lang.annotation.Target;
76.51 +
76.52 +/**Specifies which options from the enclosing class should be used for this hint.
76.53 + *
76.54 + * Only applies to methods marked with the {@link Hint} annotation.
76.55 + *
76.56 + * @author lahvac
76.57 + */
76.58 +@Retention(RetentionPolicy.SOURCE)
76.59 +@Target(ElementType.METHOD)
76.60 +public @interface UseOptions {
76.61 +
76.62 + /**Keys (values of the compile-time constants) of the options that should be used
76.63 + * for this hint method.
76.64 + */
76.65 + public String[] value();
76.66 +
76.67 +}
77.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
77.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/support/FixFactory.java Wed May 08 21:47:42 2013 +0200
77.3 @@ -0,0 +1,171 @@
77.4 +/*
77.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
77.6 + *
77.7 + * Copyright 1997-2012 Oracle and/or its affiliates. All rights reserved.
77.8 + *
77.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
77.10 + * Other names may be trademarks of their respective owners.
77.11 + *
77.12 + * The contents of this file are subject to the terms of either the GNU
77.13 + * General Public License Version 2 only ("GPL") or the Common
77.14 + * Development and Distribution License("CDDL") (collectively, the
77.15 + * "License"). You may not use this file except in compliance with the
77.16 + * License. You can obtain a copy of the License at
77.17 + * http://www.netbeans.org/cddl-gplv2.html
77.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
77.19 + * specific language governing permissions and limitations under the
77.20 + * License. When distributing the software, include this License Header
77.21 + * Notice in each file and include the License file at
77.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
77.23 + * particular file as subject to the "Classpath" exception as provided
77.24 + * by Oracle in the GPL Version 2 section of the License file that
77.25 + * accompanied this code. If applicable, add the following below the
77.26 + * License Header, with the fields enclosed by brackets [] replaced by
77.27 + * your own identifying information:
77.28 + * "Portions Copyrighted [year] [name of copyright owner]"
77.29 + *
77.30 + * Contributor(s):
77.31 + *
77.32 + * Portions Copyrighted 2007-2012 Sun Microsystems, Inc.
77.33 + */
77.34 +package org.netbeans.spi.java.hints.support;
77.35 +
77.36 +import com.sun.source.tree.ModifiersTree;
77.37 +import com.sun.source.tree.Tree.Kind;
77.38 +import com.sun.source.util.TreePath;
77.39 +import java.util.Collections;
77.40 +import java.util.EnumSet;
77.41 +import java.util.Set;
77.42 +import javax.lang.model.element.Modifier;
77.43 +import org.netbeans.api.java.source.CompilationInfo;
77.44 +import org.netbeans.api.java.source.TreeMaker;
77.45 +import org.netbeans.api.java.source.TreePathHandle;
77.46 +import org.netbeans.api.java.source.WorkingCopy;
77.47 +import org.netbeans.spi.editor.hints.Fix;
77.48 +import org.netbeans.spi.java.hints.JavaFix;
77.49 +import org.openide.util.Parameters;
77.50 +
77.51 +/** Factory for creating generally useful fixes. Currently, changes to the modifiers
77.52 + * are supported.
77.53 + *
77.54 + * @author Dusan Balek
77.55 + */
77.56 +public final class FixFactory {
77.57 +
77.58 + private FixFactory() {}
77.59 +
77.60 + /** Creates a fix, which when invoked adds a set of modifiers to the existing ones
77.61 + * @param compilationInfo CompilationInfo to work on
77.62 + * @param treePath TreePath to a ModifiersTree.
77.63 + * @param toAdd set of Modifiers to add
77.64 + * @param text text displayed as a fix description
77.65 + */
77.66 + public static final Fix addModifiersFix(CompilationInfo compilationInfo, TreePath treePath, Set<Modifier> toAdd, String text) {
77.67 + Parameters.notNull("compilationInfo", compilationInfo);
77.68 + Parameters.notNull("treePath", treePath);
77.69 + Parameters.notNull("toAdd", toAdd);
77.70 + Parameters.notNull("text", text);
77.71 +
77.72 + return changeModifiersFix(compilationInfo, treePath, toAdd, Collections.<Modifier>emptySet(), text);
77.73 + }
77.74 +
77.75 + /** Creates a fix, which when invoked removes a set of modifiers from the existing ones
77.76 + * @param compilationInfo CompilationInfo to work on
77.77 + * @param treePath TreePath to a ModifiersTree.
77.78 + * @param toRemove set of Modifiers to remove
77.79 + * @param text text displayed as a fix description
77.80 + */
77.81 + public static final Fix removeModifiersFix(CompilationInfo compilationInfo, TreePath treePath, Set<Modifier> toRemove, String text) {
77.82 + Parameters.notNull("compilationInfo", compilationInfo);
77.83 + Parameters.notNull("treePath", treePath);
77.84 + Parameters.notNull("toRemove", toRemove);
77.85 + Parameters.notNull("text", text);
77.86 +
77.87 + return changeModifiersFix(compilationInfo, treePath, Collections.<Modifier>emptySet(), toRemove, text);
77.88 + }
77.89 +
77.90 + /** Creates a fix, which when invoked changes the existing modifiers
77.91 + * @param compilationInfo CompilationInfo to work on
77.92 + * @param treePath TreePath to a ModifiersTree.
77.93 + * @param toAdd set of Modifiers to add
77.94 + * @param toRemove set of Modifiers to remove
77.95 + * @param text text displayed as a fix description
77.96 + */
77.97 + public static final Fix changeModifiersFix(CompilationInfo compilationInfo, TreePath treePath, Set<Modifier> toAdd, Set<Modifier> toRemove, String text) {
77.98 + Parameters.notNull("compilationInfo", compilationInfo);
77.99 + Parameters.notNull("treePath", treePath);
77.100 + Parameters.notNull("toAdd", toAdd);
77.101 + Parameters.notNull("toRemove", toRemove);
77.102 + Parameters.notNull("text", text);
77.103 +
77.104 + if (treePath.getLeaf().getKind() != Kind.MODIFIERS) {
77.105 + return null;
77.106 + }
77.107 + return new ChangeModifiersFixImpl(TreePathHandle.create(treePath, compilationInfo), toAdd, toRemove, text).toEditorFix();
77.108 + }
77.109 +
77.110 + private static final class ChangeModifiersFixImpl extends JavaFix {
77.111 +
77.112 + private final TreePathHandle modsHandle;
77.113 + private final Set<Modifier> toAdd;
77.114 + private final Set<Modifier> toRemove;
77.115 + private final String text;
77.116 +
77.117 + public ChangeModifiersFixImpl(TreePathHandle modsHandle, Set<Modifier> toAdd, Set<Modifier> toRemove, String text) {
77.118 + super(modsHandle);
77.119 + this.modsHandle = modsHandle;
77.120 + this.toAdd = toAdd;
77.121 + this.toRemove = toRemove;
77.122 + this.text = text;
77.123 + }
77.124 +
77.125 + public String getText() {
77.126 + return text;
77.127 + }
77.128 +
77.129 + @Override
77.130 + protected void performRewrite(TransformationContext ctx) {
77.131 + WorkingCopy wc = ctx.getWorkingCopy();
77.132 + TreePath path = ctx.getPath();
77.133 + TreeMaker make = wc.getTreeMaker();
77.134 + ModifiersTree newMods = (ModifiersTree) path.getLeaf();
77.135 + for (Modifier a : toAdd) {
77.136 + newMods = make.addModifiersModifier(newMods, a);
77.137 + }
77.138 + for (Modifier r : toRemove) {
77.139 + newMods = make.removeModifiersModifier(newMods, r);
77.140 + }
77.141 + wc.rewrite(path.getLeaf(), newMods);
77.142 + }
77.143 +
77.144 + @Override
77.145 + public boolean equals(Object obj) {
77.146 + if (obj == null) {
77.147 + return false;
77.148 + }
77.149 + if (getClass() != obj.getClass()) {
77.150 + return false;
77.151 + }
77.152 + final ChangeModifiersFixImpl other = (ChangeModifiersFixImpl) obj;
77.153 + if (this.modsHandle != other.modsHandle && (this.modsHandle == null || !this.modsHandle.equals(other.modsHandle))) {
77.154 + return false;
77.155 + }
77.156 + if (this.toAdd != other.toAdd && (this.toAdd == null || !this.toAdd.equals(other.toAdd))) {
77.157 + return false;
77.158 + }
77.159 + if (this.toRemove != other.toRemove && (this.toRemove == null || !this.toRemove.equals(other.toRemove))) {
77.160 + return false;
77.161 + }
77.162 + return true;
77.163 + }
77.164 +
77.165 + @Override
77.166 + public int hashCode() {
77.167 + int hash = 5;
77.168 + hash = 71 * hash + (this.modsHandle != null ? this.modsHandle.hashCode() : 0);
77.169 + hash = 71 * hash + (this.toAdd != null ? this.toAdd.hashCode() : 0);
77.170 + hash = 71 * hash + (this.toRemove != null ? this.toRemove.hashCode() : 0);
77.171 + return hash;
77.172 + }
77.173 + }
77.174 +}
78.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
78.2 +++ b/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/support/TransformationSupport.java Wed May 08 21:47:42 2013 +0200
78.3 @@ -0,0 +1,311 @@
78.4 +/*
78.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
78.6 + *
78.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
78.8 + *
78.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
78.10 + * Other names may be trademarks of their respective owners.
78.11 + *
78.12 + * The contents of this file are subject to the terms of either the GNU
78.13 + * General Public License Version 2 only ("GPL") or the Common
78.14 + * Development and Distribution License("CDDL") (collectively, the
78.15 + * "License"). You may not use this file except in compliance with the
78.16 + * License. You can obtain a copy of the License at
78.17 + * http://www.netbeans.org/cddl-gplv2.html
78.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
78.19 + * specific language governing permissions and limitations under the
78.20 + * License. When distributing the software, include this License Header
78.21 + * Notice in each file and include the License file at
78.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
78.23 + * particular file as subject to the "Classpath" exception as provided
78.24 + * by Oracle in the GPL Version 2 section of the License file that
78.25 + * accompanied this code. If applicable, add the following below the
78.26 + * License Header, with the fields enclosed by brackets [] replaced by
78.27 + * your own identifying information:
78.28 + * "Portions Copyrighted [year] [name of copyright owner]"
78.29 + *
78.30 + * If you wish your version of this file to be governed by only the CDDL
78.31 + * or only the GPL Version 2, indicate your decision by adding
78.32 + * "[Contributor] elects to include this software in this distribution
78.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
78.34 + * single choice of license, a recipient has the option to distribute
78.35 + * your version of this file under either the CDDL, the GPL Version 2 or
78.36 + * to extend the choice of license to its licensees as provided above.
78.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
78.38 + * Version 2 license, then the option applies only if the new code is
78.39 + * made subject to such option by the copyright holder.
78.40 + *
78.41 + * Contributor(s):
78.42 + *
78.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
78.44 + */
78.45 +package org.netbeans.spi.java.hints.support;
78.46 +
78.47 +import com.sun.source.util.TreePath;
78.48 +import java.util.*;
78.49 +import java.util.Map.Entry;
78.50 +import java.util.concurrent.atomic.AtomicBoolean;
78.51 +import javax.lang.model.type.TypeMirror;
78.52 +import org.netbeans.api.annotations.common.NonNull;
78.53 +import org.netbeans.api.java.source.CompilationInfo;
78.54 +import org.netbeans.api.java.source.ModificationResult;
78.55 +import org.netbeans.api.java.source.TypeMirrorHandle;
78.56 +import org.netbeans.api.java.source.WorkingCopy;
78.57 +import org.netbeans.api.java.source.matching.Matcher;
78.58 +import org.netbeans.api.java.source.matching.Occurrence;
78.59 +import org.netbeans.api.java.source.matching.Pattern;
78.60 +import org.netbeans.api.project.Project;
78.61 +import org.netbeans.modules.java.hints.jackpot.spi.PatternConvertor;
78.62 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
78.63 +import org.netbeans.modules.java.hints.providers.spi.HintDescriptionFactory;
78.64 +import org.netbeans.modules.java.hints.providers.spi.Trigger;
78.65 +import org.netbeans.modules.java.hints.spiimpl.JavaFixImpl;
78.66 +import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
78.67 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch;
78.68 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.BatchResult;
78.69 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchUtilities;
78.70 +import org.netbeans.modules.java.hints.spiimpl.batch.ProgressHandleWrapper;
78.71 +import org.netbeans.modules.java.hints.spiimpl.batch.Scopes;
78.72 +import org.netbeans.modules.java.hints.spiimpl.hints.HintsInvoker;
78.73 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
78.74 +import org.netbeans.modules.java.hints.spiimpl.pm.PatternCompiler;
78.75 +import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
78.76 +import org.netbeans.spi.editor.hints.*;
78.77 +import org.netbeans.spi.java.hints.HintContext;
78.78 +import org.netbeans.spi.java.hints.JavaFix;
78.79 +import org.openide.util.Exceptions;
78.80 +
78.81 +/**
78.82 + * Static utility classes for processing jackpot patterns.
78.83 + * <a href="https://bitbucket.org/jlahoda/jackpot30/wiki/RulesLanguage">Rules Language</a>
78.84 + * @author Jan Becicka
78.85 + * @since 1.1
78.86 + */
78.87 +public final class TransformationSupport {
78.88 +
78.89 + private String jackpotPattern;
78.90 + private Transformer transformer;
78.91 + private AtomicBoolean cancel = new AtomicBoolean();
78.92 +
78.93 + private TransformationSupport(String jackpotPattern, Transformer transformer) {
78.94 + this.jackpotPattern = jackpotPattern;
78.95 + this.transformer = transformer;
78.96 + }
78.97 +
78.98 + /**
78.99 + * Creates new TransformationSupport representing given jackpotPattern.
78.100 + * @param jackpotPattern
78.101 + * @return
78.102 + */
78.103 + public static @NonNull TransformationSupport create(@NonNull String jackpotPattern) {
78.104 + return new TransformationSupport(jackpotPattern, null);
78.105 + }
78.106 +
78.107 + /**
78.108 + * Creates new TransformationSupport representing given jackpotPattern with custom Transformer.
78.109 + * @param inputJackpotPattern
78.110 + * @param t
78.111 + * @see Transformer
78.112 + * @return
78.113 + */
78.114 + public static @NonNull TransformationSupport create(@NonNull String inputJackpotPattern, @NonNull Transformer t) {
78.115 + return new TransformationSupport(inputJackpotPattern, t);
78.116 + }
78.117 +
78.118 + /**
78.119 + * Option to cancel query.
78.120 + * @param cancel
78.121 + * @return
78.122 + */
78.123 + public @NonNull TransformationSupport setCancel(@NonNull AtomicBoolean cancel) {
78.124 + this.cancel = cancel;
78.125 + return this;
78.126 + }
78.127 +
78.128 +
78.129 + /**
78.130 + * Run current transformation on all projects and collect results.
78.131 + * @return collection of {@link ModificationResult}
78.132 + */
78.133 + public @NonNull Collection<? extends ModificationResult> processAllProjects() {
78.134 + if (transformer!=null) {
78.135 + return performTransformation(jackpotPattern, transformer, cancel);
78.136 + } else {
78.137 + return performTransformation(jackpotPattern, cancel);
78.138 + }
78.139 + }
78.140 +
78.141 +
78.142 + /**
78.143 + * Process current transformation on given treePath and performs rewrite on
78.144 + * workingCopy.
78.145 + * @param workingCopy
78.146 + * @param treePath
78.147 + */
78.148 + public void transformTreePath(@NonNull WorkingCopy workingCopy, @NonNull TreePath treePath) {
78.149 + if (transformer!=null) {
78.150 + throw new UnsupportedOperationException("Not implemented yet");
78.151 + } else {
78.152 + performTransformation(workingCopy, treePath, jackpotPattern, cancel);
78.153 + }
78.154 + }
78.155 +
78.156 +
78.157 + /**
78.158 + * Transformer callback which is called for each occurrence during processing
78.159 + * of {@link #performTransformation(java.lang.String, org.netbeans.spi.java.hints.support.JackpotSupport.Transformer, java.util.concurrent.atomic.AtomicBoolean)
78.160 + */
78.161 + public interface Transformer {
78.162 +
78.163 + /**
78.164 + * Implement custom transformation of occurrence here.
78.165 + * @param copy
78.166 + * @param occurrence
78.167 + */
78.168 + public void transform(WorkingCopy copy, Occurrence occurrence);
78.169 +
78.170 + }
78.171 +
78.172 +
78.173 +
78.174 + /**
78.175 + * Performs transformation described by jackpotPattern on given workingCopy.
78.176 + * @param workingCopy
78.177 + * @param jackpotPattern
78.178 + * @param cancel
78.179 + */
78.180 + private static void performTransformation(WorkingCopy workingCopy, TreePath on, String jackpotPattern, AtomicBoolean cancel) {
78.181 + Iterable<? extends HintDescription> hints = PatternConvertor.create(jackpotPattern);
78.182 + HintsInvoker inv = new HintsInvoker(HintsSettings.getSettingsFor(workingCopy.getFileObject()), cancel);
78.183 + Map<HintDescription, List<ErrorDescription>> computeHints = inv.computeHints(workingCopy, on, false, hints, new ArrayList<MessageImpl>());
78.184 +
78.185 + if (computeHints == null || cancel.get()) return ;
78.186 +
78.187 + List<ErrorDescription> errs = new ArrayList<ErrorDescription>();
78.188 + for (Entry<HintDescription, List<ErrorDescription>> entry: computeHints.entrySet()) {
78.189 + errs.addAll(entry.getValue());
78.190 + }
78.191 + List<MessageImpl> problems = new LinkedList<MessageImpl>();
78.192 +
78.193 + try {
78.194 + if (BatchUtilities.applyFixes(workingCopy, Collections.<Project, Set<String>>emptyMap(), errs, null, new ArrayList<RefactoringElementImplementation>(), problems)) {
78.195 + throw new IllegalStateException();
78.196 + }
78.197 + } catch (IllegalStateException ex) {
78.198 + Exceptions.printStackTrace(ex);
78.199 + } catch (Exception ex) {
78.200 + Exceptions.printStackTrace(ex);
78.201 + }
78.202 +
78.203 + if (!problems.isEmpty()) {
78.204 + throw new IllegalStateException(problems.get(0).text);
78.205 + }
78.206 + }
78.207 +
78.208 + /**
78.209 + * Performs jackpotPattern transformation in all open projects.
78.210 + * @param jackpotPattern
78.211 + * @param cancel
78.212 + * @return
78.213 + */
78.214 + private static Collection<? extends ModificationResult> performTransformation(String jackpotPattern, AtomicBoolean cancel) {
78.215 + Collection<MessageImpl> problems = new LinkedList<MessageImpl>();
78.216 + BatchResult batchResult = BatchSearch.findOccurrences(PatternConvertor.create(jackpotPattern), Scopes.allOpenedProjectsScope());
78.217 + return BatchUtilities.applyFixes(batchResult, new ProgressHandleWrapper(1, 1), cancel, problems);
78.218 + }
78.219 +
78.220 + /**
78.221 + * Performs transformation defined by transformer on all occurrences, which matches inputJackpotPattern.
78.222 + * @param inputJackpotPattern
78.223 + * @param transformer
78.224 + * @return collection of ModificationResults.
78.225 + */
78.226 + private static Collection<? extends ModificationResult> performTransformation(final String inputJackpotPattern, final Transformer transformer, AtomicBoolean cancel) {
78.227 + List<HintDescription> descriptions = new ArrayList<HintDescription>();
78.228 +
78.229 + for (HintDescription hd : PatternConvertor.create(inputJackpotPattern)) {
78.230 + final String triggerPattern = ((Trigger.PatternDescription) hd.getTrigger()).getPattern();
78.231 + descriptions.add(HintDescriptionFactory.create().setTrigger(hd.getTrigger()).setWorker(new HintDescription.Worker() {
78.232 + @Override public Collection<? extends ErrorDescription> createErrors(HintContext ctx) {
78.233 + final Map<String, TypeMirrorHandle<?>> constraintsHandles = new HashMap<String, TypeMirrorHandle<?>>();
78.234 +
78.235 + for (Map.Entry<String, TypeMirror> c : ctx.getConstraints().entrySet()) {
78.236 + constraintsHandles.put(c.getKey(), TypeMirrorHandle.create(c.getValue()));
78.237 + }
78.238 +
78.239 + Fix fix = new JavaFix(ctx.getInfo(), ctx.getPath()) {
78.240 + @Override protected String getText() {
78.241 + return "";
78.242 + }
78.243 + @Override protected void performRewrite(JavaFix.TransformationContext ctx) {
78.244 + WorkingCopy wc = ctx.getWorkingCopy();
78.245 + Map<String, TypeMirror> constraints = new HashMap<String, TypeMirror>();
78.246 +
78.247 + for (Map.Entry<String, TypeMirrorHandle<?>> c : constraintsHandles.entrySet()) {
78.248 + constraints.put(c.getKey(), c.getValue().resolve(wc));
78.249 + }
78.250 +
78.251 + Pattern pattern = PatternCompiler.compile(wc, triggerPattern, constraints, Collections.<String>emptyList());
78.252 + Collection<? extends Occurrence> occurrence = Matcher.create(wc).setTreeTopSearch().setSearchRoot(ctx.getPath()).match(pattern);
78.253 +
78.254 + assert occurrence.size() == 1;
78.255 +
78.256 + transformer.transform(wc, occurrence.iterator().next());
78.257 + }
78.258 + }.toEditorFix();
78.259 +
78.260 + return Collections.singletonList(ErrorDescriptionFactory.createErrorDescription(Severity.WARNING, "", Collections.singletonList(fix), ctx.getInfo().getFileObject(), 0, 0));
78.261 + }
78.262 + }).produce());
78.263 +
78.264 + }
78.265 +
78.266 + BatchSearch.BatchResult batchResult = BatchSearch.findOccurrences(descriptions, Scopes.allOpenedProjectsScope());
78.267 + return BatchUtilities.applyFixes(batchResult, new ProgressHandleWrapper(1, 1), cancel, new ArrayList<MessageImpl>());
78.268 + }
78.269 +
78.270 + /**
78.271 + * Performs transformation described by transformationJackpotPattern on all occurences described by inputJackpotPattern.
78.272 + * @param inputJackpotPattern
78.273 + * @param transformationJackpotPattern
78.274 + * @param cancel
78.275 + * @return
78.276 + */
78.277 + private static Collection<? extends ModificationResult> performTransformation(String inputJackpotPattern, final String transformationJackpotPattern, AtomicBoolean cancel) {
78.278 + return performTransformation(inputJackpotPattern, new Transformer() {
78.279 +
78.280 + @Override
78.281 + public void transform(WorkingCopy copy, Occurrence occurrence) {
78.282 + try {
78.283 + Fix toFix = TransformationSupport.rewriteFix(copy, "whatever", occurrence.getOccurrenceRoot(), transformationJackpotPattern, occurrence.getVariables(), occurrence.getMultiVariables(), occurrence.getVariables2Names(), Collections.<String, TypeMirror>emptyMap(), Collections.<String, String>emptyMap());
78.284 + TransformationSupport.process(((JavaFixImpl) toFix).jf, copy, false, null, new ArrayList<RefactoringElementImplementation>());
78.285 + } catch (Exception ex) {
78.286 + Exceptions.printStackTrace(ex);
78.287 + }
78.288 + }
78.289 + }, cancel);
78.290 + }
78.291 +
78.292 + private static ChangeInfo process(JavaFix jf, WorkingCopy wc, boolean canShowUI, Map<org.openide.filesystems.FileObject, byte[]> resourceContent, Collection<? super RefactoringElementImplementation> fileChanges) throws Exception {
78.293 + return JavaFixImpl.Accessor.INSTANCE.process(jf, wc, canShowUI, resourceContent, fileChanges);
78.294 + }
78.295 +
78.296 + /**
78.297 + *
78.298 + * @param info
78.299 + * @param displayName
78.300 + * @param what
78.301 + * @param to
78.302 + * @param parameters
78.303 + * @param parametersMulti
78.304 + * @param parameterNames
78.305 + * @param constraints
78.306 + * @param options
78.307 + * @param imports
78.308 + * @return
78.309 + */
78.310 + private static Fix rewriteFix(CompilationInfo info, String displayName, TreePath what, final String to, Map<String, TreePath> parameters, Map<String, Collection<? extends TreePath>> parametersMulti, final Map<String, String> parameterNames, Map<String, TypeMirror> constraints, Map<String, String> options, String... imports) {
78.311 + return JavaFixImpl.Accessor.INSTANCE.rewriteFix(info, displayName, what, to, parameters, parametersMulti, parameterNames, constraints, options, imports);
78.312 + }
78.313 +
78.314 +}
79.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
79.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/providers/code/CodeHintProviderImplTest.java Wed May 08 21:47:42 2013 +0200
79.3 @@ -0,0 +1,114 @@
79.4 +/*
79.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
79.6 + *
79.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
79.8 + *
79.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
79.10 + * Other names may be trademarks of their respective owners.
79.11 + *
79.12 + * The contents of this file are subject to the terms of either the GNU
79.13 + * General Public License Version 2 only ("GPL") or the Common
79.14 + * Development and Distribution License("CDDL") (collectively, the
79.15 + * "License"). You may not use this file except in compliance with the
79.16 + * License. You can obtain a copy of the License at
79.17 + * http://www.netbeans.org/cddl-gplv2.html
79.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
79.19 + * specific language governing permissions and limitations under the
79.20 + * License. When distributing the software, include this License Header
79.21 + * Notice in each file and include the License file at
79.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
79.23 + * particular file as subject to the "Classpath" exception as provided
79.24 + * by Oracle in the GPL Version 2 section of the License file that
79.25 + * accompanied this code. If applicable, add the following below the
79.26 + * License Header, with the fields enclosed by brackets [] replaced by
79.27 + * your own identifying information:
79.28 + * "Portions Copyrighted [year] [name of copyright owner]"
79.29 + *
79.30 + * If you wish your version of this file to be governed by only the CDDL
79.31 + * or only the GPL Version 2, indicate your decision by adding
79.32 + * "[Contributor] elects to include this software in this distribution
79.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
79.34 + * single choice of license, a recipient has the option to distribute
79.35 + * your version of this file under either the CDDL, the GPL Version 2 or
79.36 + * to extend the choice of license to its licensees as provided above.
79.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
79.38 + * Version 2 license, then the option applies only if the new code is
79.39 + * made subject to such option by the copyright holder.
79.40 + *
79.41 + * Contributor(s):
79.42 + *
79.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
79.44 + */
79.45 +
79.46 +package org.netbeans.modules.java.hints.providers.code;
79.47 +
79.48 +import com.sun.source.tree.Tree.Kind;
79.49 +import java.util.Arrays;
79.50 +import java.util.Collection;
79.51 +import java.util.HashSet;
79.52 +import java.util.Map;
79.53 +import java.util.Set;
79.54 +import org.junit.Test;
79.55 +import org.netbeans.spi.java.hints.ConstraintVariableType;
79.56 +import org.netbeans.spi.java.hints.Hint;
79.57 +import org.netbeans.spi.java.hints.TriggerPattern;
79.58 +import org.netbeans.spi.java.hints.TriggerTreeKind;
79.59 +import org.netbeans.spi.java.hints.HintContext;
79.60 +import static org.junit.Assert.*;
79.61 +import org.netbeans.modules.java.hints.providers.code.CodeHintProviderImpl.WorkerImpl;
79.62 +import org.netbeans.modules.java.hints.spiimpl.SPIAccessor;
79.63 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
79.64 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
79.65 +import org.netbeans.spi.editor.hints.ErrorDescription;
79.66 +
79.67 +/**
79.68 + *
79.69 + * @author lahvac
79.70 + */
79.71 +@Hint(displayName="foo", description="bar", id="hintPattern", category="general")
79.72 +public class CodeHintProviderImplTest {
79.73 +
79.74 + public CodeHintProviderImplTest() {
79.75 + }
79.76 +
79.77 + @Test
79.78 + public void testComputeHints() throws Exception {
79.79 + Map<HintMetadata, ? extends Collection<? extends HintDescription>> hints = new CodeHintProviderImpl().computeHints();
79.80 +
79.81 + Set<String> golden = new HashSet<String>(Arrays.asList(
79.82 + "$1.toURL():public static org.netbeans.spi.editor.hints.ErrorDescription org.netbeans.modules.java.hints.providers.code.CodeHintProviderImplTest.hintPattern1(org.netbeans.spi.java.hints.HintContext)",
79.83 + "[METHOD_INVOCATION]:public static org.netbeans.spi.editor.hints.ErrorDescription org.netbeans.modules.java.hints.providers.code.CodeHintProviderImplTest.hintPattern2(org.netbeans.spi.java.hints.HintContext)"
79.84 + ));
79.85 +
79.86 + for (Collection<? extends HintDescription> hds : hints.values()) {
79.87 + for (HintDescription d : hds) {
79.88 + golden.remove(toString(d));
79.89 + }
79.90 + }
79.91 +
79.92 + assertTrue(golden.toString(), golden.isEmpty());
79.93 + }
79.94 +
79.95 + private static String toString(HintDescription hd) throws Exception {
79.96 + StringBuilder sb = new StringBuilder();
79.97 +
79.98 + sb.append(hd.getTrigger());
79.99 + sb.append(":");
79.100 +
79.101 + //TODO: constraints
79.102 + sb.append(((WorkerImpl) hd.getWorker()).getMethod().toGenericString());
79.103 +
79.104 + return sb.toString();
79.105 + }
79.106 +
79.107 + @TriggerPattern(value="$1.toURL()", constraints=@ConstraintVariableType(variable="$1", type="java.io.File"))
79.108 + public static ErrorDescription hintPattern1(HintContext ctx) {
79.109 + return null;
79.110 + }
79.111 +
79.112 + @TriggerTreeKind(Kind.METHOD_INVOCATION)
79.113 + public static ErrorDescription hintPattern2(HintContext ctx) {
79.114 + return null;
79.115 + }
79.116 +
79.117 +}
79.118 \ No newline at end of file
80.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
80.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/providers/code/FSWrapperTest.java Wed May 08 21:47:42 2013 +0200
80.3 @@ -0,0 +1,221 @@
80.4 +/*
80.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
80.6 + *
80.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
80.8 + *
80.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
80.10 + * Other names may be trademarks of their respective owners.
80.11 + *
80.12 + * The contents of this file are subject to the terms of either the GNU
80.13 + * General Public License Version 2 only ("GPL") or the Common
80.14 + * Development and Distribution License("CDDL") (collectively, the
80.15 + * "License"). You may not use this file except in compliance with the
80.16 + * License. You can obtain a copy of the License at
80.17 + * http://www.netbeans.org/cddl-gplv2.html
80.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
80.19 + * specific language governing permissions and limitations under the
80.20 + * License. When distributing the software, include this License Header
80.21 + * Notice in each file and include the License file at
80.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
80.23 + * particular file as subject to the "Classpath" exception as provided
80.24 + * by Oracle in the GPL Version 2 section of the License file that
80.25 + * accompanied this code. If applicable, add the following below the
80.26 + * License Header, with the fields enclosed by brackets [] replaced by
80.27 + * your own identifying information:
80.28 + * "Portions Copyrighted [year] [name of copyright owner]"
80.29 + *
80.30 + * If you wish your version of this file to be governed by only the CDDL
80.31 + * or only the GPL Version 2, indicate your decision by adding
80.32 + * "[Contributor] elects to include this software in this distribution
80.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
80.34 + * single choice of license, a recipient has the option to distribute
80.35 + * your version of this file under either the CDDL, the GPL Version 2 or
80.36 + * to extend the choice of license to its licensees as provided above.
80.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
80.38 + * Version 2 license, then the option applies only if the new code is
80.39 + * made subject to such option by the copyright holder.
80.40 + *
80.41 + * Contributor(s):
80.42 + *
80.43 + * Portions Copyrighted 2010 Sun Microsystems, Inc.
80.44 + */
80.45 +
80.46 +package org.netbeans.modules.java.hints.providers.code;
80.47 +
80.48 +import java.lang.annotation.Annotation;
80.49 +import java.lang.reflect.AnnotatedElement;
80.50 +import java.lang.reflect.Array;
80.51 +import java.lang.reflect.Method;
80.52 +import java.util.ArrayList;
80.53 +import java.util.LinkedList;
80.54 +import java.util.List;
80.55 +import java.util.Map;
80.56 +import java.util.prefs.Preferences;
80.57 +import javax.sound.sampled.LineListener;
80.58 +import javax.swing.JComponent;
80.59 +import javax.swing.JPanel;
80.60 +import static org.junit.Assert.assertEquals;
80.61 +import static org.junit.Assert.assertNotNull;
80.62 +import static org.junit.Assert.fail;
80.63 +import org.junit.Test;
80.64 +import org.netbeans.modules.java.hints.providers.code.FSWrapper.AnnotatableWrapper;
80.65 +import org.netbeans.modules.java.hints.providers.code.FSWrapper.ClassWrapper;
80.66 +import org.netbeans.modules.java.hints.providers.code.FSWrapper.MethodWrapper;
80.67 +import org.netbeans.spi.java.hints.CustomizerProvider;
80.68 +import org.netbeans.spi.java.hints.Hint;
80.69 +import org.netbeans.spi.java.hints.HintContext;
80.70 +import org.netbeans.spi.java.hints.TestAnnotations.TestAnnotation1;
80.71 +import org.netbeans.spi.java.hints.TestAnnotations.TestAnnotation2;
80.72 +import org.netbeans.spi.java.hints.TestAnnotations.TestAnnotation3;
80.73 +import org.netbeans.spi.java.hints.TestAnnotations.TestEnum;
80.74 +
80.75 +/**
80.76 + *
80.77 + * @author lahvac
80.78 + */
80.79 +public class FSWrapperTest {
80.80 +
80.81 + public FSWrapperTest() {
80.82 + }
80.83 +
80.84 + @Test
80.85 + public void testWrappedClasses() throws Exception {
80.86 + Class[] classes = new Class[] {TestClass.class};
80.87 + Iterable<? extends ClassWrapper> wrapped = FSWrapper.listClasses();
80.88 +
80.89 + OUTER: for (Class<?> c : classes) {
80.90 + for (ClassWrapper w : wrapped) {
80.91 + if (w.getName().equals(c.getName())) {
80.92 + checkClassWrapper(c, w);
80.93 + continue OUTER;
80.94 + }
80.95 + }
80.96 +
80.97 + fail(c.getName());
80.98 + }
80.99 + }
80.100 +
80.101 + private static void checkClassWrapper(Class<?> c, ClassWrapper cw) throws Exception {
80.102 + checkAnnotations(c, cw);
80.103 +
80.104 + OUTER: for (Method m : c.getDeclaredMethods()) {
80.105 + if (m.getAnnotations().length == 0) continue;
80.106 +
80.107 + for (MethodWrapper wrapped : cw.getMethods()) {
80.108 + if (wrapped.getName().equals(m.getName())) {
80.109 + assertEquals(m, FSWrapper.resolveMethod(wrapped.getClazz().getName(), wrapped.getName()));
80.110 + checkAnnotations(m, wrapped);
80.111 + continue OUTER;
80.112 + }
80.113 + }
80.114 +
80.115 + fail(m.getName());
80.116 + }
80.117 + }
80.118 +
80.119 + private static void checkAnnotations(AnnotatedElement el, AnnotatableWrapper aw) throws Exception {
80.120 + for (Annotation ann : el.getAnnotations()) {
80.121 + Annotation wrapper = aw.getAnnotation(ann.annotationType());
80.122 +
80.123 + assertNotNull(ann.annotationType().getName(), wrapper);
80.124 +
80.125 + checkAnnotation(ann, wrapper);
80.126 + }
80.127 + }
80.128 +
80.129 + private static void checkAnnotation(Annotation real, Annotation wrapped) throws Exception {
80.130 + for (Method m : real.annotationType().getDeclaredMethods()) {
80.131 + Object realValue = m.invoke(real);
80.132 + Object wrappedValue = m.invoke(wrapped);
80.133 +
80.134 + checkValue(realValue, wrappedValue);
80.135 + }
80.136 + }
80.137 +
80.138 + private static void checkValue(Object o1, Object o2) throws Exception {
80.139 + assertEquals(o1.getClass().isAnnotation(), o2.getClass().isAnnotation());
80.140 + if (o1.getClass().isAnnotation()) {
80.141 + assertEquals(((Annotation) o1).annotationType(), ((Annotation) o2).annotationType());
80.142 + } else {
80.143 + assertEquals(o1.getClass(), o2.getClass());
80.144 + }
80.145 +
80.146 + if (o1.getClass().isArray()) {
80.147 + assertEquals(Array.getLength(o1), Array.getLength(o2));
80.148 +
80.149 + for (int c = 0; c < Array.getLength(o1); c++) {
80.150 + checkValue(Array.get(o1, c), Array.get(o2, c));
80.151 + }
80.152 + } else if (o1.getClass().isAnnotation()) {
80.153 + checkAnnotation((Annotation) o1, (Annotation) o2);
80.154 + } else {
80.155 + assertEquals(o1, o2);
80.156 + }
80.157 + }
80.158 +
80.159 + @Hint(displayName="foo", description="bar", category="")
80.160 + @TestAnnotation1(
80.161 + b1=true,
80.162 + b3=true,
80.163 + i1=42,
80.164 + i3=84,
80.165 + s1="a42",
80.166 + s3="a84",
80.167 + a1=@TestAnnotation2(a1=@TestAnnotation3(as1={"u1a2", "u1b2"}, as3="u1c2")),
80.168 +// a3=@TestAnnotation2(a1=@TestAnnotation3(as1={"u1a2", "u1b2"}, as3="u1c2")),
80.169 + c1=String.class,
80.170 + c3=String.class,
80.171 + e1=TestEnum.C,
80.172 + e3=TestEnum.D,
80.173 + ab1={false, true},
80.174 + ab3={false, true, false},
80.175 + ai1={84, 42},
80.176 + ai3={84, 42, 84},
80.177 + as1={"c42", "c84"},
80.178 + as3={"c42", "c84", "c42"},
80.179 + aa1={@TestAnnotation2(a1=@TestAnnotation3(as1={"u3a2", "u3b2"}, as3="u3c2")), @TestAnnotation2(a1=@TestAnnotation3(as1={"u4a2", "u4b2"}, as3="u4c2"))},
80.180 +// aa3={@TestAnnotation2(a1=@TestAnnotation3(as1={"u5a2", "u5b2"}, as3="u5c2")), @TestAnnotation2(a1=@TestAnnotation3(as1={"u6a2", "u6b2"}, as3="u6c2"))},
80.181 + ac1={List.class, Integer.class},
80.182 + ac3={LineListener.class, LinkedList.class},
80.183 + ae1={TestEnum.C, TestEnum.D},
80.184 + ae3={TestEnum.D, TestEnum.C}
80.185 + )
80.186 + public static class TestClass {
80.187 + @TestAnnotation1(
80.188 + b1=false,
80.189 + b2=true,
80.190 + i1=43,
80.191 + i2=85,
80.192 + s1="w42",
80.193 + s2="w84",
80.194 + a1=@TestAnnotation2(a1=@TestAnnotation3(as1={"u7a2", "u7b2"}, as3="u7c2")),
80.195 +// a2=@TestAnnotation2(a1=@TestAnnotation3(as1={"u8a2", "u8b2"}, as3="u8c2")),
80.196 + c1=String.class,
80.197 + c2=String.class,
80.198 + e1=TestEnum.C,
80.199 + e3=TestEnum.D,
80.200 + ab1={false, true},
80.201 + ab2={false, true, false},
80.202 + ai1={85, 43},
80.203 + ai2={85, 43, 85},
80.204 + as1={"d42", "d84"},
80.205 + as2={"e42", "e84", "e42"},
80.206 + aa1={@TestAnnotation2(a1=@TestAnnotation3(as1={"u9a2", "u9b2"}, as3="u9c2")), @TestAnnotation2(a1=@TestAnnotation3(as1={"uaa2", "u4b2"}, as3="uac2"))},
80.207 +// aa2={@TestAnnotation2(a1=@TestAnnotation3(as1={"uba2", "ubb2"}, as3="ubc2")), @TestAnnotation2(a1=@TestAnnotation3(as1={"uca2", "ucb2"}, as3="ucc2"))},
80.208 + ac1={ArrayList.class, Float.class},
80.209 + ac2={StringBuilder.class, Map.class},
80.210 + ae1={TestEnum.C, TestEnum.D},
80.211 + ae3={TestEnum.D, TestEnum.C}
80.212 + )
80.213 + public static void test(HintContext ctx) {
80.214 +
80.215 + }
80.216 + }
80.217 +
80.218 + public static class CustomizerImpl implements CustomizerProvider {
80.219 + @Override public JComponent getCustomizer(Preferences prefs) {
80.220 + return new JPanel();
80.221 + }
80.222 + }
80.223 +
80.224 +}
81.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
81.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/providers/code/TestAnnotations.java Wed May 08 21:47:42 2013 +0200
81.3 @@ -0,0 +1,109 @@
81.4 +/*
81.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
81.6 + *
81.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
81.8 + *
81.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
81.10 + * Other names may be trademarks of their respective owners.
81.11 + *
81.12 + * The contents of this file are subject to the terms of either the GNU
81.13 + * General Public License Version 2 only ("GPL") or the Common
81.14 + * Development and Distribution License("CDDL") (collectively, the
81.15 + * "License"). You may not use this file except in compliance with the
81.16 + * License. You can obtain a copy of the License at
81.17 + * http://www.netbeans.org/cddl-gplv2.html
81.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
81.19 + * specific language governing permissions and limitations under the
81.20 + * License. When distributing the software, include this License Header
81.21 + * Notice in each file and include the License file at
81.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
81.23 + * particular file as subject to the "Classpath" exception as provided
81.24 + * by Oracle in the GPL Version 2 section of the License file that
81.25 + * accompanied this code. If applicable, add the following below the
81.26 + * License Header, with the fields enclosed by brackets [] replaced by
81.27 + * your own identifying information:
81.28 + * "Portions Copyrighted [year] [name of copyright owner]"
81.29 + *
81.30 + * If you wish your version of this file to be governed by only the CDDL
81.31 + * or only the GPL Version 2, indicate your decision by adding
81.32 + * "[Contributor] elects to include this software in this distribution
81.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
81.34 + * single choice of license, a recipient has the option to distribute
81.35 + * your version of this file under either the CDDL, the GPL Version 2 or
81.36 + * to extend the choice of license to its licensees as provided above.
81.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
81.38 + * Version 2 license, then the option applies only if the new code is
81.39 + * made subject to such option by the copyright holder.
81.40 + *
81.41 + * Contributor(s):
81.42 + *
81.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
81.44 + */
81.45 +//placed in this package intentionally: the JavaHintsAnnotationProcessor ignores all annotations outside this package
81.46 +package org.netbeans.spi.java.hints;
81.47 +
81.48 +import java.lang.annotation.Retention;
81.49 +import java.lang.annotation.RetentionPolicy;
81.50 +
81.51 +/**
81.52 + *
81.53 + * @author lahvac
81.54 + */
81.55 +public class TestAnnotations {
81.56 +
81.57 + @Retention(RetentionPolicy.RUNTIME)
81.58 + public @interface TestAnnotation1 {
81.59 + public boolean b1();
81.60 + public boolean b2() default false;
81.61 + public boolean b3() default false;
81.62 + public int i1();
81.63 + public int i2() default 1;
81.64 + public int i3() default 1;
81.65 + public String s1();
81.66 + public String s2() default "";
81.67 + public String s3() default "";
81.68 + public TestAnnotation2 a1();
81.69 +// public TestAnnotation2 a2() default @TestAnnotation2(a1=@TestAnnotation3(as1={"a", "b"}, as3="c"));
81.70 +// public TestAnnotation2 a3() default @TestAnnotation2(a1=@TestAnnotation3(as1={"a2", "b2"}, as3="c2"));
81.71 + public Class c1();
81.72 + public Class c2() default Void.class;
81.73 + public Class c3() default Void.class;
81.74 + public TestEnum e1();
81.75 +// public TestEnum e2() default TestEnum.A;
81.76 + public TestEnum e3()/* default TestEnum.A*/;
81.77 + public boolean[] ab1();
81.78 + public boolean[] ab2() default false;
81.79 + public boolean[] ab3() default false;
81.80 + public int[] ai1();
81.81 + public int[] ai2() default 1;
81.82 + public int[] ai3() default 1;
81.83 + public String[] as1();
81.84 + public String[] as2() default "";
81.85 + public String[] as3() default "";
81.86 + public TestAnnotation2[] aa1();
81.87 +// public TestAnnotation2[] aa2() default @TestAnnotation2(a1=@TestAnnotation3(as1={"a", "b"}, as3="c"));
81.88 +// public TestAnnotation2[] aa3() default @TestAnnotation2(a1=@TestAnnotation3(as1={"a2", "b2"}, as3="c2"));
81.89 + public Class[] ac1();
81.90 + public Class[] ac2() default Void.class;
81.91 + public Class[] ac3() default Void.class;
81.92 + public TestEnum[] ae1();
81.93 +// public TestEnum[] ae2() default TestEnum.A;
81.94 + public TestEnum[] ae3()/* default TestEnum.A*/;
81.95 + }
81.96 +
81.97 + public @interface TestAnnotation2 {
81.98 + public TestAnnotation3 a1();
81.99 +// public TestAnnotation3 a2() default @TestAnnotation3(as1={"d", "e"}, as3="f");
81.100 +// public TestAnnotation3 a3() default @TestAnnotation3(as1={"g", "h"}, as3="i");
81.101 + }
81.102 +
81.103 + public @interface TestAnnotation3 {
81.104 + public String[] as1();
81.105 + public String[] as2() default {""};
81.106 + public String[] as3() default {""};
81.107 + }
81.108 +
81.109 + public enum TestEnum {
81.110 + A, B, C, D;
81.111 + }
81.112 +}
82.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
82.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/TestBase.java Wed May 08 21:47:42 2013 +0200
82.3 @@ -0,0 +1,124 @@
82.4 +/*
82.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
82.6 + *
82.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
82.8 + *
82.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
82.10 + * Other names may be trademarks of their respective owners.
82.11 + *
82.12 + * The contents of this file are subject to the terms of either the GNU
82.13 + * General Public License Version 2 only ("GPL") or the Common
82.14 + * Development and Distribution License("CDDL") (collectively, the
82.15 + * "License"). You may not use this file except in compliance with the
82.16 + * License. You can obtain a copy of the License at
82.17 + * http://www.netbeans.org/cddl-gplv2.html
82.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
82.19 + * specific language governing permissions and limitations under the
82.20 + * License. When distributing the software, include this License Header
82.21 + * Notice in each file and include the License file at
82.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
82.23 + * particular file as subject to the "Classpath" exception as provided
82.24 + * by Oracle in the GPL Version 2 section of the License file that
82.25 + * accompanied this code. If applicable, add the following below the
82.26 + * License Header, with the fields enclosed by brackets [] replaced by
82.27 + * your own identifying information:
82.28 + * "Portions Copyrighted [year] [name of copyright owner]"
82.29 + *
82.30 + * If you wish your version of this file to be governed by only the CDDL
82.31 + * or only the GPL Version 2, indicate your decision by adding
82.32 + * "[Contributor] elects to include this software in this distribution
82.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
82.34 + * single choice of license, a recipient has the option to distribute
82.35 + * your version of this file under either the CDDL, the GPL Version 2 or
82.36 + * to extend the choice of license to its licensees as provided above.
82.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
82.38 + * Version 2 license, then the option applies only if the new code is
82.39 + * made subject to such option by the copyright holder.
82.40 + *
82.41 + * Contributor(s):
82.42 + *
82.43 + * Portions Copyrighted 2008-2009 Sun Microsystems, Inc.
82.44 + */
82.45 +
82.46 +package org.netbeans.modules.java.hints.spiimpl;
82.47 +
82.48 +import java.io.File;
82.49 +import javax.swing.text.Document;
82.50 +import org.netbeans.api.java.lexer.JavaTokenId;
82.51 +import org.netbeans.api.java.source.CompilationInfo;
82.52 +import org.netbeans.api.java.source.JavaSource;
82.53 +import org.netbeans.api.java.source.JavaSource.Phase;
82.54 +import org.netbeans.api.java.source.SourceUtilsTestUtil;
82.55 +import org.netbeans.api.java.source.TestUtilities;
82.56 +import org.netbeans.api.lexer.Language;
82.57 +import org.netbeans.junit.NbTestCase;
82.58 +import org.netbeans.modules.java.source.TreeLoader;
82.59 +import org.openide.cookies.EditorCookie;
82.60 +import org.openide.filesystems.FileObject;
82.61 +import org.openide.filesystems.FileUtil;
82.62 +import org.openide.loaders.DataObject;
82.63 +
82.64 +/**
82.65 + *
82.66 + * @author Jan Lahoda
82.67 + */
82.68 +public class TestBase extends NbTestCase {
82.69 +
82.70 + public TestBase(String name) {
82.71 + super(name);
82.72 + }
82.73 +
82.74 + @Override
82.75 + protected void setUp() throws Exception {
82.76 + super.setUp();
82.77 + SourceUtilsTestUtil.prepareTest(new String[0], new Object[0]);
82.78 + TreeLoader.DISABLE_CONFINEMENT_TEST = true;
82.79 + clearWorkDir();
82.80 +
82.81 + FileUtil.refreshFor(File.listRoots());
82.82 + }
82.83 +
82.84 + private int workDirPart = 0;
82.85 +
82.86 + protected void prepareTest(String fileName, String code) throws Exception {
82.87 + FileObject workFO = FileUtil.createFolder(new File(getWorkDir(), String.valueOf(workDirPart++)));
82.88 +
82.89 + assertNotNull(workFO);
82.90 +
82.91 + workFO.refresh();
82.92 +
82.93 + sourceRoot = workFO.createFolder("src");
82.94 + FileObject buildRoot = workFO.createFolder("build");
82.95 + FileObject cache = workFO.createFolder("cache");
82.96 +
82.97 + FileObject data = FileUtil.createData(sourceRoot, fileName);
82.98 + File dataFile = FileUtil.toFile(data);
82.99 +
82.100 + assertNotNull(dataFile);
82.101 +
82.102 + TestUtilities.copyStringToFile(dataFile, code);
82.103 +
82.104 + SourceUtilsTestUtil.prepareTest(sourceRoot, buildRoot, cache);
82.105 +
82.106 + DataObject od = DataObject.find(data);
82.107 + EditorCookie ec = od.getLookup().lookup(EditorCookie.class);
82.108 +
82.109 + assertNotNull(ec);
82.110 +
82.111 + doc = ec.openDocument();
82.112 + doc.putProperty(Language.class, JavaTokenId.language());
82.113 +
82.114 + JavaSource js = JavaSource.forFileObject(data);
82.115 +
82.116 + assertNotNull(js);
82.117 +
82.118 + info = SourceUtilsTestUtil.getCompilationInfo(js, Phase.RESOLVED);
82.119 +
82.120 + assertNotNull(info);
82.121 + }
82.122 +
82.123 + protected FileObject sourceRoot;
82.124 + protected CompilationInfo info;
82.125 + protected Document doc;
82.126 +
82.127 +}
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/TestUtilities.java Wed May 08 21:47:42 2013 +0200
83.3 @@ -0,0 +1,67 @@
83.4 +/*
83.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
83.6 + *
83.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
83.8 + *
83.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
83.10 + * Other names may be trademarks of their respective owners.
83.11 + *
83.12 + * The contents of this file are subject to the terms of either the GNU
83.13 + * General Public License Version 2 only ("GPL") or the Common
83.14 + * Development and Distribution License("CDDL") (collectively, the
83.15 + * "License"). You may not use this file except in compliance with the
83.16 + * License. You can obtain a copy of the License at
83.17 + * http://www.netbeans.org/cddl-gplv2.html
83.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
83.19 + * specific language governing permissions and limitations under the
83.20 + * License. When distributing the software, include this License Header
83.21 + * Notice in each file and include the License file at
83.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
83.23 + * particular file as subject to the "Classpath" exception as provided
83.24 + * by Oracle in the GPL Version 2 section of the License file that
83.25 + * accompanied this code. If applicable, add the following below the
83.26 + * License Header, with the fields enclosed by brackets [] replaced by
83.27 + * your own identifying information:
83.28 + * "Portions Copyrighted [year] [name of copyright owner]"
83.29 + *
83.30 + * Contributor(s):
83.31 + *
83.32 + * Portions Copyrighted 2007 Sun Microsystems, Inc.
83.33 + */
83.34 +package org.netbeans.modules.java.hints.spiimpl;
83.35 +
83.36 +import junit.framework.Assert;
83.37 +
83.38 +/**
83.39 + *
83.40 + * @author Jan Lahoda
83.41 + */
83.42 +public class TestUtilities {
83.43 +
83.44 + private TestUtilities() {
83.45 + }
83.46 +
83.47 + public static String detectOffsets(String source, int[] positionOrSpan) {
83.48 + return detectOffsets(source, positionOrSpan, "\\|");
83.49 + }
83.50 +
83.51 + public static String detectOffsets(String source, int[] positionOrSpan, String delimiter) {
83.52 + //for now, the position/span delimiter is '|', without possibility of escaping:
83.53 + String[] split = source.split(delimiter);
83.54 +
83.55 + Assert.assertTrue("incorrect number of position markers (|)", positionOrSpan.length == split.length - 1);
83.56 +
83.57 + StringBuilder sb = new StringBuilder();
83.58 + int index = 0;
83.59 + int offset = 0;
83.60 +
83.61 + for (String s : split) {
83.62 + sb.append(s);
83.63 + if (index < positionOrSpan.length)
83.64 + positionOrSpan[index++] = (offset += s.length());
83.65 + }
83.66 +
83.67 + return sb.toString();
83.68 + }
83.69 +
83.70 +}
84.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
84.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/UtilitiesTest.java Wed May 08 21:47:42 2013 +0200
84.3 @@ -0,0 +1,632 @@
84.4 +/*
84.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
84.6 + *
84.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
84.8 + *
84.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
84.10 + * Other names may be trademarks of their respective owners.
84.11 + *
84.12 + * The contents of this file are subject to the terms of either the GNU
84.13 + * General Public License Version 2 only ("GPL") or the Common
84.14 + * Development and Distribution License("CDDL") (collectively, the
84.15 + * "License"). You may not use this file except in compliance with the
84.16 + * License. You can obtain a copy of the License at
84.17 + * http://www.netbeans.org/cddl-gplv2.html
84.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
84.19 + * specific language governing permissions and limitations under the
84.20 + * License. When distributing the software, include this License Header
84.21 + * Notice in each file and include the License file at
84.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
84.23 + * particular file as subject to the "Classpath" exception as provided
84.24 + * by Oracle in the GPL Version 2 section of the License file that
84.25 + * accompanied this code. If applicable, add the following below the
84.26 + * License Header, with the fields enclosed by brackets [] replaced by
84.27 + * your own identifying information:
84.28 + * "Portions Copyrighted [year] [name of copyright owner]"
84.29 + *
84.30 + * If you wish your version of this file to be governed by only the CDDL
84.31 + * or only the GPL Version 2, indicate your decision by adding
84.32 + * "[Contributor] elects to include this software in this distribution
84.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
84.34 + * single choice of license, a recipient has the option to distribute
84.35 + * your version of this file under either the CDDL, the GPL Version 2 or
84.36 + * to extend the choice of license to its licensees as provided above.
84.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
84.38 + * Version 2 license, then the option applies only if the new code is
84.39 + * made subject to such option by the copyright holder.
84.40 + *
84.41 + * Contributor(s):
84.42 + *
84.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
84.44 + */
84.45 +
84.46 +package org.netbeans.modules.java.hints.spiimpl;
84.47 +
84.48 +import com.sun.source.tree.IfTree;
84.49 +import com.sun.source.tree.LambdaExpressionTree;
84.50 +import com.sun.source.tree.MemberSelectTree;
84.51 +import com.sun.source.tree.ModifiersTree;
84.52 +import com.sun.source.tree.Scope;
84.53 +import com.sun.source.tree.Tree;
84.54 +import com.sun.source.tree.Tree.Kind;
84.55 +import com.sun.source.tree.VariableTree;
84.56 +import com.sun.source.util.SourcePositions;
84.57 +import com.sun.source.util.TreePath;
84.58 +import com.sun.source.util.TreeScanner;
84.59 +import com.sun.tools.javac.tree.JCTree;
84.60 +import java.util.ArrayList;
84.61 +import java.util.Arrays;
84.62 +import java.util.Collection;
84.63 +import java.util.Collections;
84.64 +import java.util.LinkedList;
84.65 +import java.util.List;
84.66 +import javax.lang.model.element.Element;
84.67 +import javax.lang.model.element.ElementKind;
84.68 +import javax.lang.model.type.TypeMirror;
84.69 +import javax.tools.Diagnostic;
84.70 +import javax.tools.JavaFileObject;
84.71 +import org.netbeans.api.java.classpath.ClassPath;
84.72 +import org.netbeans.api.java.source.ClasspathInfo;
84.73 +import org.netbeans.api.java.source.CompilationController;
84.74 +import org.netbeans.api.java.source.JavaSource;
84.75 +import org.netbeans.api.java.source.JavaSource.Phase;
84.76 +import org.netbeans.api.java.source.Task;
84.77 +import org.netbeans.junit.RandomlyFails;
84.78 +import org.netbeans.modules.java.source.pretty.VeryPretty;
84.79 +import org.netbeans.modules.java.source.save.DiffContext;
84.80 +
84.81 +/**
84.82 + *
84.83 + * @author lahvac
84.84 + */
84.85 +public class UtilitiesTest extends TestBase {
84.86 +
84.87 + public UtilitiesTest(String name) {
84.88 + super(name);
84.89 + }
84.90 +
84.91 + public void testParseAndAttributeExpressionStatement() throws Exception {
84.92 + prepareTest("test/Test.java", "package test; public class Test{}");
84.93 +
84.94 + Scope s = Utilities.constructScope(info, Collections.singletonMap("$1", info.getTreeUtilities().parseType("int", info.getTopLevelElements().get(0))));
84.95 + Tree result = Utilities.parseAndAttribute(info, "$1 = 1;", s);
84.96 +
84.97 + assertTrue(result.getKind().name(), result.getKind() == Kind.EXPRESSION_STATEMENT);
84.98 + }
84.99 +
84.100 + public void testParseAndAttributeVariable() throws Exception {
84.101 + prepareTest("test/Test.java", "package test; public class Test{}");
84.102 +
84.103 + Scope s = Utilities.constructScope(info, Collections.singletonMap("$1", info.getTreeUtilities().parseType("int", info.getTopLevelElements().get(0))));
84.104 + Tree result = Utilities.parseAndAttribute(info, "int $2 = $1;", s);
84.105 +
84.106 + assertTrue(result.getKind().name(), result.getKind() == Kind.VARIABLE);
84.107 + }
84.108 +
84.109 + public void testParseAndAttributeMultipleStatements() throws Exception {
84.110 + prepareTest("test/Test.java", "package test; public class Test{}");
84.111 +
84.112 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.113 + Tree result = Utilities.parseAndAttribute(info, "String $2 = $1; int $l = $2.length(); System.err.println($l);", s);
84.114 +
84.115 + assertTrue(result.getKind().name(), result.getKind() == Kind.BLOCK);
84.116 +
84.117 + String golden = "{\n" +
84.118 + " $$1$;\n" +
84.119 + " String $2 = $1;\n" +
84.120 + " int $l = $2.length();\n" +
84.121 + " System.err.println($l);\n" +
84.122 + " $$2$;\n" +
84.123 + "}";
84.124 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.125 + }
84.126 +
84.127 + public void testParseAndAttributeMethod() throws Exception {
84.128 + prepareTest("test/Test.java", "package test; public class Test{}");
84.129 +
84.130 + Scope s = Utilities.constructScope(info, Collections.singletonMap("$1", info.getTreeUtilities().parseType("int", info.getTopLevelElements().get(0))));
84.131 + String methodCode = "private int test(int i) { return i; }";
84.132 + Tree result = Utilities.parseAndAttribute(info, methodCode, s);
84.133 +
84.134 + assertEquals(Kind.METHOD, result.getKind());
84.135 + assertEquals(methodCode.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " ").trim());
84.136 + }
84.137 +
84.138 + public void testParseAndAttributeMultipleClassMembers() throws Exception {
84.139 + prepareTest("test/Test.java", "package test; public class Test{}");
84.140 +
84.141 + Scope s = Utilities.constructScope(info, Collections.singletonMap("$1", info.getTreeUtilities().parseType("int", info.getTopLevelElements().get(0))));
84.142 + String code = "private int i; private int getI() { return i; } private void setI(int i) { this.i = i; }";
84.143 + Tree result = Utilities.parseAndAttribute(info, code, s);
84.144 +
84.145 + String golden = "class $ {\n" +
84.146 + " $$1$;\n" +
84.147 + " private int i;\n" +
84.148 + " private int getI() {\n" +
84.149 + " return i;\n" +
84.150 + " }\n" +
84.151 + " private void setI(int i) {\n" +
84.152 + " this.i = i;\n" +
84.153 + " }\n" +
84.154 + "}";
84.155 +
84.156 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " ").trim());
84.157 + }
84.158 +
84.159 + public void testParseAndAttributeFieldModifiersVariable() throws Exception {
84.160 + prepareTest("test/Test.java", "package test; public class Test{}");
84.161 +
84.162 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.163 + String code = "$mods$ java.lang.String $name;";
84.164 + Tree result = Utilities.parseAndAttribute(info, code, s);
84.165 +
84.166 + String golden = "$mods$ java.lang.String $name";
84.167 +
84.168 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " ").trim());
84.169 + }
84.170 +
84.171 + public void testParseAndAttributeIfWithParenthetised() throws Exception {
84.172 + prepareTest("test/Test.java", "package test; public class Test{}");
84.173 +
84.174 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.175 + String code = "if ($c) { $1$; System.err.println('a'); $2$; }";
84.176 + Tree result = Utilities.parseAndAttribute(info, code, s);
84.177 +
84.178 + IfTree it = (IfTree) result;
84.179 +
84.180 + assertEquals(Kind.PARENTHESIZED, it.getCondition().getKind());
84.181 +
84.182 + String golden = "if ($c) { $1$; System.err.println('a'); $2$; }";
84.183 +
84.184 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " ").trim());
84.185 + }
84.186 +
84.187 + public void testParseAndAttributeMultipleStatements2() throws Exception {
84.188 + prepareTest("test/Test.java", "package test; public class Test{}");
84.189 +
84.190 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.191 + Tree result = Utilities.parseAndAttribute(info, "$type $name = $map.get($key); if ($name == null) { $map.put($key, $name = $init); }", s);
84.192 +
84.193 + assertTrue(result.getKind().name(), result.getKind() == Kind.BLOCK);
84.194 +
84.195 + String golden = "{" +
84.196 + " $$1$;" +
84.197 + " $type $name = $map.get($key);" +
84.198 + " if ($name == null) {" +
84.199 + " $map.put($key, $name = $init);" +
84.200 + " }" +
84.201 + " $$2$;\n" +
84.202 + "}";
84.203 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.204 + }
84.205 +
84.206 + public void testParseAndAttributeMethodDeclarationWithMultiparameters() throws Exception {
84.207 + prepareTest("test/Test.java", "package test; public class Test{}");
84.208 +
84.209 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.210 + Tree result = Utilities.parseAndAttribute(info, "public void t($params$) {}", s);
84.211 +
84.212 + assertTrue(result.getKind().name(), result.getKind() == Kind.METHOD);
84.213 +
84.214 + String golden = " public void t($params$) { }";
84.215 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.216 + }
84.217 +
84.218 + public void testParseAndAttributeMethodModifiersVariable() throws Exception {
84.219 + prepareTest("test/Test.java", "package test; public class Test{}");
84.220 +
84.221 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.222 + String code = "$mods$ $type $name() { $r$; }";
84.223 + Tree result = Utilities.parseAndAttribute(info, code, s);
84.224 +
84.225 + String golden = "$mods$ $type $name() { $r$; }";
84.226 +
84.227 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " ").trim());
84.228 + }
84.229 +
84.230 + public void testSimpleExpression() throws Exception {
84.231 + prepareTest("test/Test.java", "package test; public class Test{}");
84.232 +
84.233 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.234 + Tree result = Utilities.parseAndAttribute(info, "$1.isDirectory()", s);
84.235 +
84.236 + assertTrue(result.getKind().name(), result.getKind() == Kind.METHOD_INVOCATION);
84.237 +
84.238 + String golden = "$1.isDirectory()";
84.239 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.240 + }
84.241 +
84.242 + public void testARMResourceVariable1() throws Exception {
84.243 + prepareTest("test/Test.java", "package test; public class Test{}");
84.244 +
84.245 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.246 + Tree result = Utilities.parseAndAttribute(info, "try ($t$) { $stmts$; } catch $catches$", s);
84.247 +
84.248 + assertTrue(result.getKind().name(), result.getKind() == Kind.TRY);
84.249 +
84.250 + String golden = "try ($t$) { $stmts$; }$catches$";
84.251 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.252 + }
84.253 +
84.254 + public void testARMResourceVariable2() throws Exception {
84.255 + prepareTest("test/Test.java", "package test; public class Test{}");
84.256 +
84.257 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.258 + Tree result = Utilities.parseAndAttribute(info, "try ($t$; $type $name = $init) { $stmts$; } catch $catches$", s);
84.259 +
84.260 + assertTrue(result.getKind().name(), result.getKind() == Kind.TRY);
84.261 +
84.262 + String golden = "try ($t$ final $type $name = $init;) { $stmts$; }$catches$";
84.263 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.264 + }
84.265 +
84.266 + public void testARMResourceNotVariable() throws Exception {
84.267 + prepareTest("test/Test.java", "package test; public class Test{}");
84.268 +
84.269 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.270 + Tree result = Utilities.parseAndAttribute(info, "try ($t $n = $init$) { $stmts$; } catch $catches$", s);
84.271 +
84.272 + assertTrue(result.getKind().name(), result.getKind() == Kind.TRY);
84.273 +
84.274 + String golden = "try (final $t $n = $init$;) { $stmts$; }$catches$";
84.275 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.276 + }
84.277 +
84.278 + public void testParseAndAttributeType() throws Exception {
84.279 + prepareTest("test/Test.java", "package test; public class Test{}");
84.280 +
84.281 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.282 + Tree result = Utilities.parseAndAttribute(info, "\njava. util \n.List \n", s);
84.283 +
84.284 + assertTrue(result.getKind().name(), result.getKind() == Kind.MEMBER_SELECT);
84.285 +
84.286 + assertEquals(ElementKind.INTERFACE, info.getTrees().getElement(new TreePath(new TreePath(info.getCompilationUnit()), result)).getKind());
84.287 + assertEquals(info.getElements().getTypeElement("java.util.List"), info.getTrees().getElement(new TreePath(new TreePath(info.getCompilationUnit()), result)));
84.288 + }
84.289 +
84.290 + public void testCatchMultiparam() throws Exception {
84.291 + prepareTest("test/Test.java", "package test; public class Test{}");
84.292 +
84.293 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.294 + Tree result = Utilities.parseAndAttribute(info, "try {\n }\n catch $catch$ finally {\n }\n", s);
84.295 +
84.296 + assertTrue(result.getKind().name(), result.getKind() == Kind.TRY);
84.297 +
84.298 + String golden = "try {\n }$catch$ finally {\n }";
84.299 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.300 + }
84.301 +
84.302 + public void testCaseMultiparam() throws Exception {
84.303 + prepareTest("test/Test.java", "package test; public class Test{}");
84.304 +
84.305 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.306 + Tree result = Utilities.parseAndAttribute(info, "switch ($v) {case $c1$ case 1: ; case $c2$; case 3: ;}", s);
84.307 +
84.308 + assertTrue(result.getKind().name(), result.getKind() == Kind.SWITCH);
84.309 +
84.310 + String golden = "switch ($v) { $c1$ case 1: ; $c2$ case 3: ; }";
84.311 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.312 + }
84.313 +
84.314 + public void testOrdinaryCatch() throws Exception {
84.315 + prepareTest("test/Test.java", "package test; public class Test{}");
84.316 +
84.317 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.318 + Tree result = Utilities.parseAndAttribute(info, "try {\n }\n catch (NullPointerException ex) { } finally {\n }\n", s);
84.319 +
84.320 + assertTrue(result.getKind().name(), result.getKind() == Kind.TRY);
84.321 +
84.322 + String golden = "try {\n } catch (NullPointerException ex) { } finally {\n }";
84.323 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.324 + }
84.325 +
84.326 + public void testClassPattern() throws Exception {
84.327 + prepareTest("test/Test.java", "package test; public class Test{}");
84.328 +
84.329 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.330 + Tree result = Utilities.parseAndAttribute(info, "$mods$ class $name extends java.util.LinkedList { $methods$; }\n", s);
84.331 +
84.332 + assertTrue(result.getKind().name(), result.getKind() == Kind.CLASS);
84.333 +
84.334 + String golden = " $mods$ class $name extends java.util.LinkedList { $name() { super(); } $methods$ }";
84.335 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.336 + }
84.337 +
84.338 + public void testErrorsForPatterns1() throws Exception {
84.339 + prepareTest("test/Test.java", "package test; public class Test{}");
84.340 +
84.341 + SourcePositions[] positions = new SourcePositions[1];
84.342 + Collection<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
84.343 + String code = "foo bar";
84.344 + Tree result = Utilities.parseAndAttribute(info, code, null, positions, errors);
84.345 +
84.346 + assertDiagnostics(errors, "7-7:compiler.err.expected");
84.347 + assertPositions(result, positions[0], code, "foo", "foo bar");
84.348 + }
84.349 +
84.350 + @RandomlyFails
84.351 + public void testErrorsForPatterns2() throws Exception {
84.352 + prepareTest("test/Test.java", "package test; public class Test{}");
84.353 +
84.354 + SourcePositions[] positions = new SourcePositions[1];
84.355 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.356 + Collection<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
84.357 + String code = "$1.isDirectory()";
84.358 + Tree result = Utilities.parseAndAttribute(info, code, s, positions, errors);
84.359 +
84.360 + assertDiagnostics(errors, "0-0:compiler.err.cant.resolve.location");
84.361 + assertPositions(result, positions[0], code, "$1", "$1.isDirectory", "$1.isDirectory()");
84.362 + }
84.363 +
84.364 + public void testErrorsForPatterns3() throws Exception {
84.365 + prepareTest("test/Test.java", "package test; public class Test{}");
84.366 +
84.367 + SourcePositions[] positions = new SourcePositions[1];
84.368 + Collection<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
84.369 + String code = "if ($cond) { foo() } else $else;";
84.370 + Tree result = Utilities.parseAndAttribute(info, code, null, positions, errors);
84.371 +
84.372 + assertDiagnostics(errors, "18-18:compiler.err.expected");
84.373 + assertPositions(result, positions[0], code, "$cond", "$else", "$else;", "($cond)", "foo", "foo()", "foo() ", "if ($cond) { foo() } else $else;", "{ foo() }");
84.374 + }
84.375 +
84.376 + public void testPositionsForCorrectStatement() throws Exception {
84.377 + prepareTest("test/Test.java", "package test; public class Test{}");
84.378 +
84.379 + SourcePositions[] positions = new SourcePositions[1];
84.380 + Collection<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
84.381 + String code = "assert true;";
84.382 + Tree result = Utilities.parseAndAttribute(info, code, null, positions, errors);
84.383 +
84.384 + assertTrue(errors.isEmpty());
84.385 + assertPositions(result, positions[0], code, "assert true;", "true");
84.386 + }
84.387 +
84.388 + public void testCasePattern() throws Exception {
84.389 + prepareTest("test/Test.java", "package test; public class Test{}");
84.390 +
84.391 + SourcePositions[] positions = new SourcePositions[1];
84.392 + Collection<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
84.393 + String code = "case $expr: foo bar $stmts$;\n";
84.394 + Tree result = Utilities.parseAndAttribute(info, code, null, positions, errors);
84.395 +
84.396 + assertTrue(result.getKind().name(), result.getKind() == Kind.CASE);
84.397 +
84.398 + String golden = "case $expr: foo bar; $stmts$; ";
84.399 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.400 + assertDiagnostics(errors, "19-19:compiler.err.expected");
84.401 + assertPositions(result, positions[0], code, "$expr", "$stmts$", "$stmts$;", "case $expr: foo bar $stmts$;", "foo", "foo bar ");
84.402 + }
84.403 +
84.404 + public void testLambdaPattern() throws Exception {
84.405 + prepareTest("test/Test.java", "package test; public class Test{}");
84.406 +
84.407 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.408 + Tree result = Utilities.parseAndAttribute(info, "new $type() {\n $mods$ $resultType $methodName($args$) {\n $statements$;\n }\n }\n", s);
84.409 +
84.410 + assertTrue(result.getKind().name(), result.getKind() == Kind.NEW_CLASS);
84.411 +
84.412 + String golden = "new $type(){ $mods$ $resultType $methodName($args$) { $statements$; } }";
84.413 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.414 +
84.415 + Collection<Diagnostic<? extends JavaFileObject>> errors = new LinkedList<Diagnostic<? extends JavaFileObject>>();
84.416 +
84.417 + result = Utilities.parseAndAttribute(info, "new $type() {\n $mods$ $resultType $methodName($args$) {\n $statements$;\n }\n }\n", null, errors);
84.418 + assertTrue(result.getKind().name(), result.getKind() == Kind.NEW_CLASS);
84.419 +
84.420 + golden = "new $type(){ $mods$ $resultType $methodName($args$) { $statements$; } }";
84.421 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.422 + assertTrue(errors.toString(), errors.isEmpty());
84.423 + }
84.424 +
84.425 + public void testPackagePattern() throws Exception {
84.426 + prepareTest("test/a/Test.java", "package test.a; public class Test{}");
84.427 +
84.428 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.429 + Tree result = Utilities.parseAndAttribute(info, "test.$1", s);
84.430 +
84.431 + assertTrue(result.getKind().name(), result.getKind() == Kind.MEMBER_SELECT);
84.432 +
84.433 + String golden = "test.$1";
84.434 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.435 +
84.436 + Element total = info.getTrees().getElement(new TreePath(new TreePath(info.getCompilationUnit()), result));
84.437 +
84.438 + assertTrue(Utilities.isError(total));
84.439 +
84.440 + Element testPack = info.getTrees().getElement(new TreePath(new TreePath(info.getCompilationUnit()), ((MemberSelectTree) result).getExpression()));
84.441 +
84.442 + assertFalse(Utilities.isError(testPack));
84.443 + assertEquals(info.getElements().getPackageElement("test"), testPack);
84.444 + }
84.445 +
84.446 + public void DtestMultiStatementVarWithModifiers() throws Exception {
84.447 + prepareTest("test/Test.java", "package test; public class Test{}");
84.448 +
84.449 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.450 + Tree result = Utilities.parseAndAttribute(info, "$mods$ $type $name; $name = $init;", s);
84.451 +
84.452 + assertTrue(result.getKind().name(), result.getKind() == Kind.BLOCK);
84.453 +
84.454 + String golden = "{ $$1$; $mods$$type $name; $name = $init; $$2$; }";
84.455 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.456 + }
84.457 +
84.458 + public void testParseAndAttributeMultipleStatementsWithBefore() throws Exception {
84.459 + prepareTest("test/Test.java", "package test; public class Test{}");
84.460 +
84.461 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.462 + Tree result = Utilities.parseAndAttribute(info, "$before$; String $2 = $1; int $l = $2.length(); System.err.println($l);", s);
84.463 +
84.464 + assertTrue(result.getKind().name(), result.getKind() == Kind.BLOCK);
84.465 +
84.466 + String golden = "{\n" +
84.467 + " $before$;\n" +
84.468 + " String $2 = $1;\n" +
84.469 + " int $l = $2.length();\n" +
84.470 + " System.err.println($l);\n" +
84.471 + " $$2$;\n" +
84.472 + "}";
84.473 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.474 + }
84.475 +
84.476 + public void testParseAndAttributeMultipleStatementsWithAfter() throws Exception {
84.477 + prepareTest("test/Test.java", "package test; public class Test{}");
84.478 +
84.479 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.480 + Tree result = Utilities.parseAndAttribute(info, "String $2 = $1; int $l = $2.length(); System.err.println($l); $after$;", s);
84.481 +
84.482 + assertTrue(result.getKind().name(), result.getKind() == Kind.BLOCK);
84.483 +
84.484 + String golden = "{\n" +
84.485 + " $$1$;\n" +
84.486 + " String $2 = $1;\n" +
84.487 + " int $l = $2.length();\n" +
84.488 + " System.err.println($l);\n" +
84.489 + " $after$;\n" +
84.490 + "}";
84.491 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.492 + }
84.493 +
84.494 + public void testMethodFormalParams() throws Exception {
84.495 + prepareTest("test/Test.java", "package test; public class Test{}");
84.496 +
84.497 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.498 + Tree result = Utilities.parseAndAttribute(info, "$mods$ $ret $name($pref$, $type $name, $suff$) throws $throws$ { $body$; }", s);
84.499 +
84.500 + assertTrue(result.getKind().name(), result.getKind() == Kind.METHOD);
84.501 +
84.502 + String golden = " $mods$ $ret $name($pref$, $type $name, $suff$) throws $throws$ { $body$; }";
84.503 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " "));
84.504 + }
84.505 +
84.506 + public void testPartialModifiers() throws Exception {
84.507 + prepareTest("test/Test.java", "package test; public class Test{}");
84.508 +
84.509 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.510 + Tree result = Utilities.parseAndAttribute(info, "$mods$ @Deprecated public $type $name;", s);
84.511 +
84.512 + assertTrue(result.getKind().name(), result.getKind() == Kind.VARIABLE);
84.513 +
84.514 + ModifiersTree mods = ((VariableTree) result).getModifiers();
84.515 + String golden = "$mods$,@Deprecated(), [public]";
84.516 +
84.517 + assertEquals(golden.replaceAll("[ \n\r]+", " "), mods.getAnnotations().toString() + ", " + mods.getFlags().toString());
84.518 + }
84.519 +
84.520 + public void testBrokenPlatform226678() throws Exception {
84.521 + prepareTest("test/Test.java", "package test; public class Test{}");
84.522 +
84.523 + JavaSource.create(ClasspathInfo.create(ClassPath.EMPTY, ClassPath.EMPTY, ClassPath.EMPTY), info.getFileObject()).runUserActionTask(new Task<CompilationController>() {
84.524 + @Override public void run(CompilationController parameter) throws Exception {
84.525 + parameter.toPhase(Phase.RESOLVED);
84.526 + info = parameter;
84.527 + }
84.528 + }, true);
84.529 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.530 + String methodCode = "private int test(int i) { return i; }";
84.531 + Tree result = Utilities.parseAndAttribute(info, methodCode, s);
84.532 +
84.533 + assertEquals(Kind.METHOD, result.getKind());
84.534 + assertEquals(methodCode.replaceAll("[ \n\r]+", " "), result.toString().replaceAll("[ \n\r]+", " ").trim());
84.535 + }
84.536 +
84.537 + public void testLambdaExpression1() throws Exception {
84.538 + prepareTest("test/Test.java", "package test; public class Test{}");
84.539 +
84.540 + Scope s = Utilities.constructScope(info, Collections.<String, TypeMirror>emptyMap());
84.541 + Tree result = Utilities.parseAndAttribute(info, "($args$) -> $expression", s);
84.542 +
84.543 + assertTrue(result.getKind().name(), result.getKind() == Kind.LAMBDA_EXPRESSION);
84.544 +
84.545 + LambdaExpressionTree let = (LambdaExpressionTree) result;
84.546 +
84.547 + assertEquals(Kind.IDENTIFIER, let.getParameters().get(0).getKind());
84.548 + String golden = "($args$)->$expression";
84.549 +
84.550 + assertEquals(golden.replaceAll("[ \n\r]+", " "), result.toString());
84.551 + }
84.552 +
84.553 + public void testToHumanReadableTime() {
84.554 + long time = 202;
84.555 + assertEquals( "5s", Utilities.toHumanReadableTime(time += 5 * 1000));
84.556 + assertEquals( "3m5s", Utilities.toHumanReadableTime(time += 3 * 60 * 1000));
84.557 + assertEquals("7h3m5s", Utilities.toHumanReadableTime(time += 7 * 60 * 60 * 1000));
84.558 + }
84.559 +
84.560 + public void testGeneralization() throws Exception {
84.561 + performGeneralizationTest("package test;\n" +
84.562 + "public class Test {\n" +
84.563 + " class Inner {\n" +
84.564 + " Inner(int i) {}\n" +
84.565 + " }\n" +
84.566 + " public static void main(String[] args) {\n" +
84.567 + " int i = 1;\n" +
84.568 + " Test c = null;\n" +
84.569 + " c.new Inner(i++) {};\n" +
84.570 + " }\n" +
84.571 + "}\n",
84.572 + "package test;\n" +
84.573 + "public class Test {\n" +
84.574 + " class Inner {\n" +
84.575 + " Inner(int $0) { super(); }\n" +
84.576 + " }\n" +
84.577 + " public static void main(String[] $1) {\n" +
84.578 + " int $2 = 1;\n" +
84.579 + " Test $3 = null;\n" +
84.580 + " $4;\n" + //XXX
84.581 + " }\n" +
84.582 + "}\n");
84.583 + }
84.584 + private void performGeneralizationTest(String code, String generalized) throws Exception {
84.585 + prepareTest("test/Test.java", code);
84.586 +
84.587 + Tree generalizedTree = Utilities.generalizePattern(info, new TreePath(info.getCompilationUnit()));
84.588 + VeryPretty vp = new VeryPretty(new DiffContext(info));
84.589 +
84.590 + vp.print((JCTree) generalizedTree);
84.591 +
84.592 + String repr = vp.toString();
84.593 +
84.594 + assertEquals(generalized.replaceAll("[ \n\t]+", " "),
84.595 + repr.replaceAll("[ \n\t]+", " "));
84.596 + }
84.597 +
84.598 + private void assertDiagnostics(Collection<Diagnostic<? extends JavaFileObject>> errors, String... golden) {
84.599 + List<String> actual = new ArrayList<String>(errors.size());
84.600 +
84.601 + for (Diagnostic<? extends JavaFileObject> d : errors) {
84.602 + actual.add(d.getStartPosition() + "-" + d.getEndPosition() + ":" + d.getCode());
84.603 + }
84.604 +
84.605 + assertEquals(Arrays.asList(golden), actual);
84.606 + }
84.607 +
84.608 + private void assertPositions(Tree t, final SourcePositions sp, final String code, String... golden) {
84.609 + final List<String> actual = new ArrayList<String>(golden.length);
84.610 +
84.611 + new TreeScanner<Void, Void>() {
84.612 + @Override
84.613 + public Void scan(Tree node, Void p) {
84.614 + if (node != null) {
84.615 + int start = (int) sp.getStartPosition(null, node);
84.616 + int end = (int) sp.getEndPosition(null, node);
84.617 +
84.618 + if (start >= 0 && end >= 0) {
84.619 + actual.add(code.substring(start, end));
84.620 + }
84.621 + }
84.622 + return super.scan(node, p);
84.623 + }
84.624 + }.scan(t, null);
84.625 +
84.626 + Collections.sort(actual);
84.627 +
84.628 + List<String> goldenList = new ArrayList<String>(Arrays.asList(golden));
84.629 +
84.630 + Collections.sort(goldenList);
84.631 +
84.632 + assertEquals(goldenList, actual);
84.633 + }
84.634 +
84.635 +}
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearchTest.java Wed May 08 21:47:42 2013 +0200
85.3 @@ -0,0 +1,458 @@
85.4 +/*
85.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
85.6 + *
85.7 + * Copyright 2009-2011 Oracle and/or its affiliates. All rights reserved.
85.8 + *
85.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
85.10 + * Other names may be trademarks of their respective owners.
85.11 + *
85.12 + * The contents of this file are subject to the terms of either the GNU
85.13 + * General Public License Version 2 only ("GPL") or the Common
85.14 + * Development and Distribution License("CDDL") (collectively, the
85.15 + * "License"). You may not use this file except in compliance with the
85.16 + * License. You can obtain a copy of the License at
85.17 + * http://www.netbeans.org/cddl-gplv2.html
85.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
85.19 + * specific language governing permissions and limitations under the
85.20 + * License. When distributing the software, include this License Header
85.21 + * Notice in each file and include the License file at
85.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
85.23 + * particular file as subject to the "Classpath" exception as provided
85.24 + * by Oracle in the GPL Version 2 section of the License file that
85.25 + * accompanied this code. If applicable, add the following below the
85.26 + * License Header, with the fields enclosed by brackets [] replaced by
85.27 + * your own identifying information:
85.28 + * "Portions Copyrighted [year] [name of copyright owner]"
85.29 + *
85.30 + * If you wish your version of this file to be governed by only the CDDL
85.31 + * or only the GPL Version 2, indicate your decision by adding
85.32 + * "[Contributor] elects to include this software in this distribution
85.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
85.34 + * single choice of license, a recipient has the option to distribute
85.35 + * your version of this file under either the CDDL, the GPL Version 2 or
85.36 + * to extend the choice of license to its licensees as provided above.
85.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
85.38 + * Version 2 license, then the option applies only if the new code is
85.39 + * made subject to such option by the copyright holder.
85.40 + *
85.41 + * Contributor(s):
85.42 + *
85.43 + * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
85.44 + */
85.45 +package org.netbeans.modules.java.hints.spiimpl.batch;
85.46 +
85.47 +import org.netbeans.modules.java.hints.spiimpl.batch.TestUtils.File;
85.48 +import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
85.49 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
85.50 +import java.net.URL;
85.51 +import java.util.ArrayList;
85.52 +import java.util.Arrays;
85.53 +import java.util.Collection;
85.54 +import java.util.Collections;
85.55 +import java.util.HashMap;
85.56 +import java.util.HashSet;
85.57 +import java.util.Iterator;
85.58 +import java.util.LinkedList;
85.59 +import java.util.List;
85.60 +import java.util.Map;
85.61 +import java.util.Map.Entry;
85.62 +import java.util.Set;
85.63 +import java.util.concurrent.atomic.AtomicBoolean;
85.64 +import java.util.regex.Pattern;
85.65 +import junit.framework.TestSuite;
85.66 +import org.netbeans.api.java.classpath.ClassPath;
85.67 +import org.netbeans.api.java.classpath.GlobalPathRegistry;
85.68 +import org.netbeans.api.java.classpath.GlobalPathRegistryEvent;
85.69 +import org.netbeans.api.java.classpath.GlobalPathRegistryListener;
85.70 +import org.netbeans.api.java.source.CompilationController;
85.71 +import org.netbeans.api.java.source.SourceUtilsTestUtil;
85.72 +import org.netbeans.core.startup.Main;
85.73 +import org.netbeans.junit.NbTestCase;
85.74 +import org.netbeans.junit.NbTestSuite;
85.75 +import org.netbeans.junit.RandomlyFails;
85.76 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.BatchResult;
85.77 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Folder;
85.78 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Resource;
85.79 +import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
85.80 +import org.netbeans.modules.parsing.impl.indexing.MimeTypes;
85.81 +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater;
85.82 +import org.netbeans.spi.editor.hints.ErrorDescription;
85.83 +import org.netbeans.spi.java.classpath.ClassPathProvider;
85.84 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
85.85 +import org.openide.filesystems.FileObject;
85.86 +import org.openide.filesystems.FileStateInvalidException;
85.87 +import org.openide.filesystems.FileUtil;
85.88 +
85.89 +import org.openide.util.Exceptions;
85.90 +import org.openide.util.lookup.ServiceProvider;
85.91 +import static org.netbeans.modules.java.hints.spiimpl.batch.TestUtils.writeFilesAndWaitForScan;
85.92 +import static org.netbeans.modules.java.hints.spiimpl.batch.TestUtils.prepareHints;
85.93 +
85.94 +/**
85.95 + *
85.96 + * @author lahvac
85.97 + */
85.98 +public class BatchSearchTest extends NbTestCase {
85.99 +
85.100 + public BatchSearchTest(String name) {
85.101 + super(name);
85.102 + }
85.103 +
85.104 + public static TestSuite suite() {
85.105 + TestSuite result = new NbTestSuite();
85.106 +
85.107 + result.addTestSuite(BatchSearchTest.class);
85.108 +// result.addTest(new BatchSearchTest("testBatchSearchFolderRemoteIndex"));
85.109 +
85.110 + return result;
85.111 + }
85.112 +
85.113 + //XXX: copied from CustomIndexerImplTest:
85.114 + @Override
85.115 + protected void setUp() throws Exception {
85.116 + SourceUtilsTestUtil.prepareTest(new String[0], new Object[0]);
85.117 + Main.initializeURLFactory();
85.118 + org.netbeans.api.project.ui.OpenProjects.getDefault().getOpenProjects();
85.119 + prepareTest();
85.120 + MimeTypes.setAllMimeTypes(Collections.singleton("text/x-java"));
85.121 + sourceCP = ClassPathSupport.createClassPath(src1, src2);
85.122 + GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {sourceCP});
85.123 + RepositoryUpdater.getDefault().start(true);
85.124 + super.setUp();
85.125 + }
85.126 +
85.127 + @Override
85.128 + protected void tearDown() throws Exception {
85.129 + super.tearDown();
85.130 + GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, new ClassPath[] {sourceCP});
85.131 + }
85.132 +
85.133 + public void testBatchSearch1() throws Exception {
85.134 + writeFilesAndWaitForScan(src1,
85.135 + new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
85.136 + new File("test/Test2.java", "package test; public class Test2 { private void test() { new javax.swing.ImageIcon(null); } }"));
85.137 + writeFilesAndWaitForScan(src2,
85.138 + new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
85.139 + new File("test/Test2.java", "package test; public class Test2 { private void test() { new javax.swing.ImageIcon(null); } }"));
85.140 +
85.141 + Iterable<? extends HintDescription> hints = prepareHints("$1.isDirectory()");
85.142 + BatchResult result = BatchSearch.findOccurrences(hints, Scopes.allOpenedProjectsScope());
85.143 + Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
85.144 +
85.145 + for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
85.146 + Collection<String> resourcesRepr = new LinkedList<String>();
85.147 +
85.148 + for (Resource r : e.getValue()) {
85.149 + resourcesRepr.add(r.getRelativePath());
85.150 + }
85.151 +
85.152 + output.put(e.getKey().getURL().toExternalForm(), resourcesRepr);
85.153 + }
85.154 +
85.155 + Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
85.156 +
85.157 + golden.put(src1.getURL().toExternalForm(), Arrays.asList("test/Test1.java"));
85.158 + golden.put(src2.getURL().toExternalForm(), Arrays.asList("test/Test1.java"));
85.159 +
85.160 + assertEquals(golden, output);
85.161 + }
85.162 +
85.163 + public void testBatchSearchSpan() throws Exception {
85.164 + String code = "package test;\n" +
85.165 + "public class Test {\n" +
85.166 + " private void m() {\n" +
85.167 + " a(c.i().getFileObject());\n" +
85.168 + " if (span != null && span[0] != (-1) && span[1] != (-1));\n" +
85.169 + " c.i().getFileObject(\"\");\n" +
85.170 + " }\n" +
85.171 + "}\n";
85.172 +
85.173 + writeFilesAndWaitForScan(src1, new File("test/Test.java", code));
85.174 +
85.175 + Iterable<? extends HintDescription> hints = prepareHints("$0.getFileObject($1)");
85.176 + BatchResult result = BatchSearch.findOccurrences(hints, Scopes.allOpenedProjectsScope());
85.177 +
85.178 + assertEquals(1, result.getResources().size());
85.179 + Iterator<? extends Resource> resources = result.getResources().iterator().next().iterator();
85.180 + Resource r = resources.next();
85.181 +
85.182 + assertFalse(resources.hasNext());
85.183 +
85.184 + Set<String> snipets = new HashSet<String>();
85.185 +
85.186 + for (int[] span : r.getCandidateSpans()) {
85.187 + snipets.add(code.substring(span[0], span[1]));
85.188 + }
85.189 +
85.190 + Set<String> golden = new HashSet<String>(Arrays.asList("c.i().getFileObject(\"\")"));
85.191 + assertEquals(golden, snipets);
85.192 + }
85.193 +
85.194 + @RandomlyFails
85.195 + public void testBatchSearchNotIndexed() throws Exception {
85.196 + writeFilesAndWaitForScan(src1,
85.197 + new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
85.198 + new File("test/Test2.java", "package test; public class Test2 { private void test() { new javax.swing.ImageIcon(null); } }"));
85.199 + writeFilesAndWaitForScan(src3,
85.200 + new File("test/Test1.java", "package test; public class Test1 { private void test() { Test2 f = null; f.isDirectory(); } }"),
85.201 + new File("test/Test2.java", "package test; public class Test2 { public boolean isDirectory() {return false} }"));
85.202 +
85.203 + Iterable<? extends HintDescription> hints = prepareHints("$1.isDirectory()", "$1", "test.Test2");
85.204 + BatchResult result = BatchSearch.findOccurrences(hints, Scopes.specifiedFoldersScope(Folder.convert(src1, src3, empty)));
85.205 + Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
85.206 +
85.207 + for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
85.208 + Collection<String> resourcesRepr = new LinkedList<String>();
85.209 +
85.210 + for (Resource r : e.getValue()) {
85.211 + resourcesRepr.add(r.getRelativePath());
85.212 + }
85.213 +
85.214 + output.put(e.getKey().getURL().toExternalForm(), resourcesRepr);
85.215 + }
85.216 +
85.217 + Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
85.218 +
85.219 + golden.put(src1.getURL().toExternalForm(), Arrays.asList("test/Test1.java"));
85.220 + golden.put(src3.getURL().toExternalForm(), Arrays.asList("test/Test1.java"));
85.221 +
85.222 + assertEquals(golden, output);
85.223 +
85.224 + //check verification:
85.225 + Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result, false);
85.226 + Map<String, Map<String, Iterable<String>>> verifiedGolden = new HashMap<String, Map<String, Iterable<String>>>();
85.227 +
85.228 + verifiedGolden.put(src1.getURL().toExternalForm(), Collections.<String, Iterable<String>>singletonMap("test/Test1.java", Arrays.<String>asList()));
85.229 + verifiedGolden.put(src3.getURL().toExternalForm(), Collections.<String, Iterable<String>>singletonMap("test/Test1.java", Arrays.asList("0:75-0:86:verifier:")));
85.230 +
85.231 + assertEquals(verifiedGolden, verifiedOutput);
85.232 + }
85.233 +
85.234 + public void testBatchSearchForceIndexingOfProperDirectory() throws Exception {
85.235 + FileObject data = FileUtil.createFolder(workdir, "data");
85.236 + FileObject dataSrc1 = FileUtil.createFolder(data, "src1");
85.237 + FileObject dataSrc2 = FileUtil.createFolder(data, "src2");
85.238 + writeFilesAndWaitForScan(dataSrc1,
85.239 + new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
85.240 + new File("test/Test2.java", "package test; public class Test2 { private void test() { new javax.swing.ImageIcon(null); } }"));
85.241 + writeFilesAndWaitForScan(dataSrc2,
85.242 + new File("test/Test1.java", "package test; public class Test1 { private void test() { Test2 f = null; f.isDirectory(); } }"),
85.243 + new File("test/Test2.java", "package test; public class Test2 { public boolean isDirectory() {return false} }"));
85.244 +
85.245 + ClassPathProviderImpl.setSourceRoots(Arrays.asList(dataSrc1, dataSrc2));
85.246 +
85.247 + Iterable<? extends HintDescription> hints = prepareHints("$1.isDirectory()", "$1", "test.Test2");
85.248 + BatchResult result = BatchSearch.findOccurrences(hints, Scopes.specifiedFoldersScope(Folder.convert(data)));
85.249 + Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
85.250 +
85.251 + for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
85.252 + Collection<String> resourcesRepr = new HashSet<String>();
85.253 +
85.254 + for (Resource r : e.getValue()) {
85.255 + resourcesRepr.add(r.getRelativePath());
85.256 + }
85.257 +
85.258 + output.put(e.getKey().getURL().toExternalForm(), resourcesRepr);
85.259 + }
85.260 +
85.261 + Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
85.262 +
85.263 + golden.put(data.getURL().toExternalForm(), new HashSet<String>(Arrays.asList("src1/test/Test1.java", "src2/test/Test1.java")));
85.264 +
85.265 + assertEquals(golden, output);
85.266 +
85.267 + //check verification:
85.268 + final Set<FileObject> added = new HashSet<FileObject>();
85.269 + final Set<FileObject> removed = new HashSet<FileObject>();
85.270 +
85.271 + GlobalPathRegistry.getDefault().addGlobalPathRegistryListener(new GlobalPathRegistryListener() {
85.272 + public void pathsAdded(GlobalPathRegistryEvent event) {
85.273 + for (ClassPath cp : event.getChangedPaths()) {
85.274 + added.addAll(Arrays.asList(cp.getRoots()));
85.275 + }
85.276 + }
85.277 + public void pathsRemoved(GlobalPathRegistryEvent event) {
85.278 + for (ClassPath cp : event.getChangedPaths()) {
85.279 + removed.addAll(Arrays.asList(cp.getRoots()));
85.280 + }
85.281 + }
85.282 + });
85.283 +
85.284 +// verifiedGolden.put(data.getURL().toExternalForm(), Arrays.asList("0:75-0:86:verifier:TODO: No display name"));
85.285 + Map<String, Map<String, Iterable<String>>> verifiedOutput = verifiedSpans(result, false);
85.286 + Map<String, Map<String, Iterable<String>>> verifiedGolden = new HashMap<String, Map<String, Iterable<String>>>();
85.287 +
85.288 + Map<String, Iterable<String>> verifiedGoldenPart = new HashMap<String, Iterable<String>>();
85.289 +
85.290 + verifiedGoldenPart.put("src1/test/Test1.java", Arrays.<String>asList());
85.291 + verifiedGoldenPart.put("src2/test/Test1.java", Arrays.<String>asList("0:75-0:86:verifier:"));
85.292 +
85.293 + verifiedGolden.put(data.getURL().toExternalForm(), verifiedGoldenPart);
85.294 +
85.295 + assertEquals(verifiedGolden, verifiedOutput);
85.296 + assertEquals(new HashSet<FileObject>(Arrays.asList(dataSrc1, dataSrc2)), added);
85.297 + assertEquals(new HashSet<FileObject>(Arrays.asList(dataSrc1, dataSrc2)), removed);
85.298 + }
85.299 +
85.300 + public void testBatchSearchFolderNoIndex() throws Exception {
85.301 + FileObject data = FileUtil.createFolder(workdir, "data");
85.302 + FileObject dataSrc1 = FileUtil.createFolder(data, "src1");
85.303 + FileObject dataSrc2 = FileUtil.createFolder(data, "src2");
85.304 + writeFilesAndWaitForScan(dataSrc1,
85.305 + new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
85.306 + new File("test/Test2.java", "package test; public class Test2 { private void test() { new javax.swing.ImageIcon(null); } }"));
85.307 + writeFilesAndWaitForScan(dataSrc2,
85.308 + new File("test/Test1.java", "package test; public class Test1 { private void test() { Test2 f = null; f.isDirectory(); } }"),
85.309 + new File("test/Test2.java", "package test; public class Test2 { public boolean isDirectory() {return false} }"));
85.310 +
85.311 + Iterable<? extends HintDescription> hints = prepareHints("$1.isDirectory()");
85.312 + BatchResult result = BatchSearch.findOccurrences(hints, Scopes.specifiedFoldersScope(Folder.convert(Collections.singleton(data)))); //XXX: should be a no-index variant!
85.313 + Map<String, Iterable<String>> output = toDebugOutput(result);
85.314 + Map<String, Iterable<String>> golden = new HashMap<String, Iterable<String>>();
85.315 +
85.316 + golden.put(data.getURL().toExternalForm(), new HashSet<String>(Arrays.asList("src1/test/Test1.java", "src2/test/Test1.java")));
85.317 +
85.318 + assertEquals(golden, output);
85.319 + }
85.320 +
85.321 + private FileObject workdir;
85.322 + private FileObject src1;
85.323 + private FileObject src2;
85.324 + private FileObject src3;
85.325 + private FileObject empty;
85.326 + private ClassPath sourceCP;
85.327 +
85.328 + private void prepareTest() throws Exception {
85.329 + workdir = SourceUtilsTestUtil.makeScratchDir(this);
85.330 +
85.331 + src1 = FileUtil.createFolder(workdir, "src1");
85.332 + src2 = FileUtil.createFolder(workdir, "src2");
85.333 + src3 = FileUtil.createFolder(workdir, "src3");
85.334 + empty = FileUtil.createFolder(workdir, "empty");
85.335 +
85.336 + ClassPathProviderImpl.setSourceRoots(Arrays.asList(src1, src2, src3));
85.337 +
85.338 + FileObject cache = FileUtil.createFolder(workdir, "cache");
85.339 +
85.340 + CacheFolder.setCacheFolder(cache);
85.341 + }
85.342 +
85.343 + private Map<String, Iterable<String>> toDebugOutput(BatchResult result) throws Exception {
85.344 + Map<String, Iterable<String>> output = new HashMap<String, Iterable<String>>();
85.345 +
85.346 + for (Entry<FileObject, Collection<? extends Resource>> e : result.getResourcesWithRoots().entrySet()) {
85.347 + Collection<String> resourcesRepr = new HashSet<String>();
85.348 +
85.349 + for (Resource r : e.getValue()) {
85.350 + resourcesRepr.add(r.getRelativePath());
85.351 + }
85.352 +
85.353 + output.put(e.getKey().getURL().toExternalForm(), resourcesRepr);
85.354 + }
85.355 +
85.356 + return output;
85.357 + }
85.358 +
85.359 + private Map<String, Map<String, Iterable<String>>> verifiedSpans(BatchResult candidates, boolean doNotRegisterClassPath) throws Exception {
85.360 + final Map<String, Map<String, Iterable<String>>> result = new HashMap<String, Map<String, Iterable<String>>>();
85.361 + List<MessageImpl> errors = new LinkedList<MessageImpl>();
85.362 + BatchSearch.getVerifiedSpans(candidates, new ProgressHandleWrapper(1), new BatchSearch.VerifiedSpansCallBack() {
85.363 + public void groupStarted() {}
85.364 + public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception {
85.365 + Map<String, Iterable<String>> files = result.get(r.getRoot().getURL().toExternalForm());
85.366 +
85.367 + if (files == null) {
85.368 + result.put(r.getRoot().getURL().toExternalForm(), files = new HashMap<String, Iterable<String>>());
85.369 + }
85.370 +
85.371 + Collection<String> currentHints = new LinkedList<String>();
85.372 +
85.373 + for (ErrorDescription ed : hints) {
85.374 + currentHints.add(ed.toString());
85.375 + }
85.376 +
85.377 + files.put(r.getRelativePath(), currentHints);
85.378 +
85.379 + return true;
85.380 + }
85.381 + public void groupFinished() {}
85.382 + public void cannotVerifySpan(Resource r) {
85.383 + fail("Cannot verify: " +r.getRelativePath());
85.384 + }
85.385 + }, doNotRegisterClassPath, errors, new AtomicBoolean());
85.386 +
85.387 + return result;
85.388 + }
85.389 +
85.390 + @ServiceProvider(service=ClassPathProvider.class)
85.391 + public static final class ClassPathProviderImpl implements ClassPathProvider {
85.392 +
85.393 + private static Collection<FileObject> sourceRoots;
85.394 +
85.395 + public synchronized static void setSourceRoots(Collection<FileObject> sourceRoots) {
85.396 + ClassPathProviderImpl.sourceRoots = sourceRoots;
85.397 + }
85.398 +
85.399 + public synchronized static Collection<FileObject> getSourceRoots() {
85.400 + return sourceRoots;
85.401 + }
85.402 +
85.403 + public synchronized ClassPath findClassPath(FileObject file, String type) {
85.404 + if (ClassPath.BOOT.equals(type)) {
85.405 + return ClassPathSupport.createClassPath(getBootClassPath().toArray(new URL[0]));
85.406 + }
85.407 +
85.408 + if (ClassPath.COMPILE.equals(type)) {
85.409 + return ClassPathSupport.createClassPath(new URL[0]);
85.410 + }
85.411 +
85.412 + if (ClassPath.SOURCE.equals(type) && sourceRoots != null) {
85.413 + for (FileObject sr : sourceRoots) {
85.414 + if (file.equals(sr) || FileUtil.isParentOf(sr, file)) {
85.415 + return ClassPathSupport.createClassPath(sr);
85.416 + }
85.417 + }
85.418 + }
85.419 +
85.420 + return null;
85.421 + }
85.422 +
85.423 + }
85.424 +
85.425 + //TODO: copied from SourceUtilsTestUtil:
85.426 + private static List<URL> bootClassPath;
85.427 +
85.428 + public static synchronized List<URL> getBootClassPath() {
85.429 + if (bootClassPath == null) {
85.430 + try {
85.431 + String cp = System.getProperty("sun.boot.class.path");
85.432 + List<URL> urls = new ArrayList<URL>();
85.433 + String[] paths = cp.split(Pattern.quote(System.getProperty("path.separator")));
85.434 +
85.435 + for (String path : paths) {
85.436 + java.io.File f = new java.io.File(path);
85.437 +
85.438 + if (!f.canRead())
85.439 + continue;
85.440 +
85.441 + FileObject fo = FileUtil.toFileObject(f);
85.442 +
85.443 + if (FileUtil.isArchiveFile(fo)) {
85.444 + fo = FileUtil.getArchiveRoot(fo);
85.445 + }
85.446 +
85.447 + if (fo != null) {
85.448 + urls.add(fo.getURL());
85.449 + }
85.450 + }
85.451 +
85.452 + bootClassPath = urls;
85.453 + } catch (FileStateInvalidException e) {
85.454 + Exceptions.printStackTrace(e);
85.455 + }
85.456 + }
85.457 +
85.458 + return bootClassPath;
85.459 + }
85.460 +
85.461 +}
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
86.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchUtilitiesTest.java Wed May 08 21:47:42 2013 +0200
86.3 @@ -0,0 +1,222 @@
86.4 +/*
86.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
86.6 + *
86.7 + * Copyright 2009-2011 Oracle and/or its affiliates. All rights reserved.
86.8 + *
86.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
86.10 + * Other names may be trademarks of their respective owners.
86.11 + *
86.12 + * The contents of this file are subject to the terms of either the GNU
86.13 + * General Public License Version 2 only ("GPL") or the Common
86.14 + * Development and Distribution License("CDDL") (collectively, the
86.15 + * "License"). You may not use this file except in compliance with the
86.16 + * License. You can obtain a copy of the License at
86.17 + * http://www.netbeans.org/cddl-gplv2.html
86.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
86.19 + * specific language governing permissions and limitations under the
86.20 + * License. When distributing the software, include this License Header
86.21 + * Notice in each file and include the License file at
86.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
86.23 + * particular file as subject to the "Classpath" exception as provided
86.24 + * by Oracle in the GPL Version 2 section of the License file that
86.25 + * accompanied this code. If applicable, add the following below the
86.26 + * License Header, with the fields enclosed by brackets [] replaced by
86.27 + * your own identifying information:
86.28 + * "Portions Copyrighted [year] [name of copyright owner]"
86.29 + *
86.30 + * If you wish your version of this file to be governed by only the CDDL
86.31 + * or only the GPL Version 2, indicate your decision by adding
86.32 + * "[Contributor] elects to include this software in this distribution
86.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
86.34 + * single choice of license, a recipient has the option to distribute
86.35 + * your version of this file under either the CDDL, the GPL Version 2 or
86.36 + * to extend the choice of license to its licensees as provided above.
86.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
86.38 + * Version 2 license, then the option applies only if the new code is
86.39 + * made subject to such option by the copyright holder.
86.40 + *
86.41 + * Contributor(s):
86.42 + *
86.43 + * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
86.44 + */
86.45 +package org.netbeans.modules.java.hints.spiimpl.batch;
86.46 +
86.47 +import org.netbeans.modules.java.hints.spiimpl.batch.TestUtils.File;
86.48 +import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
86.49 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearchTest.ClassPathProviderImpl;
86.50 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
86.51 +import java.util.Arrays;
86.52 +import java.util.Collection;
86.53 +import java.util.Collections;
86.54 +import java.util.HashMap;
86.55 +import java.util.LinkedList;
86.56 +import java.util.List;
86.57 +import java.util.Map;
86.58 +import java.util.concurrent.atomic.AtomicBoolean;
86.59 +import org.netbeans.api.editor.mimelookup.MimePath;
86.60 +import org.netbeans.api.java.classpath.ClassPath;
86.61 +import org.netbeans.api.java.classpath.GlobalPathRegistry;
86.62 +import org.netbeans.api.java.lexer.JavaTokenId;
86.63 +import org.netbeans.api.java.source.ModificationResult;
86.64 +import org.netbeans.api.java.source.SourceUtilsTestUtil;
86.65 +import org.netbeans.api.java.source.TestUtilities;
86.66 +import org.netbeans.api.lexer.InputAttributes;
86.67 +import org.netbeans.api.lexer.Language;
86.68 +import org.netbeans.api.lexer.LanguagePath;
86.69 +import org.netbeans.api.lexer.Token;
86.70 +import org.netbeans.core.startup.Main;
86.71 +import org.netbeans.junit.NbTestCase;
86.72 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.BatchResult;
86.73 +import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.Folder;
86.74 +import org.netbeans.modules.java.source.parsing.JavacParser;
86.75 +import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
86.76 +import org.netbeans.modules.parsing.impl.indexing.RepositoryUpdater;
86.77 +import org.netbeans.spi.editor.mimelookup.MimeDataProvider;
86.78 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
86.79 +import org.netbeans.spi.lexer.LanguageEmbedding;
86.80 +import org.netbeans.spi.lexer.LanguageProvider;
86.81 +import org.openide.LifecycleManager;
86.82 +import org.openide.filesystems.FileObject;
86.83 +import org.openide.filesystems.FileUtil;
86.84 +
86.85 +import org.openide.loaders.DataObject;
86.86 +import org.openide.util.Lookup;
86.87 +import org.openide.util.lookup.Lookups;
86.88 +import org.openide.util.lookup.ServiceProvider;
86.89 +import static org.netbeans.modules.java.hints.spiimpl.batch.TestUtils.writeFilesAndWaitForScan;
86.90 +import static org.netbeans.modules.java.hints.spiimpl.batch.TestUtils.prepareHints;
86.91 +import org.netbeans.modules.parsing.impl.indexing.MimeTypes;
86.92 +
86.93 +/**
86.94 + *
86.95 + * @author lahvac
86.96 + */
86.97 +public class BatchUtilitiesTest extends NbTestCase {
86.98 +
86.99 + public BatchUtilitiesTest(String name) {
86.100 + super(name);
86.101 + }
86.102 +
86.103 + //XXX: copied from CustomIndexerImplTest:
86.104 + @Override
86.105 + protected void setUp() throws Exception {
86.106 + SourceUtilsTestUtil.prepareTest(new String[] {"org/netbeans/modules/java/source/resources/layer.xml", "org/netbeans/lib/java/lexer/layer.xml"}, new Object[0]);
86.107 + Main.initializeURLFactory();
86.108 + org.netbeans.api.project.ui.OpenProjects.getDefault().getOpenProjects();
86.109 + prepareTest();
86.110 + MimeTypes.setAllMimeTypes(Collections.singleton("text/x-java"));
86.111 + GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, new ClassPath[] {ClassPathSupport.createClassPath(src1, src2)});
86.112 + RepositoryUpdater.getDefault().start(true);
86.113 + super.setUp();
86.114 + }
86.115 +
86.116 + public void testBatchSearchNotIndexed() throws Exception {
86.117 + writeFilesAndWaitForScan(src1,
86.118 + new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
86.119 + new File("test/Test2.java", "package test; public class Test2 { private void test() { new javax.swing.ImageIcon(null); } }"));
86.120 + writeFilesAndWaitForScan(src3,
86.121 + new File("test/Test1.java", "package test; public class Test1 { private void test() { java.io.File f = null; f.isDirectory(); } }"),
86.122 + new File("test/Test2.java", "package test; public class Test2 { public boolean isDirectory() {return false} }"));
86.123 +
86.124 + Iterable<? extends HintDescription> hints = prepareHints("$1.isDirectory() => !$1.isFile()", "$1", "java.io.File");
86.125 + BatchResult result = BatchSearch.findOccurrences(hints, Scopes.specifiedFoldersScope(Folder.convert(src1, src3, empty)));
86.126 + List<MessageImpl> problems = new LinkedList<MessageImpl>();
86.127 + Collection<? extends ModificationResult> changes = BatchUtilities.applyFixes(result, new ProgressHandleWrapper(100), new AtomicBoolean(), problems);
86.128 +
86.129 + assertTrue(problems.toString(), problems.isEmpty());
86.130 +
86.131 + Map<FileObject, String> file2New = new HashMap<FileObject, String>();
86.132 +
86.133 + for (ModificationResult mr : changes) {
86.134 + for (FileObject file : mr.getModifiedFileObjects()) {
86.135 + assertNull(file2New.put(file, mr.getResultingSource(file)));
86.136 + }
86.137 + }
86.138 +
86.139 + FileObject src1Test1 = src1.getFileObject("test/Test1.java");
86.140 + String src1Test1Real = file2New.remove(src1Test1);
86.141 + String src1Test1Golden = "package test; public class Test1 { private void test() { java.io.File f = null; !f.isFile(); } }";
86.142 +
86.143 + assertEquals(src1Test1Golden, src1Test1Real);
86.144 +
86.145 + FileObject src3Test1 = src3.getFileObject("test/Test1.java");
86.146 + String src3Test1Real = file2New.remove(src3Test1);
86.147 + String src3Test1Golden = "package test; public class Test1 { private void test() { java.io.File f = null; !f.isFile(); } }";
86.148 +
86.149 + assertEquals(src3Test1Golden, src3Test1Real);
86.150 +
86.151 + assertTrue(file2New.toString(), file2New.isEmpty());
86.152 + }
86.153 +
86.154 +// public void testRemoveUnusedImports() throws Exception {
86.155 +// writeFilesAndWaitForScan(src1,
86.156 +// new File("test/Test1.java", "package test;\n import java.util.List;\n public class Test1 { }"));
86.157 +// writeFilesAndWaitForScan(src2,
86.158 +// new File("test/Test2.java", "package test;\n import java.util.LinkedList;\n public class Test2 { }"));
86.159 +//
86.160 +// FileObject test1 = src1.getFileObject("test/Test1.java");
86.161 +// FileObject test2 = src2.getFileObject("test/Test2.java");
86.162 +//
86.163 +// System.err.println(DataObject.find(test1).getClass());
86.164 +// BatchUtilities.removeUnusedImports(Arrays.asList(test1, test2));
86.165 +//
86.166 +// LifecycleManager.getDefault().saveAll();
86.167 +//
86.168 +// assertEquals("package test;\n public class Test1 { }", TestUtilities.copyFileToString(FileUtil.toFile(test1)));
86.169 +// assertEquals("package test;\n public class Test2 { }", TestUtilities.copyFileToString(FileUtil.toFile(test2)));
86.170 +// }
86.171 +
86.172 + private FileObject src1;
86.173 + private FileObject src2;
86.174 + private FileObject src3;
86.175 + private FileObject empty;
86.176 +
86.177 + private void prepareTest() throws Exception {
86.178 + FileObject workdir = SourceUtilsTestUtil.makeScratchDir(this);
86.179 +
86.180 + src1 = FileUtil.createFolder(workdir, "src1");
86.181 + src2 = FileUtil.createFolder(workdir, "src2");
86.182 + src3 = FileUtil.createFolder(workdir, "src3");
86.183 + empty = FileUtil.createFolder(workdir, "empty");
86.184 +
86.185 + ClassPathProviderImpl.setSourceRoots(Arrays.asList(src1, src2, src3));
86.186 +
86.187 + FileObject cache = FileUtil.createFolder(workdir, "cache");
86.188 +
86.189 + CacheFolder.setCacheFolder(cache);
86.190 + }
86.191 +
86.192 + @ServiceProvider(service=MimeDataProvider.class)
86.193 + public static final class JavaLexerProvider implements MimeDataProvider {
86.194 +
86.195 + private Lookup javaLookup = Lookups.fixed(JavaTokenId.language());
86.196 +
86.197 + public Lookup getLookup(MimePath mimePath) {
86.198 + if (mimePath.getPath().endsWith(JavacParser.MIME_TYPE)) {
86.199 + return javaLookup;
86.200 + }
86.201 +
86.202 + return Lookup.EMPTY;
86.203 + }
86.204 +
86.205 + }
86.206 +
86.207 + @ServiceProvider(service=LanguageProvider.class)
86.208 + public static final class JavaLanguageProvider extends LanguageProvider {
86.209 +
86.210 + @Override
86.211 + public Language<?> findLanguage(String mimeType) {
86.212 + if ("text/x-java".equals(mimeType)) {
86.213 + return JavaTokenId.language();
86.214 + }
86.215 +
86.216 + return null;
86.217 + }
86.218 +
86.219 + @Override
86.220 + public LanguageEmbedding<?> findLanguageEmbedding(Token<?> token, LanguagePath languagePath, InputAttributes inputAttributes) {
86.221 + return null;
86.222 + }
86.223 +
86.224 + }
86.225 +}
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/ProgressHandleWrapperTest.java Wed May 08 21:47:42 2013 +0200
87.3 @@ -0,0 +1,66 @@
87.4 +/*
87.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
87.6 + *
87.7 + * Copyright 2009-2011 Oracle and/or its affiliates. All rights reserved.
87.8 + *
87.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
87.10 + * Other names may be trademarks of their respective owners.
87.11 + *
87.12 + * The contents of this file are subject to the terms of either the GNU
87.13 + * General Public License Version 2 only ("GPL") or the Common
87.14 + * Development and Distribution License("CDDL") (collectively, the
87.15 + * "License"). You may not use this file except in compliance with the
87.16 + * License. You can obtain a copy of the License at
87.17 + * http://www.netbeans.org/cddl-gplv2.html
87.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
87.19 + * specific language governing permissions and limitations under the
87.20 + * License. When distributing the software, include this License Header
87.21 + * Notice in each file and include the License file at
87.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
87.23 + * particular file as subject to the "Classpath" exception as provided
87.24 + * by Oracle in the GPL Version 2 section of the License file that
87.25 + * accompanied this code. If applicable, add the following below the
87.26 + * License Header, with the fields enclosed by brackets [] replaced by
87.27 + * your own identifying information:
87.28 + * "Portions Copyrighted [year] [name of copyright owner]"
87.29 + *
87.30 + * If you wish your version of this file to be governed by only the CDDL
87.31 + * or only the GPL Version 2, indicate your decision by adding
87.32 + * "[Contributor] elects to include this software in this distribution
87.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
87.34 + * single choice of license, a recipient has the option to distribute
87.35 + * your version of this file under either the CDDL, the GPL Version 2 or
87.36 + * to extend the choice of license to its licensees as provided above.
87.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
87.38 + * Version 2 license, then the option applies only if the new code is
87.39 + * made subject to such option by the copyright holder.
87.40 + *
87.41 + * Contributor(s):
87.42 + *
87.43 + * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
87.44 + */
87.45 +package org.netbeans.modules.java.hints.spiimpl.batch;
87.46 +
87.47 +import org.netbeans.junit.NbTestCase;
87.48 +
87.49 +/**
87.50 + *
87.51 + * @author lahvac
87.52 + */
87.53 +public class ProgressHandleWrapperTest extends NbTestCase {
87.54 +
87.55 + public ProgressHandleWrapperTest(String name) {
87.56 + super(name);
87.57 + }
87.58 +
87.59 + public void testNoProgress() {
87.60 + ProgressHandleWrapper w = new ProgressHandleWrapper(new ProgressHandleWrapper.ProgressHandleAbstraction() {
87.61 + public void start(int totalWork) {}
87.62 + public void progress(int currentWorkDone) {}
87.63 + public void progress(String message) {}
87.64 + public void finish() {}
87.65 + }, 1);
87.66 +
87.67 + w.finish();
87.68 + }
87.69 +}
88.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
88.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/batch/TestUtils.java Wed May 08 21:47:42 2013 +0200
88.3 @@ -0,0 +1,135 @@
88.4 +/*
88.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
88.6 + *
88.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
88.8 + *
88.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
88.10 + * Other names may be trademarks of their respective owners.
88.11 + *
88.12 + * The contents of this file are subject to the terms of either the GNU
88.13 + * General Public License Version 2 only ("GPL") or the Common
88.14 + * Development and Distribution License("CDDL") (collectively, the
88.15 + * "License"). You may not use this file except in compliance with the
88.16 + * License. You can obtain a copy of the License at
88.17 + * http://www.netbeans.org/cddl-gplv2.html
88.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
88.19 + * specific language governing permissions and limitations under the
88.20 + * License. When distributing the software, include this License Header
88.21 + * Notice in each file and include the License file at
88.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
88.23 + * particular file as subject to the "Classpath" exception as provided
88.24 + * by Oracle in the GPL Version 2 section of the License file that
88.25 + * accompanied this code. If applicable, add the following below the
88.26 + * License Header, with the fields enclosed by brackets [] replaced by
88.27 + * your own identifying information:
88.28 + * "Portions Copyrighted [year] [name of copyright owner]"
88.29 + *
88.30 + * If you wish your version of this file to be governed by only the CDDL
88.31 + * or only the GPL Version 2, indicate your decision by adding
88.32 + * "[Contributor] elects to include this software in this distribution
88.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
88.34 + * single choice of license, a recipient has the option to distribute
88.35 + * your version of this file under either the CDDL, the GPL Version 2 or
88.36 + * to extend the choice of license to its licensees as provided above.
88.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
88.38 + * Version 2 license, then the option applies only if the new code is
88.39 + * made subject to such option by the copyright holder.
88.40 + *
88.41 + * Contributor(s):
88.42 + *
88.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
88.44 + */
88.45 +package org.netbeans.modules.java.hints.spiimpl.batch;
88.46 +
88.47 +import java.util.Collection;
88.48 +import java.util.Collections;
88.49 +import org.netbeans.spi.java.hints.HintContext;
88.50 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.Worker;
88.51 +import org.netbeans.modules.java.hints.providers.spi.Trigger.PatternDescription;
88.52 +import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
88.53 +import org.netbeans.spi.editor.hints.ErrorDescription;
88.54 +import org.netbeans.modules.java.hints.providers.spi.HintDescriptionFactory;
88.55 +import java.util.HashMap;
88.56 +import java.util.Map;
88.57 +import org.netbeans.api.java.source.SourceUtils;
88.58 +import org.netbeans.api.java.source.TestUtilities;
88.59 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
88.60 +import org.openide.filesystems.FileObject;
88.61 +import org.openide.filesystems.FileUtil;
88.62 +
88.63 +import static org.junit.Assert.*;
88.64 +import org.netbeans.spi.java.hints.JavaFixUtilities;
88.65 +
88.66 +/**
88.67 + *
88.68 + * @author lahvac
88.69 + */
88.70 +public class TestUtils {
88.71 +
88.72 + public static void writeFiles(FileObject sourceRoot, File... files) throws Exception {
88.73 + for (FileObject c : sourceRoot.getChildren()) {
88.74 + c.delete();
88.75 + }
88.76 +
88.77 + for (File f : files) {
88.78 + FileObject fo = FileUtil.createData(sourceRoot, f.filename);
88.79 + TestUtilities.copyStringToFile(fo, f.content);
88.80 + }
88.81 + }
88.82 +
88.83 + public static void writeFilesAndWaitForScan(FileObject sourceRoot, File... files) throws Exception {
88.84 + writeFiles(sourceRoot, files);
88.85 + SourceUtils.waitScanFinished();
88.86 + }
88.87 +
88.88 + public static final class File {
88.89 + public final String filename;
88.90 + public final String content;
88.91 + public final boolean index;
88.92 +
88.93 + public File(String filename, String content) {
88.94 + this(filename, content, true);
88.95 + }
88.96 +
88.97 + public File(String filename, String content, boolean index) {
88.98 + this.filename = filename;
88.99 + this.content = content;
88.100 + this.index = index;
88.101 + }
88.102 + }
88.103 +
88.104 + public static Iterable<? extends HintDescription> prepareHints(String rule, String... constraints) {
88.105 + final String[] split = rule.split("=>");
88.106 +
88.107 + Worker w;
88.108 +
88.109 + if (split.length == 2) {
88.110 + w = new HintDescription.Worker() {
88.111 + @Override public Collection<? extends ErrorDescription> createErrors(HintContext ctx) {
88.112 + return Collections.singletonList(ErrorDescriptionFactory.forName(ctx, ctx.getPath(), "", JavaFixUtilities.rewriteFix(ctx, "", ctx.getPath(), split[1])));
88.113 + }
88.114 + };
88.115 + } else {
88.116 + w = new HintDescription.Worker() {
88.117 + @Override public Collection<? extends ErrorDescription> createErrors(HintContext ctx) {
88.118 + return Collections.singletonList(ErrorDescriptionFactory.forName(ctx, ctx.getPath(), ""));
88.119 + }
88.120 + };
88.121 + }
88.122 +
88.123 + assertTrue(constraints.length % 2 == 0);
88.124 +
88.125 + Map<String, String> constr = new HashMap<String, String>();
88.126 +
88.127 + for (int i = 0; i < constraints.length; i += 2) {
88.128 + constr.put(constraints[i], constraints[i + 1]);
88.129 + }
88.130 +
88.131 + HintDescription hd = HintDescriptionFactory.create()
88.132 + .setTrigger(PatternDescription.create(split[0], constr))
88.133 + .setWorker(w)
88.134 + .produce();
88.135 +
88.136 + return Collections.singletonList(hd);
88.137 + }
88.138 +}
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/hints/HintsInvokerTest.java Wed May 08 21:47:42 2013 +0200
89.3 @@ -0,0 +1,895 @@
89.4 +/*
89.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
89.6 + *
89.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
89.8 + *
89.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
89.10 + * Other names may be trademarks of their respective owners.
89.11 + *
89.12 + * The contents of this file are subject to the terms of either the GNU
89.13 + * General Public License Version 2 only ("GPL") or the Common
89.14 + * Development and Distribution License("CDDL") (collectively, the
89.15 + * "License"). You may not use this file except in compliance with the
89.16 + * License. You can obtain a copy of the License at
89.17 + * http://www.netbeans.org/cddl-gplv2.html
89.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
89.19 + * specific language governing permissions and limitations under the
89.20 + * License. When distributing the software, include this License Header
89.21 + * Notice in each file and include the License file at
89.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
89.23 + * particular file as subject to the "Classpath" exception as provided
89.24 + * by Oracle in the GPL Version 2 section of the License file that
89.25 + * accompanied this code. If applicable, add the following below the
89.26 + * License Header, with the fields enclosed by brackets [] replaced by
89.27 + * your own identifying information:
89.28 + * "Portions Copyrighted [year] [name of copyright owner]"
89.29 + *
89.30 + * If you wish your version of this file to be governed by only the CDDL
89.31 + * or only the GPL Version 2, indicate your decision by adding
89.32 + * "[Contributor] elects to include this software in this distribution
89.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
89.34 + * single choice of license, a recipient has the option to distribute
89.35 + * your version of this file under either the CDDL, the GPL Version 2 or
89.36 + * to extend the choice of license to its licensees as provided above.
89.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
89.38 + * Version 2 license, then the option applies only if the new code is
89.39 + * made subject to such option by the copyright holder.
89.40 + *
89.41 + * Contributor(s):
89.42 + *
89.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
89.44 + */
89.45 +
89.46 +package org.netbeans.modules.java.hints.spiimpl.hints;
89.47 +
89.48 +import com.sun.source.tree.Tree.Kind;
89.49 +import com.sun.source.util.TreePath;
89.50 +import java.util.Arrays;
89.51 +import java.util.Collection;
89.52 +import java.util.Collections;
89.53 +import java.util.EnumSet;
89.54 +import java.util.HashMap;
89.55 +import java.util.LinkedList;
89.56 +import java.util.List;
89.57 +import java.util.Map;
89.58 +import java.util.concurrent.atomic.AtomicBoolean;
89.59 +import javax.swing.text.Document;
89.60 +import static org.junit.Assert.*;
89.61 +import org.netbeans.api.java.source.CompilationInfo;
89.62 +import org.netbeans.modules.java.hints.spiimpl.TestBase;
89.63 +import org.netbeans.spi.java.hints.HintContext;
89.64 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
89.65 +import org.netbeans.modules.java.hints.providers.spi.HintDescription.Worker;
89.66 +import org.netbeans.modules.java.hints.providers.spi.HintDescriptionFactory;
89.67 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
89.68 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata.Options;
89.69 +import org.netbeans.modules.java.hints.providers.spi.Trigger.Kinds;
89.70 +import org.netbeans.modules.java.hints.providers.spi.Trigger.PatternDescription;
89.71 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
89.72 +import org.netbeans.spi.java.hints.ErrorDescriptionFactory;
89.73 +import org.netbeans.spi.editor.hints.ErrorDescription;
89.74 +import org.netbeans.spi.editor.hints.Fix;
89.75 +import org.netbeans.spi.java.hints.JavaFixUtilities;
89.76 +import org.openide.LifecycleManager;
89.77 +import org.openide.cookies.EditorCookie;
89.78 +import org.openide.filesystems.FileObject;
89.79 +import org.openide.loaders.DataObject;
89.80 +
89.81 +/**
89.82 + *
89.83 + * @author user
89.84 + */
89.85 +public class HintsInvokerTest extends TestBase {
89.86 +
89.87 + public HintsInvokerTest(String name) {
89.88 + super(name);
89.89 + }
89.90 +
89.91 +// public static TestSuite suite() {
89.92 +// NbTestSuite r = new NbTestSuite();
89.93 +// r.addTest(new HintsInvokerTest("testPatternVariable1"));
89.94 +// return r;
89.95 +// }
89.96 +
89.97 + public void testPattern1() throws Exception {
89.98 + performAnalysisTest("test/Test.java",
89.99 + "|package test;\n" +
89.100 + "import java.io.File;\n" +
89.101 + "public class Test {\n" +
89.102 + " private void test(File f) {\n" +
89.103 + " f.toURL();\n" +
89.104 + " }\n" +
89.105 + "}\n",
89.106 + "4:11-4:16:verifier:HINT");
89.107 + }
89.108 +
89.109 + public void testPattern2() throws Exception {
89.110 + performAnalysisTest("test/Test.java",
89.111 + "|package test;\n" +
89.112 + "\n" +
89.113 + "public class Test {\n" +
89.114 + " private void test(java.io.File f) {\n" +
89.115 + " f.toURL();\n" +
89.116 + " }\n" +
89.117 + "}\n",
89.118 + "4:11-4:16:verifier:HINT");
89.119 + }
89.120 +
89.121 + public void testKind1() throws Exception {
89.122 + performAnalysisTest("test/Test.java",
89.123 + "|package test;\n" +
89.124 + "\n" +
89.125 + "public class Test {\n" +
89.126 + " private void test(java.io.File f) {\n" +
89.127 + " f.toURL();\n" +
89.128 + " }\n" +
89.129 + "}\n",
89.130 + "4:11-4:16:verifier:HINT");
89.131 + }
89.132 +
89.133 + public void testPatternVariable1() throws Exception {
89.134 + performFixTest("test/Test.java",
89.135 + "|package test;\n" +
89.136 + "\n" +
89.137 + "public class Test {\n" +
89.138 + " private void test() {\n" +
89.139 + " {\n" +
89.140 + " int y;\n" +
89.141 + " y = 1;\n" +
89.142 + " }\n" +
89.143 + " int z;\n" +
89.144 + " {\n" +
89.145 + " int y;\n" +
89.146 + " z = 1;\n" +
89.147 + " }\n" +
89.148 + " }\n" +
89.149 + "}\n",
89.150 + "4:9-7:10:verifier:HINT",
89.151 + "FixImpl",
89.152 + "package test; public class Test { private void test() { { int y = 1; } int z; { int y; z = 1; } } } ");
89.153 + }
89.154 +
89.155 + public void testPatternAssert1() throws Exception {
89.156 + performAnalysisTest("test/Test.java",
89.157 + "|package test;\n" +
89.158 + "\n" +
89.159 + "public class Test {\n" +
89.160 + " private void test() {\n" +
89.161 + " assert true : \"\";\n" +
89.162 + " }\n" +
89.163 + "}\n",
89.164 + "4:9-4:15:verifier:HINT");
89.165 + }
89.166 +
89.167 + public void testPatternStatementAndSingleStatementBlockAreSame() throws Exception {
89.168 + performAnalysisTest("test/Test.java",
89.169 + "|package test;\n" +
89.170 + "\n" +
89.171 + "public class Test {\n" +
89.172 + " private int test() {\n" +
89.173 + " if (true) {\n" +
89.174 + " return 0;\n" +
89.175 + " }\n" +
89.176 + " }\n" +
89.177 + "}\n",
89.178 + "4:9-4:11:verifier:HINT");
89.179 + }
89.180 +
89.181 + public void testPatternFalseOccurrence() throws Exception {
89.182 + performAnalysisTest("test/Test.java",
89.183 + "|package test;\n" +
89.184 + "\n" +
89.185 + "public class Test {\n" +
89.186 + " private int test(java.io.File f) {\n" +
89.187 + " f.toURI().toURL();\n" +
89.188 + " }\n" +
89.189 + "}\n");
89.190 + }
89.191 +
89.192 + public void testStatementVariables1() throws Exception {
89.193 + performFixTest("test/Test.java",
89.194 + "|package test;\n" +
89.195 + "\n" +
89.196 + "public class Test {\n" +
89.197 + " private int test(java.io.File f) {\n" +
89.198 + " if (true)\n" +
89.199 + " System.err.println(1);\n" +
89.200 + " else\n" +
89.201 + " System.err.println(2);\n" +
89.202 + " }\n" +
89.203 + "}\n",
89.204 + "4:9-4:11:verifier:HINT",
89.205 + "FixImpl",
89.206 + ("package test;\n" +
89.207 + "\n" +
89.208 + "public class Test {\n" +
89.209 + " private int test(java.io.File f) {\n" +
89.210 + " if (false)\n" +
89.211 + " System.err.println(2);\n" +
89.212 + " else\n" +
89.213 + " System.err.println(1);\n" +
89.214 + " }\n" +
89.215 + "}\n").replaceAll("[ \t\n]+", " "));
89.216 + }
89.217 +
89.218 + public void testStatementVariables2() throws Exception {
89.219 + performFixTest("test/Test.java",
89.220 + "|package test;\n" +
89.221 + "\n" +
89.222 + "public class Test {\n" +
89.223 + " private int test(java.io.File f) {\n" +
89.224 + " if (true)\n" +
89.225 + " return 1;\n" +
89.226 + " else\n" +
89.227 + " return 2;\n" +
89.228 + " }\n" +
89.229 + "}\n",
89.230 + "4:9-4:11:verifier:HINT",
89.231 + "FixImpl",
89.232 + ("package test;\n" +
89.233 + "\n" +
89.234 + "public class Test {\n" +
89.235 + " private int test(java.io.File f) {\n" +
89.236 + " if (false)\n" +
89.237 + " return 2;\n" +
89.238 + " else\n" +
89.239 + " return 1;\n" +
89.240 + " }\n" +
89.241 + "}\n").replaceAll("[ \t\n]+", " "));
89.242 + }
89.243 +
89.244 + public void testMultiStatementVariables1() throws Exception {
89.245 + performFixTest("test/Test.java",
89.246 + "|package test;\n" +
89.247 + "\n" +
89.248 + "public class Test {\n" +
89.249 + " private int test(int j) {\n" +
89.250 + " j++;\n" +
89.251 + " j++;\n" +
89.252 + " int i = 3;\n" +
89.253 + " j++;\n" +
89.254 + " j++;\n" +
89.255 + " return i;\n" +
89.256 + " }\n" +
89.257 + "}\n",
89.258 + "3:29-10:6:verifier:HINT",
89.259 + "FixImpl",
89.260 + ("package test;\n" +
89.261 + "\n" +
89.262 + "public class Test {\n" +
89.263 + " private int test(int j) {\n" +
89.264 + " j++;\n" +
89.265 + " j++;\n" +
89.266 + " float i = 3;\n" +
89.267 + " j++;\n" +
89.268 + " j++;\n" +
89.269 + " return i;\n" +
89.270 + " }\n" +
89.271 + "}\n").replaceAll("[ \t\n]+", " "));
89.272 + }
89.273 +
89.274 + public void testMultiStatementVariables2() throws Exception {
89.275 + performFixTest("test/Test.java",
89.276 + "|package test;\n" +
89.277 + "\n" +
89.278 + "public class Test {\n" +
89.279 + " private int test(int j) {\n" +
89.280 + " int i = 3;\n" +
89.281 + " return i;\n" +
89.282 + " }\n" +
89.283 + "}\n",
89.284 + "3:29-6:6:verifier:HINT",
89.285 + "FixImpl",
89.286 + ("package test;\n" +
89.287 + "\n" +
89.288 + "public class Test {\n" +
89.289 + " private int test(int j) {\n" +
89.290 + " float i = 3;\n" +
89.291 + " return i;\n" +
89.292 + " }\n" +
89.293 + "}\n").replaceAll("[ \t\n]+", " "));
89.294 + }
89.295 +
89.296 + public void testMultiStatementVariables3() throws Exception {
89.297 + performFixTest("test/Test.java",
89.298 + "|package test;\n" +
89.299 + "\n" +
89.300 + "public class Test {\n" +
89.301 + " private int test() {\n" +
89.302 + " System.err.println();\n" +
89.303 + " System.err.println();\n" +
89.304 + " int i = 3;\n" +
89.305 + " System.err.println(i);\n" +
89.306 + " System.err.println(i);\n" +
89.307 + " return i;\n" +
89.308 + " }\n" +
89.309 + "}\n",
89.310 + "3:24-10:6:verifier:HINT",
89.311 + "FixImpl",
89.312 + ("package test;\n" +
89.313 + "\n" +
89.314 + "public class Test {\n" +
89.315 + " private int test() {\n" +
89.316 + " System.err.println();\n" +
89.317 + " System.err.println();\n" +
89.318 + " float i = 3;\n" +
89.319 + " System.err.println(i);\n" +
89.320 + " System.err.println(i);\n" +
89.321 + " return i;\n" +
89.322 + " }\n" +
89.323 + "}\n").replaceAll("[ \t\n]+", " "));
89.324 + }
89.325 +
89.326 + public void testMultiStatementVariablesAndBlocks() throws Exception {
89.327 + performFixTest("test/Test.java",
89.328 + "|package test;\n" +
89.329 + "\n" +
89.330 + "public class Test {\n" +
89.331 + " private void test() {" +
89.332 + " if (true)\n" +
89.333 + " System.err.println();\n" +
89.334 + " }\n" +
89.335 + "}\n",
89.336 + "3:35-3:37:verifier:HINT",
89.337 + "FixImpl",
89.338 + ("package test;\n" +
89.339 + "\n" +
89.340 + "public class Test {\n" +
89.341 + " private void test() {" +
89.342 + " if (false) {\n" +
89.343 + " System.err.println();\n" +
89.344 + " }\n" +
89.345 + " }\n" +
89.346 + "}\n").replaceAll("[ \t\n]+", " "));
89.347 + }
89.348 +
89.349 + public void testOneStatement2MultipleBlock() throws Exception {
89.350 + performFixTest("test/Test.java",
89.351 + "|package test;\n" +
89.352 + "\n" +
89.353 + "public class Test {\n" +
89.354 + " private void test() {\n" +
89.355 + " System.err.println(\"\");\n" +
89.356 + " }\n" +
89.357 + "}\n",
89.358 + "4:9-4:32:verifier:HINT",
89.359 + "FixImpl",
89.360 + ("package test;\n" +
89.361 + "\n" +
89.362 + "public class Test {\n" +
89.363 + " private void test() {\n" +
89.364 + " System.err.println(\"\");\n" +
89.365 + " System.err.println(\"\");\n" +
89.366 + " }\n" +
89.367 + "}\n").replaceAll("[ \t\n]+", " "));
89.368 + }
89.369 +
89.370 + public void testOneStatement2MultipleStatement() throws Exception {
89.371 + performFixTest("test/Test.java",
89.372 + "|package test;\n" +
89.373 + "\n" +
89.374 + "public class Test {\n" +
89.375 + " private void test() {\n" +
89.376 + " if (true)\n" +
89.377 + " System.err.println(\"\");\n" +
89.378 + " }\n" +
89.379 + "}\n",
89.380 + "5:13-5:36:verifier:HINT",
89.381 + "FixImpl",
89.382 + ("package test;\n" +
89.383 + "\n" +
89.384 + "public class Test {\n" +
89.385 + " private void test() {\n" +
89.386 + " if (true) {\n" +
89.387 + " System.err.println(\"\");\n" +
89.388 + " System.err.println(\"\");\n" +
89.389 + " }\n" +
89.390 + " }\n" +
89.391 + "}\n").replaceAll("[ \t\n]+", " "));
89.392 + }
89.393 +
89.394 + public void testMultiple2OneStatement1() throws Exception {
89.395 + performFixTest("test/Test.java",
89.396 + "|package test;\n" +
89.397 + "\n" +
89.398 + "public class Test {\n" +
89.399 + " private void test() {\n" +
89.400 + " System.err.println(\"\");\n" +
89.401 + " System.err.println(\"\");\n" +
89.402 + " }\n" +
89.403 + "}\n",
89.404 + "4:9-4:32:verifier:HINT",
89.405 + "FixImpl",
89.406 + ("package test;\n" +
89.407 + "\n" +
89.408 + "public class Test {\n" +
89.409 + " private void test() {\n" +
89.410 + " System.err.println(\"\");\n" +
89.411 + " }\n" +
89.412 + "}\n").replaceAll("[ \t\n]+", " "));
89.413 + }
89.414 +
89.415 + public void testMultiple2OneStatement2() throws Exception {
89.416 + performFixTest("test/Test.java",
89.417 + "|package test;\n" +
89.418 + "\n" +
89.419 + "public class Test {\n" +
89.420 + " private void test() {\n" +
89.421 + " int i = 0;\n" +
89.422 + " System.err.println(\"\");\n" +
89.423 + " System.err.println(\"\");\n" +
89.424 + " i++;\n" +
89.425 + " }\n" +
89.426 + "}\n",
89.427 + "5:9-5:32:verifier:HINT",
89.428 + "FixImpl",
89.429 + ("package test;\n" +
89.430 + "\n" +
89.431 + "public class Test {\n" +
89.432 + " private void test() {\n" +
89.433 + " int i = 0;\n" +
89.434 + " System.err.println(\"\");\n" +
89.435 + " i++;\n" +
89.436 + " }\n" +
89.437 + "}\n").replaceAll("[ \t\n]+", " "));
89.438 + }
89.439 +
89.440 + public void testMemberSelectInsideMemberSelect() throws Exception {
89.441 + performFixTest("test/Test.java",
89.442 + "|package test;\n" +
89.443 + "\n" +
89.444 + "public class Test {\n" +
89.445 + " public Test test;\n" +
89.446 + " public String name;\n" +
89.447 + " private void test() {\n" +
89.448 + " Test t = null;\n" +
89.449 + " String s = t.test.toString();\n" +
89.450 + " }\n" +
89.451 + "}\n",
89.452 + "7:22-7:26:verifier:HINT",
89.453 + "FixImpl",
89.454 + ("package test;\n" +
89.455 + "\n" +
89.456 + "public class Test {\n" +
89.457 + " public Test test;\n" +
89.458 + " public String name;\n" +
89.459 + " private void test() {\n" +
89.460 + " Test t = null;\n" +
89.461 + " String s = t.getTest().toString();\n" +
89.462 + " }\n" +
89.463 + "}\n").replaceAll("[ \t\n]+", " "));
89.464 + }
89.465 +
89.466 + public void testPackageInfo() throws Exception {
89.467 + performAnalysisTest("test/package-info.java",
89.468 + "|package test;\n");
89.469 + }
89.470 +
89.471 + public void testSuppressWarnings() throws Exception {
89.472 + performAnalysisTest("test/Test.java",
89.473 + "|package test;\n" +
89.474 + "@SuppressWarnings(\"test\")\n" +
89.475 + "public class Test {\n" +
89.476 + " public Test test;\n" +
89.477 + " public String name;\n" +
89.478 + " private void test() {\n" +
89.479 + " Test t = null;\n" +
89.480 + " String s = t.test.toString();\n" +
89.481 + " }\n" +
89.482 + "}\n");
89.483 + }
89.484 +
89.485 + public void testRewriteOneToMultipleClassMembers() throws Exception {
89.486 + performFixTest("test/Test.java",
89.487 + "|package test;\n" +
89.488 + "\n" +
89.489 + "public class Test {\n" +
89.490 + " private int i;\n" +
89.491 + "}\n",
89.492 + "3:17-3:18:verifier:HINT",
89.493 + "FixImpl",
89.494 + ("package test;\n" +
89.495 + "\n" +
89.496 + "public class Test {\n" +
89.497 + " private int i;\n" +
89.498 + " public int getI() {\n" +
89.499 + " return i;\n" +
89.500 + " }\n" +
89.501 + "}\n").replaceAll("[ \t\n]+", " "));
89.502 + }
89.503 +
89.504 + public void testImports1() throws Exception {
89.505 + performFixTest("test/Test.java",
89.506 + "|package test;\n" +
89.507 + "\n" +
89.508 + "public class Test {\n" +
89.509 + " private void test() {\n" +
89.510 + " new java.util.LinkedList();\n" +
89.511 + " }" +
89.512 + "}\n",
89.513 + "4:9-4:35:verifier:HINT",
89.514 + "FixImpl",
89.515 + ("package test;\n" +
89.516 + "import java.util.ArrayList;\n" +
89.517 + "public class Test {\n" +
89.518 + " private void test() {\n" +
89.519 + " new ArrayList();\n" +
89.520 + " }" +
89.521 + "}\n").replaceAll("[ \t\n]+", " "));
89.522 + }
89.523 +
89.524 + public void testImports2() throws Exception {
89.525 + performFixTest("test/Test.java",
89.526 + "|package test;\n" +
89.527 + "import java.util.LinkedList;\n" +
89.528 + "public class Test {\n" +
89.529 + " private void test() {\n" +
89.530 + " LinkedList l;\n" +
89.531 + " }" +
89.532 + "}\n",
89.533 + "4:20-4:21:verifier:HINT",
89.534 + "FixImpl",
89.535 + ("package test;\n" +
89.536 + "import java.util.ArrayList;\n" +
89.537 + "import java.util.LinkedList;\n" +
89.538 + "public class Test {\n" +
89.539 + " private void test() {\n" +
89.540 + " ArrayList l;\n" +
89.541 + " }" +
89.542 + "}\n").replaceAll("[ \t\n]+", " "));
89.543 + }
89.544 +
89.545 + public void testMultiParameters() throws Exception {
89.546 + performFixTest("test/Test.java",
89.547 + "|package test;\n" +
89.548 + "import java.util.Arrays;\n" +
89.549 + "public class Test {\n" +
89.550 + " { Arrays.asList(\"a\", \"b\", \"c\"); }\n" +
89.551 + "}\n",
89.552 + "3:14-3:20:verifier:HINT",
89.553 + "FixImpl",
89.554 + ("package test;\n" +
89.555 + "import java.util.Arrays;\n" +
89.556 + "public class Test {\n" +
89.557 + " { Arrays.asList(\"d\", \"a\", \"b\", \"c\"); }\n" +
89.558 + "}\n").replaceAll("[ \t\n]+", " "));
89.559 + }
89.560 +
89.561 + public void testTypeParametersMethod() throws Exception {
89.562 + performFixTest("test/Test.java",
89.563 + "|package test;\n" +
89.564 + "import java.util.Arrays;\n" +
89.565 + "public class Test {\n" +
89.566 + " { Arrays.<String>asList(\"a\", \"b\", \"c\"); }\n" +
89.567 + "}\n",
89.568 + "3:22-3:28:verifier:HINT",
89.569 + "FixImpl",
89.570 + ("package test;\n" +
89.571 + "import java.util.Arrays;\n" +
89.572 + "public class Test {\n" +
89.573 + " { Arrays.<String>asList(\"d\", \"a\", \"b\", \"c\"); }\n" +
89.574 + "}\n").replaceAll("[ \t\n]+", " "));
89.575 + }
89.576 +
89.577 + public void testTypeParametersNewClass() throws Exception {
89.578 + performFixTest("test/Test.java",
89.579 + "|package test;\n" +
89.580 + "import java.util.Arrays;\n" +
89.581 + "import java.util.HashSet;\n" +
89.582 + "public class Test {\n" +
89.583 + " { new HashSet<String>(Arrays.<String>asList(\"a\", \"b\", \"c\")); }\n" +
89.584 + "}\n",
89.585 + "4:7-4:64:verifier:HINT",
89.586 + "FixImpl",
89.587 + ("package test;\n" +
89.588 + "import java.util.Arrays;\n" +
89.589 + "import java.util.HashSet;\n" +
89.590 + "public class Test {\n" +
89.591 + " { new HashSet<String>(Arrays.<String>asList(\"d\", \"a\", \"b\", \"c\")); }\n" +
89.592 + "}\n").replaceAll("[ \t\n]+", " "));
89.593 + }
89.594 +
89.595 + public void testChangeFieldType1() throws Exception {
89.596 + performFixTest("test/Test.java",
89.597 + "|package test;\n" +
89.598 + "public class Test {\n" +
89.599 + " private String name = null;\n" +
89.600 + "}\n",
89.601 + "2:20-2:24:verifier:HINT",
89.602 + "FixImpl",
89.603 + ("package test;\n" +
89.604 + "public class Test {\n" +
89.605 + " private CharSequence name = null;\n" +
89.606 + "}\n").replaceAll("[ \t\n]+", " "));
89.607 + }
89.608 +
89.609 + public void testChangeFieldType2() throws Exception {
89.610 + performFixTest("test/Test.java",
89.611 + "|package test;\n" +
89.612 + "public class Test {\n" +
89.613 + " String name = null;\n" +
89.614 + "}\n",
89.615 + "2:12-2:16:verifier:HINT",
89.616 + "FixImpl",
89.617 + ("package test;\n" +
89.618 + "public class Test {\n" +
89.619 + " CharSequence name = null;\n" +
89.620 + "}\n").replaceAll("[ \t\n]+", " "));
89.621 + }
89.622 +
89.623 + public void testChangeFieldType3() throws Exception {
89.624 + performFixTest("test/Test.java",
89.625 + "|package test;\n" +
89.626 + "public class Test {\n" +
89.627 + " private static final String name = \"test\".substring(0, 4);\n" +
89.628 + "}\n",
89.629 + "2:33-2:37:verifier:HINT",
89.630 + "FixImpl",
89.631 + ("package test;\n" +
89.632 + "public class Test {\n" +
89.633 + " private static final CharSequence name = \"test\".substring(0, 4);\n" +
89.634 + "}\n").replaceAll("[ \t\n]+", " "));
89.635 + }
89.636 +
89.637 + public void testIdentifier() throws Exception {
89.638 + performFixTest("test/Test.java",
89.639 + "|package test;\n" +
89.640 + "public class Test {\n" +
89.641 + " private int l;" +
89.642 + " {System.err.println(l);}\n" +
89.643 + "}\n",
89.644 + "2:44-2:45:verifier:HINT",
89.645 + "FixImpl",
89.646 + ("package test;\n" +
89.647 + "public class Test {\n" +
89.648 + " private int l;" +
89.649 + " {System.err.println(2);}\n" +
89.650 + "}\n").replaceAll("[ \t\n]+", " "));
89.651 + }
89.652 +
89.653 + public void testLambda() throws Exception {
89.654 + performAnalysisTest("test/Test.java",
89.655 + "|package test;\n" +
89.656 + "public class Test {\n" +
89.657 + " { new java.io.FileFilter() {public boolean accept(java.io.File f) { return true; } } }\n" +
89.658 + "}\n",
89.659 + "2:7-2:89:verifier:HINT");
89.660 + }
89.661 +
89.662 + public void testAddCasesToSwitch() throws Exception {
89.663 + performFixTest("test/Test.java",
89.664 + "|package test;\n" +
89.665 + "public class Test {\n" +
89.666 + " {\n" +
89.667 + " E e = null;\n" +
89.668 + " switch (e) {\n" +
89.669 + " case A: System.err.println(1); break;\n" +
89.670 + " case D: System.err.println(2); break;\n" +
89.671 + " case E: System.err.println(3); break;\n" +
89.672 + " }\n" +
89.673 + " }\n" +
89.674 + " public enum E {A, B, C, D, E, F;}\n" +
89.675 + "}\n",
89.676 + "4:9-4:15:verifier:HINT",
89.677 + "FixImpl",
89.678 + ("package test;\n" +
89.679 + "public class Test {\n" +
89.680 + " {\n" +
89.681 + " E e = null;\n" +
89.682 + " switch (e) {\n" +
89.683 + " case A: System.err.println(1); break;\n" +
89.684 + " case B:case C:\n" +
89.685 +// " case C:\n" +
89.686 + " case D: System.err.println(2); break;\n" +
89.687 + " case E: System.err.println(3); break;\n" +
89.688 + " }\n" +
89.689 + " }\n" +
89.690 + " public enum E {A, B, C, D, E, F;}\n" +
89.691 + "}\n").replaceAll("[ \t\n]+", " "));
89.692 + }
89.693 +
89.694 + private static final Map<String, HintDescription> test2Hint;
89.695 +
89.696 + static {
89.697 + test2Hint = new HashMap<String, HintDescription>();
89.698 + test2Hint.put("testPattern1", HintDescriptionFactory.create().setTrigger(PatternDescription.create("$1.toURL()", Collections.singletonMap("$1", "java.io.File"))).setWorker(new WorkerImpl()).produce());
89.699 + test2Hint.put("testPattern2", test2Hint.get("testPattern1"));
89.700 + test2Hint.put("testKind1", HintDescriptionFactory.create().setTrigger(new Kinds(EnumSet.of(Kind.METHOD_INVOCATION))).setWorker(new WorkerImpl()).produce());
89.701 + test2Hint.put("testPatternVariable1", HintDescriptionFactory.create().setTrigger(PatternDescription.create("{ $1 $2; $2 = $3; }", Collections.<String, String>emptyMap())).setWorker(new WorkerImpl("{ $1 $2 = $3; }")).produce());
89.702 + Map<String, String> constraints = new HashMap<String, String>();
89.703 +
89.704 + constraints.put("$1", "boolean");
89.705 + constraints.put("$2", "java.lang.Object");
89.706 +
89.707 + test2Hint.put("testPatternAssert1", HintDescriptionFactory.create().setTrigger(PatternDescription.create("assert $1 : $2;", constraints)).setWorker(new WorkerImpl()).produce());
89.708 + test2Hint.put("testPatternStatementAndSingleStatementBlockAreSame", HintDescriptionFactory.create().setTrigger(PatternDescription.create("if ($1) return $2;", Collections.<String, String>emptyMap())).setWorker(new WorkerImpl()).produce());
89.709 + test2Hint.put("testPatternFalseOccurrence", HintDescriptionFactory.create().setTrigger(PatternDescription.create("$1.toURL()", Collections.singletonMap("$1", "java.io.File"))).setWorker(new WorkerImpl()).produce());
89.710 + test2Hint.put("testStatementVariables1", HintDescriptionFactory.create().setTrigger(PatternDescription.create("if ($1) $2; else $3;", constraints)).setWorker(new WorkerImpl("if (!$1) $3; else $2;")).produce());
89.711 + test2Hint.put("testStatementVariables2", test2Hint.get("testStatementVariables1"));
89.712 + test2Hint.put("testMultiStatementVariables1", HintDescriptionFactory.create().setTrigger(PatternDescription.create("{ $pref$; int $i = 3; $inf$; return $i; }", Collections.<String, String>emptyMap())).setWorker(new WorkerImpl("{ $pref$; float $i = 3; $inf$; return $i; }")).produce());
89.713 + test2Hint.put("testMultiStatementVariables2", test2Hint.get("testMultiStatementVariables1"));
89.714 + test2Hint.put("testMultiStatementVariables3", test2Hint.get("testMultiStatementVariables1"));
89.715 + test2Hint.put("testMultiStatementVariablesAndBlocks", HintDescriptionFactory.create().setTrigger(PatternDescription.create("if ($c) {$s1$; System.err.println(); $s2$; }", Collections.<String, String>emptyMap())).setWorker(new WorkerImpl("if (!$c) {$s1$; System.err.println(); $s2$; }")).produce());
89.716 + test2Hint.put("testOneStatement2MultipleBlock", HintDescriptionFactory.create().setTrigger(PatternDescription.create("System.err.println($1);", Collections.<String, String>emptyMap())).setWorker(new WorkerImpl("System.err.println($1); System.err.println($1);")).produce());
89.717 + test2Hint.put("testOneStatement2MultipleStatement", test2Hint.get("testOneStatement2MultipleBlock"));
89.718 + test2Hint.put("testMultiple2OneStatement1", HintDescriptionFactory.create().setTrigger(PatternDescription.create("System.err.println($1); System.err.println($2);", Collections.<String, String>emptyMap())).setWorker(new WorkerImpl("System.err.println($1);")).produce());
89.719 + test2Hint.put("testMultiple2OneStatement2", test2Hint.get("testMultiple2OneStatement1"));
89.720 + test2Hint.put("testMemberSelectInsideMemberSelect", HintDescriptionFactory.create().setTrigger(PatternDescription.create("$Test.test", Collections.<String, String>singletonMap("$Test", "test.Test"))).setWorker(new WorkerImpl("$Test.getTest()")).produce());
89.721 + test2Hint.put("testPackageInfo", HintDescriptionFactory.create().setTrigger(PatternDescription.create("$Test.test", Collections.<String, String>singletonMap("$Test", "test.Test"))).setWorker(new WorkerImpl("$Test.getTest()")).produce());
89.722 + HintMetadata metadata = HintMetadata.Builder.create("no-id").addOptions(Options.NON_GUI).addSuppressWarnings("test").build();
89.723 + test2Hint.put("testSuppressWarnings", HintDescriptionFactory.create().setTrigger(PatternDescription.create("$Test.test", Collections.<String, String>singletonMap("$Test", "test.Test"))).setWorker(new WorkerImpl("$Test.getTest()")).setMetadata(metadata).produce());
89.724 + test2Hint.put("testRewriteOneToMultipleClassMembers", HintDescriptionFactory.create().setTrigger(PatternDescription.create("private int i;", Collections.<String, String>emptyMap())).setWorker(new WorkerImpl("private int i; public int getI() { return i; }")).produce());
89.725 +// test2Hint.put("testImports1", HintDescriptionFactory.create().setTrigger(PatternDescription.create("new LinkedList()", Collections.<String, String>emptyMap(), "import java.util.LinkedList;")).setWorker(new WorkerImpl("new ArrayList()", "import java.util.ArrayList;\n")).produce());
89.726 +// test2Hint.put("testImports2", HintDescriptionFactory.create().setTrigger(PatternDescription.create("LinkedList $0;", Collections.<String, String>emptyMap(), "import java.util.LinkedList;")).setWorker(new WorkerImpl("ArrayList $0;", "import java.util.ArrayList;\n")).produce());
89.727 + test2Hint.put("testImports1", HintDescriptionFactory.create().setTrigger(PatternDescription.create("new LinkedList()", Collections.<String, String>emptyMap(), "import java.util.LinkedList;")).setWorker(new WorkerImpl("new java.util.ArrayList()")).produce());
89.728 + test2Hint.put("testImports2", HintDescriptionFactory.create().setTrigger(PatternDescription.create("LinkedList $0;", Collections.<String, String>emptyMap(), "import java.util.LinkedList;")).setWorker(new WorkerImpl("java.util.ArrayList $0;")).produce());
89.729 + test2Hint.put("testMultiParameters", HintDescriptionFactory.create().setTrigger(PatternDescription.create("java.util.Arrays.asList($1$)", Collections.<String,String>emptyMap())).setWorker(new WorkerImpl("java.util.Arrays.asList(\"d\", $1$)")).produce());
89.730 + test2Hint.put("testTypeParametersMethod", HintDescriptionFactory.create().setTrigger(PatternDescription.create("java.util.Arrays.<$T>asList($1$)", Collections.<String,String>emptyMap())).setWorker(new WorkerImpl("java.util.Arrays.<$T>asList(\"d\", $1$)")).produce());
89.731 + test2Hint.put("testTypeParametersNewClass", HintDescriptionFactory.create().setTrigger(PatternDescription.create("new java.util.HashSet<$T1$>(java.util.Arrays.<$T$>asList($1$))", Collections.<String,String>emptyMap())).setWorker(new WorkerImpl("new java.util.HashSet<$T1$>(java.util.Arrays.<$T$>asList(\"d\", $1$))")).produce());
89.732 + test2Hint.put("testChangeFieldType1", HintDescriptionFactory.create().setTrigger(PatternDescription.create("$modifiers$ java.lang.String $name = $initializer;", Collections.<String, String>emptyMap())).setWorker(new WorkerImpl("$modifiers$ java.lang.CharSequence $name = $initializer;")).produce());
89.733 + test2Hint.put("testChangeFieldType2", test2Hint.get("testChangeFieldType1"));
89.734 + test2Hint.put("testChangeFieldType3", test2Hint.get("testChangeFieldType1"));
89.735 + test2Hint.put("testIdentifier", HintDescriptionFactory.create().setTrigger(PatternDescription.create("$i", Collections.<String, String>singletonMap("$i", "int"))).setWorker(new WorkerImpl("2")).produce());
89.736 + test2Hint.put("testLambda", HintDescriptionFactory.create().setTrigger(PatternDescription.create("new $type() { $mods$ $retType $name($params$) { $body$; } }", Collections.<String, String>emptyMap())).setWorker(new WorkerImpl()).produce());
89.737 + test2Hint.put("testAddCasesToSwitch", HintDescriptionFactory.create().setTrigger(PatternDescription.create("switch ($var) { case $c1$; case D: $stmts$; case $c2$; }", Collections.<String,String>singletonMap("$var", "test.Test.E"))).setWorker(new WorkerImpl("switch ($var) { case $c1$ case B: case C: case D: $stmts$; case $c2$ }")).produce());
89.738 + }
89.739 +
89.740 +// @Override
89.741 + protected List<ErrorDescription> computeErrors(CompilationInfo info, TreePath path, int pos) {
89.742 + HintDescription hd = test2Hint.get(getName());
89.743 +
89.744 + assertNotNull(hd);
89.745 +
89.746 + return new HintsInvoker(HintsSettings.getGlobalSettings(), new AtomicBoolean()).computeHints(info, Collections.singletonList(hd));
89.747 + }
89.748 +
89.749 +// @Override
89.750 + protected String toDebugString(CompilationInfo info, Fix f) {
89.751 + return "FixImpl";
89.752 + }
89.753 +
89.754 +// @Override
89.755 +// public void testIssue105979() throws Exception {}
89.756 +//
89.757 +// @Override
89.758 +// public void testIssue108246() throws Exception {}
89.759 +//
89.760 +// @Override
89.761 +// public void testIssue113933() throws Exception {}
89.762 +//
89.763 +// @Override
89.764 +// public void testNoHintsForSimpleInitialize() throws Exception {}
89.765 +
89.766 + private static final class WorkerImpl implements Worker {
89.767 +
89.768 + private final String fix;
89.769 +
89.770 + public WorkerImpl() {
89.771 + this(null);
89.772 + }
89.773 +
89.774 + public WorkerImpl(String fix) {
89.775 + this.fix = fix;
89.776 + }
89.777 +
89.778 + public Collection<? extends ErrorDescription> createErrors(HintContext ctx) {
89.779 + if (ctx.getInfo().getTreeUtilities().isSynthetic(ctx.getPath())) {
89.780 + return null;
89.781 + }
89.782 +
89.783 + List<Fix> fixes = new LinkedList<Fix>();
89.784 +
89.785 + if (fix != null) {
89.786 + fixes.add(JavaFixUtilities.rewriteFix(ctx, "Rewrite", ctx.getPath(), fix));
89.787 + }
89.788 +
89.789 + return Collections.singletonList(ErrorDescriptionFactory.forName(ctx, ctx.getPath(), "HINT", fixes.toArray(new Fix[0])));
89.790 + }
89.791 + }
89.792 +
89.793 +
89.794 + //XXX:copied from TreeRuleTestBase:
89.795 +
89.796 + protected void performAnalysisTest(String fileName, String code, String... golden) throws Exception {
89.797 + int[] offset = new int[1];
89.798 +
89.799 + code = org.netbeans.modules.java.hints.spiimpl.TestUtilities.detectOffsets(code, offset);
89.800 +
89.801 + performAnalysisTest(fileName, code, offset[0], golden);
89.802 + }
89.803 +
89.804 + protected void performAnalysisTest(String fileName, String code, int pos, String... golden) throws Exception {
89.805 + prepareTest(fileName, code);
89.806 +
89.807 + TreePath path = info.getTreeUtilities().pathFor(pos);
89.808 +
89.809 + List<ErrorDescription> errors = computeErrors(info, path, pos);
89.810 + List<String> errorsNames = new LinkedList<String>();
89.811 +
89.812 + errors = errors != null ? errors : Collections.<ErrorDescription>emptyList();
89.813 +
89.814 + for (ErrorDescription e : errors) {
89.815 + errorsNames.add(e.toString());
89.816 + }
89.817 +
89.818 + assertTrue("The warnings provided by the hint do not match expected warnings. Provided warnings: " + errorsNames.toString(), Arrays.equals(golden, errorsNames.toArray(new String[0])));
89.819 + }
89.820 +
89.821 + protected String performFixTest(String fileName, String code, String errorDescriptionToString, String fixDebugString, String golden) throws Exception {
89.822 + int[] offset = new int[1];
89.823 +
89.824 + code = org.netbeans.modules.java.hints.spiimpl.TestUtilities.detectOffsets(code, offset);
89.825 +
89.826 + return performFixTest(fileName, code, offset[0], errorDescriptionToString, fixDebugString, golden);
89.827 + }
89.828 +
89.829 + protected String performFixTest(String fileName, String code, int pos, String errorDescriptionToString, String fixDebugString, String golden) throws Exception {
89.830 + return performFixTest(fileName, code, pos, errorDescriptionToString, fixDebugString, fileName, golden);
89.831 + }
89.832 +
89.833 + protected String performFixTest(String fileName, String code, String errorDescriptionToString, String fixDebugString, String goldenFileName, String golden) throws Exception {
89.834 + int[] offset = new int[1];
89.835 +
89.836 + code = org.netbeans.modules.java.hints.spiimpl.TestUtilities.detectOffsets(code, offset);
89.837 +
89.838 + return performFixTest(fileName, code, offset[0], errorDescriptionToString, fixDebugString, goldenFileName, golden);
89.839 + }
89.840 +
89.841 + protected String performFixTest(String fileName, String code, int pos, String errorDescriptionToString, String fixDebugString, String goldenFileName, String golden) throws Exception {
89.842 + prepareTest(fileName, code);
89.843 +
89.844 + TreePath path = info.getTreeUtilities().pathFor(pos);
89.845 +
89.846 + List<ErrorDescription> errors = computeErrors(info, path, pos);
89.847 +
89.848 + ErrorDescription toFix = null;
89.849 +
89.850 + for (ErrorDescription d : errors) {
89.851 + if (errorDescriptionToString.equals(d.toString())) {
89.852 + toFix = d;
89.853 + break;
89.854 + }
89.855 + }
89.856 +
89.857 + assertNotNull("Error: \"" + errorDescriptionToString + "\" not found. All ErrorDescriptions: " + errors.toString(), toFix);
89.858 +
89.859 + assertTrue("Must be computed", toFix.getFixes().isComputed());
89.860 +
89.861 + List<Fix> fixes = toFix.getFixes().getFixes();
89.862 + List<String> fixNames = new LinkedList<String>();
89.863 + Fix toApply = null;
89.864 +
89.865 + for (Fix f : fixes) {
89.866 + if (fixDebugString.equals(toDebugString(info, f))) {
89.867 + toApply = f;
89.868 + }
89.869 +
89.870 + fixNames.add(toDebugString(info, f));
89.871 + }
89.872 +
89.873 + assertNotNull("Cannot find fix to invoke: " + fixNames.toString(), toApply);
89.874 +
89.875 + toApply.implement();
89.876 +
89.877 + FileObject toCheck = sourceRoot.getFileObject(goldenFileName);
89.878 +
89.879 + assertNotNull(toCheck);
89.880 +
89.881 + DataObject toCheckDO = DataObject.find(toCheck);
89.882 + EditorCookie ec = toCheckDO.getLookup().lookup(EditorCookie.class);
89.883 + Document toCheckDocument = ec.openDocument();
89.884 +
89.885 + String realCode = toCheckDocument.getText(0, toCheckDocument.getLength());
89.886 +
89.887 + //ignore whitespaces:
89.888 + realCode = realCode.replaceAll("[ \t\n]+", " ");
89.889 +
89.890 + if (golden != null) {
89.891 + assertEquals("The output code does not match the expected code.", golden, realCode);
89.892 + }
89.893 +
89.894 + LifecycleManager.getDefault().saveAll();
89.895 +
89.896 + return realCode;
89.897 + }
89.898 +}
89.899 \ No newline at end of file
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/pm/BulkSearchTestPerformer.java Wed May 08 21:47:42 2013 +0200
90.3 @@ -0,0 +1,694 @@
90.4 +/*
90.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
90.6 + *
90.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
90.8 + *
90.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
90.10 + * Other names may be trademarks of their respective owners.
90.11 + *
90.12 + * The contents of this file are subject to the terms of either the GNU
90.13 + * General Public License Version 2 only ("GPL") or the Common
90.14 + * Development and Distribution License("CDDL") (collectively, the
90.15 + * "License"). You may not use this file except in compliance with the
90.16 + * License. You can obtain a copy of the License at
90.17 + * http://www.netbeans.org/cddl-gplv2.html
90.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
90.19 + * specific language governing permissions and limitations under the
90.20 + * License. When distributing the software, include this License Header
90.21 + * Notice in each file and include the License file at
90.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
90.23 + * particular file as subject to the "Classpath" exception as provided
90.24 + * by Oracle in the GPL Version 2 section of the License file that
90.25 + * accompanied this code. If applicable, add the following below the
90.26 + * License Header, with the fields enclosed by brackets [] replaced by
90.27 + * your own identifying information:
90.28 + * "Portions Copyrighted [year] [name of copyright owner]"
90.29 + *
90.30 + * If you wish your version of this file to be governed by only the CDDL
90.31 + * or only the GPL Version 2, indicate your decision by adding
90.32 + * "[Contributor] elects to include this software in this distribution
90.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
90.34 + * single choice of license, a recipient has the option to distribute
90.35 + * your version of this file under either the CDDL, the GPL Version 2 or
90.36 + * to extend the choice of license to its licensees as provided above.
90.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
90.38 + * Version 2 license, then the option applies only if the new code is
90.39 + * made subject to such option by the copyright holder.
90.40 + *
90.41 + * Contributor(s):
90.42 + *
90.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
90.44 + */
90.45 +
90.46 +package org.netbeans.modules.java.hints.spiimpl.pm;
90.47 +
90.48 +import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch.BulkPattern;
90.49 +import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch.EncodingContext;
90.50 +import com.sun.source.util.TreePath;
90.51 +import java.io.ByteArrayInputStream;
90.52 +import java.io.ByteArrayOutputStream;
90.53 +import java.io.File;
90.54 +import java.util.Arrays;
90.55 +import java.util.Collection;
90.56 +import java.util.Collections;
90.57 +import java.util.HashMap;
90.58 +import java.util.HashSet;
90.59 +import java.util.LinkedList;
90.60 +import java.util.List;
90.61 +import java.util.Map;
90.62 +import java.util.Map.Entry;
90.63 +import java.util.Set;
90.64 +import java.util.concurrent.atomic.AtomicBoolean;
90.65 +import java.util.regex.Pattern;
90.66 +import javax.swing.text.Document;
90.67 +import org.netbeans.api.java.lexer.JavaTokenId;
90.68 +import org.netbeans.api.java.source.CompilationInfo;
90.69 +import org.netbeans.api.java.source.JavaSource;
90.70 +import org.netbeans.api.java.source.JavaSource.Phase;
90.71 +import org.netbeans.api.java.source.SourceUtilsTestUtil;
90.72 +import org.netbeans.api.java.source.TestUtilities;
90.73 +import org.netbeans.api.java.source.TreePathHandle;
90.74 +import org.netbeans.api.lexer.Language;
90.75 +import org.netbeans.junit.NbTestCase;
90.76 +import org.netbeans.modules.java.source.TreeLoader;
90.77 +import org.openide.cookies.EditorCookie;
90.78 +import org.openide.filesystems.FileObject;
90.79 +import org.openide.filesystems.FileUtil;
90.80 +import org.openide.loaders.DataObject;
90.81 +import static org.junit.Assert.*;
90.82 +import org.netbeans.junit.RandomlyFails;
90.83 +
90.84 +/**
90.85 + *
90.86 + * @author lahvac
90.87 + */
90.88 +public abstract class BulkSearchTestPerformer extends NbTestCase {
90.89 +
90.90 + public BulkSearchTestPerformer(String name) {
90.91 + super(name);
90.92 + }
90.93 +
90.94 + @Override
90.95 + protected void setUp() throws Exception {
90.96 + super.setUp();
90.97 + SourceUtilsTestUtil.prepareTest(new String[] {"org/netbeans/modules/java/editor/resources/layer.xml"}, new Object[0]);
90.98 + TreeLoader.DISABLE_CONFINEMENT_TEST = true;
90.99 + }
90.100 +
90.101 +// public static TestSuite suite() {
90.102 +// NbTestSuite s = new NbTestSuite();
90.103 +//
90.104 +// s.addTestSuite(NFABasedBulkSearchTest.class);
90.105 +//
90.106 +// return s;
90.107 +// }
90.108 +
90.109 + public void testSimple1() throws Exception {
90.110 + performTest("package test; public class Test { private void test() { System.err./**/println(\"\");}}",
90.111 + Collections.singletonMap("System.err.println(\"\")", Arrays.asList("System.err./**/println(\"\")")),
90.112 + Arrays.asList("System.err.println(\"\" + \"\")"));
90.113 + }
90.114 +
90.115 + public void testDontCare() throws Exception {
90.116 + performTest("package test; public class Test { private void test() { System.err./**/println(\"\" + \"\");}}",
90.117 + Collections.singletonMap("System.err.println($1)", Arrays.asList("System.err./**/println(\"\" + \"\")")),
90.118 + Collections.<String>emptyList());
90.119 + }
90.120 +
90.121 + public void testMemberSelectAndIdentifier() throws Exception {
90.122 + performTest("package test; public class Test { private static void test() { test();}}",
90.123 + Collections.singletonMap("test.Test.test()", Arrays.asList("test()")),
90.124 + Collections.<String>emptyList());
90.125 + }
90.126 +
90.127 + public void testUnpureMemberSelect() throws Exception {
90.128 + performTest("package test; public class Test { private static void test() { new StringBuilder().append(\"\");}}",
90.129 + Collections.<String, List<String>>emptyMap(),
90.130 + Arrays.asList("test.append(\"\")"));
90.131 + }
90.132 +
90.133 + public void testMemberSelectWithVariables1() throws Exception {
90.134 + performTest("package test; public class Test { private static void test() { new StringBuilder().append(\"\");}}",
90.135 + Collections.singletonMap("$0.append(\"\")", Arrays.asList("new StringBuilder().append(\"\")")),
90.136 + Collections.<String>emptyList());
90.137 + }
90.138 +
90.139 + public void testMemberSelectWithVariables2() throws Exception {
90.140 + performTest("package test; public class Test { private void append(char c) { append(\"\");}}",
90.141 + Collections.singletonMap("$0.append(\"\")", Arrays.asList("append(\"\")")),
90.142 + Collections.<String>emptyList());
90.143 + }
90.144 +
90.145 + public void testLocalVariables() throws Exception {
90.146 + performTest("package test; public class Test { private void test() { { int y; y = 1; } }}",
90.147 + Collections.singletonMap("{ int $1; $1 = 1; }", Arrays.asList("{ int y; y = 1; }")),
90.148 + Collections.<String>emptyList());
90.149 + }
90.150 +
90.151 + public void testAssert() throws Exception {
90.152 + performTest("package test; public class Test { private void test() { assert true : \"\"; }}",
90.153 + Collections.singletonMap("assert $1 : $2;", Arrays.asList("assert true : \"\";")),
90.154 + Collections.<String>emptyList());
90.155 + }
90.156 +
90.157 + public void testStatementAndSingleBlockStatementAreSame1() throws Exception {
90.158 + performTest("package test; public class Test { private void test() { { int y; { y = 1; } } }}",
90.159 + Collections.singletonMap("{ int $1; $1 = 1; }", Arrays.asList("{ int y; { y = 1; } }")),
90.160 + Collections.<String>emptyList());
90.161 + }
90.162 +
90.163 + public void testStatementAndSingleBlockStatementAreSame2() throws Exception {
90.164 + performTest("package test; public class Test { private void test() { { int y; y = 1; } }}",
90.165 + Collections.singletonMap("{ int $1; { $1 = 1; } }", Arrays.asList("{ int y; y = 1; }")),
90.166 + Collections.<String>emptyList());
90.167 + }
90.168 +
90.169 + public void testStatementVariables1() throws Exception {
90.170 + performTest("package test; public class Test { public int test1() { if (true) return 1; else return 2; } }",
90.171 + Collections.singletonMap("if ($1) $2; else $3;", Arrays.asList("if (true) return 1; else return 2;")),
90.172 + Collections.<String>emptyList());
90.173 + }
90.174 +
90.175 + public void testMultiStatementVariables1() throws Exception {
90.176 + performTest("package test; public class Test { public int test1(int i) { System.err.println(i); System.err.println(i); i = 3; System.err.println(i); System.err.println(i); return i; } }",
90.177 + Collections.singletonMap("{ $s1$; i = 3; $s2$; return i; }", Arrays.asList("{ System.err.println(i); System.err.println(i); i = 3; System.err.println(i); System.err.println(i); return i; }")),
90.178 + Collections.<String>emptyList());
90.179 + }
90.180 +
90.181 + public void testMultiStatementVariables2() throws Exception {
90.182 + performTest("package test; public class Test { public int test1(int i) { i = 3; return i; } }",
90.183 + Collections.singletonMap("{ $s1$; i = 3; $s2$; return i; }", Arrays.asList("{ i = 3; return i; }")),
90.184 + Collections.<String>emptyList());
90.185 + }
90.186 +
90.187 + public void testMultiStatementVariablesAndBlocks1() throws Exception {
90.188 + performTest("package test; public class Test { public void test1() { if (true) System.err.println(); } }",
90.189 + Collections.singletonMap("if ($c) {$s1$; System.err.println(); $s2$; }", Arrays.asList("if (true) System.err.println();")),
90.190 + Collections.<String>emptyList());
90.191 + }
90.192 +
90.193 + public void testMultiStatementVariablesAndBlocks2() throws Exception {
90.194 + performTest("package test; public class Test { public void test1() { if (true) System.err.println(); } }",
90.195 + Collections.singletonMap("if ($c) {$s1$; System.err.println(); }", Arrays.asList("if (true) System.err.println();")),
90.196 + Collections.<String>emptyList());
90.197 + }
90.198 +
90.199 + public void testMultiStatementVariablesAndBlocks3() throws Exception {
90.200 + performTest("package test; public class Test { public void test1() { if (true) System.err.println(); } }",
90.201 + Collections.singletonMap("if ($c) {System.err.println(); $s2$; }", Arrays.asList("if (true) System.err.println();")),
90.202 + Collections.<String>emptyList());
90.203 + }
90.204 +
90.205 + public void testMultiStatementVariablesAndBlocks4() throws Exception {
90.206 + performTest("package test; public class Test { public void test1() { if (true) System.err.println(); } }",
90.207 + Collections.singletonMap("{ $s1$; System.err.println(); $s2$; }", Arrays.asList("System.err.println();")),
90.208 + Collections.<String>emptyList());
90.209 + }
90.210 +
90.211 + public void testTwoPatterns() throws Exception {
90.212 + Map<String, List<String>> contained = new HashMap<String, List<String>>();
90.213 +
90.214 + contained.put("if ($a) $ret = $b; else $ret = $c;", Arrays.asList("if (b) q = 2; else q = 3;"));
90.215 + contained.put("{ $p$; $T $v; if($a) $v = $b; else $v = $c; $q$; }", Arrays.asList("{ int q; if (b) q = 2; else q = 3; }"));
90.216 +
90.217 + performTest("package test; public class Test { public void test1(boolean b) { int q; if (b) q = 2; else q = 3; } }",
90.218 + contained,
90.219 + Collections.<String>emptyList());
90.220 + }
90.221 +
90.222 + public void testEffectiveNewClass() throws Exception {
90.223 + performTest("package test; import javax.swing.ImageIcon; public class Test { public void test1(java.awt.Image i) { new ImageIcon(i); new String(i); } }",
90.224 + Collections.singletonMap("new javax.swing.ImageIcon($1)", Arrays.asList("new ImageIcon(i)")),
90.225 + Collections.<String>emptyList());
90.226 + }
90.227 +
90.228 + public void testSynchronizedAndMultiStatementVariables() throws Exception {
90.229 + performTest("package test; public class Test {public void test() { Object o = null; int i = 0; synchronized (o) {} } }",
90.230 + Collections.singletonMap("synchronized($var) {$stmts$;}", Arrays.asList("synchronized (o) {}")),
90.231 + Collections.<String>emptyList());
90.232 + }
90.233 +
90.234 + public void testJackpot30_2() throws Exception {
90.235 + String code = "package test;\n" +
90.236 + "public class Test {\n" +
90.237 + " private void m() {\n" +
90.238 + " a(c.i().getFileObject());\n" +
90.239 + " if (span != null && span[0] != (-1) && span[1] != (-1));\n" +
90.240 + " }\n" +
90.241 + "}\n";
90.242 +
90.243 + performTest(code,
90.244 + Collections.<String, List<String>>emptyMap(),
90.245 + Arrays.asList("$0.getFileObject($1)"));
90.246 + }
90.247 +
90.248 + public void testIdentifierInPureMemberSelect() throws Exception {
90.249 + String code = "package test;\n" +
90.250 + "public class Test {\n" +
90.251 + " public Test test;\n" +
90.252 + " public String name;\n" +
90.253 + " private void test() {\n" +
90.254 + " Test t = null;\n" +
90.255 + " String s = t.test.name;\n" +
90.256 + " }\n" +
90.257 + "}\n";
90.258 +
90.259 + performTest(code,
90.260 + Collections.singletonMap("$Test.test", Arrays.asList("test", "t.test")),
90.261 + Collections.<String>emptyList());
90.262 + }
90.263 +
90.264 + @RandomlyFails
90.265 + public void testNoExponentialTimeComplexity() throws Exception {
90.266 + try {
90.267 + String code = "package test;\n" +
90.268 + "public class Test {\n" +
90.269 + " private void test() {\n" +
90.270 + " Object o;\n" +
90.271 + " if(o == null) {\n" +
90.272 + " f(\"\");\n" +
90.273 + " }|\n" +
90.274 + " }\n" +
90.275 + "}";
90.276 + String pattern = "{ $p$; $T $v; if($a) $v = $b; else $v = $c; }";
90.277 +
90.278 + measure(code, "\na(\"\");", 5, pattern); //to load needed classes, etc.
90.279 +
90.280 + int rep = 1;
90.281 + long baseline;
90.282 +
90.283 + while (true) {
90.284 + baseline = measure(code, "\na(\"\");", rep, pattern);
90.285 +
90.286 + if (baseline >= 2000) {
90.287 + break;
90.288 + }
90.289 +
90.290 + rep *= 2;
90.291 + }
90.292 +
90.293 + long doubleSize = measure(code, "\na(\"\");", 2 * rep, pattern);
90.294 +
90.295 + assertTrue("baseline=" + baseline + ", actual=" + String.valueOf(doubleSize), doubleSize <= 4 * baseline);
90.296 + } catch (OutOfMemoryError oome) {
90.297 + //OK
90.298 + }
90.299 + }
90.300 +
90.301 + public void testMultiParameter1() throws Exception {
90.302 + performTest("package test; public class Test { { java.util.Arrays.asList(\"a\", \"b\", \"c\"); } }",
90.303 + Collections.singletonMap("java.util.Arrays.asList($params$)", Arrays.asList("java.util.Arrays.asList(\"a\", \"b\", \"c\")")),
90.304 + Collections.<String>emptyList());
90.305 + }
90.306 +
90.307 + public void testMultiParameter2() throws Exception {
90.308 + performTest("package test; public class Test { { java.util.Arrays.asList(); } }",
90.309 + Collections.singletonMap("java.util.Arrays.asList($params$)", Arrays.asList("java.util.Arrays.asList()")),
90.310 + Collections.<String>emptyList());
90.311 + }
90.312 +
90.313 + public void testTypeParameter() throws Exception {
90.314 + performTest("package test; public class Test { { java.util.Arrays.<String>asList(); } }",
90.315 + Collections.singletonMap("java.util.Arrays.<$1>asList($params$)", Arrays.asList("java.util.Arrays.<String>asList()")),
90.316 + Collections.<String>emptyList());
90.317 + }
90.318 +
90.319 + public void testField1() throws Exception {
90.320 + String code = "package test;\n" +
90.321 + "public class Test {\n" +
90.322 + " String name = null;\n" +
90.323 + "}\n";
90.324 +
90.325 + performTest(code,
90.326 + Collections.singletonMap("$modifiers$ java.lang.String $name = $initializer;", Arrays.asList("String name = null;")),
90.327 + Collections.<String>emptyList());
90.328 + }
90.329 +
90.330 + public void testField2() throws Exception {
90.331 + String code = "package test;\n" +
90.332 + "public class Test {\n" +
90.333 + " private String name = null;\n" +
90.334 + "}\n";
90.335 +
90.336 + performTest(code,
90.337 + Collections.singletonMap("$modifiers$ java.lang.String $name = $initializer;", Arrays.asList("private String name = null;")),
90.338 + Collections.<String>emptyList());
90.339 + }
90.340 +
90.341 + public void testMemberSelectWithVariable() throws Exception {
90.342 + String code = "package test;\n" +
90.343 + "import java.util.Arrays;\n" +
90.344 + "public class Test {" +
90.345 + " {\n" +
90.346 + " foo.bar(0, 3, 4);\n" +
90.347 + " }\n" +
90.348 + "}\n";
90.349 +
90.350 + performTest(code,
90.351 + Collections.singletonMap("$foo.$bar($p1, $p2$)", Arrays.asList("foo.bar(0, 3, 4)")),
90.352 + Collections.<String>emptyList());
90.353 + }
90.354 +
90.355 + public void testCheckIdentifiers1() throws Exception {
90.356 + String code = "package test;\n" +
90.357 + "import static java.util.Arrays.*;\n" +
90.358 + "public class Test {" +
90.359 + " {\n" +
90.360 + " toString(new int[] {0, 3, 4});\n" +
90.361 + " }\n" +
90.362 + "}\n";
90.363 +
90.364 + performTest(code,
90.365 + Collections.singletonMap("java.util.Arrays.toString($x)", Arrays.asList("toString(new int[] {0, 3, 4})")),
90.366 + Collections.<String>emptyList());
90.367 + }
90.368 +
90.369 + public void testCheckIdentifiers2() throws Exception {
90.370 + String code = "package test;\n" +
90.371 + "public class Test {" +
90.372 + " {\n" +
90.373 + " toString(new int[] {0, 3, 4});\n" +
90.374 + " }\n" +
90.375 + "}\n";
90.376 +
90.377 + performTest(code,
90.378 + Collections.<String, List<String>>emptyMap(),
90.379 + Collections.singletonList("java.util.Arrays.toString($x)"));
90.380 + }
90.381 +
90.382 + public void testCheckIdentifiers3() throws Exception {
90.383 + String code = "package test;\n" +
90.384 + "import static java.util.Arrays.*;\n" +
90.385 + "public class Test {" +
90.386 + " {\n" +
90.387 + " Foo.toString(new int[] {0, 3, 4});\n" +
90.388 + " }\n" +
90.389 + "}\n";
90.390 +
90.391 + performTest(code,
90.392 + Collections.<String, List<String>>emptyMap(),
90.393 + Collections.singletonList("java.util.Arrays.toString($x)"));
90.394 + }
90.395 +
90.396 + public void testCheckIdentifiers4() throws Exception {
90.397 + String code = "package test;\n" +
90.398 + "public class Test {" +
90.399 + " {\n" +
90.400 + " java.util.Arrays.toString(new int[] {0, 3, 4});\n" +
90.401 + " }\n" +
90.402 + "}\n";
90.403 +
90.404 + performTest(code,
90.405 + Collections.singletonMap("Arrays", Arrays.asList("java.util.Arrays")), //could be imported in the input pattern
90.406 + Collections.<String>emptyList());
90.407 + }
90.408 +
90.409 + public void testLambdaInput() throws Exception {
90.410 + String code = "package test; public class Test {public void test() { new java.io.FilenameFilter() { public boolean accept(java.io.File dir, String name) { return true; } }; } }";
90.411 +
90.412 + performTest(code,
90.413 + Collections.singletonMap("new $type() {public $retType $name($params$) { $body$; } }", Arrays.asList("new java.io.FilenameFilter() { public boolean accept(java.io.File dir, String name) { return true; } }")),
90.414 +
90.415 + Collections.<String>emptyList());
90.416 + }
90.417 +
90.418 + public void testDoubleCheckedLockingWithVariable() throws Exception {
90.419 + String dcl = "if (o == null) {\n" +
90.420 + " Object o1 = new Object();\n" +
90.421 + " synchronized (Test.class) {\n" +
90.422 + " if (o == null) {\n" +
90.423 + " o = o1;\n" +
90.424 + " }\n" +
90.425 + " }\n" +
90.426 + " }";
90.427 + String code = "package test;\n" +
90.428 + "public class Test {\n" +
90.429 + " private Object o;\n" +
90.430 + " private void t() {\n" +
90.431 + " " + dcl + "\n" +
90.432 + " }\n" +
90.433 + "}\n";
90.434 +
90.435 + performTest(code,
90.436 + Collections.singletonMap("if ($var == null) {$pref$; synchronized ($lock) { if ($var == null) { $init$; } } }", Arrays.asList(dcl)),
90.437 + Collections.<String>emptyList());
90.438 + }
90.439 +
90.440 + public void testMethodName1() throws Exception {
90.441 + String code = "package test; public class Test {public void test() { clone(); } }";
90.442 +
90.443 + performTest(code,
90.444 + Collections.<String, List<String>>emptyMap(),
90.445 + Collections.<String>singletonList("public void clone() {$stmts$;}"));
90.446 + }
90.447 +
90.448 + public void testMethodName2() throws Exception {
90.449 + String code = "package test; public class Test {public void test() { clone(); } }";
90.450 +
90.451 + performTest(code,
90.452 + Collections.singletonMap("public void test() {$stmts$;}", Arrays.asList("public void test() { clone(); }")),
90.453 + Collections.<String>emptyList());
90.454 + }
90.455 +
90.456 + public void testBooleanLiterals() throws Exception {
90.457 + String code = "package test; public class Test { public void test() { if (false) { System.err.println(\"false\"); } if (true) { System.err.println(\"true\"); } } }";
90.458 +
90.459 + performTest(code,
90.460 + Collections.singletonMap("if (true) $then; else $else$;", Arrays.asList("if (true) { System.err.println(\"true\"); }")),
90.461 + Collections.<String>emptyList());
90.462 + }
90.463 +
90.464 + public void testEfficientMultiMatching() throws Exception {
90.465 + String code = "package test; public class Test { private void m() {} }";
90.466 +
90.467 + performTest(code,
90.468 + Collections.<String, List<String>>emptyMap(),
90.469 + Collections.singletonList("$mods$ class $name implements $i$ { }"));
90.470 + }
90.471 +
90.472 + private long measure(String baseCode, String toInsert, int repetitions, String pattern) throws Exception {
90.473 + int pos = baseCode.indexOf('|');
90.474 +
90.475 + assertTrue(pos != (-1));
90.476 +
90.477 + baseCode = baseCode.replaceAll(Pattern.quote("|"), "");
90.478 +
90.479 + StringBuilder code = new StringBuilder(baseCode.length() + repetitions * toInsert.length());
90.480 +
90.481 + code.append(baseCode);
90.482 +
90.483 + while (repetitions-- > 0) {
90.484 + code.insert(pos, toInsert);
90.485 + }
90.486 +
90.487 + long startTime = System.currentTimeMillis();
90.488 +
90.489 + performTest(code.toString(),
90.490 + Collections.<String, List<String>>emptyMap(),
90.491 + Arrays.asList(pattern));
90.492 +
90.493 + long endTime = System.currentTimeMillis();
90.494 +
90.495 + return endTime - startTime;
90.496 + }
90.497 +
90.498 + public void XtestMeasureTime() throws Exception {
90.499 + String code = TestUtilities.copyFileToString(new File("/usr/local/home/lahvac/src/nb//outgoing/java.editor/src/org/netbeans/modules/editor/java/JavaCompletionProvider.java"));
90.500 + List<String> patterns = new LinkedList<String>();
90.501 +
90.502 + for (int cntr = 0; cntr < 1000; cntr++) {
90.503 + patterns.add("System.err.println($1)");
90.504 + }
90.505 +
90.506 + performTest(code,
90.507 + Collections.<String, List<String>>emptyMap(),
90.508 + patterns);
90.509 + }
90.510 +
90.511 + public void testMatches1() throws Exception {
90.512 + performMatchesTest("package test; public class Test { private void test() { f.isDirectory(); } }", Arrays.asList("$1.isDirectory()", "new ImageIcon($1)"), true);
90.513 + }
90.514 +
90.515 + public void testSerialization() throws Exception {
90.516 + String text = "package test; public class Test { public void test1(boolean b) { int q; if (b) q = 2; else q = 3; } }";
90.517 +
90.518 + prepareTest("test/Test.java", text);
90.519 +
90.520 + ByteArrayOutputStream out = new ByteArrayOutputStream();
90.521 + EncodingContext ec = new EncodingContext(out, false);
90.522 +
90.523 + createSearch().encode(info.getCompilationUnit(), ec, new AtomicBoolean());
90.524 +
90.525 + boolean matches = createSearch().matches(new ByteArrayInputStream(out.toByteArray()), new AtomicBoolean(), createSearch().create(info, new AtomicBoolean(), "{ $p$; $T $v; if($a) $v = $b; else $v = $c; $q$; }"));
90.526 +
90.527 + assertTrue(matches);
90.528 + }
90.529 +
90.530 + public void testFrequencies() throws Exception {
90.531 + String text = "package test; public class Test { public void test1(boolean b) { java.io.File f = null; f.isDirectory(); f.isDirectory(); new javax.swing.ImageIcon(null); } }";
90.532 +
90.533 + prepareTest("test/Test.java", text);
90.534 +
90.535 + ByteArrayOutputStream out = new ByteArrayOutputStream();
90.536 + EncodingContext ec = new EncodingContext(out, false);
90.537 +
90.538 + createSearch().encode(info.getCompilationUnit(), ec, new AtomicBoolean());
90.539 +
90.540 + Map<String, Integer> actual = createSearch().matchesWithFrequencies(new ByteArrayInputStream(out.toByteArray()), createSearch().create(info, new AtomicBoolean(), "$1.isDirectory()", "new ImageIcon($1)"), new AtomicBoolean());
90.541 + Map<String, Integer> golden = new HashMap<String, Integer>();
90.542 +
90.543 + golden.put("$1.isDirectory()", 2);
90.544 + golden.put("new ImageIcon($1)", 1);
90.545 +
90.546 + assertEquals(golden, actual);
90.547 + }
90.548 +
90.549 + public void testPatternEncodingAndIdentifiers() throws Exception {
90.550 + String text = "package test; public class Test { }";
90.551 +
90.552 + prepareTest("test/Test.java", text);
90.553 +
90.554 + BulkPattern bp = createSearch().create(info, new AtomicBoolean(), "$0.isDirectory()");
90.555 +
90.556 + assertEquals(Arrays.asList(new HashSet<String>(Arrays.asList("isDirectory"))), bp.getIdentifiers());
90.557 + //TODO: the actual code for kinds differs for NFABased search and REBased search:
90.558 +// assertEquals(Arrays.asList(new HashSet<String>(Arrays.asList(Kind.METHOD_INVOCATION.name()))), bp.getKinds());
90.559 + }
90.560 +
90.561 + public void testModifiersMultiVariable() throws Exception {
90.562 + String code = "package test;\n" +
90.563 + "public class Test {\n" +
90.564 + " @Deprecated @Override public Test test;\n" +
90.565 + "}\n";
90.566 +
90.567 + performTest(code,
90.568 + Collections.singletonMap("$mods$ @Deprecated public $type $name = $init$;", Arrays.asList("@Deprecated @Override public Test test;")),
90.569 + Collections.<String>emptyList());
90.570 + }
90.571 +
90.572 + protected abstract BulkSearch createSearch();
90.573 +
90.574 + private void performMatchesTest(String text, List<String> patterns, boolean golden) throws Exception {
90.575 + prepareTest("test/Test.java", text);
90.576 +
90.577 + BulkPattern p = createSearch().create(info, new AtomicBoolean(), patterns);
90.578 +
90.579 + boolean result = createSearch().matches(info, new AtomicBoolean(), new TreePath(info.getCompilationUnit()), p);
90.580 +
90.581 + assertEquals(golden, result);
90.582 + }
90.583 +
90.584 + private void performTest(String text, Map<String, List<String>> containedPatterns, Collection<String> notContainedPatterns) throws Exception {
90.585 + prepareTest("test/Test.java", text);
90.586 +
90.587 + List<String> patterns = new LinkedList<String>();
90.588 +
90.589 + patterns.addAll(containedPatterns.keySet());
90.590 + patterns.addAll(notContainedPatterns);
90.591 +
90.592 + long s1 = System.currentTimeMillis();
90.593 + BulkPattern p = createSearch().create(info, new AtomicBoolean(), patterns);
90.594 + long e1 = System.currentTimeMillis();
90.595 +
90.596 +// System.err.println("create: " + (e1 - s1));
90.597 +
90.598 + long s2 = System.currentTimeMillis();
90.599 + Map<String, Collection<TreePath>> result = createSearch().match(info, new AtomicBoolean(), new TreePath(info.getCompilationUnit()), p);
90.600 + long e2 = System.currentTimeMillis();
90.601 +
90.602 +// System.err.println("match: " + (e2 - s2));
90.603 +
90.604 + assertTrue(result.toString(), result.keySet().containsAll(containedPatterns.keySet()));
90.605 +
90.606 + for (Entry<String, Collection<TreePath>> e : result.entrySet()) {
90.607 + List<String> actual = new LinkedList<String>();
90.608 +
90.609 + for (TreePath tp : e.getValue()) {
90.610 + assertNotNull(TreePathHandle.create(tp, info).resolve(info));
90.611 +
90.612 + int start = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), tp.getLeaf());
90.613 + int end = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), tp.getLeaf());
90.614 +
90.615 + actual.add(info.getText().substring(start, end));
90.616 + }
90.617 +
90.618 + assertEquals(e.getKey(), containedPatterns.get(e.getKey()), actual);
90.619 + }
90.620 +
90.621 +
90.622 + Set<String> none = new HashSet<String>(result.keySet());
90.623 +
90.624 + none.retainAll(notContainedPatterns);
90.625 +
90.626 + assertTrue(none.isEmpty());
90.627 +
90.628 + if (!verifyIndexingData())
90.629 + return ;
90.630 +
90.631 + //ensure the returned identifiers/treeKinds are correct:
90.632 + ByteArrayOutputStream data = new ByteArrayOutputStream();
90.633 + EncodingContext ec = new EncodingContext(data, false);
90.634 +
90.635 + createSearch().encode(info.getCompilationUnit(), ec, new AtomicBoolean());
90.636 +
90.637 + for (int i = 0; i < containedPatterns.size(); i++) {
90.638 + assertTrue("expected: " + p.getIdentifiers().get(i) + ", but exist only: " + ec.getIdentifiers(), ec.getIdentifiers().containsAll(p.getIdentifiers().get(i)));
90.639 +
90.640 + for (List<String> phrase : p.getRequiredContent().get(i)) {
90.641 + assertTrue("expected: " + phrase + ", but exist only: " + ec.getContent() + "(all phrases: " + p.getRequiredContent().get(i) + ")", Collections.indexOfSubList(ec.getContent(), phrase) != (-1));
90.642 + }
90.643 + }
90.644 +
90.645 + data.close();
90.646 + assertEquals(!containedPatterns.isEmpty(), createSearch().matches(new ByteArrayInputStream(data.toByteArray()), new AtomicBoolean(), p));
90.647 + }
90.648 +
90.649 + private void prepareTest(String fileName, String code) throws Exception {
90.650 + clearWorkDir();
90.651 +
90.652 + FileUtil.refreshFor(File.listRoots());
90.653 +
90.654 + FileObject workFO = FileUtil.toFileObject(getWorkDir());
90.655 +
90.656 + assertNotNull(workFO);
90.657 +
90.658 + workFO.refresh();
90.659 +
90.660 + sourceRoot = workFO.createFolder("src");
90.661 + FileObject buildRoot = workFO.createFolder("build");
90.662 + FileObject cache = workFO.createFolder("cache");
90.663 +
90.664 + FileObject data = FileUtil.createData(sourceRoot, fileName);
90.665 + File dataFile = FileUtil.toFile(data);
90.666 +
90.667 + assertNotNull(dataFile);
90.668 +
90.669 + TestUtilities.copyStringToFile(dataFile, code);
90.670 +
90.671 + SourceUtilsTestUtil.prepareTest(sourceRoot, buildRoot, cache);
90.672 +
90.673 + DataObject od = DataObject.find(data);
90.674 + EditorCookie ec = od.getLookup().lookup(EditorCookie.class);
90.675 +
90.676 + assertNotNull(ec);
90.677 +
90.678 + doc = ec.openDocument();
90.679 + doc.putProperty(Language.class, JavaTokenId.language());
90.680 +
90.681 + JavaSource js = JavaSource.forFileObject(data);
90.682 +
90.683 + assertNotNull(js);
90.684 +
90.685 + info = SourceUtilsTestUtil.getCompilationInfo(js, Phase.RESOLVED);
90.686 +
90.687 + assertNotNull(info);
90.688 + }
90.689 +
90.690 + private FileObject sourceRoot;
90.691 + private CompilationInfo info;
90.692 + private Document doc;
90.693 +
90.694 + protected boolean verifyIndexingData() {
90.695 + return true;
90.696 + }
90.697 +}
91.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
91.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/pm/CopyFinderBasedBulkSearchTest.java Wed May 08 21:47:42 2013 +0200
91.3 @@ -0,0 +1,99 @@
91.4 +/*
91.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
91.6 + *
91.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
91.8 + *
91.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
91.10 + * Other names may be trademarks of their respective owners.
91.11 + *
91.12 + * The contents of this file are subject to the terms of either the GNU
91.13 + * General Public License Version 2 only ("GPL") or the Common
91.14 + * Development and Distribution License("CDDL") (collectively, the
91.15 + * "License"). You may not use this file except in compliance with the
91.16 + * License. You can obtain a copy of the License at
91.17 + * http://www.netbeans.org/cddl-gplv2.html
91.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
91.19 + * specific language governing permissions and limitations under the
91.20 + * License. When distributing the software, include this License Header
91.21 + * Notice in each file and include the License file at
91.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
91.23 + * particular file as subject to the "Classpath" exception as provided
91.24 + * by Oracle in the GPL Version 2 section of the License file that
91.25 + * accompanied this code. If applicable, add the following below the
91.26 + * License Header, with the fields enclosed by brackets [] replaced by
91.27 + * your own identifying information:
91.28 + * "Portions Copyrighted [year] [name of copyright owner]"
91.29 + *
91.30 + * If you wish your version of this file to be governed by only the CDDL
91.31 + * or only the GPL Version 2, indicate your decision by adding
91.32 + * "[Contributor] elects to include this software in this distribution
91.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
91.34 + * single choice of license, a recipient has the option to distribute
91.35 + * your version of this file under either the CDDL, the GPL Version 2 or
91.36 + * to extend the choice of license to its licensees as provided above.
91.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
91.38 + * Version 2 license, then the option applies only if the new code is
91.39 + * made subject to such option by the copyright holder.
91.40 + *
91.41 + * Contributor(s):
91.42 + *
91.43 + * Portions Copyrighted 2009 Sun Microsystems, Inc.
91.44 + */
91.45 +
91.46 +package org.netbeans.modules.java.hints.spiimpl.pm;
91.47 +
91.48 +/**
91.49 + *
91.50 + * @author lahvac
91.51 + */
91.52 +public class CopyFinderBasedBulkSearchTest extends BulkSearchTestPerformer {
91.53 +
91.54 + public CopyFinderBasedBulkSearchTest(String name) {
91.55 + super(name);
91.56 + }
91.57 +
91.58 + @Override
91.59 + protected BulkSearch createSearch() {
91.60 + return new CopyFinderBasedBulkSearch();
91.61 + }
91.62 +
91.63 + @Override
91.64 + protected boolean verifyIndexingData() {
91.65 + return false;
91.66 + }
91.67 +
91.68 + @Override
91.69 + public void testSerialization() throws Exception {
91.70 + //XXX
91.71 + }
91.72 +
91.73 + @Override
91.74 + public void testFrequencies() throws Exception {
91.75 + //XXX: serialization is a prerequisite
91.76 + }
91.77 +
91.78 + @Override
91.79 + public void testPatternEncodingAndIdentifiers() throws Exception {
91.80 + //XXX
91.81 + }
91.82 +
91.83 + @Override
91.84 + public void testNoExponentialTimeComplexity() throws Exception {
91.85 + //XXX
91.86 + }
91.87 +
91.88 + @Override
91.89 + public void testCheckIdentifiers2() throws Exception {
91.90 + //not critical, only improves performance on vast amounts of sources,
91.91 + //and NFA based search is used in such case anyway.
91.92 + //XXX
91.93 + }
91.94 +
91.95 + @Override
91.96 + public void testCheckIdentifiers3() throws Exception {
91.97 + //not critical, only improves performance on vast amounts of sources,
91.98 + //and NFA based search is used in such case anyway.
91.99 + //XXX
91.100 + }
91.101 +
91.102 +}
91.103 \ No newline at end of file
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
92.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/pm/NFABasedBulkSearchTest.java Wed May 08 21:47:42 2013 +0200
92.3 @@ -0,0 +1,69 @@
92.4 +/*
92.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
92.6 + *
92.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
92.8 + *
92.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
92.10 + * Other names may be trademarks of their respective owners.
92.11 + *
92.12 + * The contents of this file are subject to the terms of either the GNU
92.13 + * General Public License Version 2 only ("GPL") or the Common
92.14 + * Development and Distribution License("CDDL") (collectively, the
92.15 + * "License"). You may not use this file except in compliance with the
92.16 + * License. You can obtain a copy of the License at
92.17 + * http://www.netbeans.org/cddl-gplv2.html
92.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
92.19 + * specific language governing permissions and limitations under the
92.20 + * License. When distributing the software, include this License Header
92.21 + * Notice in each file and include the License file at
92.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
92.23 + * particular file as subject to the "Classpath" exception as provided
92.24 + * by Oracle in the GPL Version 2 section of the License file that
92.25 + * accompanied this code. If applicable, add the following below the
92.26 + * License Header, with the fields enclosed by brackets [] replaced by
92.27 + * your own identifying information:
92.28 + * "Portions Copyrighted [year] [name of copyright owner]"
92.29 + *
92.30 + * If you wish your version of this file to be governed by only the CDDL
92.31 + * or only the GPL Version 2, indicate your decision by adding
92.32 + * "[Contributor] elects to include this software in this distribution
92.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
92.34 + * single choice of license, a recipient has the option to distribute
92.35 + * your version of this file under either the CDDL, the GPL Version 2 or
92.36 + * to extend the choice of license to its licensees as provided above.
92.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
92.38 + * Version 2 license, then the option applies only if the new code is
92.39 + * made subject to such option by the copyright holder.
92.40 + *
92.41 + * Contributor(s):
92.42 + *
92.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
92.44 + */
92.45 +
92.46 +package org.netbeans.modules.java.hints.spiimpl.pm;
92.47 +
92.48 +/**
92.49 + *
92.50 + * @author lahvac
92.51 + */
92.52 +public class NFABasedBulkSearchTest extends BulkSearchTestPerformer {
92.53 +
92.54 + public NFABasedBulkSearchTest(String name) {
92.55 + super(name);
92.56 + }
92.57 +
92.58 +// public static TestSuite suite() {
92.59 +// NbTestSuite r = new NbTestSuite();
92.60 +//
92.61 +// r.addTest(new NFABasedBulkSearchTest("testField1"));
92.62 +// r.addTest(new NFABasedBulkSearchTest("testField2"));
92.63 +//
92.64 +// return r;
92.65 +// }
92.66 +
92.67 + @Override
92.68 + protected BulkSearch createSearch() {
92.69 + return new NFABasedBulkSearch();
92.70 + }
92.71 +
92.72 +}
93.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
93.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/pm/PatternCompilerTest.java Wed May 08 21:47:42 2013 +0200
93.3 @@ -0,0 +1,203 @@
93.4 +/*
93.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
93.6 + *
93.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
93.8 + *
93.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
93.10 + * Other names may be trademarks of their respective owners.
93.11 + *
93.12 + * The contents of this file are subject to the terms of either the GNU
93.13 + * General Public License Version 2 only ("GPL") or the Common
93.14 + * Development and Distribution License("CDDL") (collectively, the
93.15 + * "License"). You may not use this file except in compliance with the
93.16 + * License. You can obtain a copy of the License at
93.17 + * http://www.netbeans.org/cddl-gplv2.html
93.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
93.19 + * specific language governing permissions and limitations under the
93.20 + * License. When distributing the software, include this License Header
93.21 + * Notice in each file and include the License file at
93.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
93.23 + * particular file as subject to the "Classpath" exception as provided
93.24 + * by Oracle in the GPL Version 2 section of the License file that
93.25 + * accompanied this code. If applicable, add the following below the
93.26 + * License Header, with the fields enclosed by brackets [] replaced by
93.27 + * your own identifying information:
93.28 + * "Portions Copyrighted [year] [name of copyright owner]"
93.29 + *
93.30 + * If you wish your version of this file to be governed by only the CDDL
93.31 + * or only the GPL Version 2, indicate your decision by adding
93.32 + * "[Contributor] elects to include this software in this distribution
93.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
93.34 + * single choice of license, a recipient has the option to distribute
93.35 + * your version of this file under either the CDDL, the GPL Version 2 or
93.36 + * to extend the choice of license to its licensees as provided above.
93.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
93.38 + * Version 2 license, then the option applies only if the new code is
93.39 + * made subject to such option by the copyright holder.
93.40 + *
93.41 + * Contributor(s):
93.42 + *
93.43 + * Portions Copyrighted 2008-2009 Sun Microsystems, Inc.
93.44 + */
93.45 +
93.46 +package org.netbeans.modules.java.hints.spiimpl.pm;
93.47 +
93.48 +import com.sun.source.tree.Tree;
93.49 +import com.sun.source.util.SourcePositions;
93.50 +import com.sun.source.util.TreePath;
93.51 +import java.util.Arrays;
93.52 +import java.util.HashMap;
93.53 +import java.util.Iterator;
93.54 +import java.util.Map;
93.55 +import java.util.Map.Entry;
93.56 +import java.util.concurrent.atomic.AtomicBoolean;
93.57 +import org.netbeans.modules.java.hints.spiimpl.TestBase;
93.58 +import org.netbeans.api.java.source.matching.Matcher;
93.59 +import org.netbeans.api.java.source.matching.Occurrence;
93.60 +import org.openide.util.Pair;
93.61 +
93.62 +/**
93.63 + *
93.64 + * @author Jan Lahoda
93.65 + */
93.66 +public class PatternCompilerTest extends TestBase {
93.67 +
93.68 + public PatternCompilerTest(String name) {
93.69 + super(name);
93.70 + }
93.71 +
93.72 + public void testSimple1() throws Exception {
93.73 + performVariablesTest("package test; public class Test {public void test() {int i = |1 + 2|;}}", "$1+$2",
93.74 + Pair.<String, String>of("$1", "1"),
93.75 + Pair.<String, String>of("$2", "2"));
93.76 + }
93.77 +
93.78 + public void testTyped1() throws Exception {
93.79 + performVariablesTest("package test; public class Test {public void test() {|String.valueOf(\"t\")|;}}", "String.valueOf($1{String})",
93.80 + Pair.<String, String>of("$1", "\"t\""));
93.81 + }
93.82 +
93.83 +// public void testTyped2() throws Exception {
93.84 +// performVariablesTest("package test; public class Test {public void test() {|String.valueOf(\"t\")|;}}", "$2{java.lang.String}.valueOf($1{String})",
93.85 +// new Pair<String, String>("$1", "\"t\""),
93.86 +// new Pair<String, String>("$2", "String"));
93.87 +// }
93.88 +
93.89 + public void testTyped3() throws Exception {
93.90 + performVariablesTest("package test; public class Test {public void test(String str) {|str.valueOf(\"t\")|;}}", "String.valueOf($1{String})",
93.91 + Pair.<String, String>of("$1", "\"t\""));
93.92 + }
93.93 +
93.94 + public void testTyped4() throws Exception {
93.95 + performVariablesTest("package test; public class Test {public void test() {|Integer.bitCount(1)|;}}", "$2{java.lang.String}.valueOf($1{String})",
93.96 + (Pair[]) null);
93.97 + }
93.98 +
93.99 + public void testTyped5() throws Exception {
93.100 + performVariablesTest("package test; public class Test {public void test() {java.io.File f = null; |f.toURI().toURL()|;}}", "$1{java.io.File}.toURL()",
93.101 + (Pair[]) null);
93.102 + }
93.103 +
93.104 + public void testTypedPrimitiveType() throws Exception {
93.105 + performVariablesTest("package test; public class Test {public void test(int i) {|test(1)|;}}", "$0{test.Test}.test($1{int})",
93.106 + Pair.<String, String>of("$1", "1"));
93.107 + }
93.108 +
93.109 + public void testMemberSelectVSIdentifier() throws Exception {
93.110 + performVariablesTest("package test; public class Test {void test1() {} void test2() {|test1()|;}}", "$1{test.Test}.test1()",
93.111 + new Pair[0]);
93.112 + }
93.113 +
93.114 + public void testSubClass() throws Exception {
93.115 + performVariablesTest("package test; public class Test {void test() {String s = null; |s.toString()|;}}", "$1{java.lang.CharSequence}.toString()",
93.116 + Pair.<String, String>of("$1", "s"));
93.117 + }
93.118 +
93.119 + public void testEquality1() throws Exception {
93.120 + performVariablesTest("package test; public class Test {void test() {|test()|;}}", "$1{test.Test}.test()",
93.121 + new Pair[0]);
93.122 + }
93.123 +
93.124 + public void testEquality2() throws Exception {
93.125 + performVariablesTest("package test; public class Test {void test() {String s = null; |String.valueOf(1).charAt(0)|;}}", "$1{java.lang.String}.charAt(0)",
93.126 + Pair.<String, String>of("$1", "String.valueOf(1)"));
93.127 + }
93.128 +
93.129 + public void testEquality3() throws Exception {
93.130 + performVariablesTest("package test; public class Test {void test() {String s = null; |s.charAt(0)|;}}", "java.lang.String.valueOf(1).charAt(0)",
93.131 + (Pair[]) null);
93.132 + }
93.133 +
93.134 + public void testType1() throws Exception {
93.135 + performVariablesTest("package test; public class Test {void test() {|String| s;}}", "java.lang.String",
93.136 + new Pair[0]);
93.137 + }
93.138 +
93.139 + public void testStatements1() throws Exception {
93.140 + performVariablesTest("package test; public class Test {void test() {|assert true : \"\";|}}", "assert $1{boolean} : $2{java.lang.Object};",
93.141 + new Pair[0]);
93.142 + }
93.143 +
93.144 + protected void performVariablesTest(String code, String pattern, Pair<String, String>... duplicates) throws Exception {
93.145 + String[] split = code.split("\\|");
93.146 +
93.147 + assertEquals(Arrays.toString(split), 3, split.length);
93.148 +
93.149 + int start = split[0].length();
93.150 + int end = start + split[1].length();
93.151 +
93.152 + code = split[0] + split[1] + split[2];
93.153 +
93.154 + prepareTest("test/Test.java", code);
93.155 +
93.156 + TreePath tp = info.getTreeUtilities().pathFor((start + end) / 2);
93.157 +
93.158 + while (tp != null) {
93.159 + Tree t = tp.getLeaf();
93.160 + SourcePositions sp = info.getTrees().getSourcePositions();
93.161 +
93.162 + if ( start == sp.getStartPosition(info.getCompilationUnit(), t)
93.163 + && end == sp.getEndPosition(info.getCompilationUnit(), t)) {
93.164 + break;
93.165 + }
93.166 +
93.167 + tp = tp.getParentPath();
93.168 + }
93.169 +
93.170 + assertNotNull(tp);
93.171 +
93.172 + //XXX:
93.173 + Iterator<? extends Occurrence> vars = Matcher.create(info).setCancel(new AtomicBoolean()).setSearchRoot(tp).setTreeTopSearch().match(PatternCompilerUtilities.compile(info, pattern)).iterator();
93.174 +
93.175 + if (duplicates == null) {
93.176 + assertFalse(vars.hasNext());
93.177 + return ;
93.178 + }
93.179 +
93.180 + assertNotNull(vars);
93.181 + assertTrue(vars.hasNext());
93.182 +
93.183 + Map<String, String> actual = new HashMap<String, String>();
93.184 +
93.185 + for (Entry<String, TreePath> e : vars.next().getVariables().entrySet()) {
93.186 + int[] span = new int[] {
93.187 + (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), e.getValue().getLeaf()),
93.188 + (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), e.getValue().getLeaf())
93.189 + };
93.190 +
93.191 + actual.put(e.getKey(), info.getText().substring(span[0], span[1]));
93.192 + }
93.193 +
93.194 + assertFalse(vars.hasNext());
93.195 +
93.196 + for (Pair<String, String> dup : duplicates) {
93.197 + String span = actual.remove(dup.first());
93.198 +
93.199 + if (span == null) {
93.200 + fail(dup.first());
93.201 + }
93.202 + assertEquals(dup.first()+ ":" + span, span, dup.second());
93.203 + }
93.204 + }
93.205 +
93.206 +}
94.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
94.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/pm/PatternCompilerUtilities.java Wed May 08 21:47:42 2013 +0200
94.3 @@ -0,0 +1,88 @@
94.4 +/*
94.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
94.6 + *
94.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
94.8 + *
94.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
94.10 + * Other names may be trademarks of their respective owners.
94.11 + *
94.12 + * The contents of this file are subject to the terms of either the GNU
94.13 + * General Public License Version 2 only ("GPL") or the Common
94.14 + * Development and Distribution License("CDDL") (collectively, the
94.15 + * "License"). You may not use this file except in compliance with the
94.16 + * License. You can obtain a copy of the License at
94.17 + * http://www.netbeans.org/cddl-gplv2.html
94.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
94.19 + * specific language governing permissions and limitations under the
94.20 + * License. When distributing the software, include this License Header
94.21 + * Notice in each file and include the License file at
94.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
94.23 + * particular file as subject to the "Classpath" exception as provided
94.24 + * by Oracle in the GPL Version 2 section of the License file that
94.25 + * accompanied this code. If applicable, add the following below the
94.26 + * License Header, with the fields enclosed by brackets [] replaced by
94.27 + * your own identifying information:
94.28 + * "Portions Copyrighted [year] [name of copyright owner]"
94.29 + *
94.30 + * If you wish your version of this file to be governed by only the CDDL
94.31 + * or only the GPL Version 2, indicate your decision by adding
94.32 + * "[Contributor] elects to include this software in this distribution
94.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
94.34 + * single choice of license, a recipient has the option to distribute
94.35 + * your version of this file under either the CDDL, the GPL Version 2 or
94.36 + * to extend the choice of license to its licensees as provided above.
94.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
94.38 + * Version 2 license, then the option applies only if the new code is
94.39 + * made subject to such option by the copyright holder.
94.40 + *
94.41 + * Contributor(s):
94.42 + *
94.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
94.44 + */
94.45 +package org.netbeans.modules.java.hints.spiimpl.pm;
94.46 +
94.47 +import java.util.Collections;
94.48 +import java.util.HashMap;
94.49 +import java.util.Map;
94.50 +import java.util.regex.Matcher;
94.51 +import javax.lang.model.type.TypeMirror;
94.52 +import org.netbeans.api.java.source.CompilationInfo;
94.53 +import org.netbeans.modules.java.hints.spiimpl.pm.PatternCompiler;
94.54 +import org.netbeans.api.java.source.matching.Pattern;
94.55 +import org.netbeans.modules.java.hints.spiimpl.Hacks;
94.56 +
94.57 +/**
94.58 + *
94.59 + * @author lahvac
94.60 + */
94.61 +public class PatternCompilerUtilities {
94.62 +
94.63 + public static Pattern compile(CompilationInfo info, String pattern) {
94.64 + Map<String, TypeMirror> constraints = new HashMap<String, TypeMirror>();
94.65 + pattern = parseOutTypesFromPattern(info, pattern, constraints);
94.66 +
94.67 + return PatternCompiler.compile(info, pattern, constraints, Collections.<String>emptyList());
94.68 + }
94.69 +
94.70 + public static String parseOutTypesFromPattern(CompilationInfo info, String pattern, Map<String, TypeMirror> variablesToTypes) {
94.71 + java.util.regex.Pattern p = java.util.regex.Pattern.compile("(\\$[0-9])(\\{([^}]*)\\})?");
94.72 + StringBuilder filtered = new StringBuilder();
94.73 + Matcher m = p.matcher(pattern);
94.74 + int i = 0;
94.75 +
94.76 + while (m.find()) {
94.77 + filtered.append(pattern.substring(i, m.start()));
94.78 + i = m.end();
94.79 +
94.80 + String var = m.group(1);
94.81 + String type = m.group(3);
94.82 +
94.83 + filtered.append(var);
94.84 + variablesToTypes.put(var, type != null ? Hacks.parseFQNType(info, type) : null);
94.85 + }
94.86 +
94.87 + filtered.append(pattern.substring(i));
94.88 +
94.89 + return filtered.toString();
94.90 + }
94.91 +}
95.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
95.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/modules/java/hints/spiimpl/processor/JavaHintsAnnotationProcessorTest.java Wed May 08 21:47:42 2013 +0200
95.3 @@ -0,0 +1,149 @@
95.4 +/*
95.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
95.6 + *
95.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
95.8 + *
95.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
95.10 + * Other names may be trademarks of their respective owners.
95.11 + *
95.12 + * The contents of this file are subject to the terms of either the GNU
95.13 + * General Public License Version 2 only ("GPL") or the Common
95.14 + * Development and Distribution License("CDDL") (collectively, the
95.15 + * "License"). You may not use this file except in compliance with the
95.16 + * License. You can obtain a copy of the License at
95.17 + * http://www.netbeans.org/cddl-gplv2.html
95.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
95.19 + * specific language governing permissions and limitations under the
95.20 + * License. When distributing the software, include this License Header
95.21 + * Notice in each file and include the License file at
95.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
95.23 + * particular file as subject to the "Classpath" exception as provided
95.24 + * by Oracle in the GPL Version 2 section of the License file that
95.25 + * accompanied this code. If applicable, add the following below the
95.26 + * License Header, with the fields enclosed by brackets [] replaced by
95.27 + * your own identifying information:
95.28 + * "Portions Copyrighted [year] [name of copyright owner]"
95.29 + *
95.30 + * If you wish your version of this file to be governed by only the CDDL
95.31 + * or only the GPL Version 2, indicate your decision by adding
95.32 + * "[Contributor] elects to include this software in this distribution
95.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
95.34 + * single choice of license, a recipient has the option to distribute
95.35 + * your version of this file under either the CDDL, the GPL Version 2 or
95.36 + * to extend the choice of license to its licensees as provided above.
95.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
95.38 + * Version 2 license, then the option applies only if the new code is
95.39 + * made subject to such option by the copyright holder.
95.40 + *
95.41 + * Contributor(s):
95.42 + *
95.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
95.44 + */
95.45 +package org.netbeans.modules.java.hints.spiimpl.processor;
95.46 +
95.47 +import java.io.ByteArrayOutputStream;
95.48 +import java.io.File;
95.49 +import org.netbeans.junit.NbTestCase;
95.50 +import org.openide.util.test.AnnotationProcessorTestUtils;
95.51 +import org.openide.util.test.TestFileUtils;
95.52 +
95.53 +/**
95.54 + *
95.55 + * @author lahvac
95.56 + */
95.57 +public class JavaHintsAnnotationProcessorTest extends NbTestCase {
95.58 +
95.59 + public JavaHintsAnnotationProcessorTest(String name) {
95.60 + super(name);
95.61 + }
95.62 +
95.63 + public void testErrors1() throws Exception {
95.64 + File src = new File(getWorkDir(), "src");
95.65 + File dest = new File(getWorkDir(), "classes");
95.66 + AnnotationProcessorTestUtils.makeSource(src, "p.H",
95.67 + "import org.netbeans.spi.java.hints.*;\n",
95.68 + "import org.netbeans.spi.editor.hints.*;\n",
95.69 + "@Hint(category=\"general\")\n",
95.70 + "public class H {\n",
95.71 + " @TriggerPattern(\"$1.$2\")\n",
95.72 + " public static String h1(HintContext ctx) { return null;}\n",
95.73 + " @TriggerPattern(\"$1.$2.$3\")\n",
95.74 + " public static ErrorDescription h2() { return null;}\n",
95.75 + " @TriggerPatterns({@TriggerPattern(\"$1.$2.$3.$4\")})\n",
95.76 + " private ErrorDescription h3(HintContext ctx) { return null;}\n",
95.77 + " @TriggerPattern(value=\"$1.isEmpty()\", constraints=@ConstraintVariableType(variable=\"$unknown\", type=\"java.lang.String\"))\n",
95.78 + " public static ErrorDescription h4(HintContext ctx) { return null;}\n",
95.79 + "}\n");
95.80 + TestFileUtils.writeFile(new File(src, "p/Bundle.properties"), "");
95.81 + ByteArrayOutputStream err = new ByteArrayOutputStream();
95.82 + assertFalse(AnnotationProcessorTestUtils.runJavac(src, null, dest, null, err));
95.83 + String errors = err.toString();
95.84 + assertTrue(errors.contains("error: The return type must be either org.netbeans.spi.editor.hints.ErrorDescription or java.util.List<org.netbeans.spi.editor.hints.ErrorDescription>"));
95.85 + assertTrue(errors.contains("error: The method must have exactly one parameter of type org.netbeans.spi.java.hints.HintContext"));
95.86 + assertTrue(errors.contains("error: The method must be static"));
95.87 + assertTrue(errors.contains("warning: Variable $unknown not used in the pattern"));
95.88 + }
95.89 +
95.90 + public void testErrors2() throws Exception {
95.91 + File src = new File(getWorkDir(), "src");
95.92 + File dest = new File(getWorkDir(), "classes");
95.93 + AnnotationProcessorTestUtils.makeSource(src, "p.H",
95.94 + "import org.netbeans.spi.java.hints.*;\n",
95.95 + "import org.netbeans.spi.editor.hints.*;\n",
95.96 + "import java.util.*;\n",
95.97 + "@Hint(displayName=\"#DN_p.H\", description=\"#DESC_p.H\", category=\"general\")\n",
95.98 + "public class H {\n",
95.99 + " @TriggerPattern(\"$1.$2.$3\")\n",
95.100 + " public static List<ErrorDescription> hint(HintContext ctx) { return null;}\n",
95.101 + "}\n");
95.102 + TestFileUtils.writeFile(new File(src, "p/Bundle.properties"), "DN_p.H=DN_p.H\nDESC_p.H=DESC_p.H\n");
95.103 + ByteArrayOutputStream err = new ByteArrayOutputStream();
95.104 + assertTrue(AnnotationProcessorTestUtils.runJavac(src, null, dest, null, err));
95.105 + }
95.106 +
95.107 + public void testCustomizerProvider() throws Exception {
95.108 + File src = new File(getWorkDir(), "src");
95.109 + File dest = new File(getWorkDir(), "classes");
95.110 + AnnotationProcessorTestUtils.makeSource(src, "p.H",
95.111 + "import org.netbeans.spi.java.hints.*;\n",
95.112 + "import org.netbeans.spi.editor.hints.*;\n",
95.113 + "import java.util.*;\n",
95.114 + "import java.util.prefs.*;\n",
95.115 + "import javax.swing.*;\n",
95.116 + "@Hint(displayName=\"dn\", description=\"desc\", category=\"general\", customizerProvider=H.Customizer.class)\n",
95.117 + "public class H {\n",
95.118 + " @TriggerPattern(\"$1.$2.$3\")\n",
95.119 + " public static List<ErrorDescription> hint(HintContext ctx) { return null;}\n",
95.120 + " static final class Customizer implements CustomizerProvider {\n",
95.121 + " @Override public JComponent getCustomizer(Preferences prefs) {\n",
95.122 + " return new JPanel();\n",
95.123 + " }\n",
95.124 + " }\n",
95.125 + "}\n");
95.126 + TestFileUtils.writeFile(new File(src, "p/Bundle.properties"), "DN_p.H=DN_p.H\nDESC_p.H=DESC_p.H\n");
95.127 + ByteArrayOutputStream err = new ByteArrayOutputStream();
95.128 + assertFalse(AnnotationProcessorTestUtils.runJavac(src, null, dest, null, err));
95.129 + String errors = err.toString();
95.130 + assertTrue(errors.contains("error: Customizer provider must be public"));
95.131 + assertTrue(errors.contains("error: Customizer provider must provide a public default constructor"));
95.132 + }
95.133 +
95.134 + public void testErrorsMessagesOnMethod() throws Exception {
95.135 + File src = new File(getWorkDir(), "src");
95.136 + File dest = new File(getWorkDir(), "classes");
95.137 + AnnotationProcessorTestUtils.makeSource(src, "p.H",
95.138 + "import org.netbeans.spi.java.hints.*;\n",
95.139 + "import org.netbeans.spi.editor.hints.*;\n",
95.140 + "import org.openide.util.NbBundle.Messages;\n",
95.141 + "import java.util.*;\n",
95.142 + "public class H {\n",
95.143 + " @Hint(displayName=\"#DN_p.H\", description=\"#DESC_p.H\", category=\"general\")\n",
95.144 + " @TriggerPattern(\"$1.$2.$3\")\n",
95.145 + " @Messages({\"DN_p.H=1\", \"DESC_p.H=2\"})\n",
95.146 + " public static List<ErrorDescription> hint(HintContext ctx) { return null;}\n",
95.147 + "}\n");
95.148 + ByteArrayOutputStream err = new ByteArrayOutputStream();
95.149 + boolean result = AnnotationProcessorTestUtils.runJavac(src, null, dest, null, err);
95.150 + assertTrue(err.toString(), result);
95.151 + }
95.152 +}
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
96.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/spi/java/hints/JavaFixUtilitiesTest.java Wed May 08 21:47:42 2013 +0200
96.3 @@ -0,0 +1,1161 @@
96.4 +/*
96.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
96.6 + *
96.7 + * Copyright 2008-2010 Oracle and/or its affiliates. All rights reserved.
96.8 + *
96.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
96.10 + * Other names may be trademarks of their respective owners.
96.11 + *
96.12 + * The contents of this file are subject to the terms of either the GNU
96.13 + * General Public License Version 2 only ("GPL") or the Common
96.14 + * Development and Distribution License("CDDL") (collectively, the
96.15 + * "License"). You may not use this file except in compliance with the
96.16 + * License. You can obtain a copy of the License at
96.17 + * http://www.netbeans.org/cddl-gplv2.html
96.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
96.19 + * specific language governing permissions and limitations under the
96.20 + * License. When distributing the software, include this License Header
96.21 + * Notice in each file and include the License file at
96.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
96.23 + * particular file as subject to the "Classpath" exception as provided
96.24 + * by Oracle in the GPL Version 2 section of the License file that
96.25 + * accompanied this code. If applicable, add the following below the
96.26 + * License Header, with the fields enclosed by brackets [] replaced by
96.27 + * your own identifying information:
96.28 + * "Portions Copyrighted [year] [name of copyright owner]"
96.29 + *
96.30 + * If you wish your version of this file to be governed by only the CDDL
96.31 + * or only the GPL Version 2, indicate your decision by adding
96.32 + * "[Contributor] elects to include this software in this distribution
96.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
96.34 + * single choice of license, a recipient has the option to distribute
96.35 + * your version of this file under either the CDDL, the GPL Version 2 or
96.36 + * to extend the choice of license to its licensees as provided above.
96.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
96.38 + * Version 2 license, then the option applies only if the new code is
96.39 + * made subject to such option by the copyright holder.
96.40 + *
96.41 + * Contributor(s):
96.42 + *
96.43 + * Portions Copyrighted 2008-2010 Sun Microsystems, Inc.
96.44 + */
96.45 +
96.46 +package org.netbeans.spi.java.hints;
96.47 +
96.48 +import org.netbeans.modules.java.hints.providers.spi.HintDescriptionFactory;
96.49 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
96.50 +import com.sun.source.tree.ClassTree;
96.51 +import com.sun.source.tree.ExpressionTree;
96.52 +import com.sun.source.tree.VariableTree;
96.53 +import com.sun.source.util.TreePath;
96.54 +import java.util.Collection;
96.55 +import java.util.Collections;
96.56 +import java.util.HashMap;
96.57 +import java.util.List;
96.58 +import java.util.Map;
96.59 +import java.util.Map.Entry;
96.60 +import java.util.concurrent.atomic.AtomicBoolean;
96.61 +import javax.lang.model.element.ExecutableElement;
96.62 +import javax.lang.model.element.TypeElement;
96.63 +import javax.lang.model.type.TypeMirror;
96.64 +import javax.lang.model.util.ElementFilter;
96.65 +import org.netbeans.modules.java.hints.spiimpl.TestBase;
96.66 +import org.netbeans.modules.java.hints.spiimpl.hints.HintsInvoker;
96.67 +import org.netbeans.modules.java.hints.providers.spi.Trigger.PatternDescription;
96.68 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
96.69 +import org.netbeans.modules.java.hints.spiimpl.pm.PatternCompilerUtilities;
96.70 +import org.netbeans.spi.editor.hints.ErrorDescription;
96.71 +import org.netbeans.spi.editor.hints.Fix;
96.72 +import org.openide.LifecycleManager;
96.73 +import org.openide.modules.SpecificationVersion;
96.74 +import org.openide.util.MapFormat;
96.75 +
96.76 +/**
96.77 + *
96.78 + * @author Jan Lahoda
96.79 + */
96.80 +public class JavaFixUtilitiesTest extends TestBase {
96.81 +
96.82 + public JavaFixUtilitiesTest(String name) {
96.83 + super(name);
96.84 + }
96.85 +
96.86 + public void testSimple() throws Exception {
96.87 + SpecificationVersion v = computeSpecVersion("/**\n" +
96.88 + " * @since 1.5\n" +
96.89 + " */\n");
96.90 +
96.91 + assertEquals(0, v.compareTo(new SpecificationVersion("1.5")));
96.92 + }
96.93 +
96.94 + public void testSimpleDate() throws Exception {
96.95 + SpecificationVersion v = computeSpecVersion("/**\n" +
96.96 + " * @since 1.5 (16 May 2005)\n" +
96.97 + " */\n");
96.98 +
96.99 + assertEquals(0, v.compareTo(new SpecificationVersion("1.5")));
96.100 + }
96.101 +
96.102 + public void testLongText() throws Exception {
96.103 + SpecificationVersion v = computeSpecVersion("/**\n" +
96.104 + " * @since 1.123.2.1 - branch propsheet_issue_29447\n" +
96.105 + " */\n");
96.106 +
96.107 + assertEquals(0, v.compareTo(new SpecificationVersion("1.123.2.1")));
96.108 + }
96.109 +
96.110 + public void testModuleName() throws Exception {
96.111 + SpecificationVersion v = computeSpecVersion("/**\n" +
96.112 + " * @since org.openide.filesystems 7.15\n" +
96.113 + " */\n");
96.114 +
96.115 + assertEquals(0, v.compareTo(new SpecificationVersion("7.15")));
96.116 + }
96.117 +
96.118 + public void testModuleNameMajor() throws Exception {
96.119 + SpecificationVersion v = computeSpecVersion("/**\n" +
96.120 + " * @since org.openide/1 4.42\n" +
96.121 + " */\n");
96.122 +
96.123 + assertEquals(0, v.compareTo(new SpecificationVersion("4.42")));
96.124 + }
96.125 +
96.126 + public void testEnd() throws Exception {
96.127 + SpecificationVersion v = computeSpecVersion("/**\n" +
96.128 + " * @since 1.5 */\n");
96.129 +
96.130 + assertEquals(0, v.compareTo(new SpecificationVersion("1.5")));
96.131 + }
96.132 +
96.133 + public void testOpenAPI() throws Exception {
96.134 + SpecificationVersion v = computeSpecVersion("/**\n" +
96.135 + " * @since OpenAPI version 2.12" +
96.136 + " */\n");
96.137 +
96.138 + assertEquals(0, v.compareTo(new SpecificationVersion("2.12")));
96.139 +
96.140 + }
96.141 +
96.142 + private SpecificationVersion computeSpecVersion(String javadoc) throws Exception {
96.143 + prepareTest("test/Test.java",
96.144 + "package test;\n" +
96.145 + "public class Test {\n" +
96.146 + javadoc +
96.147 + " public void test() {\n" +
96.148 + " }\n" +
96.149 + "}\n");
96.150 +
96.151 + TypeElement te = info.getElements().getTypeElement("test.Test");
96.152 + ExecutableElement method = ElementFilter.methodsIn(te.getEnclosedElements()).iterator().next();
96.153 +
96.154 + return JavaFixUtilities.computeSpecVersion(info, method);
96.155 + }
96.156 +
96.157 + public void testArithmetic1() throws Exception {
96.158 + performArithmeticTest("1 + 2", "3");
96.159 + performArithmeticTest("1f + 2", "3.0F");
96.160 + performArithmeticTest("1 + 2f", "3.0F");
96.161 + performArithmeticTest("1.0 + 2f", "3.0");
96.162 + performArithmeticTest("1 + 2.0", "3.0");
96.163 + performArithmeticTest("1L + 2", "3L");
96.164 + }
96.165 +
96.166 + public void testArithmetic2() throws Exception {
96.167 + performArithmeticTest("1 * 2", "2");
96.168 + performArithmeticTest("1f * 2", "2.0F");
96.169 + performArithmeticTest("1 * 2f", "2.0F");
96.170 + performArithmeticTest("1.0 * 2f", "2.0");
96.171 + performArithmeticTest("1 * 2.0", "2.0");
96.172 + performArithmeticTest("1L * 2", "2L");
96.173 + }
96.174 +
96.175 + public void testArithmetic3() throws Exception {
96.176 + performArithmeticTest("4 / 2", "2");
96.177 + performArithmeticTest("4f / 2", "2.0F");
96.178 + performArithmeticTest("4 / 2f", "2.0F");
96.179 + performArithmeticTest("4.0 / 2f", "2.0");
96.180 + performArithmeticTest("4 / 2.0", "2.0");
96.181 + performArithmeticTest("4L / 2", "2L");
96.182 + }
96.183 +
96.184 + public void testArithmetic4() throws Exception {
96.185 + performArithmeticTest("5 % 2", "1");
96.186 + performArithmeticTest("5f % 2", "1.0F");
96.187 + performArithmeticTest("5 % 2f", "1.0F");
96.188 + performArithmeticTest("5.0 % 2f", "1.0");
96.189 + performArithmeticTest("5 % 2.0", "1.0");
96.190 + performArithmeticTest("5L % 2", "1L");
96.191 + }
96.192 +
96.193 + public void testArithmetic5() throws Exception {
96.194 + performArithmeticTest("5 - 2", "3");
96.195 + performArithmeticTest("5f - 2", "3.0F");
96.196 + performArithmeticTest("5 - 2f", "3.0F");
96.197 + performArithmeticTest("5.0 - 2f", "3.0");
96.198 + performArithmeticTest("5 - 2.0", "3.0");
96.199 + performArithmeticTest("5L - 2", "3L");
96.200 + }
96.201 +
96.202 + public void testArithmetic6() throws Exception {
96.203 + performArithmeticTest("5 | 2", "7");
96.204 + performArithmeticTest("5L | 2", "7L");
96.205 + performArithmeticTest("5 | 2L", "7L");
96.206 + }
96.207 +
96.208 + public void testArithmetic7() throws Exception {
96.209 + performArithmeticTest("5 & 4", "4");
96.210 + performArithmeticTest("5L & 4", "4L");
96.211 + performArithmeticTest("5 & 4L", "4L");
96.212 + }
96.213 +
96.214 + public void testArithmetic8() throws Exception {
96.215 + performArithmeticTest("5 ^ 4", "1");
96.216 + performArithmeticTest("5L ^ 4", "1L");
96.217 + performArithmeticTest("5 ^ 4L", "1L");
96.218 + }
96.219 +
96.220 + public void testArithmetic9() throws Exception {
96.221 + performArithmeticTest("5 << 2", "20");
96.222 + performArithmeticTest("5L << 2", "20L");
96.223 + performArithmeticTest("5 << 2L", "20L");
96.224 + }
96.225 +
96.226 + public void testArithmeticA() throws Exception {
96.227 + performArithmeticTest("-20 >> 2", "-5");
96.228 + performArithmeticTest("-20L >> 2", "-5L");
96.229 + performArithmeticTest("-20 >> 2L", "-5L");
96.230 + }
96.231 +
96.232 + public void testArithmeticB() throws Exception {
96.233 + performArithmeticTest("-20 >>> 2", "1073741819");
96.234 + }
96.235 +
96.236 + public void testArithmeticC() throws Exception {
96.237 + performArithmeticTest("0 + -20", "-20");
96.238 + performArithmeticTest("0 + +20", "20");
96.239 + }
96.240 +
96.241 + public void testArithmeticComplex() throws Exception {
96.242 + performArithmeticTest("1 + 2 * 4 - 5", "4");
96.243 + performArithmeticTest("1f + 2 * 4.0 - 5", "4.0");
96.244 + performArithmeticTest("1L + 2 * 4 - 5", "4L");
96.245 + }
96.246 +
96.247 + private static final String ARITHMETIC = "public class Test { private Object o = __VAL__; }";
96.248 + private void performArithmeticTest(String orig, String nue) throws Exception {
96.249 + String code = replace("0");
96.250 +
96.251 + prepareTest("Test.java", code);
96.252 + ClassTree clazz = (ClassTree) info.getCompilationUnit().getTypeDecls().get(0);
96.253 + VariableTree variable = (VariableTree) clazz.getMembers().get(1);
96.254 + ExpressionTree init = variable.getInitializer();
96.255 + TreePath tp = new TreePath(new TreePath(new TreePath(new TreePath(info.getCompilationUnit()), clazz), variable), init);
96.256 + Fix fix = JavaFixUtilities.rewriteFix(info, "A", tp, orig, Collections.<String, TreePath>emptyMap(), Collections.<String, Collection<? extends TreePath>>emptyMap(), Collections.<String, String>emptyMap(), Collections.<String, TypeMirror>emptyMap(), Collections.<String, String>emptyMap());
96.257 + fix.implement();
96.258 +
96.259 + String golden = replace(nue);
96.260 + String out = doc.getText(0, doc.getLength());
96.261 +
96.262 + assertEquals(golden, out);
96.263 +
96.264 + LifecycleManager.getDefault().saveAll();
96.265 + }
96.266 +
96.267 + private static String replace(String val) {
96.268 + MapFormat f = new MapFormat(Collections.singletonMap("VAL", val));
96.269 +
96.270 + f.setLeftBrace("__");
96.271 + f.setRightBrace("__");
96.272 +
96.273 + return f.format(ARITHMETIC);
96.274 + }
96.275 +
96.276 + public void testRewriteWithParenthesis1() throws Exception {
96.277 + performRewriteTest("package test;\n" +
96.278 + "public class Test {\n" +
96.279 + " int i = new String(\"a\" + \"b\").length();\n" +
96.280 + "}\n",
96.281 + "new String($1)=>$1",
96.282 + "package test;\n" +
96.283 + "public class Test {\n" +
96.284 + " int i = (\"a\" + \"b\").length();\n" +
96.285 + "}\n");
96.286 + }
96.287 +
96.288 + public void testRewriteWithParenthesis2() throws Exception {
96.289 + performRewriteTest("package test;\n" +
96.290 + "public class Test {\n" +
96.291 + " int i = Integer.valueOf(1 + 2) * 3;\n" +
96.292 + "}\n",
96.293 + "Integer.valueOf($1)=>$1",
96.294 + "package test;\n" +
96.295 + "public class Test {\n" +
96.296 + " int i = (1 + 2) * 3;\n" +
96.297 + "}\n");
96.298 + }
96.299 +
96.300 + public void testRewriteWithoutParenthesis1() throws Exception {
96.301 + performRewriteTest("package test;\n" +
96.302 + "public class Test {\n" +
96.303 + " int i = new String(\"a\" + \"b\").length();\n" +
96.304 + "}\n",
96.305 + "new String($1)=>java.lang.String.format(\"%s%s\", $1, \"\")",
96.306 + "package test;\n" +
96.307 + "public class Test {\n" +
96.308 + " int i = String.format(\"%s%s\", \"a\" + \"b\", \"\").length();\n" +
96.309 + "}\n");
96.310 + }
96.311 +
96.312 + public void testRewriteWithoutParenthesis2() throws Exception {
96.313 + performRewriteTest("package test;\n" +
96.314 + "public class Test {\n" +
96.315 + " String s = (\"a\" + \"b\").intern();\n" +
96.316 + "}\n",
96.317 + "($1).intern()=>$1",
96.318 + "package test;\n" +
96.319 + "public class Test {\n" +
96.320 + " String s = \"a\" + \"b\";\n" +
96.321 + "}\n");
96.322 + }
96.323 +
96.324 + public void testRewriteWithoutParenthesis3() throws Exception {
96.325 + performRewriteTest("package test;\n" +
96.326 + "public class Test {\n" +
96.327 + " int i = Integer.valueOf(1 + 2) + 3;\n" +
96.328 + "}\n",
96.329 + "Integer.valueOf($1)=>$1",
96.330 + "package test;\n" +
96.331 + "public class Test {\n" +
96.332 + " int i = 1 + 2 + 3;\n" +
96.333 + "}\n");
96.334 + }
96.335 +
96.336 + public void testRewriteWithoutParenthesis4() throws Exception {
96.337 + performRewriteTest("package test;\n" +
96.338 + "public class Test {\n" +
96.339 + " int i = Integer.valueOf(1 * 2) + 3;\n" +
96.340 + "}\n",
96.341 + "Integer.valueOf($1)=>$1",
96.342 + "package test;\n" +
96.343 + "public class Test {\n" +
96.344 + " int i = 1 * 2 + 3;\n" +
96.345 + "}\n");
96.346 + }
96.347 +
96.348 + public void testRewriteWithoutParenthesis5() throws Exception {
96.349 + performRewriteTest("package test;\n" +
96.350 + "public class Test {\n" +
96.351 + " int i = new Integer(1 * 2).hashCode();\n" +
96.352 + "}\n",
96.353 + "$1.hashCode()=>$1.hashCode()",
96.354 + "package test;\n" +
96.355 + "public class Test {\n" +
96.356 + " int i = new Integer(1 * 2).hashCode();\n" +
96.357 + "}\n");
96.358 + }
96.359 +
96.360 + public void testRewriteWithoutParenthesis6() throws Exception {
96.361 + performRewriteTest("package test;\n" +
96.362 + "public class Test {\n" +
96.363 + " {\n" +
96.364 + " System.err.println(\"a\" + 1);\n" +
96.365 + " }\n" +
96.366 + "}\n",
96.367 + "System.err.println($t)=>D.println($t)",
96.368 + "package test;\n" +
96.369 + "public class Test {\n" +
96.370 + " {\n" +
96.371 + " D.println(\"a\" + 1);\n" +
96.372 + " }\n" +
96.373 + "}\n");
96.374 + }
96.375 +
96.376 + public void testRewriteWithoutParenthesis7() throws Exception {
96.377 + performRewriteTest("package test;\n" +
96.378 + "public class Test {\n" +
96.379 + " {\n" +
96.380 + " new String(\"a\" + 1);\n" +
96.381 + " }\n" +
96.382 + "}\n",
96.383 + "new String($t)=>new D($t)",
96.384 + "package test;\n" +
96.385 + "public class Test {\n" +
96.386 + " {\n" +
96.387 + " new D(\"a\" + 1);\n" +
96.388 + " }\n" +
96.389 + "}\n");
96.390 + }
96.391 +
96.392 + public void testTopLevelRewriteWithoutParenthesis1() throws Exception {
96.393 + performRewriteTest("package test;\n" +
96.394 + "public class Test {\n" +
96.395 + " int i = (1 + 2) * 2;\n" +
96.396 + "}\n",
96.397 + "$1 + $2=>3",
96.398 + "package test;\n" +
96.399 + "public class Test {\n" +
96.400 + " int i = 3 * 2;\n" +
96.401 + "}\n");
96.402 + }
96.403 +
96.404 + public void testTopLevelRewriteKeepParenthesis1() throws Exception {
96.405 + performRewriteTest("package test;\n" +
96.406 + "public class Test {\n" +
96.407 + " int i = (1 * 2) + 2;\n" +
96.408 + "}\n",
96.409 + "$1 * $2=>2",
96.410 + "package test;\n" +
96.411 + "public class Test {\n" +
96.412 + " int i = (2) + 2;\n" +
96.413 + "}\n");
96.414 + }
96.415 +
96.416 + public void testTopLevelRewriteKeepParenthesis2() throws Exception {
96.417 + performRewriteTest("package test;\n" +
96.418 + "public class Test {\n" +
96.419 + " { if (1 > 2) ; }\n" +
96.420 + "}\n",
96.421 + "$1 > $2=>false",
96.422 + "package test;\n" +
96.423 + "public class Test {\n" +
96.424 + " { if (false) ; }\n" +
96.425 + "}\n");
96.426 + }
96.427 +
96.428 + public void testRewriteCatchMultiVariable() throws Exception {
96.429 + performRewriteTest("package test;\n" +
96.430 + "public class Test {\n" +
96.431 + " { try { } catch {NullPointerException ex} { } }\n" +
96.432 + "}\n",
96.433 + "try { } catch $catches$ => try { new Object(); } catch $catches$",
96.434 + "package test;\n" +
96.435 + "public class Test {\n" +
96.436 + " { try { new Object();\n } catch {NullPointerException ex} { } }\n" +
96.437 + "}\n");
96.438 + }
96.439 +
96.440 + public void testRewriteCaseMultiVariable() throws Exception {
96.441 + performRewriteTest("package test;\n" +
96.442 + "public class Test {\n" +
96.443 + " { int i = 0; switch (i) {case 0: System.err.println(1); break; case 1: System.err.println(2); break; case 2: System.err.println(3); break; }\n" +
96.444 + "}\n",
96.445 + "switch ($v) { case $p$ case 2: $stmts$; } => switch ($v) { case $p$ case 3: $stmts$; }",
96.446 + "package test;\n" +
96.447 + "public class Test {\n" +
96.448 + //XXX: whitespaces:
96.449 +// " { int i = 0; switch (i) {case 0: System.err.println(1); break; case 1: System.err.println(2); break; case 3: System.err.println(3); break; }\n" +
96.450 + " { int i = 0; switch (i) {case 0: System.err.println(1); break; case 1: System.err.println(2); break; case 3: System.err.println(3); break; }\n" +
96.451 + "}\n");
96.452 + }
96.453 +
96.454 + public void testRewriteMemberSelectVariable() throws Exception {
96.455 + performRewriteTest("package test;\n" +
96.456 + "public class Test {\n" +
96.457 + " { java.io.File f = null; boolean b = f.isDirectory(); }\n" +
96.458 + "}\n",
96.459 + "$file.$m() => foo.Bar.$m($file)",
96.460 + "package test;\n" +
96.461 + "public class Test {\n" +
96.462 + " { java.io.File f = null; boolean b = foo.Bar.isDirectory(f); }\n" +
96.463 + "}\n");
96.464 + }
96.465 +
96.466 + public void testRewriteIdent2IdentMemberSelectPattern() throws Exception {
96.467 + performRewriteTest("package test;\n" +
96.468 + "public class Test {\n" +
96.469 + " private boolean b; private void t() { boolean c = b; }\n" +
96.470 + "}\n",
96.471 + "$0{test.Test}.b => !$0.b",
96.472 + "package test;\n" +
96.473 + "public class Test {\n" +
96.474 + " private boolean b; private void t() { boolean c = !b; }\n" +
96.475 + "}\n");
96.476 + }
96.477 +
96.478 + public void testCarefulRewriteInImports() throws Exception {
96.479 + performRewriteTest("package test;\n" +
96.480 + "import javax.swing.text.AbstractDocument;\n" +
96.481 + "public class Test {\n" +
96.482 + "}\n",
96.483 + "javax.swing.text.AbstractDocument => javax.swing.text.Document",
96.484 + "package test;\n" +
96.485 + "import javax.swing.text.Document;\n" +
96.486 + "public class Test {\n" +
96.487 + "}\n");
96.488 + }
96.489 +
96.490 + public void testRemoveFromParent1() throws Exception {
96.491 + performRemoveFromParentTest("package test;\n" +
96.492 + "public class Test {\n" +
96.493 + " private int I;" +
96.494 + "}\n",
96.495 + "$mods$ int $f;",
96.496 + "package test;\n" +
96.497 + "public class Test {\n" +
96.498 + "}\n");
96.499 + }
96.500 +
96.501 + public void testRemoveFromParent2() throws Exception {
96.502 + performRemoveFromParentTest("package test;\n" +
96.503 + "public class Test extends java.util.ArrayList {\n" +
96.504 + "}\n",
96.505 + "java.util.ArrayList",
96.506 + "package test;\n" +
96.507 + "public class Test {\n" +
96.508 + "}\n");
96.509 + }
96.510 +
96.511 + public void testRemoveFromParentExpressionStatement206116() throws Exception {
96.512 + performRemoveFromParentTest("package test;\n" +
96.513 + "import java.io.InputStream;\n" +
96.514 + "public class Test {\n" +
96.515 + " private void t() throws Exception {\n" +
96.516 + " System.err.println();\n" +
96.517 + " System.err.println(\"a\");\n" +
96.518 + " }\n" +
96.519 + "}\n",
96.520 + "System.err.println()",
96.521 + "package test;\n" +
96.522 + "import java.io.InputStream;\n" +
96.523 + "public class Test {\n" +
96.524 + " private void t() throws Exception {\n" +
96.525 + " System.err.println(\"a\");\n" +
96.526 + " }\n" +
96.527 + "}\n");
96.528 + }
96.529 +
96.530 + public void testUnresolvableTarget() throws Exception {
96.531 + performRewriteTest("package test;\n" +
96.532 + "public class Test extends java.util.ArrayList {\n" +
96.533 + "}\n",
96.534 + "java.util.ArrayList => Test",
96.535 + "package test;\n" +
96.536 + "public class Test extends Test {\n" +
96.537 + "}\n");
96.538 + }
96.539 +
96.540 + public void testTryWithResourceTarget() throws Exception {
96.541 + performRewriteTest("package test;\n" +
96.542 + "import java.io.InputStream;\n" +
96.543 + "public class Test {\n" +
96.544 + " private void t() throws Exception {\n" +
96.545 + " InputStream in = null;\n" +
96.546 + " try {\n" +
96.547 + " } finally {\n" +
96.548 + " in.close()\n" +
96.549 + " }\n" +
96.550 + " }\n" +
96.551 + "}\n",
96.552 + "$type $var = $init; try {} finally {$var.close();} => try ($type $var = $init) {} finally {$var.close();}",
96.553 + "package test;\n" +
96.554 + "import java.io.InputStream;\n" +
96.555 + "public class Test {\n" +
96.556 + " private void t() throws Exception {\n" +
96.557 +// " try (InputStream in = null) {\n" +
96.558 + //XXX:
96.559 + " try (final InputStream in = null) {\n" +
96.560 + " } finally {\n" +
96.561 + " in.close()\n" +
96.562 + " }\n" +
96.563 + " }\n" +
96.564 + "}\n");
96.565 + }
96.566 +
96.567 + public void testSingle2MultipleStatements() throws Exception {
96.568 + performRewriteTest("package test;\n" +
96.569 + "import java.io.InputStream;\n" +
96.570 + "public class Test {\n" +
96.571 + " private void t() throws Exception {\n" +
96.572 + " int i = 0;\n" +
96.573 + " }\n" +
96.574 + "}\n",
96.575 + "$type $var = $init; => $type $var; $var = $init;",
96.576 + "package test;\n" +
96.577 + "import java.io.InputStream;\n" +
96.578 + "public class Test {\n" +
96.579 + " private void t() throws Exception {\n" +
96.580 + " int i;\n" +
96.581 + " i = 0;\n" +
96.582 + " }\n" +
96.583 + "}\n");
96.584 + }
96.585 +
96.586 + public void testSingle2MultipleStatements2() throws Exception {
96.587 + performRewriteTest("package test;\n" +
96.588 + "import java.io.InputStream;\n" +
96.589 + "public class Test {\n" +
96.590 + " private void t() throws Exception {\n" +
96.591 + " while (true)\n" +
96.592 + " if (true) {\n" +
96.593 + " System.err.println();\n" +
96.594 + " }\n" +
96.595 + " }\n" +
96.596 + "}\n",
96.597 + "if (true) $then; => if (true) $then; System.err.println();",
96.598 + "package test;\n" +
96.599 + "import java.io.InputStream;\n" +
96.600 + "public class Test {\n" +
96.601 + " private void t() throws Exception {\n" +
96.602 + " while (true) {\n" +
96.603 + " if (true) {\n" +
96.604 + " System.err.println();\n" +
96.605 + " }\n" +
96.606 + " System.err.println();\n" +
96.607 + " }\n" +
96.608 + " }\n" +
96.609 + "}\n");
96.610 + }
96.611 +
96.612 + public void testMultipleStatementsWrapComments1() throws Exception {
96.613 + performRewriteTest("package test;\n" +
96.614 + "import java.io.InputStream;\n" +
96.615 + "public class Test {\n" +
96.616 + " private void t() throws Exception {\n" +
96.617 + " if (1 == 1) {\n" +
96.618 + " System.err.println();\n" +
96.619 + " System.err.println(\"a\");\n" +
96.620 + " \n" +
96.621 + " \n" +
96.622 + " //C\n" +
96.623 + " System.err.println(\"b\");\n" +
96.624 + " }\n" +
96.625 + " }\n" +
96.626 + "}\n",
96.627 + "if ($cond) { System.err.println(); $stmts$;} => while ($cond) { $stmts$;}",
96.628 + "package test;\n" +
96.629 + "import java.io.InputStream;\n" +
96.630 + "public class Test {\n" +
96.631 + " private void t() throws Exception {\n" +
96.632 + " while (1 == 1) {\n" +
96.633 + " System.err.println(\"a\");\n" +
96.634 + " \n" +
96.635 + " \n" +
96.636 + " //C\n" +
96.637 + " System.err.println(\"b\");\n" +
96.638 + " }\n" +
96.639 + " }\n" +
96.640 + "}\n");
96.641 + }
96.642 +
96.643 + public void testMultipleStatementsWrapComments2() throws Exception {
96.644 + performRewriteTest("package test;\n" +
96.645 + "import java.io.InputStream;\n" +
96.646 + "public class Test {\n" +
96.647 + " private void t() throws Exception {\n" +
96.648 + " if (1 == 1) {\n" +
96.649 + " System.err.println();\n" +
96.650 + " System.err.println(\"a\");\n" +
96.651 + " \n" +
96.652 + " \n" +
96.653 + " //C\n" +
96.654 + " System.err.println(\"b\");\n" +
96.655 + " }\n" +
96.656 + " }\n" +
96.657 + "}\n",
96.658 + "if ($cond) { $stmts$;} => while ($cond) { $stmts$;}",
96.659 + "package test;\n" +
96.660 + "import java.io.InputStream;\n" +
96.661 + "public class Test {\n" +
96.662 + " private void t() throws Exception {\n" +
96.663 + " while (1 == 1) {\n" +
96.664 + " System.err.println();\n" +
96.665 + " System.err.println(\"a\");\n" +
96.666 + " \n" +
96.667 + " \n" +
96.668 + " //C\n" +
96.669 + " System.err.println(\"b\");\n" +
96.670 + " }\n" +
96.671 + " }\n" +
96.672 + "}\n");
96.673 + }
96.674 +
96.675 + public void testReplaceTypeParameters1() throws Exception {
96.676 + performRewriteTest("package test;\n" +
96.677 + "import java.io.InputStream;\n" +
96.678 + "public class Test {\n" +
96.679 + " private <A, B> void t() {\n" +
96.680 + " }\n" +
96.681 + "}\n",
96.682 + "$mods$ <$O, $T> $ret $name() { $body$; } => $mods$ <$T, $O> $ret $name() { $body$; }",
96.683 + "package test;\n" +
96.684 + "import java.io.InputStream;\n" +
96.685 + "public class Test {\n" +
96.686 + " private <B, A> void t() {\n" +
96.687 + " }\n" +
96.688 + "}\n");
96.689 + }
96.690 +
96.691 + public void testReplaceTypeParameters2() throws Exception {
96.692 + performRewriteTest("package test;\n" +
96.693 + "import java.io.InputStream;\n" +
96.694 + "public class Test {\n" +
96.695 + " private <A, B> void t() {\n" +
96.696 + " }\n" +
96.697 + "}\n",
96.698 + "$mods$ <$T$> $ret $name() { $body$; } => $mods$ <C, $T$> $ret $name() { $body$; }",
96.699 + "package test;\n" +
96.700 + "import java.io.InputStream;\n" +
96.701 + "public class Test {\n" +
96.702 + " private <C, A, B> void t() {\n" +
96.703 + " }\n" +
96.704 + "}\n");
96.705 + }
96.706 +
96.707 + public void testAdd2Modifiers() throws Exception {
96.708 + performRewriteTest("package test;\n" +
96.709 + "import java.io.InputStream;\n" +
96.710 + "public class Test {\n" +
96.711 + " void t() {\n" +
96.712 + " }\n" +
96.713 + "}\n",
96.714 + "$mods$ $ret $name() { $body$; } => $mods$ @java.lang.Deprecated private $ret $name() { $body$; }",
96.715 + "package test;\n" +
96.716 + "import java.io.InputStream;\n" +
96.717 + "public class Test {\n" +
96.718 + " @Deprecated\n" +
96.719 + " private void t() {\n" +
96.720 + " }\n" +
96.721 + "}\n");
96.722 + }
96.723 +
96.724 + public void testReplaceInModifiers() throws Exception {
96.725 + performRewriteTest("package test;\n" +
96.726 + "import java.io.InputStream;\n" +
96.727 + "public class Test {\n" +
96.728 + " public @Override void t() {\n" +
96.729 + " }\n" +
96.730 + "}\n",
96.731 + "$mods$ public @Override $ret $name() { $body$; } => $mods$ private @Deprecated $ret $name() { $body$; }",
96.732 + "package test;\n" +
96.733 + "import java.io.InputStream;\n" +
96.734 + "public class Test {\n" +
96.735 + " private @Deprecated void t() {\n" +
96.736 + " }\n" +
96.737 + "}\n");
96.738 + }
96.739 +
96.740 + public void testKeepInModifiers() throws Exception {
96.741 + performRewriteTest("package test;\n" +
96.742 + "import java.io.InputStream;\n" +
96.743 + "public class Test {\n" +
96.744 + " public @Override void t() {\n" +
96.745 + " }\n" +
96.746 + "}\n",
96.747 + "$mods$ public @Override $ret $name() { $body$; } => $mods$ public @Override $ret $name() { $body$; }",
96.748 + "package test;\n" +
96.749 + "import java.io.InputStream;\n" +
96.750 + "public class Test {\n" +
96.751 + " public @Override void t() {\n" +
96.752 + " }\n" +
96.753 + "}\n");
96.754 + }
96.755 +
96.756 + public void testRemoveInModifiers() throws Exception {
96.757 + performRewriteTest("package test;\n" +
96.758 + "import java.io.InputStream;\n" +
96.759 + "public class Test {\n" +
96.760 + " public static @Deprecated @Override void t() {\n" +
96.761 + " }\n" +
96.762 + "}\n",
96.763 + "$mods$ public @Override $ret $name() { $body$; } => $mods$ $ret $name() { $body$; }",
96.764 + "package test;\n" +
96.765 + "import java.io.InputStream;\n" +
96.766 + "public class Test {\n" +
96.767 + " static @Deprecated void t() {\n" +
96.768 + " }\n" +
96.769 + "}\n");
96.770 + }
96.771 +
96.772 + public void testRewriteMethodParametersWildcard() throws Exception {
96.773 + performRewriteTest("package test;\n" +
96.774 + "import java.io.InputStream;\n" +
96.775 + "public class Test {\n" +
96.776 + " public static void t() {\n" +
96.777 + " }\n" +
96.778 + "}\n",
96.779 + "$mods$ void $name($args$) { $body$; } => $mods$ int $name($args$) { $body$; }",
96.780 + "package test;\n" +
96.781 + "import java.io.InputStream;\n" +
96.782 + "public class Test {\n" +
96.783 + " public static int t() {\n" +
96.784 + " }\n" +
96.785 + "}\n");
96.786 + }
96.787 +
96.788 + public void testRewriteClass() throws Exception {
96.789 + performRewriteTest("package test;\n" +
96.790 + "public class Test {\n" +
96.791 + "}\n",
96.792 + "$mods$ class $name<$tp$> extends $e$ implements $i$ { $members$; } => $mods$ @java.lang.Deprecated class $name<$tp$> extends $e$ implements $i$ { $members$; }",
96.793 + "package test;\n" +
96.794 + "@Deprecated\n" +
96.795 + "public class Test {\n" +
96.796 + "}\n");
96.797 + }
96.798 +
96.799 + public void testOptionalVariableInitializer1() throws Exception {
96.800 + performRewriteTest("package test;\n" +
96.801 + "public class Test {\n" +
96.802 + " private int I;\n" +
96.803 + "}\n",
96.804 + "$mods$ int $name = $init$; => $mods$ long $name = $init$;",
96.805 + "package test;\n" +
96.806 + "public class Test {\n" +
96.807 + " private long I;\n" +
96.808 + "}\n");
96.809 + }
96.810 +
96.811 + public void testOptionalVariableInitializer2() throws Exception {
96.812 + performRewriteTest("package test;\n" +
96.813 + "public class Test {\n" +
96.814 + " private int I = 1;\n" +
96.815 + "}\n",
96.816 + "$mods$ int $name = $init$; => $mods$ long $name = $init$;",
96.817 + "package test;\n" +
96.818 + "public class Test {\n" +
96.819 + " private long I = 1;\n" +
96.820 + "}\n");
96.821 + }
96.822 +
96.823 + public void testOptionalElse1() throws Exception {
96.824 + performRewriteTest("package test;\n" +
96.825 + "public class Test {\n" +
96.826 + " {\n" +
96.827 + " if (true) System.err.println(\"a\");\n" +
96.828 + " }\n" +
96.829 + "}\n",
96.830 + "if (true) $then else $else$; => if (false) $then else $else$;",
96.831 + "package test;\n" +
96.832 + "public class Test {\n" +
96.833 + " {\n" +
96.834 + " if (false) System.err.println(\"a\");\n" +
96.835 + " }\n" +
96.836 + "}\n");
96.837 + }
96.838 +
96.839 + public void testOptionalElse2() throws Exception {
96.840 + performRewriteTest("package test;\n" +
96.841 + "public class Test {\n" +
96.842 + " {\n" +
96.843 + " if (true) System.err.println(\"a\");\n" +
96.844 + " else System.err.println(\"b\");\n" +
96.845 + " }\n" +
96.846 + "}\n",
96.847 + "if (true) $then else $else$; => if (false) $then else $else$;",
96.848 + "package test;\n" +
96.849 + "public class Test {\n" +
96.850 + " {\n" +
96.851 + " if (false) System.err.println(\"a\");\n" +
96.852 + " else System.err.println(\"b\");\n" +
96.853 + " }\n" +
96.854 + "}\n");
96.855 + }
96.856 +
96.857 + public void testMultiNewArray() throws Exception {
96.858 + performRewriteTest("package test;\n" +
96.859 + "public class Test {\n" +
96.860 + " private static void t(Object... obj) {\n" +
96.861 + " Test.t(1);\n" +
96.862 + " }\n" +
96.863 + "}\n",
96.864 + "test.Test.t($args$) => test.Test.t(new Object[] {$args$})",
96.865 + "package test;\n" +
96.866 + "public class Test {\n" +
96.867 + " private static void t(Object... obj) {\n" +
96.868 + " Test.t(new Object[]{1});\n" +
96.869 + " }\n" +
96.870 + "}\n");
96.871 + }
96.872 +
96.873 + public void testFakeBlock2FakeBlock191283() throws Exception {
96.874 + performRewriteTest("package test;\n" +
96.875 + "import java.io.InputStream;\n" +
96.876 + "public class Test {\n" +
96.877 + " private void t() throws Exception {\n" +
96.878 + " System.err.println(1);\n" +
96.879 + " lock();\n" +
96.880 + " System.err.println(2);\n" +
96.881 + " unlock();\n" +
96.882 + " System.err.println(3);\n" +
96.883 + " }\n" +
96.884 + " private static void lock() {}\n" +
96.885 + " private static void unlock() {}\n" +
96.886 + "}\n",
96.887 + "test.Test.lock(); $i$; test.Test.unlock(); => lock(); try { $i$; } finally { unlock(); }",
96.888 + "package test;\n" +
96.889 + "import java.io.InputStream;\n" +
96.890 + "public class Test {\n" +
96.891 + " private void t() throws Exception {\n" +
96.892 + " System.err.println(1);\n" +
96.893 + " lock();\n" +
96.894 + " try {\n" +
96.895 + " System.err.println(2);\n" +
96.896 + " } finally {\n" +
96.897 + " unlock();\n" +
96.898 + " }\n" +
96.899 + " System.err.println(3);\n" +
96.900 + " }\n" +
96.901 + " private static void lock() {}\n" +
96.902 + " private static void unlock() {}\n" +
96.903 + "}\n");
96.904 + }
96.905 +
96.906 + public void testOptimizeNegExpression() throws Exception {
96.907 + performRewriteTest("package test;\n" +
96.908 + "public class Test {\n" +
96.909 + " private static void t(int i) {\n" +
96.910 + " if (i == 0) {\n" +
96.911 + " System.err.println(1);\n" +
96.912 + " } else {\n" +
96.913 + " System.err.println(2);\n" +
96.914 + " }\n" +
96.915 + " }\n" +
96.916 + "}\n",
96.917 + "if ($cond) $then; else $else; => if (!$cond) $else; else $then;",
96.918 + "package test;\n" +
96.919 + "public class Test {\n" +
96.920 + " private static void t(int i) {\n" +
96.921 + " if (i != 0) {\n" +
96.922 + " System.err.println(2);\n" +
96.923 + " } else {\n" +
96.924 + " System.err.println(1);\n" +
96.925 + " }\n" +
96.926 + " }\n" +
96.927 + "}\n");
96.928 + }
96.929 +
96.930 + public void testDontOptimizeNegExpression() throws Exception {
96.931 + performRewriteTest("package test;\n" +
96.932 + "public class Test {\n" +
96.933 + " private static void t(int i) {\n" +
96.934 + " if (!(i == 0)) {\n" +
96.935 + " System.err.println(1);\n" +
96.936 + " } else {\n" +
96.937 + " System.err.println(2);\n" +
96.938 + " }\n" +
96.939 + " }\n" +
96.940 + "}\n",
96.941 + "if (!$cond) $then; else $else; => if (!$cond) $else; else $then;",
96.942 + "package test;\n" +
96.943 + "public class Test {\n" +
96.944 + " private static void t(int i) {\n" +
96.945 + " if (!(i == 0)) {\n" +
96.946 + " System.err.println(2);\n" +
96.947 + " } else {\n" +
96.948 + " System.err.println(1);\n" +
96.949 + " }\n" +
96.950 + " }\n" +
96.951 + "}\n");
96.952 + }
96.953 +
96.954 + public void testCannotOptimizeNegExpression() throws Exception {
96.955 + performRewriteTest("package test;\n" +
96.956 + "public class Test {\n" +
96.957 + " private static void t(String str) {\n" +
96.958 + " if (str.isEmpty()) {\n" +
96.959 + " System.err.println(1);\n" +
96.960 + " } else {\n" +
96.961 + " System.err.println(2);\n" +
96.962 + " }\n" +
96.963 + " }\n" +
96.964 + "}\n",
96.965 + "if ($cond) $then; else $else; => if (!$cond) $else; else $then;",
96.966 + "package test;\n" +
96.967 + "public class Test {\n" +
96.968 + " private static void t(String str) {\n" +
96.969 + " if (!str.isEmpty()) {\n" +
96.970 + " System.err.println(2);\n" +
96.971 + " } else {\n" +
96.972 + " System.err.println(1);\n" +
96.973 + " }\n" +
96.974 + " }\n" +
96.975 + "}\n");
96.976 + }
96.977 +
96.978 + public void testOptimizeNegExpressionNeg() throws Exception {
96.979 + performOptimizeNegExpressionTest("!s.isEmpty()", "s.isEmpty()");
96.980 + }
96.981 +
96.982 + public void testOptimizeNegExpressionParens() throws Exception {
96.983 + performOptimizeNegExpressionTest("(!(a.length == 0))", "a.length == 0");
96.984 + }
96.985 +
96.986 + public void testOptimizeNegExpressionEquals() throws Exception {
96.987 + performOptimizeNegExpressionTest("i == 0", "i != 0");
96.988 + }
96.989 +
96.990 + public void testOptimizeNegExpressionNotEquals() throws Exception {
96.991 + performOptimizeNegExpressionTest("i != 0", "i == 0");
96.992 + }
96.993 +
96.994 + public void testOptimizeNegExpressionTrue() throws Exception {
96.995 + performOptimizeNegExpressionTest("true", "false");
96.996 + }
96.997 +
96.998 + public void testOptimizeNegExpressionFalse() throws Exception {
96.999 + performOptimizeNegExpressionTest("false", "true");
96.1000 + }
96.1001 +
96.1002 + public void testOptimizeNegExpressionDeMorganAnd() throws Exception {
96.1003 + performOptimizeNegExpressionTest("a.length != 0 && true", "a.length == 0 || false");
96.1004 + }
96.1005 +
96.1006 + public void testOptimizeNegExpressionDeMorganOr() throws Exception {
96.1007 + performOptimizeNegExpressionTest("args.length != 0 || false", "args.length == 0 && true");
96.1008 + }
96.1009 +
96.1010 + public void testOptimizeNegExpressionLess() throws Exception {
96.1011 + performOptimizeNegExpressionTest("i < 0", "i >= 0");
96.1012 + }
96.1013 +
96.1014 + public void testOptimizeNegExpressionLessEq() throws Exception {
96.1015 + performOptimizeNegExpressionTest("i <= 0", "i > 0");
96.1016 + }
96.1017 +
96.1018 + public void testOptimizeNegExpressionGreater() throws Exception {
96.1019 + performOptimizeNegExpressionTest("i > 0", "i <= 0");
96.1020 + }
96.1021 +
96.1022 + public void testOptimizeNegExpressionGreaterEq() throws Exception {
96.1023 + performOptimizeNegExpressionTest("i >= 0", "i < 0");
96.1024 + }
96.1025 +
96.1026 + public void testOptimizeNegExpressionAnd() throws Exception {
96.1027 + performOptimizeNegExpressionTest("b1 && b2", "!b1 || !b2");
96.1028 + }
96.1029 +
96.1030 + private void performOptimizeNegExpressionTest(String origExpr, String newExpr) throws Exception {
96.1031 + performRewriteTest("package test;\n" +
96.1032 + "public class Test {\n" +
96.1033 + " private static void t(String s, int i, boolean b1, boolean b2, String... a) {\n" +
96.1034 + " if (" + origExpr + ") {\n" +
96.1035 + " System.err.println(1);\n" +
96.1036 + " } else {\n" +
96.1037 + " System.err.println(2);\n" +
96.1038 + " }\n" +
96.1039 + " }\n" +
96.1040 + "}\n",
96.1041 + "if ($cond) $then; else $else; => if (!$cond) $else; else $then;",
96.1042 + "package test;\n" +
96.1043 + "public class Test {\n" +
96.1044 + " private static void t(String s, int i, boolean b1, boolean b2, String... a) {\n" +
96.1045 + " if (" + newExpr + ") {\n" +
96.1046 + " System.err.println(2);\n" +
96.1047 + " } else {\n" +
96.1048 + " System.err.println(1);\n" +
96.1049 + " }\n" +
96.1050 + " }\n" +
96.1051 + "}\n");
96.1052 + }
96.1053 +
96.1054 + public void testExpression2ExpressionStatementTolerance227429() throws Exception {
96.1055 + performRewriteTest("package test;\n" +
96.1056 + "public class Test {\n" +
96.1057 + " private static void t() {\n" +
96.1058 + " System.err.println(1);\n" +
96.1059 + " }\n" +
96.1060 + "}\n",
96.1061 + "java.lang.System.err.println($args$) => java.lang.System.out.println($args$);",
96.1062 + "package test;\n" +
96.1063 + "public class Test {\n" +
96.1064 + " private static void t() {\n" +
96.1065 + " System.out.println(1);\n" +
96.1066 + " }\n" +
96.1067 + "}\n");
96.1068 + }
96.1069 +
96.1070 + public void testSplitIfOr() throws Exception {
96.1071 + performRewriteTest("package test;\n" +
96.1072 + "public class Test {\n" +
96.1073 + " private static void t(int i) {\n" +
96.1074 + " if (i == 0 || i == 1) {\n" +
96.1075 + " System.err.println();\n" +
96.1076 + " }\n" +
96.1077 + " }\n" +
96.1078 + "}\n",
96.1079 + "if ($cond1 || $cond2) $then; => if ($cond1) $then; else if ($cond2) $then;",
96.1080 + "package test;\n" +
96.1081 + "public class Test {\n" +
96.1082 + " private static void t(int i) {\n" +
96.1083 + " if (i == 0) {\n" +
96.1084 + " System.err.println();\n" +
96.1085 + " } else if (i == 1) {\n" +
96.1086 + " System.err.println();\n" +
96.1087 + " }\n" +
96.1088 + " }\n" +
96.1089 + "}\n");
96.1090 + }
96.1091 +
96.1092 + public void testLambdaExpr2Block() throws Exception {
96.1093 + performRewriteTest("package test;\n" +
96.1094 + "import java.util.*;\n" +
96.1095 + "public class Test {\n" +
96.1096 + " public void main(List<String> list) {\n" +
96.1097 + " Collections.sort(list, (l, r) -> l.compareTo(r));\n" +
96.1098 + " }\n" +
96.1099 + "}\n",
96.1100 + "($args$) -> $expr => ($args$) -> { return $expr; }",
96.1101 + "package test;\n" +
96.1102 + "import java.util.*;\n" +
96.1103 + "public class Test {\n" +
96.1104 + " public void main(List<String> list) {\n" +
96.1105 + " Collections.sort(list, (l, r) -> {\n" +
96.1106 + " return l.compareTo(r);\n" +
96.1107 + " });\n" +
96.1108 + " }\n" +
96.1109 + "}\n");
96.1110 + }
96.1111 +
96.1112 + public void performRewriteTest(String code, String rule, String golden) throws Exception {
96.1113 + prepareTest("test/Test.java", code);
96.1114 +
96.1115 + final String[] split = rule.split("=>");
96.1116 + assertEquals(2, split.length);
96.1117 + Map<String, TypeMirror> variablesToTypesTM = new HashMap<String, TypeMirror>();
96.1118 + String plainRule = PatternCompilerUtilities.parseOutTypesFromPattern(info, split[0], variablesToTypesTM);
96.1119 + Map<String, String> variablesToTypes = new HashMap<String, String>();
96.1120 + for (Entry<String, TypeMirror> e : variablesToTypesTM.entrySet()) {
96.1121 + if (e.getValue() == null) continue;
96.1122 + variablesToTypes.put(e.getKey(), e.getValue().toString());
96.1123 + }
96.1124 + HintDescription hd = HintDescriptionFactory.create()
96.1125 + .setTrigger(PatternDescription.create(plainRule, variablesToTypes))
96.1126 + .setWorker(new HintDescription.Worker() {
96.1127 + @Override public Collection<? extends ErrorDescription> createErrors(HintContext ctx) {
96.1128 + return Collections.singletonList(ErrorDescriptionFactory.forName(ctx, ctx.getPath(), "", JavaFixUtilities.rewriteFix(ctx, "", ctx.getPath(), split[1])));
96.1129 + }
96.1130 + }).produce();
96.1131 +
96.1132 + List<ErrorDescription> computeHints = new HintsInvoker(HintsSettings.getGlobalSettings(), new AtomicBoolean()).computeHints(info, Collections.singleton(hd));
96.1133 +
96.1134 + assertEquals(computeHints.toString(), 1, computeHints.size());
96.1135 +
96.1136 + Fix fix = computeHints.get(0).getFixes().getFixes().get(0);
96.1137 +
96.1138 + fix.implement();
96.1139 +
96.1140 + assertEquals(golden, doc.getText(0, doc.getLength()));
96.1141 + }
96.1142 +
96.1143 + public void performRemoveFromParentTest(String code, String rule, String golden) throws Exception {
96.1144 + prepareTest("test/Test.java", code);
96.1145 +
96.1146 + HintDescription hd = HintDescriptionFactory.create()
96.1147 + .setTrigger(PatternDescription.create(rule, Collections.<String, String>emptyMap()))
96.1148 + .setWorker(new HintDescription.Worker() {
96.1149 + @Override public Collection<? extends ErrorDescription> createErrors(HintContext ctx) {
96.1150 + return Collections.singletonList(ErrorDescriptionFactory.forName(ctx, ctx.getPath(), "", JavaFixUtilities.removeFromParent(ctx, "", ctx.getPath())));
96.1151 + }
96.1152 + }).produce();
96.1153 +
96.1154 + List<ErrorDescription> computeHints = new HintsInvoker(HintsSettings.getGlobalSettings(), new AtomicBoolean()).computeHints(info, Collections.singleton(hd));
96.1155 +
96.1156 + assertEquals(computeHints.toString(), 1, computeHints.size());
96.1157 +
96.1158 + Fix fix = computeHints.get(0).getFixes().getFixes().get(0);
96.1159 +
96.1160 + fix.implement();
96.1161 +
96.1162 + assertEquals(golden, doc.getText(0, doc.getLength()));
96.1163 + }
96.1164 +}
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
97.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/spi/java/hints/MatcherUtilitiesTest.java Wed May 08 21:47:42 2013 +0200
97.3 @@ -0,0 +1,113 @@
97.4 +/*
97.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
97.6 + *
97.7 + * Copyright 2009-2010 Oracle and/or its affiliates. All rights reserved.
97.8 + *
97.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
97.10 + * Other names may be trademarks of their respective owners.
97.11 + *
97.12 + * The contents of this file are subject to the terms of either the GNU
97.13 + * General Public License Version 2 only ("GPL") or the Common
97.14 + * Development and Distribution License("CDDL") (collectively, the
97.15 + * "License"). You may not use this file except in compliance with the
97.16 + * License. You can obtain a copy of the License at
97.17 + * http://www.netbeans.org/cddl-gplv2.html
97.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
97.19 + * specific language governing permissions and limitations under the
97.20 + * License. When distributing the software, include this License Header
97.21 + * Notice in each file and include the License file at
97.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
97.23 + * particular file as subject to the "Classpath" exception as provided
97.24 + * by Oracle in the GPL Version 2 section of the License file that
97.25 + * accompanied this code. If applicable, add the following below the
97.26 + * License Header, with the fields enclosed by brackets [] replaced by
97.27 + * your own identifying information:
97.28 + * "Portions Copyrighted [year] [name of copyright owner]"
97.29 + *
97.30 + * If you wish your version of this file to be governed by only the CDDL
97.31 + * or only the GPL Version 2, indicate your decision by adding
97.32 + * "[Contributor] elects to include this software in this distribution
97.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
97.34 + * single choice of license, a recipient has the option to distribute
97.35 + * your version of this file under either the CDDL, the GPL Version 2 or
97.36 + * to extend the choice of license to its licensees as provided above.
97.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
97.38 + * Version 2 license, then the option applies only if the new code is
97.39 + * made subject to such option by the copyright holder.
97.40 + *
97.41 + * Contributor(s):
97.42 + *
97.43 + * Portions Copyrighted 2009-2010 Sun Microsystems, Inc.
97.44 + */
97.45 +
97.46 +package org.netbeans.spi.java.hints;
97.47 +
97.48 +import com.sun.source.util.TreePath;
97.49 +import java.util.Collection;
97.50 +import java.util.Collections;
97.51 +import java.util.HashMap;
97.52 +import java.util.Map;
97.53 +import java.util.regex.Pattern;
97.54 +import org.netbeans.modules.java.hints.spiimpl.SPIAccessor;
97.55 +import org.netbeans.modules.java.hints.spiimpl.TestBase;
97.56 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
97.57 +
97.58 +/**
97.59 + *
97.60 + * @author lahvac
97.61 + */
97.62 +public class MatcherUtilitiesTest extends TestBase {
97.63 +
97.64 + public MatcherUtilitiesTest(String name) {
97.65 + super(name);
97.66 + }
97.67 +
97.68 + public void testParentMatches1() throws Exception {
97.69 + String code = "package test; public class Test { private int test() { int i = 0; i = test(|); } }";
97.70 + int pos = code.indexOf("|");
97.71 +
97.72 + code = code.replaceAll(Pattern.quote("|"), "");
97.73 +
97.74 + prepareTest("test/Test.java", code);
97.75 +
97.76 + TreePath tp = info.getTreeUtilities().pathFor(pos);
97.77 + HintContext ctx = SPIAccessor.getINSTANCE().createHintContext(info, HintsSettings.getGlobalSettings(), null, tp, Collections.<String, TreePath>emptyMap(), Collections.<String, Collection<? extends TreePath>>emptyMap(), Collections.<String, String>emptyMap());
97.78 +
97.79 + assertTrue(MatcherUtilities.matches(ctx, ctx.getPath().getParentPath(), "$0 = $_"));
97.80 + }
97.81 +
97.82 + public void testParentMatches2() throws Exception {
97.83 + String code = "package test; public class Test { private int test() { int i = test(|); } }";
97.84 + int pos = code.indexOf("|");
97.85 +
97.86 + code = code.replaceAll(Pattern.quote("|"), "");
97.87 +
97.88 + prepareTest("test/Test.java", code);
97.89 +
97.90 + TreePath tp = info.getTreeUtilities().pathFor(pos);
97.91 + HintContext ctx = SPIAccessor.getINSTANCE().createHintContext(info, HintsSettings.getGlobalSettings(), null, tp, Collections.<String, TreePath>emptyMap(), Collections.<String, Collection<? extends TreePath>>emptyMap(), Collections.<String, String>emptyMap());
97.92 +
97.93 + assertTrue(MatcherUtilities.matches(ctx, ctx.getPath().getParentPath(), "$1 $0 = $_;"));
97.94 + }
97.95 +
97.96 + public void testOutVariables1() throws Exception {
97.97 + String code = "package test; public class Test { private int test() { int i = test(|); } }";
97.98 + int pos = code.indexOf("|");
97.99 +
97.100 + code = code.replaceAll(Pattern.quote("|"), "");
97.101 +
97.102 + prepareTest("test/Test.java", code);
97.103 +
97.104 + TreePath tp = info.getTreeUtilities().pathFor(pos);
97.105 + HintContext ctx = SPIAccessor.getINSTANCE().createHintContext(info, HintsSettings.getGlobalSettings(), null, tp, Collections.<String, TreePath>emptyMap(), Collections.<String, Collection<? extends TreePath>>emptyMap(), Collections.<String, String>emptyMap());
97.106 +
97.107 + Map<String, TreePath> outVariables = new HashMap<String, TreePath>();
97.108 + Map<String, Collection<? extends TreePath>> outMultiVariables = new HashMap<String, Collection<? extends TreePath>>();
97.109 + Map<String, String> outVariables2Names = new HashMap<String, String>();
97.110 +
97.111 + assertTrue(MatcherUtilities.matches(ctx, ctx.getPath().getParentPath(), "$1 $0 = $_;", outVariables, outMultiVariables, outVariables2Names));
97.112 + assertEquals("int", outVariables.get("$1").getLeaf().toString());
97.113 + assertEquals("i", outVariables2Names.get("$0"));
97.114 + }
97.115 +
97.116 +}
97.117 \ No newline at end of file
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
98.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/spi/java/hints/matching/CopyFinderTest.java Wed May 08 21:47:42 2013 +0200
98.3 @@ -0,0 +1,1583 @@
98.4 +/*
98.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
98.6 + *
98.7 + * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
98.8 + *
98.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
98.10 + * Other names may be trademarks of their respective owners.
98.11 + *
98.12 + * The contents of this file are subject to the terms of either the GNU
98.13 + * General Public License Version 2 only ("GPL") or the Common
98.14 + * Development and Distribution License("CDDL") (collectively, the
98.15 + * "License"). You may not use this file except in compliance with the
98.16 + * License. You can obtain a copy of the License at
98.17 + * http://www.netbeans.org/cddl-gplv2.html
98.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
98.19 + * specific language governing permissions and limitations under the
98.20 + * License. When distributing the software, include this License Header
98.21 + * Notice in each file and include the License file at
98.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
98.23 + * particular file as subject to the "Classpath" exception as provided
98.24 + * by Oracle in the GPL Version 2 section of the License file that
98.25 + * accompanied this code. If applicable, add the following below the
98.26 + * License Header, with the fields enclosed by brackets [] replaced by
98.27 + * your own identifying information:
98.28 + * "Portions Copyrighted [year] [name of copyright owner]"
98.29 + *
98.30 + * Contributor(s):
98.31 + *
98.32 + * Portions Copyrighted 2007-2010 Sun Microsystems, Inc.
98.33 + */
98.34 +package org.netbeans.spi.java.hints.matching;
98.35 +
98.36 +import com.sun.source.tree.BlockTree;
98.37 +import com.sun.source.tree.StatementTree;
98.38 +import com.sun.source.tree.Tree;
98.39 +import com.sun.source.tree.VariableTree;
98.40 +import com.sun.source.util.SourcePositions;
98.41 +import com.sun.source.util.TreePath;
98.42 +import com.sun.source.util.TreePathScanner;
98.43 +import java.io.File;
98.44 +import java.util.Arrays;
98.45 +import java.util.Collection;
98.46 +import java.util.Collections;
98.47 +import java.util.EnumSet;
98.48 +import java.util.HashMap;
98.49 +import java.util.HashSet;
98.50 +import java.util.LinkedList;
98.51 +import java.util.List;
98.52 +import java.util.Map;
98.53 +import java.util.Map.Entry;
98.54 +import java.util.Set;
98.55 +import java.util.concurrent.atomic.AtomicBoolean;
98.56 +import javax.lang.model.element.VariableElement;
98.57 +import javax.lang.model.type.TypeMirror;
98.58 +import javax.swing.text.Document;
98.59 +import org.netbeans.api.java.lexer.JavaTokenId;
98.60 +import org.netbeans.api.java.source.CompilationInfo;
98.61 +import org.netbeans.api.java.source.JavaSource;
98.62 +import org.netbeans.api.java.source.JavaSource.Phase;
98.63 +import org.netbeans.api.java.source.SourceUtilsTestUtil;
98.64 +import org.netbeans.api.java.source.TestUtilities;
98.65 +import org.netbeans.api.java.source.TreePathHandle;
98.66 +import org.netbeans.api.java.source.matching.MatchingTestAccessor;
98.67 +import org.netbeans.api.java.source.matching.Pattern;
98.68 +import org.netbeans.api.lexer.Language;
98.69 +import org.netbeans.junit.NbTestCase;
98.70 +import org.netbeans.modules.java.hints.introduce.IntroduceHint;
98.71 +import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch;
98.72 +import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch.BulkPattern;
98.73 +import org.netbeans.modules.java.hints.spiimpl.pm.PatternCompiler;
98.74 +import org.netbeans.modules.java.hints.spiimpl.pm.PatternCompilerUtilities;
98.75 +import org.netbeans.modules.java.source.matching.CopyFinder;
98.76 +import org.netbeans.modules.java.source.matching.CopyFinder.Cancel;
98.77 +import org.netbeans.modules.java.source.matching.CopyFinder.Options;
98.78 +import org.netbeans.modules.java.source.matching.CopyFinder.VariableAssignments;
98.79 +import org.openide.cookies.EditorCookie;
98.80 +import org.openide.filesystems.FileObject;
98.81 +import org.openide.filesystems.FileUtil;
98.82 +import org.openide.loaders.DataObject;
98.83 +
98.84 +/**
98.85 + *
98.86 + * @author Jan Lahoda
98.87 + */
98.88 +public class CopyFinderTest extends NbTestCase {
98.89 +
98.90 + public CopyFinderTest(String testName) {
98.91 + super(testName);
98.92 + }
98.93 +
98.94 +// public static TestSuite suite() {
98.95 +// NbTestSuite nb = new NbTestSuite();
98.96 +//
98.97 +// nb.addTest(new CopyFinderTest("testCorrectSite3"));
98.98 +//
98.99 +// return nb;
98.100 +// }
98.101 +
98.102 + @Override
98.103 + protected void setUp() throws Exception {
98.104 + SourceUtilsTestUtil.prepareTest(new String[0], new Object[0]);
98.105 + super.setUp();
98.106 + }
98.107 +
98.108 + public void testSimple1() throws Exception {
98.109 + performTest("package test; public class Test {public void test() {int i = 0; y = i + i; y = i + i;}}", 90 - 22, 95 - 22, 101 - 22, 106 - 22);
98.110 + }
98.111 +
98.112 +// public void testSimple2() throws Exception {
98.113 +// performTest("package test; public class Test {public void test() {int i = 0; y = i + i; y = i + i + i;}}", 90 - 22, 95 - 22, 101 - 22, 106 - 22);
98.114 +// }
98.115 +
98.116 + public void testSimple3() throws Exception {
98.117 + performTest("package test; public class Test {public void test() {int i = System.currentTimeMillis(); y = System.currentTimeMillis();}}", 83 - 22, 109 - 22, 115 - 22, 141 - 22);
98.118 + }
98.119 +
98.120 + public void testSimple4() throws Exception {
98.121 + performTest("package test; import java.util.ArrayList; public class Test {public void test() {Object o = new ArrayList<String>();o = new ArrayList<String>();}}", 114 - 22, 137- 22, 142 - 22, 165 - 22);
98.122 + }
98.123 +
98.124 + public void testSimple5() throws Exception {
98.125 + performTest("package test; public class Test {public void test() {Object o = null; String s = (String) o; s = (String) o; s = (String) null; o = (Object) o;}}", 103 - 22, 113 - 22, 119 - 22, 129 - 22);
98.126 + }
98.127 +
98.128 + public void testSimple6() throws Exception {
98.129 + performTest("package test; public class Test {public void test() {int i = 0; y = i + i; y = i + i;} public void test2() {int i = 0; y = i + i; y = i + i;}}", 90 - 22, 95 - 22, 101 - 22, 106 - 22);
98.130 + }
98.131 +
98.132 + public void testSimple7() throws Exception {
98.133 + performTest("package test; public class Test {public void test() {int i = 0; y = i != 0 ? i + i : i * i; y = i != 0 ? i + i : i * i; y = i != 1 ? i + i : i * i; y = i == 0 ? i + i : i * i; y = i != 0 ? i * i : i * i; y = i != 0 ? i + i : i + i; y = i != 0 ? i + i : i * 1;}}", 90 - 22, 112 - 22, 118 - 22, 140 - 22);
98.134 + }
98.135 +
98.136 + public void testSimple8() throws Exception {
98.137 + performTest("package test; public class Test {public void test() {int i = 0; int y = -i; y = -i; y = +i; y = +y;}}", 94 - 22, 96 - 22, 102 - 22, 104 - 22);
98.138 + }
98.139 +
98.140 + public void testSimple9() throws Exception {
98.141 + performTest("package test; public class Test {public void test() {int i = 0; int y = i *= 9; y = i *= 9; y = i /= 9; y = i *= 8; y = y *= 9;}}", 94 - 22, 100 - 22, 106 - 22, 112 - 22);
98.142 + }
98.143 +
98.144 + public void testSimple10() throws Exception {
98.145 + performTest("package test; public class Test {public void test() {int[] i = null; int y = i[1]; y = i[1]; y = i[y]; y = i[0];}}", 99 - 22, 103 - 22, 109 - 22, 113 - 22);
98.146 + }
98.147 +
98.148 + public void testSimple11() throws Exception {
98.149 + performTest("package test; public class Test {public void test() {int[] i = new int[0]; i = new int[0]; i = new int[1];}}", 85 - 22, 95 - 22, 101 - 22, 111 - 22);
98.150 + }
98.151 +
98.152 + public void testSimple12() throws Exception {
98.153 + performTest("package test; public class Test {public void test() {int[] i = new int[1]; i = new int[1]; i = new int[0];}}", 85 - 22, 95 - 22, 101 - 22, 111 - 22);
98.154 + }
98.155 +
98.156 + public void testSimple13() throws Exception {
98.157 + performTest("package test; public class Test {public void test() {int i = 0; int y = (i); y = (i); y = i;}}", 94 - 22, 97 - 22, 103 - 22, 106 - 22);
98.158 + }
98.159 +
98.160 + public void testSimple14() throws Exception {
98.161 + performTest("package test; public class Test {public void test() {Object o = null; boolean b = o instanceof String; b = o instanceof String; b = o instanceof Object;}}", 104 - 22, 123 - 22, 129 - 22, 148 - 22);
98.162 + }
98.163 +
98.164 + public void testSimple15() throws Exception {
98.165 + performTest("package test; public class Test {private int x = 1; private int y = 1; public void test() {int x = 1; int y = 1;}}", 90 - 22, 91 - 22, 71 - 22, 72 - 22, 121 - 22, 122 - 22, 132 - 22, 133 - 22);
98.166 + }
98.167 +
98.168 + public void testSimple16() throws Exception {
98.169 + performTest("package test; public class Test {public void test(int i) {int y = \"\".length(); test(\"\".length());} }", 88 - 22, 99 - 22, 106 - 22, 117 - 22);
98.170 + }
98.171 +
98.172 + public void testSimple17() throws Exception {
98.173 + performTest("package test; public class Test {public void test2() {int a = test(test(test(1))); a = test(test(test(1))); a = test(test(test(1)));} public int test(int i) {return 0;} }", 94 - 22, 101 - 22, 119 - 22, 126 - 22, 144 - 22, 151 - 22);
98.174 + }
98.175 +
98.176 + public void testMemberSelectAndIdentifierAreSame() throws Exception {
98.177 + performTest("package test; import static java.lang.String.*; public class Test {public void test1() {|String.valueOf(2)|; |valueOf(2)|;} }");
98.178 + }
98.179 +
98.180 + public void testVariables1() throws Exception {
98.181 + performVariablesTest("package test; import static java.lang.String.*; public class Test {public void test1() {String.valueOf(2+4);} }",
98.182 + "java.lang.String.valueOf($1)",
98.183 + new Pair[] {new Pair<String, int[]>("$1", new int[] {134 - 31, 137 - 31})},
98.184 + new Pair[0]);
98.185 + }
98.186 +
98.187 + public void testAssert1() throws Exception {
98.188 + performTest("package test; public class Test {public void test() {int i = 0; |assert i == 1;| |assert i == 1;|}}");
98.189 + }
98.190 +
98.191 + public void testReturn1() throws Exception {
98.192 + performTest("package test; public class Test {public int test1() {|return 1;|} public int test2() {|return 1;|}}");
98.193 + }
98.194 +
98.195 + public void testIf1() throws Exception {
98.196 + performTest("package test; public class Test {public void test() { int i = 0; int j; |if (i == 0) {j = 1;} else {j = 2;}| |if (i == 0) {j = 1;} else {j = 2;}| } }");
98.197 + }
98.198 +
98.199 + public void testExpressionStatement1() throws Exception {
98.200 + performTest("package test; public class Test {public void test() { int i = 0; |i = 1;| |i = 1;| } }");
98.201 + }
98.202 +
98.203 + public void testBlock1() throws Exception {
98.204 + performTest("package test; public class Test {public void test() { int i = 0; |{i = 1;}| |{i = 1;}| } }");
98.205 + }
98.206 +
98.207 + public void testSynchronized1() throws Exception {
98.208 + performTest("package test; public class Test {public void test() { Object o = null; int i = 0; |synchronized (o) {i = 1;}| |synchronized (o) {i = 1;}| } }");
98.209 + }
98.210 +
98.211 +// public void testEnhancedForLoop() throws Exception {
98.212 +// performTest("package test; public class Test {public void test(Iterable<String> i) { |for (String s : i) { System.err.println(); }| |for (String s : i) { System.err.println(); }| }");
98.213 +// }
98.214 +
98.215 +// public void testConstants() throws Exception {
98.216 +// performTest("package test; public class Test {public static final int A = 3; public void test() { int i = |3|; i = |test.Test.A|; } }");
98.217 +// }
98.218 +
98.219 + public void testOverridingImplementing1() throws Exception {
98.220 + performVariablesTest("package test; public class Test implements Runnable { { this.run(); } public void run() { } } }",
98.221 + "$0{java.lang.Runnable}.run()",
98.222 + new Pair[] {new Pair<String, int[]>("$0", new int[] {56, 60})},
98.223 + new Pair[0]);
98.224 + }
98.225 +
98.226 + public void testMemberSelectCCE() throws Exception {
98.227 + //should not throw a CCE
98.228 + //(selected regions are not duplicates)
98.229 + performTest("package test; public class Test {public static class T extends Test { public void test() { |Test.test|(); |System.err.println|(); } } }", false);
98.230 + }
98.231 +
98.232 + public void testLocalVariable() throws Exception {
98.233 + performVariablesTest("package test; public class Test {public void test1() { { int y; y = 1; } int z; { int y; z = 1; } } }",
98.234 + "{ int $1; $1 = 1; }",
98.235 + new Pair[0],
98.236 + new Pair[] {new Pair<String, String>("$1", "y")});
98.237 + }
98.238 +
98.239 + public void testStatementAndSingleBlockStatementAreSame1() throws Exception {
98.240 + performVariablesTest("package test; public class Test {public void test1() { { int x; { x = 1; } } } }",
98.241 + "{ int $1; $1 = 1; }",
98.242 + new Pair[0],
98.243 + new Pair[] {new Pair<String, String>("$1", "x")});
98.244 + }
98.245 +
98.246 + public void testStatementAndSingleBlockStatementAreSame2() throws Exception {
98.247 + performVariablesTest("package test; public class Test {public void test1() { { int x; x = 1; } } }",
98.248 + "{ int $1; { $1 = 1; } }",
98.249 + new Pair[0],
98.250 + new Pair[] {new Pair<String, String>("$1", "x")});
98.251 + }
98.252 +
98.253 + public void testStatementVariables() throws Exception {
98.254 + performVariablesTest("package test; public class Test {public int test1() { if (true) return 1; else return 2; } }",
98.255 + "if ($1) $2; else $3;",
98.256 + new Pair[] {
98.257 + new Pair<String, int[]>("$1", new int[] {89 - 31, 93 - 31}),
98.258 + new Pair<String, int[]>("$2", new int[] {95 - 31, 104 - 31}),
98.259 + new Pair<String, int[]>("$3", new int[] {110 - 31, 119 - 31})
98.260 + },
98.261 + new Pair[0]);
98.262 + }
98.263 +
98.264 + public void testThrowStatement() throws Exception {
98.265 + performVariablesTest("package test; public class Test {public void test() { throw new NullPointerException(); throw new IllegalStateException();} }",
98.266 + "throw new NullPointerException()",
98.267 + new Pair[0],
98.268 + new Pair[0]);
98.269 + }
98.270 +
98.271 + public void testMultiStatementVariables1() throws Exception {
98.272 + performVariablesTest("package test; public class Test { public int test1() { System.err.println(); System.err.println(); int i = 3; System.err.println(i); System.err.println(i); return i; } }",
98.273 + "{ $s1$; int $i = 3; $s2$; return $i; }",
98.274 + new Pair[0],
98.275 + new Pair[] {
98.276 + new Pair<String, int[]>("$s1$", new int[] {55, 76, 77, 98}),
98.277 + new Pair<String, int[]>("$s2$", new int[] {110, 132, 133, 155})
98.278 + },
98.279 + new Pair[] {new Pair<String, String>("$i", "i")});
98.280 + }
98.281 +
98.282 + public void testMultiStatementVariables2() throws Exception {
98.283 + performVariablesTest("package test; public class Test { public int test1() { int i = 3; return i; } }",
98.284 + "{ $s1$; int $i = 3; $s2$; return $i; }",
98.285 + new Pair[0],
98.286 + new Pair[] {
98.287 + new Pair<String, int[]>("$s1$", new int[] {}),
98.288 + new Pair<String, int[]>("$s2$", new int[] {}),
98.289 + },
98.290 + new Pair[] {new Pair<String, String>("$i", "i")});
98.291 + }
98.292 +
98.293 + public void testMultiStatementVariablesAndBlocks1() throws Exception {
98.294 + performVariablesTest("package test; public class Test { public void test1() { if (true) System.err.println(); } }",
98.295 + "if ($c) {$s1$; System.err.println(); $s2$; }",
98.296 + new Pair[] {new Pair<String, int[]>("$c", new int[] {60, 64})},
98.297 + new Pair[] {
98.298 + new Pair<String, int[]>("$s1$", new int[] {}),
98.299 + new Pair<String, int[]>("$s2$", new int[] {}),
98.300 + },
98.301 + new Pair[0]);
98.302 + }
98.303 +
98.304 + public void testMultiStatementVariablesAndBlocks2() throws Exception {
98.305 + performVariablesTest("package test; public class Test { public void test1() { if (true) System.err.println(); } }",
98.306 + "if ($c) {$s1$; System.err.println(); }",
98.307 + new Pair[] {new Pair<String, int[]>("$c", new int[] {60, 64})},
98.308 + new Pair[] {
98.309 + new Pair<String, int[]>("$s1$", new int[] {}),
98.310 + },
98.311 + new Pair[0]);
98.312 + }
98.313 +
98.314 + public void testMultiStatementVariablesAndBlocks3() throws Exception {
98.315 + performVariablesTest("package test; public class Test { public void test1() { if (true) System.err.println(); } }",
98.316 + "if ($c) {System.err.println(); $s2$; }",
98.317 + new Pair[] {new Pair<String, int[]>("$c", new int[] {60, 64})},
98.318 + new Pair[] {
98.319 + new Pair<String, int[]>("$s2$", new int[] {}),
98.320 + },
98.321 + new Pair[0]);
98.322 + }
98.323 +
98.324 + public void testMultiStatementVariablesAndBlocks4() throws Exception {
98.325 + performVariablesTest("package test; public class Test { public void test1() { if (true) System.err.println(); } }",
98.326 + "if ($c) { $s$; }",
98.327 + new Pair[] {new Pair<String, int[]>("$c", new int[] {60, 64})},
98.328 + new Pair[] {
98.329 + new Pair<String, int[]>("$s$", new int[] {66, 87}),
98.330 + },
98.331 + new Pair[0]);
98.332 + }
98.333 +
98.334 + public void testVariableVerification() throws Exception {
98.335 + performVariablesTest("package test; public class Test { public void test1(String[] a, String[] b) { for (int c = 0; c < a.length; c++) { String s = b[c]; System.err.println(s); } } }",
98.336 + "for(int $i = 0; $i < $array.length; $i++) { $T $var = $array[$i]; $stmts$; }",
98.337 + new Pair[0],
98.338 + new Pair[0],
98.339 + new Pair[0],
98.340 + true);
98.341 + }
98.342 +
98.343 + public void testFor() throws Exception {
98.344 + performVariablesTest("package test; public class Test { public void test1(String[] a) { for (int c = 0; c < a.length; c++) { String s = a[c]; System.err.println(s); } } }",
98.345 + "for(int $i = 0; $i < $array.length; $i++) { $T $var = $array[$i]; $stmts$; }",
98.346 + new Pair[] {
98.347 + new Pair<String, int[]>("$array", new int[] {117 - 31, 118 - 31}),
98.348 + new Pair<String, int[]>("$T", new int[] {134 - 31, 140 - 31}),
98.349 + },
98.350 + new Pair[] {
98.351 + new Pair<String, int[]>("$stmts$", new int[] {151 - 31, 173 - 31}),
98.352 + },
98.353 + new Pair[] {
98.354 + new Pair<String, String>("$i", "c"),
98.355 + new Pair<String, String>("$var", "s"),
98.356 + });
98.357 + }
98.358 +
98.359 + public void testEnhancedFor() throws Exception {
98.360 + performVariablesTest("package test; public class Test { public void test1(String[] a) { for (String s : a) { System.err.println(s); } } }",
98.361 + "for($T $var : $array) { $stmts$; }",
98.362 + new Pair[] {
98.363 + new Pair<String, int[]>("$array", new int[] {113 - 31, 114 - 31}),
98.364 + new Pair<String, int[]>("$T", new int[] {102 - 31, 108 - 31}),
98.365 + },
98.366 + new Pair[] {
98.367 + new Pair<String, int[]>("$stmts$", new int[] {118 - 31, 140 - 31}),
98.368 + },
98.369 + new Pair[] {
98.370 + new Pair<String, String>("$var", "s"),
98.371 + });
98.372 + }
98.373 +
98.374 + public void testWhile() throws Exception {
98.375 + performVariablesTest("package test; public class Test { public void test1(String[] a) { int c = 0; while (c < a.length) { String s = a[c]; System.err.println(s); c++; } } }",
98.376 + "while ($i < $array.length) { $T $var = $array[$i]; $stmts$; $i++; }",
98.377 + new Pair[] {
98.378 + new Pair<String, int[]>("$array", new int[] {120 - 31, 121 - 31}),
98.379 + new Pair<String, int[]>("$T", new int[] {132 - 31, 138 - 31}),
98.380 + new Pair<String, int[]>("$i", new int[] {116 - 31, 117 - 31}),
98.381 + },
98.382 + new Pair[] {
98.383 + new Pair<String, int[]>("$stmts$", new int[] {149 - 31, 171 - 31}),
98.384 + },
98.385 + new Pair[] {
98.386 + new Pair<String, String>("$var", "s"),
98.387 + });
98.388 + }
98.389 +
98.390 + public void testDoWhile() throws Exception {
98.391 + performVariablesTest("package test; public class Test { public void test1(String[] a) { int c = 0; do { String s = a[c]; System.err.println(s); c++; } while (c < a.length); } }",
98.392 + "do { $T $var = $array[$i]; $stmts$; $i++; } while ($i < $array.length);",
98.393 + new Pair[] {
98.394 + new Pair<String, int[]>("$array", new int[] {124 - 31, 125 - 31}),
98.395 + new Pair<String, int[]>("$T", new int[] {113 - 31, 119 - 31}),
98.396 + new Pair<String, int[]>("$i", new int[] {126 - 31, 127 - 31}),
98.397 + },
98.398 + new Pair[] {
98.399 + new Pair<String, int[]>("$stmts$", new int[] {130 - 31, 152 - 31}),
98.400 + },
98.401 + new Pair[] {
98.402 + new Pair<String, String>("$var", "s"),
98.403 + });
98.404 + }
98.405 +
98.406 + public void testArrayType() throws Exception {
98.407 + performVariablesTest("package test; public class Test { public void test1() { int[][] a; } }",
98.408 + "$T[]",
98.409 + new Pair[] {
98.410 + new Pair<String, int[]>("$T", new int[] {87 - 31, /*92*//*XXX:*/94 - 31}),
98.411 + },
98.412 + new Pair[0],
98.413 + new Pair[0]);
98.414 + }
98.415 +
98.416 + public void testSemiMatchPackage() throws Exception {
98.417 + performVariablesTest("package test; import javax.lang.model.type.TypeMirror; public class Test { }",
98.418 + "$T{java.lang.Object}.type",
98.419 + new Pair[0],
98.420 + new Pair[0],
98.421 + new Pair[0],
98.422 + true);
98.423 + }
98.424 +
98.425 + public void testNullType() throws Exception {
98.426 + performVariablesTest("package javax.lang.model.type; public class Test { }",
98.427 + "$T{java.lang.Object}.type",
98.428 + new Pair[0],
98.429 + new Pair[0],
98.430 + new Pair[0],
98.431 + true);
98.432 + }
98.433 +
98.434 + public void testTryCatch() throws Exception {
98.435 + performVariablesTest("package test; import java.io.*; public class Test { public void test() { InputStream ins = null; try { ins = new FileInputStream(\"\"); } catch (IOException e) { e.printStackTrace(); } finally {ins.close();} } }",
98.436 + "try {$stmts$;} catch (java.io.IOException $e) {$e.printStackTrace();} finally {$finally$;}",
98.437 + new Pair[] {
98.438 + new Pair<String, int[]>("$e", new int[] {176 - 31 - 2, 189 - 31 - 2}),
98.439 + },
98.440 + new Pair[] {
98.441 + new Pair<String, int[]>("$stmts$", new int[] {134 - 31, 166 - 31 - 2}),
98.442 + new Pair<String, int[]>("$finally$", new int[] {225 - 31 - 2, 237 - 31 - 2}),
98.443 + },
98.444 + new Pair[] {
98.445 + new Pair<String, String>("$e", "e"),
98.446 + });
98.447 + }
98.448 +
98.449 + public void testMultiParameters1() throws Exception {
98.450 + performVariablesTest("package test; public class Test { { java.util.Arrays.asList(\"a\", \"b\", \"c\"); }",
98.451 + "java.util.Arrays.asList($1$)",
98.452 + new Pair[] {
98.453 + },
98.454 + new Pair[] {
98.455 + new Pair<String, int[]>("$1$", new int[] {60, 63, 65, 68, 70, 73}),
98.456 + },
98.457 + new Pair[] {
98.458 + });
98.459 + }
98.460 +
98.461 + public void testMultiParameters2() throws Exception {
98.462 + performVariablesTest("package test; public class Test { { java.util.Arrays.asList(new String(\"a\"), \"b\", \"c\"); }",
98.463 + "java.util.Arrays.asList(new String(\"a\"), $1$)",
98.464 + new Pair[] {
98.465 + },
98.466 + new Pair[] {
98.467 + new Pair<String, int[]>("$1$", new int[] {77, 80, 82, 85}),
98.468 + },
98.469 + new Pair[] {
98.470 + });
98.471 + }
98.472 +
98.473 + public void testMultiParameters3() throws Exception {
98.474 + performVariablesTest("package test; public class Test { { java.util.Arrays.asList(); }",
98.475 + "java.util.Arrays.asList($1$)",
98.476 + new Pair[] {
98.477 + },
98.478 + new Pair[] {
98.479 + new Pair<String, int[]>("$1$", new int[] {}),
98.480 + },
98.481 + new Pair[] {
98.482 + });
98.483 + }
98.484 +
98.485 + public void testTypeParameters() throws Exception {
98.486 + performVariablesTest("package test; public class Test { { java.util.Arrays.<String>asList(\"a\", \"b\"); }",
98.487 + "java.util.Arrays.<$1>asList($1$)",
98.488 + new Pair[] {
98.489 + new Pair<String, int[]>("$1", new int[] {85 - 31, 91 - 31}),
98.490 + },
98.491 + new Pair[] {
98.492 + },
98.493 + new Pair[] {
98.494 + });
98.495 + }
98.496 +
98.497 + public void testModifiers() throws Exception {
98.498 + performVariablesTest("package test; public class Test { private String s; }",
98.499 + "$mods$ java.lang.String $name;",
98.500 + new Pair[] {
98.501 + new Pair<String, int[]>("$name", new int[] {65 - 31, 82 - 31}),
98.502 + new Pair<String, int[]>("$mods$", new int[] {65 - 31, 72 - 31}), //XXX: shouldn't this be a multi-variable?
98.503 + },
98.504 + new Pair[] {
98.505 + },
98.506 + new Pair[] {
98.507 + new Pair<String, String>("$name", "s"),
98.508 + });
98.509 + }
98.510 +
98.511 + public void testVariableIsFullPattern1() throws Exception {
98.512 + performVariablesTest("package test; public class Test { private int a; {System.err.println(a);} }",
98.513 + "$0{int}",
98.514 + new Pair[] {
98.515 + new Pair<String, int[]>("$0", new int[] {100 - 31, 101 - 31}),
98.516 + },
98.517 + new Pair[] {
98.518 + },
98.519 + new Pair[] {
98.520 + });
98.521 + }
98.522 +
98.523 + public void testVariableIsFullPattern2() throws Exception {
98.524 + performVariablesTest("package test; public class Test { private int a; {System.err.println(a);} }",
98.525 + "$0{int}",
98.526 + new Pair[] {
98.527 + new Pair<String, int[]>("$0", new int[] {100 - 31, 101 - 31}),
98.528 + },
98.529 + new Pair[] {
98.530 + },
98.531 + new Pair[] {
98.532 + },
98.533 + false,
98.534 + true);
98.535 + }
98.536 +
98.537 + public void testNoCCEForVariableName() throws Exception {
98.538 + performVariablesTest("package test; public class Test { { int[] arr = null; int a; arr[a] = 0;} }",
98.539 + "int $a; $a = 0;",
98.540 + new Pair[] {
98.541 + },
98.542 + new Pair[] {
98.543 + },
98.544 + new Pair[] {
98.545 + },
98.546 + true,
98.547 + true);
98.548 + }
98.549 +
98.550 + public void testVerifySameTrees1() throws Exception {
98.551 + performVariablesTest("package test; public class Test { { if (true) { System.err.println(); } else { System.err.println(); System.err.println(); } } }",
98.552 + "if ($c) $s; else $s;",
98.553 + new Pair[] {
98.554 + },
98.555 + new Pair[] {
98.556 + },
98.557 + new Pair[] {
98.558 + },
98.559 + true,
98.560 + true);
98.561 + }
98.562 +
98.563 + public void testVerifySameTreesMultiVariables1() throws Exception {
98.564 + performVariablesTest("package test; public class Test { { if (true) { System.err.println(); System.err.println(); } else { System.err.println(); System.err.println(); System.err.println(); } } }",
98.565 + "if ($c) { $s$;} else { $s$; }",
98.566 + new Pair[] {
98.567 + },
98.568 + new Pair[] {
98.569 + },
98.570 + new Pair[] {
98.571 + },
98.572 + true,
98.573 + true);
98.574 + }
98.575 +
98.576 + public void testVerifySameTreesMultiVariables2() throws Exception {
98.577 + performVariablesTest("package test; public class Test { { if (true) { System.err.println(1); System.err.println(); } else System.err.println(1); } }",
98.578 + "if ($c) { System.err.println(1); $s2$; } else { System.err.println(1); $s2$; }",
98.579 + new Pair[] {
98.580 + },
98.581 + new Pair[] {
98.582 + },
98.583 + new Pair[] {
98.584 + },
98.585 + true,
98.586 + true);
98.587 + }
98.588 +
98.589 + public void testVerifySameTreesMultiVariables3() throws Exception {
98.590 + performVariablesTest("package test; public class Test { { if (true) { System.err.println(); System.err.println(1); } else System.err.println(1); } }",
98.591 + "if ($c) { $s1$; System.err.println(1); } else { $s1$; System.err.println(1); }",
98.592 + new Pair[] {
98.593 + },
98.594 + new Pair[] {
98.595 + },
98.596 + new Pair[] {
98.597 + },
98.598 + true,
98.599 + true);
98.600 + }
98.601 +
98.602 + public void XtestVerifySameTreesMultiVariables4() throws Exception {
98.603 + performVariablesTest("package test; public class Test { { if (true) { System.err.println(); System.err.println(1); System.err.println(); } else System.err.println(1); } }",
98.604 + "if ($c) { $s1$; System.err.println(1); $s2$; } else { $s1$; System.err.println(1); $s2$; }",
98.605 + new Pair[] {
98.606 + },
98.607 + new Pair[] {
98.608 + },
98.609 + new Pair[] {
98.610 + },
98.611 + true,
98.612 + true);
98.613 + }
98.614 +
98.615 + public void testVerifySameTreesMultiVariables5() throws Exception {
98.616 + performVariablesTest("package test; public class Test { { if (true) { System.err.println(1); } else System.err.println(2); } }",
98.617 + "if ($c) { $s$; } else { $s$; }",
98.618 + new Pair[] {
98.619 + },
98.620 + new Pair[] {
98.621 + },
98.622 + new Pair[] {
98.623 + },
98.624 + true,
98.625 + true);
98.626 + }
98.627 +
98.628 + public void testSimpleRemapping1() throws Exception {
98.629 + performRemappingTest("package test;\n" +
98.630 + "public class Test {\n" +
98.631 + " void t1() {\n" +
98.632 + " int i = 0;\n" +
98.633 + " |System.err.println(i);|\n" +
98.634 + " }\n" +
98.635 + " void t2() {\n" +
98.636 + " int a = 0;\n" +
98.637 + " |System.err.println(a);|\n" +
98.638 + " }\n" +
98.639 + "}\n",
98.640 + "i",
98.641 + Options.ALLOW_REMAP_VARIABLE_TO_EXPRESSION);
98.642 + }
98.643 +
98.644 + public void testSimpleRemapping2() throws Exception {
98.645 + performRemappingTest("package test;\n" +
98.646 + "public class Test {\n" +
98.647 + " void t1() {\n" +
98.648 + " int i = 0;\n" +
98.649 + " |System.err.println(i);\n" +
98.650 + " int i2 = 0;\n" +
98.651 + " System.err.println(i2);|\n" +
98.652 + " }\n" +
98.653 + " void t2() {\n" +
98.654 + " int a = 0;\n" +
98.655 + " |System.err.println(a);\n" +
98.656 + " int a2 = 0;\n" +
98.657 + " System.err.println(a2);|\n" +
98.658 + " }\n" +
98.659 + "}\n",
98.660 + "i",
98.661 + Options.ALLOW_REMAP_VARIABLE_TO_EXPRESSION);
98.662 + }
98.663 +
98.664 + public void testSimpleRemapping3() throws Exception {
98.665 + performRemappingTest("package test;\n" +
98.666 + "public class Test {\n" +
98.667 + " void t1() {\n" +
98.668 + " |int i = 0;\n" +
98.669 + " System.err.println(i);\n" +
98.670 + " int i2 = 0;\n" +
98.671 + " System.err.println(i2);|\n" +
98.672 + " }\n" +
98.673 + " void t2() {\n" +
98.674 + " |int a = 0;\n" +
98.675 + " System.err.println(a);\n" +
98.676 + " int a2 = 0;\n" +
98.677 + " System.err.println(a2);|\n" +
98.678 + " }\n" +
98.679 + "}\n",
98.680 + "",
98.681 + Options.ALLOW_REMAP_VARIABLE_TO_EXPRESSION);
98.682 + }
98.683 +
98.684 + public void testSimpleRemapping4() throws Exception {
98.685 + performRemappingTest("package test;\n" +
98.686 + "public class Test {\n" +
98.687 + " void t1() {\n" +
98.688 + " int i = 0;\n" +
98.689 + " |System.err.println(i);|\n" +
98.690 + " }\n" +
98.691 + " void t2() {\n" +
98.692 + " int[] a = {0};\n" +
98.693 + " |System.err.println(a[0]);|\n" +
98.694 + " }\n" +
98.695 + "}\n",
98.696 + "i",
98.697 + Options.ALLOW_REMAP_VARIABLE_TO_EXPRESSION);
98.698 + }
98.699 +
98.700 + public void testPreventRemapOnExpressions1() throws Exception {
98.701 + performRemappingTest("package test;\n" +
98.702 + "public class Test {\n" +
98.703 + " void t1() {\n" +
98.704 + " Throwable t = null;\n" +
98.705 + " |System.err.println(t);|\n" +
98.706 + " }\n" +
98.707 + " void t2() {\n" +
98.708 + " Throwable t = null;\n" +
98.709 + " |System.err.println(t.getCause());|\n" +
98.710 + " }\n" +
98.711 + "}\n",
98.712 + "t",
98.713 + Options.ALLOW_REMAP_VARIABLE_TO_EXPRESSION);
98.714 + }
98.715 +
98.716 + public void testPreventRemapOnExpressions2() throws Exception {
98.717 + performRemappingTest("package test;\n" +
98.718 + "public class Test {\n" +
98.719 + " void t1() {\n" +
98.720 + " Throwable t = null;\n" +
98.721 + " |System.err.println(t);|\n" +
98.722 + " }\n" +
98.723 + " void t2() {\n" +
98.724 + " Throwable t = null;\n" +
98.725 + " System.err.println(t.getCause());\n" +
98.726 + " }\n" +
98.727 + "}\n",
98.728 + "t");
98.729 + }
98.730 +
98.731 + public void testVariableMemberSelect() throws Exception {
98.732 + performVariablesTest("package test; public class Test {public void test(String str) { str.length(); str.length(); } public void test1(String str) { str.length(); str.isEmpty(); } }",
98.733 + "{ $str.$method(); $str.$method(); }",
98.734 + new Pair[0],
98.735 + new Pair[] {new Pair<String, String>("$method", "length")});
98.736 + }
98.737 +
98.738 + public void testCorrectSite1() throws Exception {
98.739 + performVariablesTest("package test; public class Test { public void test(Object o) { o.wait(); } }",
98.740 + "$s{java.util.concurrent.locks.Condition}.wait()",
98.741 + new Pair[0],
98.742 + new Pair[0],
98.743 + new Pair[0],
98.744 + true);
98.745 + }
98.746 +
98.747 + public void testCorrectSite2() throws Exception {
98.748 + performVariablesTest("package test; public class Test { public void test(Object o) { wait(); } }",
98.749 + "$s{java.util.concurrent.locks.Condition}.wait()",
98.750 + new Pair[0],
98.751 + new Pair[0],
98.752 + new Pair[0],
98.753 + true);
98.754 + }
98.755 +
98.756 + public void testCorrectSite3() throws Exception {
98.757 + performVariablesTest("package test; public abstract class Test implements java.util.concurrent.locks.Condition { public void test() { new Runnable() { public void run() { wait(); } } } }",
98.758 + "$0{java.util.concurrent.locks.Condition}.wait()",
98.759 + new Pair[0],// {new Pair<String, int[]>("$s", new int[] {-1, -1})},
98.760 + new Pair[0],
98.761 + new Pair[0]);
98.762 + }
98.763 +
98.764 + public void testCorrectSite4() throws Exception {
98.765 + performVariablesTest("package test; public class Test { public void test() { foo.stop(); } }",
98.766 + "$0{java.lang.Thread}.stop()",
98.767 + new Pair[0],
98.768 + new Pair[0],
98.769 + new Pair[0],
98.770 + true);
98.771 + }
98.772 +
98.773 + public void testDotClassForSameClass() throws Exception {
98.774 + performTest("package test; public class Test { {Class c = |Test.class|; c = |Test.class|; c = String.class; } }");
98.775 + }
98.776 +
98.777 + public void testTryCatchVariable() throws Exception {
98.778 + performVariablesTest("package test; public class Test { { try { throw new java.io.IOException(); } catch (java.io.IOException ex) { } } }",
98.779 + "try { $stmts$; } catch $catches$",
98.780 + new Pair[] {
98.781 + },
98.782 + new Pair[] {
98.783 + new Pair<String, int[]>("$stmts$", new int[] {42, 74}),
98.784 + new Pair<String, int[]>("$catches$", new int[] {77, 111}),
98.785 + },
98.786 + new Pair[] {
98.787 + },
98.788 + false,
98.789 + true);
98.790 + }
98.791 +
98.792 + public void testMatchInterfaceNoFQN() throws Exception {
98.793 + performTest("package test; import java.util.*; public class Test { public void test() { |List| l1; |java.util.List| l2;} }");
98.794 + }
98.795 +
98.796 + public void testUnresolvableNonMatchingConstraint() throws Exception {
98.797 + performVariablesTest("package test; public class Test { private Object a; {System.err.println(a);} }",
98.798 + "System.err.println($v{does.not.Exist}",
98.799 + new Pair[0],
98.800 + new Pair[0],
98.801 + new Pair[0],
98.802 + true);
98.803 + }
98.804 +
98.805 + public void testIndexOutOfBoundsInMultiList() throws Exception {
98.806 + performVariablesTest("package test;" +
98.807 + "public class Test {" +
98.808 + " public void test() {" +
98.809 + " int i = 0;" +
98.810 + " int j = 0;" +
98.811 + " i++;" +
98.812 + " j++;" +
98.813 + " }" +
98.814 + "}",
98.815 + "{$type $i = $init; $stms$; $i++;}",
98.816 + new Pair[0],
98.817 + new Pair[0],
98.818 + new Pair[0],
98.819 + true,
98.820 + false);
98.821 + }
98.822 +
98.823 + public void testCorrectSite192812() throws Exception {
98.824 + performVariablesTest("package test; public class Test { private int i; public void test(Test t) { t.i = i - 10; } }",
98.825 + "$t = $t - $v",
98.826 + new Pair[0],
98.827 + new Pair[0],
98.828 + new Pair[0],
98.829 + true,
98.830 + true);
98.831 + }
98.832 +
98.833 + public void testCorrectSite183367() throws Exception {
98.834 + performVariablesTest("package test; public class Test { public void test(java.util.List l) { l.subList(0, 0).remove(0); } }",
98.835 + "$l{java.util.Collection}.remove($o{java.lang.Object})",
98.836 + new Pair[0],
98.837 + new Pair[0],
98.838 + new Pair[0],
98.839 + true,
98.840 + true);
98.841 + }
98.842 +
98.843 + public void testDisableVariablesWhenVerifyingDuplicates1() throws Exception {
98.844 + performVariablesTest("package test; public class Test { public void test() { int $i = 1, $j = 2; int k = $i + $i; } }",
98.845 + "$i + $i",
98.846 + new Pair[] {new Pair<String, int[]>("$i", new int[] {83, 85})},
98.847 + new Pair[0],
98.848 + new Pair[0],
98.849 + false,
98.850 + true);
98.851 + }
98.852 +
98.853 + public void testDisableVariablesWhenVerifyingDuplicates2() throws Exception {
98.854 + performVariablesTest("package test; public class Test { public void test() { int $i = 1, $j = 2; int k = $i + $i; } }",
98.855 + "$i + $i",
98.856 + new Pair[] {new Pair<String, int[]>("$i", new int[] {83, 85})},
98.857 + new Pair[0],
98.858 + new Pair[0],
98.859 + false,
98.860 + false);
98.861 + }
98.862 +
98.863 + public void testMethodMatchingMoreParams() throws Exception {
98.864 + performVariablesTest("package test; public class Test {public void test(String s1, String s2) { } }",
98.865 + "public void test($params$) { }",
98.866 + new Pair[0],
98.867 + new Pair[] {new Pair<String, int[]>("$params$", new int[] {50, 59, 61, 70})},
98.868 + new Pair[0],
98.869 + false,
98.870 + true);
98.871 + }
98.872 +
98.873 + public void testLambdaInput1() throws Exception {
98.874 + performVariablesTest("package test; public class Test {public void test() { new java.io.FilenameFilter() { public boolean accept(File dir, String name) { } }; } }",
98.875 + "new $type() {public $retType $name($params$) { $body$; } }",
98.876 + new Pair[0],
98.877 + new Pair[] {new Pair<String, int[]>("$params$", new int[] { 107, 115, 117, 128 })},
98.878 + new Pair[] {new Pair<String, String>("$name", "accept")},
98.879 + false,
98.880 + false);
98.881 + }
98.882 +
98.883 + public void testLambdaInput2() throws Exception {
98.884 + performVariablesTest("package test; public class Test {public void test() { new java.io.FilenameFilter() { public boolean accept(File dir, String name) { } }; } }",
98.885 + "new $type() { $mods$ $retType $name($params$) { $body$; } }",
98.886 + new Pair[0],
98.887 + new Pair[] {new Pair<String, int[]>("$params$", new int[] { 107, 115, 117, 128 })},
98.888 + new Pair[] {new Pair<String, String>("$name", "accept")},
98.889 + false,
98.890 + true);
98.891 + }
98.892 +
98.893 + public void testSwitch1() throws Exception {
98.894 + performVariablesTest("package test;\n" +
98.895 + "public class Test {\n" +
98.896 + " {\n" +
98.897 + " E e = null;\n" +
98.898 + " switch (e) {\n" +
98.899 + " case A: System.err.println(1); break;\n" +
98.900 + " case D: System.err.println(2); break;\n" +
98.901 + " case E: System.err.println(3); break;\n" +
98.902 + " }\n" +
98.903 + " }\n" +
98.904 + " public enum E {A, B, C, D, E, F;}\n" +
98.905 + "}\n",
98.906 + "switch ($0{test.Test.E}) { case $c1$ case D: $stmts$; case $c2$ }",
98.907 + new Pair[] {new Pair<String, int[]>("$0", new int[] {79, 80})},
98.908 + new Pair[] {
98.909 + new Pair<String, int[]>("$stmts$", new int[] { 156, 178, 179, 185 }),
98.910 + new Pair<String, int[]>("$c1$", new int[] { 97, 134 }),
98.911 + new Pair<String, int[]>("$c2$", new int[] { 199, 236 }),
98.912 + },
98.913 + new Pair[0],
98.914 + false,
98.915 + false);
98.916 + }
98.917 +
98.918 + public void testWildcard1() throws Exception {
98.919 + performTest("package test; import java.util.*; public class Test { public void test() { |List<?>| l1; |List<?>| l2;} }");
98.920 + }
98.921 +
98.922 + public void testWildcard2() throws Exception {
98.923 + performTest("package test; import java.util.*; public class Test { public void test() { |List<? extends String>| l1; |List<? extends String>| l2;} }");
98.924 + }
98.925 +
98.926 + public void testWildcard3() throws Exception {
98.927 + performTest("package test; import java.util.*; public class Test { public void test() { |List<? super String>| l1; |List<? super String>| l2;} }");
98.928 + }
98.929 +
98.930 + public void testSingleVariableStrict() throws Exception {
98.931 + performVariablesTest("package test; public class Test { public void test() { if (true) System.err.println(1); } }",
98.932 + "if ($c) $then; else $else;",
98.933 + new Pair[0],
98.934 + new Pair[0],
98.935 + new Pair[0],
98.936 + true,
98.937 + true);
98.938 + }
98.939 +
98.940 + public void testMultiVariableZeroOrOne1() throws Exception {
98.941 + performVariablesTest("package test; public class Test { public void test() { if (true) System.err.println(1); } }",
98.942 + "if ($c) $then; else $else$;",
98.943 + new Pair[] {new Pair<String, int[]>("$c", new int[] {59, 63}),
98.944 + new Pair<String, int[]>("$then", new int[] {65, 87})},
98.945 + new Pair[0],
98.946 + new Pair[0],
98.947 + false,
98.948 + true);
98.949 + }
98.950 +
98.951 + public void testMultiVariableZeroOrOne2() throws Exception {
98.952 + performVariablesTest("package test; public class Test { public void test() { if (true) System.err.println(1); else System.err.println(2); } }",
98.953 + "if ($c) $then; else $else$;",
98.954 + new Pair[] {new Pair<String, int[]>("$c", new int[] {59, 63}),
98.955 + new Pair<String, int[]>("$then", new int[] {65, 87}),
98.956 + new Pair<String, int[]>("$else$", new int[] {93, 115})},
98.957 + new Pair[0],
98.958 + new Pair[0],
98.959 + false,
98.960 + true);
98.961 + }
98.962 +
98.963 + public void testNonResolvableType() throws Exception {
98.964 + performVariablesTest("package test; public class Test { { java.io.File f = null; boolean b = f.isDirectory(); } }",
98.965 + "$1{can.not.Resolve}.$m($args$)",
98.966 + new Pair[0],
98.967 + new Pair[0],
98.968 + new Pair[0],
98.969 + true,
98.970 + true);
98.971 + }
98.972 +
98.973 + public void testTryWithResources() throws Exception {
98.974 + performVariablesTest("package test; public class Test { { try (java.io.InputStream in = null) { System.err.println(1); } } }",
98.975 + "try ($resources$) {$body$;}",
98.976 + new Pair[] {
98.977 + },
98.978 + new Pair[] {
98.979 + new Pair<String, int[]>("$resources$", new int[] {41, 70}),
98.980 + new Pair<String, int[]>("$body$", new int[] {74, 96}),
98.981 + },
98.982 + new Pair[] {
98.983 + },
98.984 + false,
98.985 + true);
98.986 + }
98.987 +
98.988 + public void testIgnoreOtherKind() throws Exception {
98.989 + performVariablesTest("package test; public class Test { private java.util.Collection<String> x() { return java.util.Collections.emptySet(); } } }",
98.990 + "$i{java.lang.Class}",
98.991 + new Pair[] {
98.992 + },
98.993 + new Pair[] {
98.994 + },
98.995 + new Pair[] {
98.996 + },
98.997 + true,
98.998 + true);
98.999 + }
98.1000 +
98.1001 + public void testSearchPackageClause() throws Exception {
98.1002 + performVariablesTest("package test.a; public class Test { }",
98.1003 + "test.$1",
98.1004 + new Pair[] {
98.1005 + },
98.1006 + new Pair[] {
98.1007 + },
98.1008 + new Pair[] {
98.1009 + new Pair<String, String>("$1", "a"),
98.1010 + },
98.1011 + false,
98.1012 + true);
98.1013 + }
98.1014 +
98.1015 + public void testPackageImport() throws Exception {
98.1016 + performVariablesTest("package test; import java.util.*; public class Test { }",
98.1017 + "java.$1",
98.1018 + new Pair[] {
98.1019 + },
98.1020 + new Pair[] {
98.1021 + },
98.1022 + new Pair[] {
98.1023 + new Pair<String, String>("$1", "util"),
98.1024 + },
98.1025 + false,
98.1026 + true);
98.1027 + }
98.1028 +
98.1029 + public void testSubclassMatching() throws Exception {
98.1030 + performVariablesTest("package test; import java.util.*; public abstract class Test { Map.Entry e; }",
98.1031 + "java.util.Map.$1",
98.1032 + new Pair[] {
98.1033 + },
98.1034 + new Pair[] {
98.1035 + },
98.1036 + new Pair[] {
98.1037 + new Pair<String, String>("$1", "Entry"),
98.1038 + },
98.1039 + false,
98.1040 + true);
98.1041 + }
98.1042 +
98.1043 + public void testMethodTypeParameters1() throws Exception {
98.1044 + performVariablesTest("package test; public class Test { private void t() { } }",
98.1045 + "$mods$ <$tp$> $ret $name($args$) { $body$; }",
98.1046 + new Pair[] {
98.1047 + new Pair<String, int[]>("$ret", new int[] {42, 46}),
98.1048 + new Pair<String, int[]>("$mods$", new int[] {34, 41}),
98.1049 + },
98.1050 + new Pair[] {
98.1051 + new Pair<String, int[]>("$tp$", new int[] {}),
98.1052 + new Pair<String, int[]>("$args$", new int[] {}),
98.1053 + new Pair<String, int[]>("$body$", new int[] {}),
98.1054 + },
98.1055 + new Pair[] {
98.1056 + new Pair<String, String>("$name", "t")
98.1057 + },
98.1058 + false,
98.1059 + false);
98.1060 + }
98.1061 +
98.1062 + public void testMethodTypeParameters2() throws Exception {
98.1063 + performVariablesTest("package test; public class Test { private <A, B> String aa(int a, int b) { a = b; b = a;} }",
98.1064 + "$mods$ <$tp$> $ret $name($args$) { $body$; }",
98.1065 + new Pair[] {
98.1066 + new Pair<String, int[]>("$ret", new int[] {49, 55}),
98.1067 + new Pair<String, int[]>("$mods$", new int[] {34, 41}),
98.1068 + },
98.1069 + new Pair[] {
98.1070 + new Pair<String, int[]>("$tp$", new int[] {43, 44, 46, 47}),
98.1071 + new Pair<String, int[]>("$args$", new int[] {59, 64, 66, 71}),
98.1072 + new Pair<String, int[]>("$body$", new int[] {75, 81, 82, 88}),
98.1073 + },
98.1074 + new Pair[] {
98.1075 + new Pair<String, String>("$name", "aa")
98.1076 + },
98.1077 + false,
98.1078 + true);
98.1079 + }
98.1080 +
98.1081 + public void testMethodTypeParameters3() throws Exception {
98.1082 + performVariablesTest("package test; public class Test { private <A> String aa(int a, int b) { a = b; b = a;} }",
98.1083 + "$mods$ <$tp> $ret $name($args$) { $body$; }",
98.1084 + new Pair[] {
98.1085 + new Pair<String, int[]>("$ret", new int[] {46, 52}),
98.1086 + new Pair<String, int[]>("$mods$", new int[] {34, 41}),
98.1087 + new Pair<String, int[]>("$tp", new int[] {43, 44}),
98.1088 + },
98.1089 + new Pair[] {
98.1090 + new Pair<String, int[]>("$args$", new int[] {56, 61, 63, 68}),
98.1091 + new Pair<String, int[]>("$body$", new int[] {72, 78, 79, 85}),
98.1092 + },
98.1093 + new Pair[] {
98.1094 + new Pair<String, String>("$name", "aa")
98.1095 + },
98.1096 + false,
98.1097 + true);
98.1098 + }
98.1099 +
98.1100 + public void testTypeParameters1() throws Exception {
98.1101 + performVariablesTest("package test; public class Test { private <A extends String> void aa() { } }",
98.1102 + "$mods$ <$tp extends $bound&$obounds$> $ret $name($args$) { $body$; }",
98.1103 + new Pair[] {
98.1104 + new Pair<String, int[]>("$ret", new int[] {61, 65}),
98.1105 + new Pair<String, int[]>("$mods$", new int[] {34, 41}),
98.1106 + new Pair<String, int[]>("$tp", new int[] {43, 59}),
98.1107 + new Pair<String, int[]>("$bound", new int[] {53, 59}),
98.1108 + },
98.1109 + new Pair[] {
98.1110 + new Pair<String, int[]>("$obounds$", new int[] {}),
98.1111 + },
98.1112 + new Pair[] {
98.1113 + new Pair<String, String>("$name", "aa"),
98.1114 + new Pair<String, String>("$tp", "A")
98.1115 + },
98.1116 + false,
98.1117 + true);
98.1118 + }
98.1119 +
98.1120 + public void testPartialModifiers1() throws Exception {
98.1121 + performVariablesTest("package test; public class Test { @Deprecated @Override private void aa() { } }",
98.1122 + "$mods$ @Deprecated private $ret $name() { $body$; }",
98.1123 + new Pair[] {
98.1124 + new Pair<String, int[]>("$ret", new int[] {64, 68}),
98.1125 + new Pair<String, int[]>("$mods$", new int[] {34, 63}),
98.1126 + },
98.1127 + new Pair[] {
98.1128 + },
98.1129 + new Pair[] {
98.1130 + new Pair<String, String>("$name", "aa"),
98.1131 + },
98.1132 + false,
98.1133 + true);
98.1134 + }
98.1135 +
98.1136 + public void testPartialModifiers2() throws Exception {
98.1137 + performVariablesTest("package test; public class Test { @Override private void aa() { } }",
98.1138 + "$mods$ @Deprecated private $ret $name() { $body$; }",
98.1139 + new Pair[0],
98.1140 + new Pair[0],
98.1141 + new Pair[0],
98.1142 + true,
98.1143 + true);
98.1144 + }
98.1145 +
98.1146 + public void testNonStaticInnerClassesMatch() throws Exception {
98.1147 + performVariablesTest("package test; import test.Test.Inner; public class Test { public class Inner { } } class Other { { Inner i = null; } }",
98.1148 + "test.Test.Inner $i = $init$;",
98.1149 + new Pair[] {
98.1150 + new Pair<String, int[]>("$i", new int[] {99, 114}),
98.1151 + new Pair<String, int[]>("$init$", new int[] {109, 113})
98.1152 + },
98.1153 + new Pair[0],
98.1154 + new Pair[] {
98.1155 + new Pair<String, String>("$i", "i")
98.1156 + },
98.1157 + false,
98.1158 + true);
98.1159 + }
98.1160 +
98.1161 + public void testNewClassTypeParams222066a() throws Exception {
98.1162 + performVariablesTest("package test; public class Test { private Object aa() { return new java.util.ArrayList(1); } }",
98.1163 + "new java.util.ArrayList<$whatever$>($param)",
98.1164 + new Pair[] {
98.1165 + new Pair<String, int[]>("$param", new int[] {87, 88})
98.1166 + },
98.1167 + new Pair[] {
98.1168 + new Pair<String, int[]>("$whatever$", new int[0])
98.1169 + },
98.1170 + new Pair[0],
98.1171 + false,
98.1172 + false);
98.1173 + }
98.1174 +
98.1175 + public void testNewClassTypeParams222066b() throws Exception {
98.1176 + performVariablesTest("package test; import java.util.ArrayList; public class Test { private Object aa() { return new ArrayList(1); } }",
98.1177 + "new java.util.ArrayList<$whatever$>($param)",
98.1178 + new Pair[] {
98.1179 + new Pair<String, int[]>("$param", new int[] {105, 106})
98.1180 + },
98.1181 + new Pair[] {
98.1182 + new Pair<String, int[]>("$whatever$", new int[0])
98.1183 + },
98.1184 + new Pair[0],
98.1185 + false,
98.1186 + false);
98.1187 + }
98.1188 +
98.1189 + public void testFindLambda() throws Exception {
98.1190 + performVariablesTest("package test; import java.util.Comparator; public class Test { private void aa() { Comparator<String> c = (l, r) -> l.compareTo(r); } }",
98.1191 + "($args$) -> $expression",
98.1192 + new Pair[] {
98.1193 + new Pair<String, int[]>("$expression", new int[] {116, 130})
98.1194 + },
98.1195 + new Pair[] {
98.1196 + new Pair<String, int[]>("$args$", new int[] {107, 108, 110, 111})
98.1197 + },
98.1198 + new Pair[0],
98.1199 + false,
98.1200 + false);
98.1201 + }
98.1202 +
98.1203 + protected void prepareTest(String code) throws Exception {
98.1204 + prepareTest(code, -1);
98.1205 + }
98.1206 +
98.1207 + protected void prepareTest(String code, int testIndex) throws Exception {
98.1208 + File workDirWithIndexFile = testIndex != (-1) ? new File(getWorkDir(), Integer.toString(testIndex)) : getWorkDir();
98.1209 + FileObject workDirWithIndex = FileUtil.toFileObject(workDirWithIndexFile);
98.1210 +
98.1211 + if (workDirWithIndex != null) {
98.1212 + workDirWithIndex.delete();
98.1213 + }
98.1214 +
98.1215 + workDirWithIndex = FileUtil.createFolder(workDirWithIndexFile);
98.1216 +
98.1217 + assertNotNull(workDirWithIndexFile);
98.1218 +
98.1219 + FileObject sourceRoot = workDirWithIndex.createFolder("src");
98.1220 + FileObject buildRoot = workDirWithIndex.createFolder("build");
98.1221 + FileObject cache = workDirWithIndex.createFolder("cache");
98.1222 +
98.1223 + FileObject data = FileUtil.createData(sourceRoot, "test/Test.java");
98.1224 +
98.1225 + TestUtilities.copyStringToFile(data, code);
98.1226 +
98.1227 + data.refresh();
98.1228 +
98.1229 + SourceUtilsTestUtil.prepareTest(sourceRoot, buildRoot, cache);
98.1230 +
98.1231 + DataObject od = DataObject.find(data);
98.1232 + EditorCookie ec = od.getLookup().lookup(EditorCookie.class);
98.1233 +
98.1234 + assertNotNull(ec);
98.1235 +
98.1236 + doc = ec.openDocument();
98.1237 +
98.1238 + doc.putProperty(Language.class, JavaTokenId.language());
98.1239 + doc.putProperty("mimeType", "text/x-java");
98.1240 +
98.1241 + JavaSource js = JavaSource.forFileObject(data);
98.1242 +
98.1243 + assertNotNull(js);
98.1244 +
98.1245 + info = SourceUtilsTestUtil.getCompilationInfo(js, Phase.RESOLVED);
98.1246 +
98.1247 + assertNotNull(info);
98.1248 + }
98.1249 +
98.1250 + private static String findRegions(String code, List<int[]> regions) {
98.1251 + String[] split = code.split("\\|");
98.1252 + StringBuilder filtered = new StringBuilder();
98.1253 +
98.1254 + filtered.append(split[0]);
98.1255 +
98.1256 + int offset = split[0].length();
98.1257 +
98.1258 + for (int cntr = 1; cntr < split.length; cntr += 2) {
98.1259 + int[] i = new int[] {
98.1260 + offset,
98.1261 + offset + split[cntr].length()
98.1262 + };
98.1263 +
98.1264 + regions.add(i);
98.1265 +
98.1266 + filtered.append(split[cntr]);
98.1267 + filtered.append(split[cntr + 1]);
98.1268 +
98.1269 + offset += split[cntr].length();
98.1270 + offset += split[cntr + 1].length();
98.1271 + }
98.1272 +
98.1273 + return filtered.toString();
98.1274 + }
98.1275 +
98.1276 + protected CompilationInfo info;
98.1277 + private Document doc;
98.1278 +
98.1279 + private void performTest(String code) throws Exception {
98.1280 + performTest(code, true);
98.1281 + }
98.1282 +
98.1283 + private void performTest(String code, boolean verify) throws Exception {
98.1284 + List<int[]> result = new LinkedList<int[]>();
98.1285 +
98.1286 + code = findRegions(code, result);
98.1287 +
98.1288 + int testIndex = 0;
98.1289 +
98.1290 + for (int[] i : result) {
98.1291 + int[] duplicates = new int[2 * (result.size() - 1)];
98.1292 + int cntr = 0;
98.1293 + List<int[]> l = new LinkedList<int[]>(result);
98.1294 +
98.1295 + l.remove(i);
98.1296 +
98.1297 + for (int[] span : l) {
98.1298 + duplicates[cntr++] = span[0];
98.1299 + duplicates[cntr++] = span[1];
98.1300 + }
98.1301 +
98.1302 + doPerformTest(code, i[0], i[1], testIndex++, verify, duplicates);
98.1303 + }
98.1304 + }
98.1305 +
98.1306 + protected void performTest(String code, int start, int end, int... duplicates) throws Exception {
98.1307 + doPerformTest(code, start, end, -1, true, duplicates);
98.1308 + }
98.1309 +
98.1310 + protected void doPerformTest(String code, int start, int end, int testIndex, int... duplicates) throws Exception {
98.1311 + doPerformTest(code, start, end, testIndex, true, duplicates);
98.1312 + }
98.1313 +
98.1314 + protected void doPerformTest(String code, int start, int end, int testIndex, boolean verify, int... duplicates) throws Exception {
98.1315 + prepareTest(code, testIndex);
98.1316 +
98.1317 + TreePath path = info.getTreeUtilities().pathFor((start + end) / 2 + 1);
98.1318 +
98.1319 + while (path != null) {
98.1320 + Tree t = path.getLeaf();
98.1321 + SourcePositions sp = info.getTrees().getSourcePositions();
98.1322 +
98.1323 + if ( start == sp.getStartPosition(info.getCompilationUnit(), t)
98.1324 + && end == sp.getEndPosition(info.getCompilationUnit(), t)) {
98.1325 + break;
98.1326 + }
98.1327 +
98.1328 + path = path.getParentPath();
98.1329 + }
98.1330 +
98.1331 + assertNotNull(path);
98.1332 +
98.1333 + Collection<TreePath> result = computeDuplicates(path);
98.1334 +
98.1335 + // assertEquals(f.result.toString(), duplicates.length / 2, f.result.size());
98.1336 +
98.1337 + if (verify) {
98.1338 + int[] dupes = new int[result.size() * 2];
98.1339 + int index = 0;
98.1340 +
98.1341 + for (TreePath tp : result) {
98.1342 + dupes[index++] = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), tp.getLeaf());
98.1343 + dupes[index++] = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), tp.getLeaf());
98.1344 + }
98.1345 +
98.1346 + assertTrue("Was: " + Arrays.toString(dupes) + " should have been: " + Arrays.toString(duplicates), Arrays.equals(duplicates, dupes));
98.1347 + }
98.1348 + }
98.1349 +
98.1350 + protected void performVariablesTest(String code, String pattern, Pair<String, int[]>[] duplicatesPos, Pair<String, String>[] duplicatesNames) throws Exception {
98.1351 + performVariablesTest(code, pattern, duplicatesPos, new Pair[0], duplicatesNames);
98.1352 + }
98.1353 +
98.1354 + protected void performVariablesTest(String code, String pattern, Pair<String, int[]>[] duplicatesPos, Pair<String, int[]>[] multiStatementPos, Pair<String, String>[] duplicatesNames) throws Exception {
98.1355 + performVariablesTest(code, pattern, duplicatesPos, multiStatementPos, duplicatesNames, false);
98.1356 + }
98.1357 +
98.1358 + protected void performVariablesTest(String code, String pattern, Pair<String, int[]>[] duplicatesPos, Pair<String, int[]>[] multiStatementPos, Pair<String, String>[] duplicatesNames, boolean noOccurrences) throws Exception {
98.1359 + performVariablesTest(code, pattern, duplicatesPos, multiStatementPos, duplicatesNames, noOccurrences, false);
98.1360 + }
98.1361 +
98.1362 + protected void performVariablesTest(String code, String pattern, Pair<String, int[]>[] duplicatesPos, Pair<String, int[]>[] multiStatementPos, Pair<String, String>[] duplicatesNames, boolean noOccurrences, boolean useBulkSearch) throws Exception {
98.1363 + prepareTest(code, -1);
98.1364 +
98.1365 + Map<String, TypeMirror> constraints = new HashMap<String, TypeMirror>();
98.1366 + String patternCode = PatternCompilerUtilities.parseOutTypesFromPattern(info, pattern, constraints);
98.1367 +
98.1368 + Pattern patternObj = PatternCompiler.compile(info, patternCode, constraints, Collections.<String>emptyList());
98.1369 + TreePath patternPath = MatchingTestAccessor.getPattern(patternObj).iterator().next();
98.1370 + Map<TreePath, VariableAssignments> result;
98.1371 +
98.1372 + if (useBulkSearch) {
98.1373 + result = new HashMap<TreePath, VariableAssignments>();
98.1374 +
98.1375 + BulkPattern bulkPattern = BulkSearch.getDefault().create(info, new AtomicBoolean(), patternCode);
98.1376 +
98.1377 + for (Entry<String, Collection<TreePath>> e : BulkSearch.getDefault().match(info, new AtomicBoolean(), new TreePath(info.getCompilationUnit()), bulkPattern).entrySet()) {
98.1378 + for (TreePath tp : e.getValue()) {
98.1379 + VariableAssignments vars = computeVariables(info, patternPath, tp, new AtomicBoolean(), MatchingTestAccessor.getVariable2Type(patternObj));
98.1380 +
98.1381 + if (vars != null) {
98.1382 + result.put(tp, vars);
98.1383 + }
98.1384 + }
98.1385 + }
98.1386 + } else {
98.1387 + result = computeDuplicates(info, patternPath, new TreePath( info.getCompilationUnit()), new AtomicBoolean(), MatchingTestAccessor.getVariable2Type(patternObj));
98.1388 + }
98.1389 +
98.1390 + if (noOccurrences) {
98.1391 + assertEquals(0, result.size());
98.1392 + return ;
98.1393 + }
98.1394 +
98.1395 + assertSame(1, result.size());
98.1396 +
98.1397 + Map<String, int[]> actual = new HashMap<String, int[]>();
98.1398 +
98.1399 + for (Entry<String, TreePath> e : result.values().iterator().next().variables.entrySet()) {
98.1400 + int[] span = new int[] {
98.1401 + (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), e.getValue().getLeaf()),
98.1402 + (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), e.getValue().getLeaf())
98.1403 + };
98.1404 +
98.1405 + actual.put(e.getKey(), span);
98.1406 + }
98.1407 +
98.1408 + for (Pair<String, int[]> dup : duplicatesPos) {
98.1409 + int[] span = actual.remove(dup.getA());
98.1410 +
98.1411 + if (span == null) {
98.1412 + fail(dup.getA());
98.1413 + }
98.1414 + assertTrue(dup.getA() + ":" + Arrays.toString(span), Arrays.equals(span, dup.getB()));
98.1415 + }
98.1416 +
98.1417 + Map<String, int[]> actualMulti = new HashMap<String, int[]>();
98.1418 +
98.1419 + for (Entry<String, Collection<? extends TreePath>> e : result.values().iterator().next().multiVariables.entrySet()) {
98.1420 + int[] span = new int[2 * e.getValue().size()];
98.1421 + int i = 0;
98.1422 +
98.1423 + for (TreePath tp : e.getValue()) {
98.1424 + span[i++] = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), tp.getLeaf());
98.1425 + span[i++] = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), tp.getLeaf());
98.1426 + }
98.1427 +
98.1428 + actualMulti.put(e.getKey(), span);
98.1429 + }
98.1430 +
98.1431 + for (Pair<String, int[]> dup : multiStatementPos) {
98.1432 + int[] span = actualMulti.remove(dup.getA());
98.1433 +
98.1434 + if (span == null) {
98.1435 + fail(dup.getA());
98.1436 + }
98.1437 + assertTrue(dup.getA() + ":" + Arrays.toString(span), Arrays.equals(span, dup.getB()));
98.1438 + }
98.1439 +
98.1440 + Map<String, String> golden = new HashMap<String, String>();
98.1441 +
98.1442 + for ( Pair<String, String> e : duplicatesNames) {
98.1443 + golden.put(e.getA(), e.getB());
98.1444 + }
98.1445 +
98.1446 + assertEquals(golden, result.values().iterator().next().variables2Names);
98.1447 + }
98.1448 +
98.1449 + protected VariableAssignments computeVariables(CompilationInfo info, TreePath searchingFor, TreePath scope, AtomicBoolean cancel, Map<String, TypeMirror> designedTypeHack) {
98.1450 + Collection<VariableAssignments> values = CopyFinder.internalComputeDuplicates(info, Collections.singletonList(searchingFor), scope, null, null, new AtomicBooleanCancel(cancel), designedTypeHack, Options.ALLOW_VARIABLES_IN_PATTERN).values();
98.1451 +
98.1452 + if (values.iterator().hasNext()) {
98.1453 + return values.iterator().next();
98.1454 + } else {
98.1455 + return null;
98.1456 + }
98.1457 + }
98.1458 +
98.1459 + protected Map<TreePath, VariableAssignments> computeDuplicates(CompilationInfo info, TreePath searchingFor, TreePath scope, AtomicBoolean cancel, Map<String, TypeMirror> designedTypeHack) {
98.1460 + return CopyFinder.internalComputeDuplicates(info, Collections.singletonList(searchingFor), scope, null, null, new AtomicBooleanCancel(cancel), designedTypeHack, Options.ALLOW_VARIABLES_IN_PATTERN, Options.ALLOW_GO_DEEPER);
98.1461 + }
98.1462 +
98.1463 + private void performRemappingTest(String code, String remappableVariables, Options... options) throws Exception {
98.1464 + List<int[]> regions = new LinkedList<int[]>();
98.1465 +
98.1466 + code = findRegions(code, regions);
98.1467 +
98.1468 + prepareTest(code, -1);
98.1469 +
98.1470 + int[] statements = new int[2];
98.1471 +
98.1472 + int[] currentRegion = regions.get(0);
98.1473 + TreePathHandle tph = IntroduceHint.validateSelectionForIntroduceMethod(info, currentRegion[0], currentRegion[1], statements);
98.1474 +
98.1475 + assertNotNull(tph);
98.1476 +
98.1477 + TreePath tp = tph.resolve(info);
98.1478 +
98.1479 + assertNotNull(tp);
98.1480 +
98.1481 + BlockTree bt = (BlockTree) tp.getParentPath().getLeaf();
98.1482 + List<TreePath> searchFor = new LinkedList<TreePath>();
98.1483 +
98.1484 + for (StatementTree t : bt.getStatements().subList(statements[0], statements[1] + 1)) {
98.1485 + searchFor.add(new TreePath(tp, t));
98.1486 + }
98.1487 +
98.1488 + final Set<VariableElement> vars = new HashSet<VariableElement>();
98.1489 +
98.1490 + for (final String name : remappableVariables.split(",")) {
98.1491 + if (name.isEmpty()) continue;
98.1492 + new TreePathScanner<Object, Object>() {
98.1493 + @Override
98.1494 + public Object visitVariable(VariableTree node, Object p) {
98.1495 + if (node.getName().contentEquals(name)) {
98.1496 + vars.add((VariableElement) info.getTrees().getElement(getCurrentPath()));
98.1497 + }
98.1498 +
98.1499 + return super.visitVariable(node, p);
98.1500 + }
98.1501 + }.scan(info.getCompilationUnit(), null);
98.1502 + }
98.1503 +
98.1504 + Set<Options> opts = EnumSet.of(Options.ALLOW_GO_DEEPER);
98.1505 +
98.1506 + opts.addAll(Arrays.asList(options));
98.1507 +
98.1508 + Map<TreePath, VariableAssignments> result = CopyFinder.internalComputeDuplicates(info, searchFor, new TreePath(info.getCompilationUnit()), null, vars, new AtomicBooleanCancel(), Collections.<String, TypeMirror>emptyMap(), opts.toArray(new Options[0]));
98.1509 + Set<List<Integer>> realSpans = new HashSet<List<Integer>>();
98.1510 +
98.1511 + for (Entry<TreePath, VariableAssignments> e : result.entrySet()) {
98.1512 + List<? extends StatementTree> parentStatements = CopyFinder.getStatements(e.getKey());
98.1513 + int dupeStart = parentStatements.indexOf(e.getKey().getLeaf());
98.1514 + int startPos = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), parentStatements.get(dupeStart));
98.1515 + int endPos = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), parentStatements.get(dupeStart + searchFor.size() - 1));
98.1516 +
98.1517 + realSpans.add(Arrays.asList(startPos, endPos));
98.1518 + }
98.1519 +
98.1520 + Set<List<Integer>> goldenSpans = new HashSet<List<Integer>>();
98.1521 +
98.1522 + for (int[] region : regions) {
98.1523 + if (region == currentRegion) continue;
98.1524 +
98.1525 + int[] stmts = new int[2];
98.1526 + TreePathHandle gtph = IntroduceHint.validateSelectionForIntroduceMethod(info, region[0], region[1], stmts);
98.1527 +
98.1528 + assertNotNull(gtph);
98.1529 +
98.1530 + TreePath gtp = gtph.resolve(info);
98.1531 +
98.1532 + assertNotNull(gtp);
98.1533 +
98.1534 + BlockTree b = (BlockTree) gtp.getParentPath().getLeaf();
98.1535 +
98.1536 + int startPos = (int) info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), b.getStatements().get(stmts[0]));
98.1537 + int endPos = (int) info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), b.getStatements().get(stmts[1]));
98.1538 +
98.1539 + goldenSpans.add(Arrays.asList(startPos, endPos));
98.1540 + }
98.1541 +
98.1542 + assertEquals(goldenSpans, realSpans);
98.1543 + }
98.1544 +
98.1545 + protected Collection<TreePath> computeDuplicates(TreePath path) {
98.1546 + return CopyFinder.internalComputeDuplicates(info, Collections.singletonList(path), new TreePath(info.getCompilationUnit()), null, null, new AtomicBooleanCancel(), null, Options.ALLOW_GO_DEEPER).keySet();
98.1547 + }
98.1548 +
98.1549 + public static final class Pair<A, B> {
98.1550 + private final A a;
98.1551 + private final B b;
98.1552 +
98.1553 + public Pair(A a, B b) {
98.1554 + this.a = a;
98.1555 + this.b = b;
98.1556 + }
98.1557 +
98.1558 + public A getA() {
98.1559 + return a;
98.1560 + }
98.1561 +
98.1562 + public B getB() {
98.1563 + return b;
98.1564 + }
98.1565 +
98.1566 + }
98.1567 +
98.1568 + private static final class AtomicBooleanCancel implements Cancel {
98.1569 +
98.1570 + private final AtomicBoolean cancel;
98.1571 +
98.1572 + public AtomicBooleanCancel() {
98.1573 + this(new AtomicBoolean());
98.1574 + }
98.1575 +
98.1576 + public AtomicBooleanCancel(AtomicBoolean cancel) {
98.1577 + this.cancel = cancel;
98.1578 + }
98.1579 +
98.1580 + @Override
98.1581 + public boolean isCancelled() {
98.1582 + return cancel.get();
98.1583 + }
98.1584 +
98.1585 + }
98.1586 +}
99.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
99.2 +++ b/java.hints/spi.java.hints/test/unit/src/org/netbeans/spi/java/hints/support/FixFactoryTest.java Wed May 08 21:47:42 2013 +0200
99.3 @@ -0,0 +1,79 @@
99.4 +/*
99.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
99.6 + *
99.7 + * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
99.8 + *
99.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
99.10 + * Other names may be trademarks of their respective owners.
99.11 + *
99.12 + * The contents of this file are subject to the terms of either the GNU
99.13 + * General Public License Version 2 only ("GPL") or the Common
99.14 + * Development and Distribution License("CDDL") (collectively, the
99.15 + * "License"). You may not use this file except in compliance with the
99.16 + * License. You can obtain a copy of the License at
99.17 + * http://www.netbeans.org/cddl-gplv2.html
99.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
99.19 + * specific language governing permissions and limitations under the
99.20 + * License. When distributing the software, include this License Header
99.21 + * Notice in each file and include the License file at
99.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
99.23 + * particular file as subject to the "Classpath" exception as provided
99.24 + * by Oracle in the GPL Version 2 section of the License file that
99.25 + * accompanied this code. If applicable, add the following below the
99.26 + * License Header, with the fields enclosed by brackets [] replaced by
99.27 + * your own identifying information:
99.28 + * "Portions Copyrighted [year] [name of copyright owner]"
99.29 + *
99.30 + * If you wish your version of this file to be governed by only the CDDL
99.31 + * or only the GPL Version 2, indicate your decision by adding
99.32 + * "[Contributor] elects to include this software in this distribution
99.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
99.34 + * single choice of license, a recipient has the option to distribute
99.35 + * your version of this file under either the CDDL, the GPL Version 2 or
99.36 + * to extend the choice of license to its licensees as provided above.
99.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
99.38 + * Version 2 license, then the option applies only if the new code is
99.39 + * made subject to such option by the copyright holder.
99.40 + *
99.41 + * Contributor(s):
99.42 + *
99.43 + * Portions Copyrighted 2013 Sun Microsystems, Inc.
99.44 + */
99.45 +package org.netbeans.spi.java.hints.support;
99.46 +
99.47 +import com.sun.source.tree.ClassTree;
99.48 +import com.sun.source.util.TreePath;
99.49 +import java.util.EnumSet;
99.50 +import javax.lang.model.element.Modifier;
99.51 +import org.netbeans.api.java.source.SourceUtilsTestUtil;
99.52 +import org.netbeans.modules.java.hints.spiimpl.TestBase;
99.53 +import org.openide.LifecycleManager;
99.54 +
99.55 +/**
99.56 + *
99.57 + * @author lahvac
99.58 + */
99.59 +public class FixFactoryTest extends TestBase {
99.60 +
99.61 + public FixFactoryTest(String name) {
99.62 + super(name);
99.63 + }
99.64 +
99.65 + @Override
99.66 + protected void setUp() throws Exception {
99.67 + super.setUp();
99.68 + SourceUtilsTestUtil.makeScratchDir(this);
99.69 + }
99.70 +
99.71 + public void testInterfaceModifiers() throws Exception {
99.72 + prepareTest("test/Test.java", "package test; public interface I { }");
99.73 +
99.74 + ClassTree i = (ClassTree) info.getCompilationUnit().getTypeDecls().get(0);
99.75 +
99.76 + FixFactory.removeModifiersFix(info, TreePath.getPath(info.getCompilationUnit(), i.getModifiers()), EnumSet.of(Modifier.PUBLIC), "").implement();
99.77 +
99.78 + LifecycleManager.getDefault().saveAll();
99.79 +
99.80 + assertEquals("package test; interface I { }", info.getFileObject().asText());
99.81 + }
99.82 +}
99.83 \ No newline at end of file
100.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
100.2 +++ b/remoting/common/borrowedtests/src/org/netbeans/api/java/source/matching/MatchingTestAccessor.java Wed May 08 21:47:42 2013 +0200
100.3 @@ -0,0 +1,62 @@
100.4 +/*
100.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
100.6 + *
100.7 + * Copyright 2012 Oracle and/or its affiliates. All rights reserved.
100.8 + *
100.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
100.10 + * Other names may be trademarks of their respective owners.
100.11 + *
100.12 + * The contents of this file are subject to the terms of either the GNU
100.13 + * General Public License Version 2 only ("GPL") or the Common
100.14 + * Development and Distribution License("CDDL") (collectively, the
100.15 + * "License"). You may not use this file except in compliance with the
100.16 + * License. You can obtain a copy of the License at
100.17 + * http://www.netbeans.org/cddl-gplv2.html
100.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
100.19 + * specific language governing permissions and limitations under the
100.20 + * License. When distributing the software, include this License Header
100.21 + * Notice in each file and include the License file at
100.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
100.23 + * particular file as subject to the "Classpath" exception as provided
100.24 + * by Oracle in the GPL Version 2 section of the License file that
100.25 + * accompanied this code. If applicable, add the following below the
100.26 + * License Header, with the fields enclosed by brackets [] replaced by
100.27 + * your own identifying information:
100.28 + * "Portions Copyrighted [year] [name of copyright owner]"
100.29 + *
100.30 + * If you wish your version of this file to be governed by only the CDDL
100.31 + * or only the GPL Version 2, indicate your decision by adding
100.32 + * "[Contributor] elects to include this software in this distribution
100.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
100.34 + * single choice of license, a recipient has the option to distribute
100.35 + * your version of this file under either the CDDL, the GPL Version 2 or
100.36 + * to extend the choice of license to its licensees as provided above.
100.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
100.38 + * Version 2 license, then the option applies only if the new code is
100.39 + * made subject to such option by the copyright holder.
100.40 + *
100.41 + * Contributor(s):
100.42 + *
100.43 + * Portions Copyrighted 2012 Sun Microsystems, Inc.
100.44 + */
100.45 +package org.netbeans.api.java.source.matching;
100.46 +
100.47 +import com.sun.source.util.TreePath;
100.48 +import java.util.Collection;
100.49 +import java.util.Map;
100.50 +import javax.lang.model.type.TypeMirror;
100.51 +
100.52 +/**
100.53 + *
100.54 + * @author lahvac
100.55 + */
100.56 +public class MatchingTestAccessor {
100.57 +
100.58 + public static Collection<? extends TreePath> getPattern(Pattern p) {
100.59 + return p.pattern;
100.60 + }
100.61 +
100.62 + public static Map<String, TypeMirror> getVariable2Type(Pattern p) {
100.63 + return p.variable2Type;
100.64 + }
100.65 +}
101.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
101.2 +++ b/remoting/common/borrowedtests/src/org/openide/util/test/TestFileUtils.java Wed May 08 21:47:42 2013 +0200
101.3 @@ -0,0 +1,271 @@
101.4 +/*
101.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
101.6 + *
101.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
101.8 + *
101.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
101.10 + * Other names may be trademarks of their respective owners.
101.11 + *
101.12 + * The contents of this file are subject to the terms of either the GNU
101.13 + * General Public License Version 2 only ("GPL") or the Common
101.14 + * Development and Distribution License("CDDL") (collectively, the
101.15 + * "License"). You may not use this file except in compliance with the
101.16 + * License. You can obtain a copy of the License at
101.17 + * http://www.netbeans.org/cddl-gplv2.html
101.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
101.19 + * specific language governing permissions and limitations under the
101.20 + * License. When distributing the software, include this License Header
101.21 + * Notice in each file and include the License file at
101.22 + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
101.23 + * particular file as subject to the "Classpath" exception as provided
101.24 + * by Oracle in the GPL Version 2 section of the License file that
101.25 + * accompanied this code. If applicable, add the following below the
101.26 + * License Header, with the fields enclosed by brackets [] replaced by
101.27 + * your own identifying information:
101.28 + * "Portions Copyrighted [year] [name of copyright owner]"
101.29 + *
101.30 + * If you wish your version of this file to be governed by only the CDDL
101.31 + * or only the GPL Version 2, indicate your decision by adding
101.32 + * "[Contributor] elects to include this software in this distribution
101.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
101.34 + * single choice of license, a recipient has the option to distribute
101.35 + * your version of this file under either the CDDL, the GPL Version 2 or
101.36 + * to extend the choice of license to its licensees as provided above.
101.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
101.38 + * Version 2 license, then the option applies only if the new code is
101.39 + * made subject to such option by the copyright holder.
101.40 + *
101.41 + * Contributor(s):
101.42 + *
101.43 + * Portions Copyrighted 2008 Sun Microsystems, Inc.
101.44 + */
101.45 +
101.46 +package org.openide.util.test;
101.47 +
101.48 +import java.io.ByteArrayOutputStream;
101.49 +import java.io.File;
101.50 +import java.io.FileInputStream;
101.51 +import java.io.FileOutputStream;
101.52 +import java.io.IOException;
101.53 +import java.io.InputStream;
101.54 +import java.io.OutputStream;
101.55 +import java.io.OutputStreamWriter;
101.56 +import java.io.PrintWriter;
101.57 +import java.util.Collections;
101.58 +import java.util.HashSet;
101.59 +import java.util.LinkedHashMap;
101.60 +import java.util.Map;
101.61 +import java.util.Set;
101.62 +import java.util.zip.CRC32;
101.63 +import java.util.zip.ZipEntry;
101.64 +import java.util.zip.ZipInputStream;
101.65 +import java.util.zip.ZipOutputStream;
101.66 +import junit.framework.Assert;
101.67 +
101.68 +/**
101.69 + * Common utility methods for massaging and inspecting files from tests.
101.70 + */
101.71 +public class TestFileUtils {
101.72 +
101.73 + private TestFileUtils() {}
101.74 +
101.75 + /**
101.76 + * Create a new data file with specified initial contents.
101.77 + * @param f a file to create (parents will be created automatically)
101.78 + * @param body the complete contents of the new file (in UTF-8 encoding)
101.79 + */
101.80 + public static File writeFile(File f, String body) throws IOException {
101.81 + f.getParentFile().mkdirs();
101.82 + OutputStream os = new FileOutputStream(f);
101.83 + PrintWriter pw = new PrintWriter(new OutputStreamWriter(os, "UTF-8"));
101.84 + pw.print(body);
101.85 + pw.flush();
101.86 + os.close();
101.87 + return f;
101.88 + }
101.89 +
101.90 + /**
101.91 + * Read the contents of a file as a single string.
101.92 + * @param a data file
101.93 + * @return its contents (in UTF-8 encoding)
101.94 + */
101.95 + public static String readFile(File file) throws IOException {
101.96 + InputStream is = new FileInputStream(file);
101.97 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
101.98 + byte[] buf = new byte[4096];
101.99 + int read;
101.100 + while ((read = is.read(buf)) != -1) {
101.101 + baos.write(buf, 0, read);
101.102 + }
101.103 + is.close();
101.104 + return baos.toString("UTF-8");
101.105 + }
101.106 +
101.107 + /**
101.108 + * Read the contents of a file as a byte array.
101.109 + * @param a data file
101.110 + * @return its raw binary contents
101.111 + */
101.112 + public static byte[] readFileBin(File file) throws IOException {
101.113 + InputStream is = new FileInputStream(file);
101.114 + ByteArrayOutputStream baos = new ByteArrayOutputStream();
101.115 + byte[] buf = new byte[4096];
101.116 + int read;
101.117 + while ((read = is.read(buf)) != -1) {
101.118 + baos.write(buf, 0, read);
101.119 + }
101.120 + is.close();
101.121 + return baos.toByteArray();
101.122 + }
101.123 +
101.124 + /**
101.125 + * Create a new ZIP file.
101.126 + * @param jar the ZIP file to create
101.127 + * @param entries a list of entries in the form of "filename:UTF8-contents"; parent dirs created automatically
101.128 + * @return the {@code jar} parameter, for convenience
101.129 + * @throws IOException for the usual reasons
101.130 + */
101.131 + public static File writeZipFile(File jar, String... entries) throws IOException {
101.132 + jar.getParentFile().mkdirs();
101.133 + writeZipFile(new FileOutputStream(jar), entries);
101.134 + return jar;
101.135 + }
101.136 +
101.137 + /**
101.138 + * Create a new ZIP file.
101.139 + * @param os a stream to which the ZIP will be written
101.140 + * @param entries a list of entries in the form of "filename:UTF8-contents"; parent dirs created automatically
101.141 + * @throws IOException for the usual reasons
101.142 + */
101.143 + public static void writeZipFile(OutputStream os, String... entries) throws IOException {
101.144 + Map<String,byte[]> binary = new LinkedHashMap<String,byte[]>();
101.145 + for (String entry : entries) {
101.146 + int colon = entry.indexOf(':');
101.147 + assert colon != -1 : entry;
101.148 + binary.put(entry.substring(0, colon), entry.substring(colon + 1).getBytes("UTF-8"));
101.149 + }
101.150 + writeZipFile(os, binary);
101.151 + }
101.152 +
101.153 + /**
101.154 + * Create a new ZIP file.
101.155 + * @param os a stream to which the ZIP will be written
101.156 + * @param entries entries as maps from filename to binary contents;; parent dirs created automatically
101.157 + * @throws IOException for the usual reasons
101.158 + */
101.159 + public static void writeZipFile(OutputStream os, Map<String,byte[]> entries) throws IOException {
101.160 + ZipOutputStream zos = new ZipOutputStream(os);
101.161 + Set<String> parents = new HashSet<String>();
101.162 + if (entries.isEmpty()) {
101.163 + entries = Collections.singletonMap("PLACEHOLDER", new byte[0]);
101.164 + }
101.165 + for (Map.Entry<String,byte[]> entry : entries.entrySet()) {
101.166 + String name = entry.getKey();
101.167 + assert name.length() > 0 && !name.endsWith("/") && !name.startsWith("/") && name.indexOf("//") == -1 : name;
101.168 + for (int i = 0; i < name.length(); i++) {
101.169 + if (name.charAt(i) == '/') {
101.170 + String parent = name.substring(0, i + 1);
101.171 + if (parents.add(parent)) {
101.172 + ZipEntry ze = new ZipEntry(parent);
101.173 + ze.setMethod(ZipEntry.STORED);
101.174 + ze.setSize(0);
101.175 + ze.setCrc(0);
101.176 + ze.setTime(0);
101.177 + zos.putNextEntry(ze);
101.178 + zos.closeEntry();
101.179 + }
101.180 + }
101.181 + }
101.182 + byte[] data = entry.getValue();
101.183 + ZipEntry ze = new ZipEntry(name);
101.184 + ze.setMethod(ZipEntry.STORED);
101.185 + ze.setSize(data.length);
101.186 + CRC32 crc = new CRC32();
101.187 + crc.update(data);
101.188 + ze.setCrc(crc.getValue());
101.189 + ze.setTime(0);
101.190 + zos.putNextEntry(ze);
101.191 + zos.write(data, 0, data.length);
101.192 + zos.closeEntry();
101.193 + }
101.194 + zos.finish();
101.195 + zos.close();
101.196 + os.close();
101.197 + }
101.198 +
101.199 + /**
101.200 + * Unpacks a ZIP file to disk.
101.201 + * All entries are unpacked, even {@code META-INF/MANIFEST.MF} if present.
101.202 + * Parent directories are created as needed (even if not mentioned in the ZIP);
101.203 + * empty ZIP directories are created too.
101.204 + * Existing files are overwritten.
101.205 + * @param zip a ZIP file
101.206 + * @param dir the base directory in which to unpack (need not yet exist)
101.207 + * @throws IOException in case of problems
101.208 + */
101.209 + public static void unpackZipFile(File zip, File dir) throws IOException {
101.210 + byte[] buf = new byte[8192];
101.211 + InputStream is = new FileInputStream(zip);
101.212 + try {
101.213 + ZipInputStream zis = new ZipInputStream(is);
101.214 + ZipEntry entry;
101.215 + while ((entry = zis.getNextEntry()) != null) {
101.216 + String name = entry.getName();
101.217 + int slash = name.lastIndexOf('/');
101.218 + File d = new File(dir, name.substring(0, slash).replace('/', File.separatorChar));
101.219 + if (!d.isDirectory() && !d.mkdirs()) {
101.220 + throw new IOException("could not make " + d);
101.221 + }
101.222 + if (slash != name.length() - 1) {
101.223 + File f = new File(dir, name.replace('/', File.separatorChar));
101.224 + OutputStream os = new FileOutputStream(f);
101.225 + try {
101.226 + int read;
101.227 + while ((read = zis.read(buf)) != -1) {
101.228 + os.write(buf, 0, read);
101.229 + }
101.230 + } finally {
101.231 + os.close();
101.232 + }
101.233 + }
101.234 + }
101.235 + } finally {
101.236 + is.close();
101.237 + }
101.238 + }
101.239 +
101.240 + /**
101.241 + * Make sure the timestamp on a file changes.
101.242 + * @param f a file to touch (make newer)
101.243 + * @param ref if not null, make f newer than this file; else make f newer than it was before
101.244 + */
101.245 + @SuppressWarnings("SleepWhileInLoop")
101.246 + public static void touch(File f, File ref) throws IOException, InterruptedException {
101.247 + long older = f.lastModified();
101.248 + if (ref != null) {
101.249 + older = Math.max(older, ref.lastModified());
101.250 + } else {
101.251 + older = Math.max(older, System.currentTimeMillis());
101.252 + }
101.253 + int maxPause = 9999;
101.254 + /* XXX consider this (as yet untested):
101.255 + long curr = System.currentTimeMillis();
101.256 + if (older > curr + maxPause) {
101.257 + throw new IllegalArgumentException("reference too far into the future, by " + (older - curr) + "msec");
101.258 + }
101.259 + */
101.260 + for (long pause = 1; pause < maxPause; pause *= 2) {
101.261 + Thread.sleep(pause);
101.262 + f.setLastModified(System.currentTimeMillis() + 1); // plus 1 needed for FileObject tests (initially FO lastModified is set to currentTimeMillis)
101.263 + if (f.lastModified() > older) {
101.264 + while (f.lastModified() >= System.currentTimeMillis()) {
101.265 +// LOG.log(Level.INFO, "Modification time is in future {0}", System.currentTimeMillis());
101.266 + Thread.sleep(10);
101.267 + }
101.268 + return;
101.269 + }
101.270 + }
101.271 + Assert.fail("Did not manage to touch " + f);
101.272 + }
101.273 +
101.274 +}