Introducing an annotation processor that can run the hints (by default, only custom rules are run).
authorjlahoda
Sat, 15 Aug 2015 13:14:20 +0200
changeset 1010dd6d5eb4f6d9
parent 1009 9261ae66626a
child 1011 1c1b055cdd0f
Introducing an annotation processor that can run the hints (by default, only custom rules are run).
cmdline/ap/build.xml
cmdline/ap/manifest.mf
cmdline/ap/nbproject/build-impl.xml
cmdline/ap/nbproject/genfiles.properties
cmdline/ap/nbproject/project.properties
cmdline/ap/nbproject/project.xml
cmdline/ap/nbproject/suite.properties
cmdline/ap/src/META-INF/services/javax.annotation.processing.Processor
cmdline/ap/src/org/netbeans/modules/jackpot30/ap/Bundle.properties
cmdline/ap/src/org/netbeans/modules/jackpot30/ap/ProcessorImpl.java
cmdline/ap/test/unit/src/org/netbeans/modules/jackpot30/ap/ProcessorImplTest.java
cmdline/build.sh
cmdline/lib/nbproject/project.properties
cmdline/lib/nbproject/project.xml
cmdline/lib/src/org/netbeans/modules/jackpot30/cmdline/lib/Utils.java
cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateAPLibJar.java
cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneJar.java
cmdline/nbproject/project.properties
cmdline/tool/nbproject/genfiles.properties
cmdline/tool/nbproject/project.xml
cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/cmdline/ap/build.xml	Sat Aug 15 13:14:20 2015 +0200
     1.3 @@ -0,0 +1,33 @@
     1.4 +<?xml version="1.0" encoding="UTF-8"?>
     1.5 +<!-- You may freely edit this file. See harness/README in the NetBeans platform -->
     1.6 +<!-- for some information on what you could do (e.g. targets to override). -->
     1.7 +<!-- If you delete this file and reopen the project it will be recreated. -->
     1.8 +<project name="org.netbeans.modules.jackpot30.ap" default="netbeans" basedir=".">
     1.9 +    <description>Builds, tests, and runs the project org.netbeans.modules.jackpot30.ap.</description>
    1.10 +    <import file="nbproject/build-impl.xml"/>
    1.11 +    <property name="bootclasspath.prepend" value="" />
    1.12 +    <import file="${suite.dir}/../findbugs-import.xml"/>
    1.13 +
    1.14 +    <target name="-check-lib-exists" depends="files-init">
    1.15 +        <condition property="jackpot.lib.exists" value="true">
    1.16 +            <available file="${build.dir}/jackpot-ap-lib.jar" />
    1.17 +        </condition>
    1.18 +    </target>
    1.19 +    <target name="build-init" depends="harness.build-init,-check-lib-exists" unless="jackpot.lib.exists">
    1.20 +        <mkdir dir="${build.dir}/" />
    1.21 +        <ant dir="../lib" target="test" inheritall="false" inheritrefs="false">
    1.22 +            <property name="test.config.standalone.includes" value="org/netbeans/modules/jackpot30/cmdline/lib/CreateAPLibJar.class"/>
    1.23 +            <property name="test.config" value="standalone"/>
    1.24 +            <property name="test-unit-sys-prop.outputDir" location="${build.dir}/" />
    1.25 +        </ant>
    1.26 +    </target>
    1.27 +    <target name="build-ap-jar" depends="compile">
    1.28 +        <delete dir="${build.dir}/temp-unpack" failonerror="false"/>
    1.29 +        <mkdir dir="${build.dir}/temp-unpack" />
    1.30 +        <unjar src="${build.dir}/jackpot-ap-lib.jar" dest="${build.dir}/temp-unpack" />
    1.31 +        <copy todir="${build.dir}/temp-unpack">
    1.32 +            <fileset dir="${build.classes.dir}"/>
    1.33 +        </copy>
    1.34 +        <jar destfile="${build.dir}/jackpot-ap.jar" basedir="${build.dir}/temp-unpack" />
    1.35 +    </target>
    1.36 +</project>
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/cmdline/ap/manifest.mf	Sat Aug 15 13:14:20 2015 +0200
     2.3 @@ -0,0 +1,6 @@
     2.4 +Manifest-Version: 1.0
     2.5 +AutoUpdate-Show-In-Client: true
     2.6 +OpenIDE-Module: org.netbeans.modules.jackpot30.ap
     2.7 +OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/jackpot30/ap/Bundle.properties
     2.8 +OpenIDE-Module-Specification-Version: 1.0
     2.9 +
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/cmdline/ap/nbproject/build-impl.xml	Sat Aug 15 13:14:20 2015 +0200
     3.3 @@ -0,0 +1,45 @@
     3.4 +<?xml version="1.0" encoding="UTF-8"?>
     3.5 +<!--
     3.6 +*** GENERATED FROM project.xml - DO NOT EDIT  ***
     3.7 +***         EDIT ../build.xml INSTEAD         ***
     3.8 +-->
     3.9 +<project name="org.netbeans.modules.jackpot30.ap-impl" basedir="..">
    3.10 +    <fail message="Please build using Ant 1.7.1 or higher.">
    3.11 +        <condition>
    3.12 +            <not>
    3.13 +                <antversion atleast="1.7.1"/>
    3.14 +            </not>
    3.15 +        </condition>
    3.16 +    </fail>
    3.17 +    <property file="nbproject/private/suite-private.properties"/>
    3.18 +    <property file="nbproject/suite.properties"/>
    3.19 +    <fail unless="suite.dir">You must set 'suite.dir' to point to your containing module suite</fail>
    3.20 +    <property file="${suite.dir}/nbproject/private/platform-private.properties"/>
    3.21 +    <property file="${suite.dir}/nbproject/platform.properties"/>
    3.22 +    <macrodef name="property" uri="http://www.netbeans.org/ns/nb-module-project/2">
    3.23 +        <attribute name="name"/>
    3.24 +        <attribute name="value"/>
    3.25 +        <sequential>
    3.26 +            <property name="@{name}" value="${@{value}}"/>
    3.27 +        </sequential>
    3.28 +    </macrodef>
    3.29 +    <macrodef name="evalprops" uri="http://www.netbeans.org/ns/nb-module-project/2">
    3.30 +        <attribute name="property"/>
    3.31 +        <attribute name="value"/>
    3.32 +        <sequential>
    3.33 +            <property name="@{property}" value="@{value}"/>
    3.34 +        </sequential>
    3.35 +    </macrodef>
    3.36 +    <property file="${user.properties.file}"/>
    3.37 +    <nbmproject2:property name="harness.dir" value="nbplatform.${nbplatform.active}.harness.dir" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
    3.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"/>
    3.39 +    <nbmproject2:evalprops property="cluster.path.evaluated" value="${cluster.path}" xmlns:nbmproject2="http://www.netbeans.org/ns/nb-module-project/2"/>
    3.40 +    <fail message="Path to 'platform' cluster missing in $${cluster.path} property or using corrupt Netbeans Platform (missing harness).">
    3.41 +        <condition>
    3.42 +            <not>
    3.43 +                <contains string="${cluster.path.evaluated}" substring="platform"/>
    3.44 +            </not>
    3.45 +        </condition>
    3.46 +    </fail>
    3.47 +    <import file="${harness.dir}/build.xml"/>
    3.48 +</project>
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/cmdline/ap/nbproject/genfiles.properties	Sat Aug 15 13:14:20 2015 +0200
     4.3 @@ -0,0 +1,8 @@
     4.4 +build.xml.data.CRC32=abf35b3d
     4.5 +build.xml.script.CRC32=434ef419
     4.6 +build.xml.stylesheet.CRC32=a56c6a5b@2.70
     4.7 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
     4.8 +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
     4.9 +nbproject/build-impl.xml.data.CRC32=abf35b3d
    4.10 +nbproject/build-impl.xml.script.CRC32=dd901283
    4.11 +nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.70
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/cmdline/ap/nbproject/project.properties	Sat Aug 15 13:14:20 2015 +0200
     5.3 @@ -0,0 +1,3 @@
     5.4 +javac.source=1.7
     5.5 +javac.compilerargs=-Xlint -Xlint:-serial
     5.6 +cp.extra=build/jackpot-ap-lib.jar:${tools.jar}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/cmdline/ap/nbproject/project.xml	Sat Aug 15 13:14:20 2015 +0200
     6.3 @@ -0,0 +1,30 @@
     6.4 +<?xml version="1.0" encoding="UTF-8"?>
     6.5 +<project xmlns="http://www.netbeans.org/ns/project/1">
     6.6 +    <type>org.netbeans.modules.apisupport.project</type>
     6.7 +    <configuration>
     6.8 +        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
     6.9 +            <code-name-base>org.netbeans.modules.jackpot30.ap</code-name-base>
    6.10 +            <suite-component/>
    6.11 +            <module-dependencies/>
    6.12 +            <test-dependencies>
    6.13 +                <test-type>
    6.14 +                    <name>unit</name>
    6.15 +                    <test-dependency>
    6.16 +                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
    6.17 +                        <compile-dependency/>
    6.18 +                    </test-dependency>
    6.19 +                    <test-dependency>
    6.20 +                        <code-name-base>org.netbeans.modules.jackpot30.test.borrowed</code-name-base>
    6.21 +                        <compile-dependency/>
    6.22 +                    </test-dependency>
    6.23 +                    <test-dependency>
    6.24 +                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
    6.25 +                        <recursive/>
    6.26 +                        <compile-dependency/>
    6.27 +                    </test-dependency>
    6.28 +                </test-type>
    6.29 +            </test-dependencies>
    6.30 +            <public-packages/>
    6.31 +        </data>
    6.32 +    </configuration>
    6.33 +</project>
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/cmdline/ap/nbproject/suite.properties	Sat Aug 15 13:14:20 2015 +0200
     7.3 @@ -0,0 +1,1 @@
     7.4 +suite.dir=${basedir}/..
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/cmdline/ap/src/META-INF/services/javax.annotation.processing.Processor	Sat Aug 15 13:14:20 2015 +0200
     8.3 @@ -0,0 +1,1 @@
     8.4 +org.netbeans.modules.jackpot30.ap.ProcessorImpl
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/cmdline/ap/src/org/netbeans/modules/jackpot30/ap/Bundle.properties	Sat Aug 15 13:14:20 2015 +0200
     9.3 @@ -0,0 +1,1 @@
     9.4 +OpenIDE-Module-Name=Jackpot 3.0 Annotation Processing
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/cmdline/ap/src/org/netbeans/modules/jackpot30/ap/ProcessorImpl.java	Sat Aug 15 13:14:20 2015 +0200
    10.3 @@ -0,0 +1,402 @@
    10.4 +/*
    10.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    10.6 + *
    10.7 + * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
    10.8 + *
    10.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   10.10 + * Other names may be trademarks of their respective owners.
   10.11 + *
   10.12 + * The contents of this file are subject to the terms of either the GNU
   10.13 + * General Public License Version 2 only ("GPL") or the Common
   10.14 + * Development and Distribution License("CDDL") (collectively, the
   10.15 + * "License"). You may not use this file except in compliance with the
   10.16 + * License. You can obtain a copy of the License at
   10.17 + * http://www.netbeans.org/cddl-gplv2.html
   10.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   10.19 + * specific language governing permissions and limitations under the
   10.20 + * License.  When distributing the software, include this License Header
   10.21 + * Notice in each file and include the License file at
   10.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   10.23 + * particular file as subject to the "Classpath" exception as provided
   10.24 + * by Oracle in the GPL Version 2 section of the License file that
   10.25 + * accompanied this code. If applicable, add the following below the
   10.26 + * License Header, with the fields enclosed by brackets [] replaced by
   10.27 + * your own identifying information:
   10.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   10.29 + *
   10.30 + * If you wish your version of this file to be governed by only the CDDL
   10.31 + * or only the GPL Version 2, indicate your decision by adding
   10.32 + * "[Contributor] elects to include this software in this distribution
   10.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   10.34 + * single choice of license, a recipient has the option to distribute
   10.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   10.36 + * to extend the choice of license to its licensees as provided above.
   10.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   10.38 + * Version 2 license, then the option applies only if the new code is
   10.39 + * made subject to such option by the copyright holder.
   10.40 + *
   10.41 + * Contributor(s):
   10.42 + *
   10.43 + * Portions Copyrighted 2015 Sun Microsystems, Inc.
   10.44 + */
   10.45 +package org.netbeans.modules.jackpot30.ap;
   10.46 +
   10.47 +import com.sun.source.tree.CompilationUnitTree;
   10.48 +import com.sun.source.tree.Tree;
   10.49 +import com.sun.source.util.SourcePositions;
   10.50 +import com.sun.source.util.TreePath;
   10.51 +import com.sun.source.util.TreePathScanner;
   10.52 +import com.sun.source.util.Trees;
   10.53 +import java.io.File;
   10.54 +import java.io.IOException;
   10.55 +import java.lang.reflect.Field;
   10.56 +import java.lang.reflect.InvocationTargetException;
   10.57 +import java.lang.reflect.Method;
   10.58 +import java.net.MalformedURLException;
   10.59 +import java.net.URL;
   10.60 +import java.util.ArrayList;
   10.61 +import java.util.Arrays;
   10.62 +import java.util.Collection;
   10.63 +import java.util.HashMap;
   10.64 +import java.util.List;
   10.65 +import java.util.Map;
   10.66 +import java.util.Map.Entry;
   10.67 +import java.util.Set;
   10.68 +import java.util.concurrent.atomic.AtomicBoolean;
   10.69 +import java.util.logging.Level;
   10.70 +import java.util.logging.Logger;
   10.71 +import java.util.prefs.AbstractPreferences;
   10.72 +import java.util.prefs.BackingStoreException;
   10.73 +import java.util.prefs.Preferences;
   10.74 +import javax.annotation.processing.AbstractProcessor;
   10.75 +import javax.annotation.processing.RoundEnvironment;
   10.76 +import javax.annotation.processing.SupportedAnnotationTypes;
   10.77 +import javax.annotation.processing.SupportedOptions;
   10.78 +import javax.lang.model.SourceVersion;
   10.79 +import javax.lang.model.element.Element;
   10.80 +import javax.lang.model.element.ElementKind;
   10.81 +import javax.lang.model.element.TypeElement;
   10.82 +import javax.tools.Diagnostic.Kind;
   10.83 +import javax.tools.JavaFileManager;
   10.84 +import javax.tools.StandardJavaFileManager;
   10.85 +import javax.tools.StandardLocation;
   10.86 +import org.netbeans.api.java.classpath.ClassPath;
   10.87 +import org.netbeans.api.java.source.ClasspathInfo;
   10.88 +import org.netbeans.api.java.source.CompilationController;
   10.89 +import org.netbeans.api.java.source.JavaSource;
   10.90 +import org.netbeans.api.java.source.Task;
   10.91 +import org.netbeans.modules.editor.tools.storage.api.ToolPreferences;
   10.92 +import org.netbeans.modules.jackpot30.cmdline.lib.Utils;
   10.93 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
   10.94 +import org.netbeans.modules.java.hints.providers.spi.HintMetadata;
   10.95 +import org.netbeans.modules.java.hints.spiimpl.RulesManager;
   10.96 +import org.netbeans.modules.java.hints.spiimpl.hints.HintsInvoker;
   10.97 +import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
   10.98 +import org.netbeans.modules.parsing.impl.indexing.CacheFolder;
   10.99 +import org.netbeans.spi.editor.hints.ErrorDescription;
  10.100 +import org.netbeans.spi.editor.hints.Severity;
  10.101 +import org.netbeans.spi.java.classpath.support.ClassPathSupport;
  10.102 +import org.openide.filesystems.FileObject;
  10.103 +import org.openide.filesystems.FileUtil;
  10.104 +import org.openide.filesystems.URLMapper;
  10.105 +import org.openide.util.Lookup;
  10.106 +
  10.107 +/**
  10.108 + *
  10.109 + * @author lahvac
  10.110 + */
  10.111 +@SupportedAnnotationTypes("*")
  10.112 +@SupportedOptions("hintsConfiguration")
  10.113 +public class ProcessorImpl extends AbstractProcessor {
  10.114 +
  10.115 +    public static final String CONFIGURATION_OPTION = "hintsConfiguration";
  10.116 +    private final Map<URL, String> sources = new HashMap<>();
  10.117 +
  10.118 +    @Override
  10.119 +    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
  10.120 +        final Trees trees = Trees.instance(processingEnv);
  10.121 +
  10.122 +        if (!roundEnv.processingOver()) {
  10.123 +            for (Element root : roundEnv.getRootElements()) {
  10.124 +                TypeElement outtermost = outtermostType(root);
  10.125 +                TreePath path = trees.getPath(outtermost);
  10.126 +
  10.127 +                if (path == null) {
  10.128 +                    //TODO: log
  10.129 +                    continue;
  10.130 +                }
  10.131 +
  10.132 +                try {
  10.133 +                    sources.put(path.getCompilationUnit().getSourceFile().toUri().toURL(), outtermost.getQualifiedName().toString());
  10.134 +                } catch (MalformedURLException ex) {
  10.135 +                    processingEnv.getMessager().printMessage(Kind.ERROR, "Unexpected exception: " + ex.getMessage());
  10.136 +                    Logger.getLogger(ProcessorImpl.class.getName()).log(Level.SEVERE, null, ex);
  10.137 +                }
  10.138 +            }
  10.139 +        } else {
  10.140 +            try {
  10.141 +                Field contextField = processingEnv.getClass().getDeclaredField("context");
  10.142 +                contextField.setAccessible(true);
  10.143 +                Object context = contextField.get(processingEnv);
  10.144 +                Method get = context.getClass().getDeclaredMethod("get", Class.class);
  10.145 +                JavaFileManager fileManager = (JavaFileManager) get.invoke(context, JavaFileManager.class);
  10.146 +
  10.147 +                if (!(fileManager instanceof StandardJavaFileManager)) {
  10.148 +                    processingEnv.getMessager().printMessage(Kind.ERROR, "The file manager is not a StandardJavaFileManager, cannot run Jackpot 3.0.");
  10.149 +                    return false;
  10.150 +                }
  10.151 +
  10.152 +                setupCache();
  10.153 +
  10.154 +                StandardJavaFileManager sfm = (StandardJavaFileManager) fileManager;
  10.155 +
  10.156 +                ClassPath bootCP = toClassPath(sfm.getLocation(StandardLocation.PLATFORM_CLASS_PATH));
  10.157 +                ClassPath compileCP = toClassPath(sfm.getLocation(StandardLocation.CLASS_PATH));
  10.158 +                Iterable<? extends File> sourcePathLocation = sfm.getLocation(StandardLocation.SOURCE_PATH);
  10.159 +                ClassPath sourceCP = sourcePathLocation != null ? toClassPath(sourcePathLocation) : inferSourcePath();
  10.160 +
  10.161 +                final Map<FileObject, String> sourceFiles = new HashMap<>();
  10.162 +
  10.163 +                for (Entry<URL, String> e : sources.entrySet()) {
  10.164 +                    FileObject fo = URLMapper.findFileObject(e.getKey());
  10.165 +                    if (fo == null) {
  10.166 +                        //XXX:
  10.167 +                        return false;
  10.168 +                    }
  10.169 +                    sourceFiles.put(fo, e.getValue());
  10.170 +                }
  10.171 +
  10.172 +                final Map<HintMetadata, ? extends Collection<? extends HintDescription>> allHints = RulesManager.getInstance().readHints(null, Arrays.asList(bootCP, compileCP, sourceCP), new AtomicBoolean());
  10.173 +                List<HintDescription> hints = new ArrayList<>();
  10.174 +                for (Collection<? extends HintDescription> v : allHints.values()) {
  10.175 +                    hints.addAll(v);
  10.176 +                }
  10.177 +                final Map<String, String> id2DisplayName = Utils.computeId2DisplayName(hints);
  10.178 +                final Map<HintMetadata, ? extends Collection<? extends HintDescription>> hardcodedHints = RulesManager.getInstance().readHints(null, null, new AtomicBoolean());
  10.179 +                final HintsSettings settings;
  10.180 +                String configurationFileLoc = processingEnv.getOptions().get(CONFIGURATION_OPTION);
  10.181 +                File configurationFile = configurationFileLoc != null ? new File(configurationFileLoc) : null;
  10.182 +
  10.183 +                if (configurationFile == null || !configurationFile.canRead()) {
  10.184 +                    settings = new HintsSettings() {
  10.185 +
  10.186 +                        @Override
  10.187 +                        public boolean isEnabled(HintMetadata hm) {
  10.188 +                            return !hardcodedHints.containsKey(hm) ? hm.enabled : false;
  10.189 +                        }
  10.190 +
  10.191 +                        @Override
  10.192 +                        public void setEnabled(HintMetadata hm, boolean bln) {
  10.193 +                            throw new UnsupportedOperationException();
  10.194 +                        }
  10.195 +
  10.196 +                        @Override
  10.197 +                        public Preferences getHintPreferences(HintMetadata hm) {
  10.198 +                            return new DummyPreferences(null, "");
  10.199 +                        }
  10.200 +
  10.201 +                        @Override
  10.202 +                        public Severity getSeverity(HintMetadata hm) {
  10.203 +                            return hm.severity;
  10.204 +                        }
  10.205 +
  10.206 +                        @Override
  10.207 +                        public void setSeverity(HintMetadata hm, Severity svrt) {
  10.208 +                            throw new UnsupportedOperationException();
  10.209 +                        }
  10.210 +                    };
  10.211 +                } else {
  10.212 +                    settings = HintsSettings.createPreferencesBasedHintsSettings(ToolPreferences.from(configurationFile.toURI()).getPreferences("hints", "text/x-java"), true, null);
  10.213 +                }
  10.214 +
  10.215 +                ClasspathInfo cpInfo = ClasspathInfo.create(bootCP, compileCP, sourceCP);
  10.216 +
  10.217 +                JavaSource.create(cpInfo, sourceFiles.keySet()).runUserActionTask(new Task<CompilationController>() {
  10.218 +
  10.219 +                    @Override
  10.220 +                    public void run(CompilationController parameter) throws Exception {
  10.221 +                        if (parameter.toPhase(JavaSource.Phase.RESOLVED).compareTo(JavaSource.Phase.RESOLVED) < 0) {
  10.222 +                            return;
  10.223 +                        }
  10.224 +
  10.225 +                        List<ErrorDescription> eds = new HintsInvoker(settings, /*XXX*/new AtomicBoolean()).computeHints(parameter);
  10.226 +
  10.227 +                        if (eds != null) {
  10.228 +                            for (ErrorDescription ed : eds) {
  10.229 +                                String outtermost = sourceFiles.get(ed.getFile());
  10.230 +                                TypeElement type = processingEnv.getElementUtils().getTypeElement(outtermost); //XXX: package-info!!!
  10.231 +                                TreePath typePath = trees.getPath(type);
  10.232 +                                TreePath posPath = pathFor(typePath.getCompilationUnit(), trees.getSourcePositions(), ed.getRange().getBegin().getOffset());
  10.233 +                                String category = Utils.categoryName(ed.getId(), id2DisplayName);
  10.234 +                                Kind diagKind;
  10.235 +                                switch (ed.getSeverity()) {
  10.236 +                                    case ERROR: diagKind = Kind.ERROR; break;
  10.237 +                                    case VERIFIER:
  10.238 +                                    case WARNING: diagKind = Kind.WARNING; break;
  10.239 +                                    case HINT:
  10.240 +                                    default: diagKind = Kind.NOTE; break;
  10.241 +                                }
  10.242 +                                trees.printMessage(diagKind, category + ed.getDescription(), posPath.getLeaf(), posPath.getCompilationUnit());
  10.243 +                            }
  10.244 +                        }
  10.245 +                    }
  10.246 +                }, true);
  10.247 +            } catch (NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchMethodException | InvocationTargetException | IOException ex) {
  10.248 +                processingEnv.getMessager().printMessage(Kind.ERROR, "Unexpected exception: " + ex.getMessage());
  10.249 +                Logger.getLogger(ProcessorImpl.class.getName()).log(Level.SEVERE, null, ex);
  10.250 +            }
  10.251 +        }
  10.252 +
  10.253 +        return false;
  10.254 +    }
  10.255 +
  10.256 +    private static ClassPath toClassPath(Iterable<? extends File> files) throws MalformedURLException {
  10.257 +        Collection<URL> roots = new ArrayList<>();
  10.258 +
  10.259 +        if (files != null) {
  10.260 +            for (File f : files) {
  10.261 +                roots.add(FileUtil.urlForArchiveOrDir(FileUtil.normalizeFile(f)));
  10.262 +            }
  10.263 +        }
  10.264 +
  10.265 +        return ClassPathSupport.createClassPath(roots.toArray(new URL[0]));
  10.266 +    }
  10.267 +
  10.268 +    private void setupCache() throws IOException {
  10.269 +        File tmp = File.createTempFile("jackpot30", null);
  10.270 +
  10.271 +        tmp.delete();
  10.272 +        tmp.mkdirs();
  10.273 +        tmp.deleteOnExit();
  10.274 +
  10.275 +        tmp = FileUtil.normalizeFile(tmp);
  10.276 +        FileUtil.refreshFor(tmp.getParentFile());
  10.277 +
  10.278 +        org.openide.filesystems.FileObject tmpFO = FileUtil.toFileObject(tmp);
  10.279 +
  10.280 +        if (tmpFO != null) {
  10.281 +            CacheFolder.setCacheFolder(tmpFO);
  10.282 +        }
  10.283 +    }
  10.284 +
  10.285 +    private TypeElement outtermostType(Element el) {
  10.286 +        while (el.getEnclosingElement().getKind() != ElementKind.PACKAGE) { //XXX: package-info!
  10.287 +            el = el.getEnclosingElement();
  10.288 +        }
  10.289 +        return (TypeElement) el;
  10.290 +    }
  10.291 +
  10.292 +    private TreePath pathFor(final CompilationUnitTree cut, final SourcePositions sp, final long pos) {
  10.293 +        class Result extends RuntimeException {
  10.294 +            final TreePath result;
  10.295 +            public Result(TreePath result) {
  10.296 +                this.result = result;
  10.297 +            }
  10.298 +        }
  10.299 +        try {
  10.300 +            new TreePathScanner<Void, Void>() {
  10.301 +                @Override
  10.302 +                public Void scan(Tree tree, Void p) {
  10.303 +                    long s = sp.getStartPosition(cut, tree);
  10.304 +                    long e = sp.getEndPosition(cut, tree);
  10.305 +                    if (s <= pos && pos <= e) {
  10.306 +                        super.scan(tree, p);
  10.307 +                        throw new Result(getCurrentPath());
  10.308 +                    }
  10.309 +                    return null;
  10.310 +                }
  10.311 +            }.scan(cut, null);
  10.312 +        } catch (Result r) {
  10.313 +            return r.result;
  10.314 +        }
  10.315 +        return null;
  10.316 +    }
  10.317 +
  10.318 +    private ClassPath inferSourcePath() {
  10.319 +        if (sources.isEmpty())
  10.320 +            return ClassPath.EMPTY;
  10.321 +        Entry<URL, String> e = sources.entrySet().iterator().next();
  10.322 +        FileObject sourceRoot = URLMapper.findFileObject(e.getKey());
  10.323 +        if (sourceRoot == null) {
  10.324 +            //unexpected
  10.325 +            return ClassPath.EMPTY;
  10.326 +        }
  10.327 +        for (String part : e.getValue().split("\\.")) {
  10.328 +            sourceRoot = sourceRoot.getParent();
  10.329 +        }
  10.330 +        return ClassPathSupport.createClassPath(sourceRoot);
  10.331 +    }
  10.332 +
  10.333 +    @Override
  10.334 +    public SourceVersion getSupportedSourceVersion() {
  10.335 +        return SourceVersion.latest();
  10.336 +    }
  10.337 +
  10.338 +    static {
  10.339 +        ClassLoader origContext = Thread.currentThread().getContextClassLoader();
  10.340 +        try {
  10.341 +            Thread.currentThread().setContextClassLoader(ProcessorImpl.class.getClassLoader());
  10.342 +            Lookup.getDefault();
  10.343 +        } finally {
  10.344 +            Thread.currentThread().setContextClassLoader(origContext);
  10.345 +        }
  10.346 +    }
  10.347 +
  10.348 +    private static final class DummyPreferences extends AbstractPreferences {
  10.349 +
  10.350 +        private final Map<String, String> values = new HashMap<>();
  10.351 +        private final Map<String, DummyPreferences> subNodes = new HashMap<>();
  10.352 +
  10.353 +        public DummyPreferences(AbstractPreferences parent, String name) {
  10.354 +            super(parent, name);
  10.355 +        }
  10.356 +
  10.357 +        @Override
  10.358 +        protected void putSpi(String key, String value) {
  10.359 +            values.put(key, value);
  10.360 +        }
  10.361 +
  10.362 +        @Override
  10.363 +        protected String getSpi(String key) {
  10.364 +            return values.get(key);
  10.365 +        }
  10.366 +
  10.367 +        @Override
  10.368 +        protected void removeSpi(String key) {
  10.369 +            values.remove(key);
  10.370 +        }
  10.371 +
  10.372 +        @Override
  10.373 +        protected void removeNodeSpi() throws BackingStoreException {
  10.374 +            ((DummyPreferences) parent()).subNodes.remove(name());
  10.375 +        }
  10.376 +
  10.377 +        @Override
  10.378 +        protected String[] keysSpi() throws BackingStoreException {
  10.379 +            return values.keySet().toArray(new String[0]);
  10.380 +        }
  10.381 +
  10.382 +        @Override
  10.383 +        protected String[] childrenNamesSpi() throws BackingStoreException {
  10.384 +            return subNodes.keySet().toArray(new String[0]);
  10.385 +        }
  10.386 +
  10.387 +        @Override
  10.388 +        protected AbstractPreferences childSpi(String name) {
  10.389 +            DummyPreferences n = subNodes.get(name);
  10.390 +            if (n == null) {
  10.391 +                subNodes.put(name, n = new DummyPreferences(this, name));
  10.392 +            }
  10.393 +            return n;
  10.394 +        }
  10.395 +
  10.396 +        @Override
  10.397 +        protected void syncSpi() throws BackingStoreException {
  10.398 +        }
  10.399 +
  10.400 +        @Override
  10.401 +        protected void flushSpi() throws BackingStoreException {
  10.402 +        }
  10.403 +
  10.404 +    }
  10.405 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/cmdline/ap/test/unit/src/org/netbeans/modules/jackpot30/ap/ProcessorImplTest.java	Sat Aug 15 13:14:20 2015 +0200
    11.3 @@ -0,0 +1,244 @@
    11.4 +/*
    11.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    11.6 + *
    11.7 + * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
    11.8 + *
    11.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   11.10 + * Other names may be trademarks of their respective owners.
   11.11 + *
   11.12 + * The contents of this file are subject to the terms of either the GNU
   11.13 + * General Public License Version 2 only ("GPL") or the Common
   11.14 + * Development and Distribution License("CDDL") (collectively, the
   11.15 + * "License"). You may not use this file except in compliance with the
   11.16 + * License. You can obtain a copy of the License at
   11.17 + * http://www.netbeans.org/cddl-gplv2.html
   11.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   11.19 + * specific language governing permissions and limitations under the
   11.20 + * License.  When distributing the software, include this License Header
   11.21 + * Notice in each file and include the License file at
   11.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   11.23 + * particular file as subject to the "Classpath" exception as provided
   11.24 + * by Oracle in the GPL Version 2 section of the License file that
   11.25 + * accompanied this code. If applicable, add the following below the
   11.26 + * License Header, with the fields enclosed by brackets [] replaced by
   11.27 + * your own identifying information:
   11.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   11.29 + *
   11.30 + * If you wish your version of this file to be governed by only the CDDL
   11.31 + * or only the GPL Version 2, indicate your decision by adding
   11.32 + * "[Contributor] elects to include this software in this distribution
   11.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   11.34 + * single choice of license, a recipient has the option to distribute
   11.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   11.36 + * to extend the choice of license to its licensees as provided above.
   11.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   11.38 + * Version 2 license, then the option applies only if the new code is
   11.39 + * made subject to such option by the copyright holder.
   11.40 + *
   11.41 + * Contributor(s):
   11.42 + *
   11.43 + * Portions Copyrighted 2015 Sun Microsystems, Inc.
   11.44 + */
   11.45 +package org.netbeans.modules.jackpot30.ap;
   11.46 +
   11.47 +import com.sun.tools.javac.Main;
   11.48 +import java.io.ByteArrayOutputStream;
   11.49 +import java.io.File;
   11.50 +import java.io.PrintStream;
   11.51 +import java.util.ArrayList;
   11.52 +import java.util.Arrays;
   11.53 +import java.util.Collections;
   11.54 +import java.util.LinkedList;
   11.55 +import java.util.List;
   11.56 +import java.util.regex.Matcher;
   11.57 +import java.util.regex.Pattern;
   11.58 +import static junit.framework.TestCase.assertEquals;
   11.59 +import static junit.framework.TestCase.assertTrue;
   11.60 +import org.netbeans.api.java.source.TestUtilities;
   11.61 +import org.netbeans.junit.NbTestCase;
   11.62 +
   11.63 +/**
   11.64 + *
   11.65 + * @author lahvac
   11.66 + */
   11.67 +public class ProcessorImplTest extends NbTestCase {
   11.68 +
   11.69 +    public ProcessorImplTest(String name) {
   11.70 +        super(name);
   11.71 +    }
   11.72 +
   11.73 +    public void testHardcoded1() throws Exception {
   11.74 +        doRunCompiler("",
   11.75 +                      "",
   11.76 +                      "src/test/Test.java",
   11.77 +                      "package test;\n" +
   11.78 +                      "public class Test {\n" +
   11.79 +                      "    private void test(java.util.Collection c) {\n" +
   11.80 +                      "        boolean b1 = c.size() == 0;\n" +
   11.81 +                      "\tboolean b2 = c.size() == 0;\n" +
   11.82 +                      "    }\n" +
   11.83 +                      "}\n",
   11.84 +                      null,
   11.85 +                      "-source",
   11.86 +                      "7",
   11.87 +                      "-Xlint:-options");
   11.88 +    }
   11.89 +
   11.90 +    public void testHardcodedWithConfiguration() throws Exception {
   11.91 +        doRunCompiler("",
   11.92 +                      "${workdir}/src/test/Test.java:4: warning: [Usage_of_size_equals_0] Usage of .size() == 0 can be replaced with .isEmpty()\n" +
   11.93 +                      "        boolean b1 = c.size() == 0;\n" +
   11.94 +                      "                      ^\n" +
   11.95 +                      "${workdir}/src/test/Test.java:5: warning: [Usage_of_size_equals_0] Usage of .size() == 0 can be replaced with .isEmpty()\n" +
   11.96 +                      "\tboolean b2 = c.size() == 0;\n" +
   11.97 +                      "\t              ^\n" +
   11.98 +                      "2 warnings\n",
   11.99 +                      "src/test/Test.java",
  11.100 +                      "package test;\n" +
  11.101 +                      "public class Test {\n" +
  11.102 +                      "    private void test(java.util.Collection c) {\n" +
  11.103 +                      "        boolean b1 = c.size() == 0;\n" +
  11.104 +                      "\tboolean b2 = c.size() == 0;\n" +
  11.105 +                      "    }\n" +
  11.106 +                      "}\n",
  11.107 +                      "cfg_hints.xml",
  11.108 +                      "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
  11.109 +                      "<!DOCTYPE configuration PUBLIC \"-//NetBeans//DTD Tool Configuration 1.0//EN\" \"http://www.netbeans.org/dtds/ToolConfiguration-1_0.dtd\">\n" +
  11.110 +                      "<configuration>\n" +
  11.111 +                      "    <tool kind=\"hints\" type=\"text/x-java\">\n" +
  11.112 +                      "    </tool>\n" +
  11.113 +                      "</configuration>\n",
  11.114 +                      null,
  11.115 +                      "-source",
  11.116 +                      "7",
  11.117 +                      "-Xlint:-options",
  11.118 +                      "-A" + ProcessorImpl.CONFIGURATION_OPTION + "=" + new File(getWorkDir(), "cfg_hints.xml").getAbsolutePath());
  11.119 +    }
  11.120 +
  11.121 +    public void testCustomWithSourcePath() throws Exception {
  11.122 +        doRunCompiler("",
  11.123 +                      "${workdir}/src/test/Test.java:4: warning: [test] test\n" +
  11.124 +                      "        boolean b1 = c.size() == 0;\n" +
  11.125 +                      "                      ^\n" +
  11.126 +                      "${workdir}/src/test/Test.java:5: warning: [test] test\n" +
  11.127 +                      "\tboolean b2 = c.size() == 0;\n" +
  11.128 +                      "\t              ^\n" +
  11.129 +                      "2 warnings\n",
  11.130 +                      "src/test/Test.java",
  11.131 +                      "package test;\n" +
  11.132 +                      "public class Test {\n" +
  11.133 +                      "    private void test(java.util.Collection c) {\n" +
  11.134 +                      "        boolean b1 = c.size() == 0;\n" +
  11.135 +                      "\tboolean b2 = c.size() == 0;\n" +
  11.136 +                      "    }\n" +
  11.137 +                      "}\n",
  11.138 +                      "src/META-INF/upgrade/test.hint",
  11.139 +                      "$coll.size() == 0 :: $coll instanceof java.util.Collection;;\n",
  11.140 +                      null,
  11.141 +                      "-source",
  11.142 +                      "7",
  11.143 +                      "-Xlint:-options",
  11.144 +                      "-sourcepath",
  11.145 +                      new File(getWorkDir(), "src").getAbsolutePath());
  11.146 +   }
  11.147 +
  11.148 +    public void testCustomWithOutSourcePath() throws Exception {
  11.149 +        doRunCompiler("",
  11.150 +                      "${workdir}/src/test/Test.java:4: warning: [test] test\n" +
  11.151 +                      "        boolean b1 = c.size() == 0;\n" +
  11.152 +                      "                      ^\n" +
  11.153 +                      "${workdir}/src/test/Test.java:5: warning: [test] test\n" +
  11.154 +                      "\tboolean b2 = c.size() == 0;\n" +
  11.155 +                      "\t              ^\n" +
  11.156 +                      "2 warnings\n",
  11.157 +                      "src/test/Test.java",
  11.158 +                      "package test;\n" +
  11.159 +                      "public class Test {\n" +
  11.160 +                      "    private void test(java.util.Collection c) {\n" +
  11.161 +                      "        boolean b1 = c.size() == 0;\n" +
  11.162 +                      "\tboolean b2 = c.size() == 0;\n" +
  11.163 +                      "    }\n" +
  11.164 +                      "}\n",
  11.165 +                      "src/META-INF/upgrade/test.hint",
  11.166 +                      "$coll.size() == 0 :: $coll instanceof java.util.Collection;;\n",
  11.167 +                      null,
  11.168 +                      "-source",
  11.169 +                      "7",
  11.170 +                      "-Xlint:-options");
  11.171 +   }
  11.172 +
  11.173 +    private void doRunCompiler(String stdOut, String stdErr, String... fileContentAndExtraOptions) throws Exception {
  11.174 +        List<String> fileAndContent = new LinkedList<String>();
  11.175 +        List<String> extraOptions = new LinkedList<String>();
  11.176 +        List<String> fileContentAndExtraOptionsList = Arrays.asList(fileContentAndExtraOptions);
  11.177 +        int nullPos = fileContentAndExtraOptionsList.indexOf(null);
  11.178 +
  11.179 +        if (nullPos == (-1)) {
  11.180 +            fileAndContent = fileContentAndExtraOptionsList;
  11.181 +            extraOptions = Collections.emptyList();
  11.182 +        } else {
  11.183 +            fileAndContent = fileContentAndExtraOptionsList.subList(0, nullPos);
  11.184 +            extraOptions = fileContentAndExtraOptionsList.subList(nullPos + 1, fileContentAndExtraOptionsList.size());
  11.185 +        }
  11.186 +
  11.187 +        assertTrue(fileAndContent.size() % 2 == 0);
  11.188 +
  11.189 +        clearWorkDir();
  11.190 +
  11.191 +        List<String> params = new ArrayList<>();
  11.192 +
  11.193 +        for (int cntr = 0; cntr < fileAndContent.size(); cntr += 2) {
  11.194 +            File target = new File(getWorkDir(), fileAndContent.get(cntr));
  11.195 +
  11.196 +            target.getParentFile().mkdirs();
  11.197 +
  11.198 +            TestUtilities.copyStringToFile(target, fileAndContent.get(cntr + 1));
  11.199 +
  11.200 +            if (target.getName().endsWith(".java"))
  11.201 +                params.add(target.getAbsolutePath());
  11.202 +        }
  11.203 +
  11.204 +        params.addAll(extraOptions);
  11.205 +
  11.206 +        File wd = getWorkDir();
  11.207 +        String[] output = new String[2];
  11.208 +        reallyRunCompiler(wd, output, params.toArray(new String[0]));
  11.209 +
  11.210 +        if (stdOut != null) {
  11.211 +            assertEquals(stdOut, output[0].replaceAll(Pattern.quote(wd.getAbsolutePath()), Matcher.quoteReplacement("${workdir}")));
  11.212 +        }
  11.213 +
  11.214 +        if (stdErr != null) {
  11.215 +            assertEquals(stdErr, output[1].replaceAll(Pattern.quote(wd.getAbsolutePath()), Matcher.quoteReplacement("${workdir}")));
  11.216 +        }
  11.217 +    }
  11.218 +
  11.219 +    protected void reallyRunCompiler(File workDir, String[] output, String... params) throws Exception {
  11.220 +        String oldUserDir = System.getProperty("user.dir");
  11.221 +
  11.222 +        System.setProperty("user.dir", workDir.getAbsolutePath());
  11.223 +
  11.224 +        PrintStream oldOut = System.out;
  11.225 +        ByteArrayOutputStream outData = new ByteArrayOutputStream();
  11.226 +        System.setOut(new PrintStream(outData, true, "UTF-8"));
  11.227 +
  11.228 +        PrintStream oldErr = System.err;
  11.229 +        ByteArrayOutputStream errData = new ByteArrayOutputStream();
  11.230 +        System.setErr(new PrintStream(errData, true, "UTF-8"));
  11.231 +
  11.232 +        try {
  11.233 +            assertEquals(0, Main.compile(params));
  11.234 +        } finally {
  11.235 +            System.setProperty("user.dir", oldUserDir);
  11.236 +            System.out.close();
  11.237 +            output[0] = new String(outData.toByteArray(), "UTF-8");
  11.238 +            System.setOut(oldOut);
  11.239 +            System.err.close();
  11.240 +            output[1] = new String(errData.toByteArray(), "UTF-8");
  11.241 +            System.setErr(oldErr);
  11.242 +
  11.243 +            System.err.println("stdout: " + output[0]);
  11.244 +            System.err.println("stderr: " + output[1]);
  11.245 +        }
  11.246 +    }
  11.247 +}
    12.1 --- a/cmdline/build.sh	Sat Aug 15 08:14:07 2015 +0200
    12.2 +++ b/cmdline/build.sh	Sat Aug 15 13:14:20 2015 +0200
    12.3 @@ -1,5 +1,5 @@
    12.4  #!/bin/bash -x
    12.5 -ant "$@" clean && ant "$@" build && ant "$@" test && (cd compiler; ant "$@" create-standalone-compiler && build/test/scripted/run )  && (cd tool; ant "$@" create-standalone-tool && build/test/scripted/run ) && (cd lib; ant "$@" create-cmdline-lib ) || exit 1
    12.6 +ant "$@" clean && ant "$@" build && ant "$@" test && (cd compiler; ant "$@" create-standalone-compiler && build/test/scripted/run )  && (cd tool; ant "$@" create-standalone-tool && build/test/scripted/run ) && (cd lib; ant "$@" create-cmdline-lib ) && (cd ap; ant "$@" build-ap-jar ) || exit 1
    12.7  mvn $MAVEN_EXTRA_ARGS install:install-file -Dfile=tool/build/jackpot/jackpot.jar -DgroupId=org.netbeans.modules.jackpot30 -DartifactId=tool -Dversion=7.3-SNAPSHOT -Dpackaging=jar -DgeneratePom=true
    12.8  (cd maven; mvn $MAVEN_EXTRA_ARGS install -DskipTests;  mvn $MAVEN_EXTRA_ARGS -Dmaven.executable=`which mvn` test)
    12.9  MAVEN_REPO=`pwd`/build/.m2
    13.1 --- a/cmdline/lib/nbproject/project.properties	Sat Aug 15 08:14:07 2015 +0200
    13.2 +++ b/cmdline/lib/nbproject/project.properties	Sat Aug 15 13:14:20 2015 +0200
    13.3 @@ -1,5 +1,5 @@
    13.4  is.autoload=true
    13.5 -javac.source=1.6
    13.6 +javac.source=1.7
    13.7  javac.compilerargs=-Xlint -Xlint:-serial
    13.8  requires.nb.javac=true
    13.9  spec.version.base=1.16.0
    14.1 --- a/cmdline/lib/nbproject/project.xml	Sat Aug 15 08:14:07 2015 +0200
    14.2 +++ b/cmdline/lib/nbproject/project.xml	Sat Aug 15 13:14:20 2015 +0200
    14.3 @@ -68,6 +68,14 @@
    14.4                      </run-dependency>
    14.5                  </dependency>
    14.6                  <dependency>
    14.7 +                    <code-name-base>org.netbeans.modules.editor.tools.storage</code-name-base>
    14.8 +                    <build-prerequisite/>
    14.9 +                    <compile-dependency/>
   14.10 +                    <run-dependency>
   14.11 +                        <specification-version>1.6</specification-version>
   14.12 +                    </run-dependency>
   14.13 +                </dependency>
   14.14 +                <dependency>
   14.15                      <code-name-base>org.netbeans.modules.jackpot30.remoting.api</code-name-base>
   14.16                      <build-prerequisite/>
   14.17                      <compile-dependency/>
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/cmdline/lib/src/org/netbeans/modules/jackpot30/cmdline/lib/Utils.java	Sat Aug 15 13:14:20 2015 +0200
    15.3 @@ -0,0 +1,94 @@
    15.4 +/*
    15.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    15.6 + *
    15.7 + * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
    15.8 + *
    15.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   15.10 + * Other names may be trademarks of their respective owners.
   15.11 + *
   15.12 + * The contents of this file are subject to the terms of either the GNU
   15.13 + * General Public License Version 2 only ("GPL") or the Common
   15.14 + * Development and Distribution License("CDDL") (collectively, the
   15.15 + * "License"). You may not use this file except in compliance with the
   15.16 + * License. You can obtain a copy of the License at
   15.17 + * http://www.netbeans.org/cddl-gplv2.html
   15.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   15.19 + * specific language governing permissions and limitations under the
   15.20 + * License.  When distributing the software, include this License Header
   15.21 + * Notice in each file and include the License file at
   15.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   15.23 + * particular file as subject to the "Classpath" exception as provided
   15.24 + * by Oracle in the GPL Version 2 section of the License file that
   15.25 + * accompanied this code. If applicable, add the following below the
   15.26 + * License Header, with the fields enclosed by brackets [] replaced by
   15.27 + * your own identifying information:
   15.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   15.29 + *
   15.30 + * If you wish your version of this file to be governed by only the CDDL
   15.31 + * or only the GPL Version 2, indicate your decision by adding
   15.32 + * "[Contributor] elects to include this software in this distribution
   15.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   15.34 + * single choice of license, a recipient has the option to distribute
   15.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   15.36 + * to extend the choice of license to its licensees as provided above.
   15.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   15.38 + * Version 2 license, then the option applies only if the new code is
   15.39 + * made subject to such option by the copyright holder.
   15.40 + *
   15.41 + * Contributor(s):
   15.42 + *
   15.43 + * Portions Copyrighted 2015 Sun Microsystems, Inc.
   15.44 + */
   15.45 +package org.netbeans.modules.jackpot30.cmdline.lib;
   15.46 +
   15.47 +import java.util.HashMap;
   15.48 +import java.util.Map;
   15.49 +import java.util.Map.Entry;
   15.50 +import org.netbeans.modules.java.hints.providers.spi.HintDescription;
   15.51 +
   15.52 +/**
   15.53 + *
   15.54 + * @author lahvac
   15.55 + */
   15.56 +public class Utils {
   15.57 +
   15.58 +    public static Map<String, String> computeId2DisplayName(Iterable<? extends HintDescription> descs) {
   15.59 +        final Map<String, String> id2DisplayName = new HashMap<>();
   15.60 +
   15.61 +        for (HintDescription hd : descs) {
   15.62 +            if (hd.getMetadata() != null) {
   15.63 +                id2DisplayName.put(hd.getMetadata().id, hd.getMetadata().displayName);
   15.64 +            }
   15.65 +        }
   15.66 +
   15.67 +        return id2DisplayName;
   15.68 +    }
   15.69 +
   15.70 +    public static String categoryName(String id, Map<String, String> id2DisplayName) {
   15.71 +        if (id != null && id.startsWith("text/x-java:")) {
   15.72 +            id = id.substring("text/x-java:".length());
   15.73 +        }
   15.74 +
   15.75 +        String idDisplayName = id2DisplayName.get(id);
   15.76 +
   15.77 +        if (idDisplayName == null) {
   15.78 +            idDisplayName = "unknown";
   15.79 +        }
   15.80 +
   15.81 +        for (Entry<String, String> remap : toIdRemap.entrySet()) {
   15.82 +            idDisplayName = idDisplayName.replace(remap.getKey(), remap.getValue());
   15.83 +        }
   15.84 +
   15.85 +        idDisplayName = idDisplayName.replaceAll("[^A-Za-z0-9]", "_").replaceAll("_+", "_");
   15.86 +
   15.87 +        idDisplayName = "[" + idDisplayName + "] ";
   15.88 +
   15.89 +        return idDisplayName;
   15.90 +    }
   15.91 +
   15.92 +    private static final Map<String, String> toIdRemap = new HashMap<String, String>() {{
   15.93 +        put("==", "equals");
   15.94 +        put("!=", "not_equals");
   15.95 +    }};
   15.96 +
   15.97 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateAPLibJar.java	Sat Aug 15 13:14:20 2015 +0200
    16.3 @@ -0,0 +1,62 @@
    16.4 +/*
    16.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
    16.6 + *
    16.7 + * Copyright 2010 Oracle and/or its affiliates. All rights reserved.
    16.8 + *
    16.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
   16.10 + * Other names may be trademarks of their respective owners.
   16.11 + *
   16.12 + * The contents of this file are subject to the terms of either the GNU
   16.13 + * General Public License Version 2 only ("GPL") or the Common
   16.14 + * Development and Distribution License("CDDL") (collectively, the
   16.15 + * "License"). You may not use this file except in compliance with the
   16.16 + * License. You can obtain a copy of the License at
   16.17 + * http://www.netbeans.org/cddl-gplv2.html
   16.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
   16.19 + * specific language governing permissions and limitations under the
   16.20 + * License.  When distributing the software, include this License Header
   16.21 + * Notice in each file and include the License file at
   16.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
   16.23 + * particular file as subject to the "Classpath" exception as provided
   16.24 + * by Oracle in the GPL Version 2 section of the License file that
   16.25 + * accompanied this code. If applicable, add the following below the
   16.26 + * License Header, with the fields enclosed by brackets [] replaced by
   16.27 + * your own identifying information:
   16.28 + * "Portions Copyrighted [year] [name of copyright owner]"
   16.29 + *
   16.30 + * If you wish your version of this file to be governed by only the CDDL
   16.31 + * or only the GPL Version 2, indicate your decision by adding
   16.32 + * "[Contributor] elects to include this software in this distribution
   16.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
   16.34 + * single choice of license, a recipient has the option to distribute
   16.35 + * your version of this file under either the CDDL, the GPL Version 2 or
   16.36 + * to extend the choice of license to its licensees as provided above.
   16.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
   16.38 + * Version 2 license, then the option applies only if the new code is
   16.39 + * made subject to such option by the copyright holder.
   16.40 + *
   16.41 + * Contributor(s):
   16.42 + *
   16.43 + * Portions Copyrighted 2010 Sun Microsystems, Inc.
   16.44 + */
   16.45 +
   16.46 +package org.netbeans.modules.jackpot30.cmdline.lib;
   16.47 +
   16.48 +import org.netbeans.modules.editor.tools.storage.api.ToolPreferences;
   16.49 +
   16.50 +/**
   16.51 + *
   16.52 + * @author lahvac
   16.53 + */
   16.54 +public class CreateAPLibJar extends CreateStandaloneLibJarNoEscape {
   16.55 +
   16.56 +    public CreateAPLibJar(String name) {
   16.57 +        super(name, "jackpot-ap-lib");
   16.58 +    }
   16.59 +
   16.60 +    @Override
   16.61 +    protected Info computeInfo() {
   16.62 +        return super.computeInfo().addAdditionalRoots(ToolPreferences.class.getName()).setEscapeJavaxLang();
   16.63 +    }
   16.64 +
   16.65 +}
    17.1 --- a/cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneJar.java	Sat Aug 15 08:14:07 2015 +0200
    17.2 +++ b/cmdline/lib/test/unit/src/org/netbeans/modules/jackpot30/cmdline/lib/CreateStandaloneJar.java	Sat Aug 15 13:14:20 2015 +0200
    17.3 @@ -63,7 +63,9 @@
    17.4  import java.util.Map;
    17.5  import java.util.Map.Entry;
    17.6  import java.util.Set;
    17.7 +import java.util.TreeMap;
    17.8  import java.util.jar.JarOutputStream;
    17.9 +import java.util.jar.Manifest;
   17.10  import java.util.regex.Pattern;
   17.11  import java.util.zip.ZipEntry;
   17.12  import org.apache.lucene.analysis.tokenattributes.OffsetAttributeImpl;
   17.13 @@ -141,7 +143,7 @@
   17.14      protected abstract Info computeInfo();
   17.15  
   17.16      public void createCompiler(File targetCompilerFile, File targetHintsFile) throws Exception {
   17.17 -        JarOutputStream out = new JarOutputStream(new FileOutputStream(targetCompilerFile));
   17.18 +        Map<String, byte[]> out = new TreeMap<>();
   17.19          List<String> toProcess = new LinkedList<String>(INCLUDE);
   17.20  
   17.21          for (FSWrapper.ClassWrapper cw : FSWrapper.listClasses()) {
   17.22 @@ -212,21 +214,23 @@
   17.23                  toProcess.add(classFromCP.getInternalName().replace('/', '.'));
   17.24              }
   17.25  
   17.26 -            out.putNextEntry(new ZipEntry(escapeJavaxLang(info, fileName)));
   17.27 -            out.write(escapeJavaxLang(info, bytes));
   17.28 +            out.put(escapeJavaxLang(info, fileName), escapeJavaxLang(info, bytes));
   17.29  
   17.30              if (COPY_REGISTRATION.contains(fqn) || info.copyMetaInfRegistration.contains(fqn)) {
   17.31                  String serviceName = "META-INF/services/" + fqn;
   17.32                  Enumeration<URL> resources = this.getClass().getClassLoader().getResources(serviceName);
   17.33  
   17.34                  if (resources.hasMoreElements()) {
   17.35 -                    out.putNextEntry(new ZipEntry(escapeJavaxLang(info, serviceName)));
   17.36 +                    try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
   17.37 +                        while (resources.hasMoreElements()) {
   17.38 +                            URL res = resources.nextElement();
   17.39  
   17.40 -                    while (resources.hasMoreElements()) {
   17.41 -                        URL res = resources.nextElement();
   17.42 +                            buffer.write(readFile(res));
   17.43 +                        }
   17.44  
   17.45 -                        out.write(readFile(res));
   17.46 +                        out.put(escapeJavaxLang(info, serviceName), buffer.toByteArray());
   17.47                      }
   17.48 +
   17.49                  }
   17.50              }
   17.51  
   17.52 @@ -275,8 +279,10 @@
   17.53              }
   17.54          }
   17.55  
   17.56 -        out.putNextEntry(new ZipEntry(escapeJavaxLang(info, "META-INF/generated-layer.xml")));
   17.57 -        XMLUtil.write(main, out, "UTF-8");
   17.58 +        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
   17.59 +        XMLUtil.write(main, bytes, "UTF-8");
   17.60 +        bytes.close();
   17.61 +        out.put(escapeJavaxLang(info, "META-INF/generated-layer.xml"), escapeJavaxLang(info, bytes.toByteArray()));
   17.62  
   17.63          List<MetaInfRegistration> registrations = new ArrayList<MetaInfRegistration>();
   17.64  
   17.65 @@ -310,7 +316,21 @@
   17.66              addMETA_INFRegistration(out, info, e.getValue());
   17.67          }
   17.68  
   17.69 -        out.close();
   17.70 +        try (JarOutputStream outStream = new JarOutputStream(new FileOutputStream(targetCompilerFile))) {
   17.71 +            Set<String> seenDirs = new HashSet<>();
   17.72 +            for (Entry<String, byte[]> e : out.entrySet()) {
   17.73 +                String[] parts = e.getKey().split("/");
   17.74 +                StringBuilder dir = new StringBuilder();
   17.75 +                for (int i = 0; i < parts.length - 1; i++) {
   17.76 +                    dir.append(parts[i]);
   17.77 +                    dir.append("/");
   17.78 +                    if (seenDirs.add(dir.toString()))
   17.79 +                        outStream.putNextEntry(new ZipEntry(dir.toString()));
   17.80 +                }
   17.81 +                outStream.putNextEntry(new ZipEntry(e.getKey()));
   17.82 +                outStream.write(e.getValue());
   17.83 +            }
   17.84 +        }
   17.85  
   17.86          Writer hints = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetHintsFile), "UTF-8"));
   17.87  
   17.88 @@ -379,7 +399,7 @@
   17.89  
   17.90      }
   17.91  
   17.92 -    private void copyResources(JarOutputStream out, Info info, Set<String> res) throws IOException {
   17.93 +    private void copyResources(Map<String, byte[]> out, Info info, Set<String> res) throws IOException {
   17.94          for (String resource : res) {
   17.95              URL url = this.getClass().getClassLoader().getResource(resource);
   17.96  
   17.97 @@ -387,8 +407,7 @@
   17.98                  continue;
   17.99              }
  17.100              
  17.101 -            out.putNextEntry(new ZipEntry(escapeJavaxLang(info, resource)));
  17.102 -            out.write(readFile(url));
  17.103 +            out.put(escapeJavaxLang(info, resource), readFile(url));
  17.104          }
  17.105      }
  17.106  
  17.107 @@ -410,25 +429,35 @@
  17.108          return data.toByteArray();
  17.109      }
  17.110  
  17.111 -    private static void addMETA_INFRegistration(JarOutputStream out, Info info, Iterable<MetaInfRegistration> registrations) throws IOException {
  17.112 +    private static void addMETA_INFRegistration(Map<String, byte[]> out, Info info, Iterable<MetaInfRegistration> registrations) throws IOException {
  17.113          String apiClassName = registrations.iterator().next().apiClassName;
  17.114 -        out.putNextEntry(new ZipEntry(escapeJavaxLang(info, "META-INF/services/" + apiClassName)));
  17.115  
  17.116 -        for (MetaInfRegistration r : registrations) {
  17.117 -            assert apiClassName.equals(r.apiClassName);
  17.118 -            out.write(r.implClassName.getBytes("UTF-8"));
  17.119 -            out.write("\n".getBytes("UTF-8"));
  17.120 -            if (r.pos != null) {
  17.121 -                out.write(("#position=" + r.pos.toString() + "\n").getBytes("UTF-8"));
  17.122 +        try (ByteArrayOutputStream buffer = new ByteArrayOutputStream()) {
  17.123 +            for (MetaInfRegistration r : registrations) {
  17.124 +                assert apiClassName.equals(r.apiClassName);
  17.125 +                buffer.write(r.implClassName.getBytes("UTF-8"));
  17.126 +                buffer.write("\n".getBytes("UTF-8"));
  17.127 +                if (r.pos != null) {
  17.128 +                    buffer.write(("#position=" + r.pos.toString() + "\n").getBytes("UTF-8"));
  17.129 +                }
  17.130              }
  17.131 +
  17.132 +            out.put(escapeJavaxLang(info, "META-INF/services/" + apiClassName), buffer.toByteArray());
  17.133          }
  17.134      }
  17.135  
  17.136      private static final Map<String, String> replaceWhat2With = new LinkedHashMap<String, String>();
  17.137  
  17.138      static {
  17.139 +        replaceWhat2With.put("javax/annotation/processing/", "jpt30/annotation/processing/");
  17.140          replaceWhat2With.put("javax/lang/", "jpt30/lang/");
  17.141          replaceWhat2With.put("javax/tools/", "jpt30/tools/");
  17.142 +        replaceWhat2With.put("com/sun/tools/", "jpt/sun/tools/");
  17.143 +        replaceWhat2With.put("com/sun/source/", "jpt/sun/source/");
  17.144 +
  17.145 +        for (String originalKey : new HashSet<>(replaceWhat2With.keySet())) {
  17.146 +            replaceWhat2With.put(originalKey.replace('/', '.'), replaceWhat2With.get(originalKey).replace('/', '.'));
  17.147 +        }
  17.148      }
  17.149              
  17.150  
  17.151 @@ -509,6 +538,7 @@
  17.152              CompilerSettingsImpl.class.getName(),
  17.153              NbMutexEventProvider.class.getName(),
  17.154              DefaultMutexImplementation.class.getName(),
  17.155 +            Utils.class.getName(),
  17.156              IndexerControl.class.getName()
  17.157          ));
  17.158  
    18.1 --- a/cmdline/nbproject/project.properties	Sat Aug 15 08:14:07 2015 +0200
    18.2 +++ b/cmdline/nbproject/project.properties	Sat Aug 15 13:14:20 2015 +0200
    18.3 @@ -1,7 +1,9 @@
    18.4  modules=\
    18.5      ${project.org.netbeans.modules.jackpot30.cmdline.lib}:\
    18.6      ${project.org.netbeans.modules.jackpot30.compiler}:\
    18.7 -    ${project.org.netbeans.modules.jackpot30.cmdline}
    18.8 +    ${project.org.netbeans.modules.jackpot30.cmdline}:\
    18.9 +    ${project.org.netbeans.modules.jackpot30.ap}
   18.10 +project.org.netbeans.modules.jackpot30.ap=ap
   18.11  project.org.netbeans.modules.jackpot30.cmdline=tool
   18.12  project.org.netbeans.modules.jackpot30.cmdline.lib=lib
   18.13  project.org.netbeans.modules.jackpot30.compiler=compiler
    19.1 --- a/cmdline/tool/nbproject/genfiles.properties	Sat Aug 15 08:14:07 2015 +0200
    19.2 +++ b/cmdline/tool/nbproject/genfiles.properties	Sat Aug 15 13:14:20 2015 +0200
    19.3 @@ -3,6 +3,6 @@
    19.4  build.xml.stylesheet.CRC32=a56c6a5b@1.44
    19.5  # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml.
    19.6  # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you.
    19.7 -nbproject/build-impl.xml.data.CRC32=28a6110c
    19.8 +nbproject/build-impl.xml.data.CRC32=c79833a9
    19.9  nbproject/build-impl.xml.script.CRC32=08f1fb11
   19.10  nbproject/build-impl.xml.stylesheet.CRC32=238281d1@2.70
    20.1 --- a/cmdline/tool/nbproject/project.xml	Sat Aug 15 08:14:07 2015 +0200
    20.2 +++ b/cmdline/tool/nbproject/project.xml	Sat Aug 15 13:14:20 2015 +0200
    20.3 @@ -74,6 +74,14 @@
    20.4                      </run-dependency>
    20.5                  </dependency>
    20.6                  <dependency>
    20.7 +                    <code-name-base>org.netbeans.modules.jackpot30.cmdline.lib</code-name-base>
    20.8 +                    <build-prerequisite/>
    20.9 +                    <compile-dependency/>
   20.10 +                    <run-dependency>
   20.11 +                        <implementation-version/>
   20.12 +                    </run-dependency>
   20.13 +                </dependency>
   20.14 +                <dependency>
   20.15                      <code-name-base>org.netbeans.modules.jackpot30.indexing</code-name-base>
   20.16                      <build-prerequisite/>
   20.17                      <compile-dependency/>
    21.1 --- a/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java	Sat Aug 15 08:14:07 2015 +0200
    21.2 +++ b/cmdline/tool/src/org/netbeans/modules/jackpot30/cmdline/Main.java	Sat Aug 15 13:14:20 2015 +0200
    21.3 @@ -84,6 +84,7 @@
    21.4  import org.netbeans.api.java.source.ModificationResult;
    21.5  import org.netbeans.api.project.ui.*;
    21.6  import org.netbeans.core.startup.MainLookup;
    21.7 +import org.netbeans.modules.jackpot30.cmdline.lib.Utils;
    21.8  import org.netbeans.modules.jackpot30.ui.settings.XMLHintPreferences;
    21.9  import org.netbeans.modules.java.hints.jackpot.spi.PatternConvertor;
   21.10  import org.netbeans.modules.java.hints.providers.spi.HintDescription;
   21.11 @@ -465,14 +466,7 @@
   21.12      }
   21.13      
   21.14      private static void findOccurrences(Iterable<? extends HintDescription> descs, Folder[] sourceRoot, ProgressHandleWrapper progress, HintsSettings settings, File out) throws IOException {
   21.15 -        final Map<String, String> id2DisplayName = new HashMap<String, String>();
   21.16 -
   21.17 -        for (HintDescription hd : descs) {
   21.18 -            if (hd.getMetadata() != null) {
   21.19 -                id2DisplayName.put(hd.getMetadata().id, hd.getMetadata().displayName);
   21.20 -            }
   21.21 -        }
   21.22 -
   21.23 +        final Map<String, String> id2DisplayName = Utils.computeId2DisplayName(descs);
   21.24          ProgressHandleWrapper w = progress.startNextPartWithEmbedding(1, 1);
   21.25          BatchResult occurrences = BatchSearch.findOccurrences(descs, Scopes.specifiedFoldersScope(sourceRoot), w, settings);
   21.26  
   21.27 @@ -508,36 +502,12 @@
   21.28  
   21.29          b.append('^');
   21.30  
   21.31 -        String id = error.getId();
   21.32 -
   21.33 -        if (id != null && id.startsWith("text/x-java:")) {
   21.34 -            id = id.substring("text/x-java:".length());
   21.35 -        }
   21.36 -
   21.37 -        String idDisplayName = id2DisplayName.get(id);
   21.38 -
   21.39 -        if (idDisplayName == null) {
   21.40 -            idDisplayName = "unknown";
   21.41 -        }
   21.42 -
   21.43 -        for (Entry<String, String> remap : toIdRemap.entrySet()) {
   21.44 -            idDisplayName = idDisplayName.replace(remap.getKey(), remap.getValue());
   21.45 -        }
   21.46 -
   21.47 -        idDisplayName = idDisplayName.replaceAll("[^A-Za-z0-9]", "_").replaceAll("_+", "_");
   21.48 -
   21.49 -        idDisplayName = "[" + idDisplayName + "] ";
   21.50 -
   21.51 +        String idDisplayName = Utils.categoryName(error.getId(), id2DisplayName);
   21.52          System.out.println(FileUtil.getFileDisplayName(error.getFile()) + ":" + (lineNumber + 1) + ": warning: " + idDisplayName + error.getDescription());
   21.53          System.out.println(line);
   21.54          System.out.println(b);
   21.55      }
   21.56  
   21.57 -    private static final Map<String, String> toIdRemap = new HashMap<String, String>() {{
   21.58 -        put("==", "equals");
   21.59 -        put("!=", "not_equals");
   21.60 -    }};
   21.61 -
   21.62      private static void apply(Iterable<? extends HintDescription> descs, Folder[] sourceRoot, ProgressHandleWrapper progress, HintsSettings settings, File out) throws IOException {
   21.63          ProgressHandleWrapper w = progress.startNextPartWithEmbedding(1, 1);
   21.64          BatchResult occurrences = BatchSearch.findOccurrences(descs, Scopes.specifiedFoldersScope(sourceRoot), w, settings);