cmdline/compiler/src/org/netbeans/modules/jackpot30/compiler/HintsAnnotationProcessingImpl.java
author Jan Lahoda <jlahoda@netbeans.org>
Sun, 03 Feb 2013 00:13:11 +0100
branchjdk8
changeset 926 d1e1adedc8cc
parent 812 8d0ac461ca68
child 941 4235164505af
permissions -rw-r--r--
Adjusting to NB-JDK8 changes
jlahoda@299
     1
/*
jlahoda@299
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jlahoda@299
     3
 *
jlahoda@518
     4
 * Copyright 2009-2011 Sun Microsystems, Inc. All rights reserved.
jlahoda@299
     5
 *
jlahoda@299
     6
 * The contents of this file are subject to the terms of either the GNU
jlahoda@299
     7
 * General Public License Version 2 only ("GPL") or the Common
jlahoda@299
     8
 * Development and Distribution License("CDDL") (collectively, the
jlahoda@299
     9
 * "License"). You may not use this file except in compliance with the
jlahoda@299
    10
 * License. You can obtain a copy of the License at
jlahoda@299
    11
 * http://www.netbeans.org/cddl-gplv2.html
jlahoda@299
    12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jlahoda@299
    13
 * specific language governing permissions and limitations under the
jlahoda@299
    14
 * License.  When distributing the software, include this License Header
jlahoda@299
    15
 * Notice in each file and include the License file at
jlahoda@299
    16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
jlahoda@299
    17
 * particular file as subject to the "Classpath" exception as provided
jlahoda@299
    18
 * by Sun in the GPL Version 2 section of the License file that
jlahoda@299
    19
 * accompanied this code. If applicable, add the following below the
jlahoda@299
    20
 * License Header, with the fields enclosed by brackets [] replaced by
jlahoda@299
    21
 * your own identifying information:
jlahoda@299
    22
 * "Portions Copyrighted [year] [name of copyright owner]"
jlahoda@299
    23
 *
jlahoda@299
    24
 * If you wish your version of this file to be governed by only the CDDL
jlahoda@299
    25
 * or only the GPL Version 2, indicate your decision by adding
jlahoda@299
    26
 * "[Contributor] elects to include this software in this distribution
jlahoda@299
    27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jlahoda@299
    28
 * single choice of license, a recipient has the option to distribute
jlahoda@299
    29
 * your version of this file under either the CDDL, the GPL Version 2 or
jlahoda@299
    30
 * to extend the choice of license to its licensees as provided above.
jlahoda@299
    31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jlahoda@299
    32
 * Version 2 license, then the option applies only if the new code is
jlahoda@299
    33
 * made subject to such option by the copyright holder.
jlahoda@299
    34
 *
jlahoda@299
    35
 * Contributor(s):
jlahoda@299
    36
 *
jlahoda@518
    37
 * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
jlahoda@299
    38
 */
jlahoda@299
    39
package org.netbeans.modules.jackpot30.compiler;
jlahoda@299
    40
jlahoda@926
    41
import com.sun.source.util.JavacTask;
jlahoda@520
    42
import com.sun.source.util.TaskEvent;
jlahoda@520
    43
import com.sun.source.util.TaskListener;
jlahoda@299
    44
import com.sun.source.util.TreePath;
jlahoda@363
    45
import com.sun.source.util.Trees;
jlahoda@363
    46
import com.sun.tools.javac.api.JavacTrees;
jlahoda@926
    47
import com.sun.tools.javac.api.MultiTaskListener;
jlahoda@375
    48
import com.sun.tools.javac.jvm.Gen;
jlahoda@812
    49
import com.sun.tools.javac.parser.ParserFactory;
jlahoda@299
    50
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
jlahoda@299
    51
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
jlahoda@299
    52
import com.sun.tools.javac.util.Context;
jlahoda@812
    53
import com.sun.tools.javac.util.Context.Key;
jlahoda@299
    54
import com.sun.tools.javac.util.Log;
jlahoda@375
    55
import com.sun.tools.javac.util.Options;
jlahoda@299
    56
import java.io.File;
jlahoda@375
    57
import java.lang.reflect.Field;
jlahoda@299
    58
import java.net.URL;
jlahoda@299
    59
import java.util.Collection;
jlahoda@299
    60
import java.util.HashSet;
jlahoda@299
    61
import java.util.LinkedList;
jlahoda@299
    62
import java.util.List;
jlahoda@299
    63
import java.util.Set;
jlahoda@363
    64
import javax.annotation.processing.AbstractProcessor;
jlahoda@520
    65
import javax.annotation.processing.ProcessingEnvironment;
jlahoda@299
    66
import javax.annotation.processing.Processor;
jlahoda@363
    67
import javax.annotation.processing.RoundEnvironment;
jlahoda@299
    68
import javax.annotation.processing.SupportedAnnotationTypes;
jlahoda@299
    69
import javax.lang.model.SourceVersion;
jlahoda@299
    70
import javax.lang.model.element.TypeElement;
jlahoda@520
    71
import javax.lang.model.util.ElementFilter;
jlahoda@299
    72
import javax.tools.Diagnostic.Kind;
jlahoda@299
    73
import javax.tools.JavaFileManager;
jlahoda@299
    74
import javax.tools.JavaFileObject;
jlahoda@299
    75
import javax.tools.StandardJavaFileManager;
jlahoda@299
    76
import javax.tools.StandardLocation;
jlahoda@299
    77
import org.netbeans.api.java.classpath.ClassPath;
jlahoda@299
    78
import org.netbeans.api.java.source.ClasspathInfo;
jlahoda@299
    79
import org.netbeans.api.java.source.CompilationInfoHack;
jlahoda@812
    80
import org.netbeans.lib.nbjavac.services.NBParserFactory;
jlahoda@518
    81
import org.netbeans.modules.jackpot30.compiler.AbstractHintsAnnotationProcessing.Reporter;
jlahoda@299
    82
import org.netbeans.spi.java.classpath.support.ClassPathSupport;
jlahoda@299
    83
import org.openide.filesystems.FileUtil;
jlahoda@299
    84
import org.openide.util.Lookup;
jlahoda@299
    85
import org.openide.util.lookup.ServiceProvider;
jlahoda@299
    86
jlahoda@299
    87
/**
jlahoda@299
    88
 *
jlahoda@299
    89
 * @author lahvac
jlahoda@299
    90
 */
jlahoda@299
    91
@SupportedAnnotationTypes("*")
jlahoda@299
    92
@ServiceProvider(service=Processor.class)
jlahoda@518
    93
public final class HintsAnnotationProcessingImpl extends AbstractProcessor {
jlahoda@370
    94
jlahoda@520
    95
    private final Collection<String> seenTypes = new LinkedList<String>();
jlahoda@520
    96
    private final Collection<AbstractHintsAnnotationProcessing> processors = new LinkedList<AbstractHintsAnnotationProcessing>();
jlahoda@299
    97
jlahoda@299
    98
    @Override
jlahoda@520
    99
    public synchronized void init(ProcessingEnvironment processingEnv) {
jlahoda@520
   100
        super.init(processingEnv);
jlahoda@299
   101
jlahoda@518
   102
        for (AbstractHintsAnnotationProcessing p : Lookup.getDefault().lookupAll(AbstractHintsAnnotationProcessing.class)) {
jlahoda@518
   103
            if (p.initialize(processingEnv)) {
jlahoda@518
   104
                processors.add(p);
jlahoda@299
   105
            }
jlahoda@363
   106
        }
jlahoda@299
   107
jlahoda@520
   108
        if (processors.isEmpty()) {
jlahoda@520
   109
            return;
jlahoda@520
   110
        }
jlahoda@520
   111
jlahoda@520
   112
        if (!(processingEnv instanceof JavacProcessingEnvironment)) {
jlahoda@520
   113
            throw new UnsupportedOperationException("Not a JavacProcessingEnvironment");
jlahoda@520
   114
        }
jlahoda@520
   115
jlahoda@520
   116
        Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
jlahoda@926
   117
        
jlahoda@926
   118
        MultiTaskListener.instance(c).add(new TaskListenerImpl());
jlahoda@520
   119
    }
jlahoda@520
   120
jlahoda@520
   121
    @Override
jlahoda@520
   122
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
jlahoda@520
   123
        for (TypeElement type : ElementFilter.typesIn(roundEnv.getRootElements())) {
jlahoda@520
   124
            seenTypes.add(type.getQualifiedName().toString());
jlahoda@520
   125
        }
jlahoda@520
   126
jlahoda@520
   127
        if (roundEnv.processingOver()) {
jlahoda@520
   128
            try {
jlahoda@520
   129
                //XXX: workarounding a bug in CRTable (see HintsAnnotationProcessingTest.testCRTable):
jlahoda@520
   130
                Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
jlahoda@520
   131
                Options.instance(c).remove("-Xjcov");
jlahoda@520
   132
                Field f = Gen.class.getDeclaredField("genCrt");
jlahoda@520
   133
                f.setAccessible(true);
jlahoda@520
   134
                f.set(Gen.instance(c), false);
jlahoda@520
   135
            } catch (Exception e) {
jlahoda@520
   136
                e.printStackTrace();
jlahoda@520
   137
            }
jlahoda@520
   138
        }
jlahoda@520
   139
        return false;
jlahoda@520
   140
    }
jlahoda@520
   141
jlahoda@520
   142
    private void doProcessing(TypeElement type) {
jlahoda@520
   143
        if (!seenTypes.remove(type.getQualifiedName().toString())) return;
jlahoda@520
   144
        
jlahoda@520
   145
        Context c = ((JavacProcessingEnvironment) processingEnv).getContext();
jlahoda@520
   146
        StandardJavaFileManager s = (StandardJavaFileManager) c.get(JavaFileManager.class);
jlahoda@520
   147
        ClassPath boot = computeClassPath(s, StandardLocation.PLATFORM_CLASS_PATH);
jlahoda@520
   148
        ClassPath compile = computeClassPath(s, StandardLocation.CLASS_PATH);
jlahoda@520
   149
        ClassPath source = computeClassPath(s, StandardLocation.SOURCE_PATH);
jlahoda@520
   150
        Trees trees = JavacTrees.instance(c);
jlahoda@520
   151
        final Log log = Log.instance(c);
jlahoda@812
   152
        final Key<ParserFactory> key = ParserFactoryKeyAccessor.getContextKey();
jlahoda@812
   153
        ParserFactory origParserFactory = c.get(key);
jlahoda@812
   154
        c.put(key, (ParserFactory) null);
jlahoda@812
   155
        NBParserFactory.preRegister(c);
jlahoda@520
   156
jlahoda@518
   157
        try {
jlahoda@520
   158
            TreePath elTree = trees.getPath(type);
jlahoda@520
   159
            JCCompilationUnit cut = (JCCompilationUnit) elTree.getCompilationUnit();
jlahoda@520
   160
jlahoda@520
   161
            if (!cut.sourcefile.toUri().isAbsolute()) {
jlahoda@520
   162
                processingEnv.getMessager().printMessage(Kind.NOTE, "Not an absolute URI: " + cut.sourcefile.toUri().toASCIIString(), type);
jlahoda@520
   163
                return ; //XXX
jlahoda@520
   164
            }
jlahoda@520
   165
jlahoda@520
   166
            CompilationInfoHack info = new CompilationInfoHack(c, ClasspathInfo.create(boot, compile, source), cut);
jlahoda@520
   167
            JavaFileObject origSourceFile = log.currentSourceFile();
jlahoda@520
   168
jlahoda@520
   169
            try {
jlahoda@520
   170
                log.useSource(cut.sourcefile);
jlahoda@520
   171
jlahoda@520
   172
                for (AbstractHintsAnnotationProcessing p : processors) {
jlahoda@520
   173
                    p.doProcess(info, processingEnv, new Reporter() {
jlahoda@520
   174
                        @Override public void warning(int offset, String message) {
jlahoda@520
   175
                            log.warning(offset, "proc.messager", message);
jlahoda@520
   176
                        }
jlahoda@520
   177
                    });
jlahoda@518
   178
                }
jlahoda@520
   179
            } finally {
jlahoda@520
   180
                log.useSource(origSourceFile);
jlahoda@520
   181
            }
jlahoda@520
   182
        } finally {
jlahoda@520
   183
            if (seenTypes.isEmpty()) {
jlahoda@520
   184
                for (AbstractHintsAnnotationProcessing p : processors) {
jlahoda@520
   185
                    p.finish();
jlahoda@518
   186
                }
jlahoda@518
   187
            }
jlahoda@812
   188
jlahoda@812
   189
            c.put(key, (ParserFactory) null);
jlahoda@812
   190
            c.put(key, origParserFactory);
jlahoda@299
   191
        }
jlahoda@299
   192
    }
jlahoda@299
   193
jlahoda@299
   194
    @Override
jlahoda@299
   195
    public SourceVersion getSupportedSourceVersion() {
jlahoda@299
   196
        return SourceVersion.latest();
jlahoda@299
   197
    }
jlahoda@299
   198
jlahoda@370
   199
    @Override
jlahoda@370
   200
    public Set<String> getSupportedOptions() {
jlahoda@518
   201
        Set<String> options = new HashSet<String>();
jlahoda@518
   202
jlahoda@518
   203
        for (AbstractHintsAnnotationProcessing p : Lookup.getDefault().lookupAll(AbstractHintsAnnotationProcessing.class)) {
jlahoda@518
   204
            options.addAll(p.getSupportedOptions());
jlahoda@518
   205
        }
jlahoda@518
   206
jlahoda@518
   207
        return options;
jlahoda@370
   208
    }
jlahoda@370
   209
jlahoda@299
   210
    private static ClassPath computeClassPath(StandardJavaFileManager m, StandardLocation kind) {
jlahoda@299
   211
        List<URL> urls = new LinkedList<URL>();
jlahoda@299
   212
        Iterable<? extends File> files = m.getLocation(kind);
jlahoda@299
   213
jlahoda@299
   214
        if (files != null) {
jlahoda@299
   215
            for (File f : files) {
jlahoda@557
   216
                urls.add(FileUtil.urlForArchiveOrDir(FileUtil.normalizeFile(f)));
jlahoda@299
   217
            }
jlahoda@299
   218
        }
jlahoda@299
   219
jlahoda@299
   220
        return ClassPathSupport.createClassPath(urls.toArray(new URL[0]));
jlahoda@299
   221
    }
jlahoda@299
   222
jlahoda@520
   223
    private final class TaskListenerImpl implements TaskListener {
jlahoda@363
   224
jlahoda@926
   225
        public TaskListenerImpl() { }
jlahoda@363
   226
jlahoda@520
   227
        @Override
jlahoda@520
   228
        public void started(TaskEvent te) {
jlahoda@520
   229
        }
jlahoda@363
   230
jlahoda@520
   231
        @Override
jlahoda@520
   232
        public void finished(TaskEvent te) {
jlahoda@520
   233
            if (te.getKind() == TaskEvent.Kind.ANALYZE) {
jlahoda@520
   234
                TypeElement toProcess = te.getTypeElement();
jlahoda@363
   235
jlahoda@520
   236
                assert toProcess != null;
jlahoda@520
   237
                doProcessing(toProcess);
jlahoda@520
   238
            }
jlahoda@363
   239
        }
jlahoda@520
   240
jlahoda@363
   241
    }
jlahoda@363
   242
jlahoda@812
   243
    private static final class ParserFactoryKeyAccessor extends ParserFactory {
jlahoda@812
   244
        ParserFactoryKeyAccessor() {
jlahoda@812
   245
            super(null);
jlahoda@812
   246
        }
jlahoda@812
   247
        public static Key<ParserFactory> getContextKey() {
jlahoda@812
   248
            return parserFactoryKey;
jlahoda@812
   249
        }
jlahoda@812
   250
    }
jlahoda@299
   251
jlahoda@299
   252
jlahoda@299
   253
    static {
jlahoda@299
   254
        try {
jlahoda@518
   255
            ClassLoader l = HintsAnnotationProcessingImpl.class.getClassLoader();
jlahoda@299
   256
jlahoda@299
   257
            if (l == null) {
jlahoda@299
   258
                l = ClassLoader.getSystemClassLoader();
jlahoda@299
   259
            }
jlahoda@299
   260
jlahoda@299
   261
            l.setClassAssertionStatus("org.netbeans.api.java.source.CompilationInfo", false);
jlahoda@299
   262
        } catch (Throwable t) {
jlahoda@299
   263
            t.printStackTrace();
jlahoda@299
   264
        }
jlahoda@299
   265
    }
jlahoda@299
   266
jlahoda@299
   267
}