sandbox/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java
branchdonation_review
changeset 1043 57843026e60b
parent 1027 205b7632914c
parent 1040 f7b6892fd754
child 1044 7feb751ba76b
     1.1 --- a/sandbox/java.hints/spi.java.hints/src/org/netbeans/modules/java/hints/spiimpl/batch/BatchSearch.java	Mon Dec 19 11:37:36 2016 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,714 +0,0 @@
     1.4 -/*
     1.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.6 - *
     1.7 - * Copyright 2009-2011 Oracle and/or its affiliates. All rights reserved.
     1.8 - *
     1.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    1.10 - * Other names may be trademarks of their respective owners.
    1.11 - *
    1.12 - * The contents of this file are subject to the terms of either the GNU
    1.13 - * General Public License Version 2 only ("GPL") or the Common
    1.14 - * Development and Distribution License("CDDL") (collectively, the
    1.15 - * "License"). You may not use this file except in compliance with the
    1.16 - * License. You can obtain a copy of the License at
    1.17 - * http://www.netbeans.org/cddl-gplv2.html
    1.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    1.19 - * specific language governing permissions and limitations under the
    1.20 - * License.  When distributing the software, include this License Header
    1.21 - * Notice in each file and include the License file at
    1.22 - * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    1.23 - * particular file as subject to the "Classpath" exception as provided
    1.24 - * by Oracle in the GPL Version 2 section of the License file that
    1.25 - * accompanied this code. If applicable, add the following below the
    1.26 - * License Header, with the fields enclosed by brackets [] replaced by
    1.27 - * your own identifying information:
    1.28 - * "Portions Copyrighted [year] [name of copyright owner]"
    1.29 - *
    1.30 - * If you wish your version of this file to be governed by only the CDDL
    1.31 - * or only the GPL Version 2, indicate your decision by adding
    1.32 - * "[Contributor] elects to include this software in this distribution
    1.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
    1.34 - * single choice of license, a recipient has the option to distribute
    1.35 - * your version of this file under either the CDDL, the GPL Version 2 or
    1.36 - * to extend the choice of license to its licensees as provided above.
    1.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
    1.38 - * Version 2 license, then the option applies only if the new code is
    1.39 - * made subject to such option by the copyright holder.
    1.40 - *
    1.41 - * Contributor(s):
    1.42 - *
    1.43 - * Portions Copyrighted 2009-2011 Sun Microsystems, Inc.
    1.44 - */
    1.45 -package org.netbeans.modules.java.hints.spiimpl.batch;
    1.46 -
    1.47 -import org.netbeans.spi.java.hints.HintContext.MessageKind;
    1.48 -import org.netbeans.modules.java.hints.providers.spi.HintDescription;
    1.49 -import com.sun.source.tree.Tree;
    1.50 -import com.sun.source.util.TreePath;
    1.51 -import java.io.IOException;
    1.52 -import java.io.OutputStreamWriter;
    1.53 -import java.io.Writer;
    1.54 -import java.nio.ByteBuffer;
    1.55 -import java.util.ArrayList;
    1.56 -import java.util.Collection;
    1.57 -import java.util.Collections;
    1.58 -import java.util.HashMap;
    1.59 -import java.util.HashSet;
    1.60 -import java.util.LinkedList;
    1.61 -import java.util.List;
    1.62 -import java.util.Map;
    1.63 -import java.util.Map.Entry;
    1.64 -import java.util.Set;
    1.65 -import java.util.concurrent.Callable;
    1.66 -import java.util.concurrent.atomic.AtomicBoolean;
    1.67 -import java.util.concurrent.atomic.AtomicInteger;
    1.68 -import java.util.concurrent.atomic.AtomicReference;
    1.69 -import java.util.logging.Level;
    1.70 -import java.util.logging.Logger;
    1.71 -import org.netbeans.api.annotations.common.NonNull;
    1.72 -import org.netbeans.api.annotations.common.NullAllowed;
    1.73 -import org.netbeans.api.fileinfo.NonRecursiveFolder;
    1.74 -import org.netbeans.api.java.classpath.ClassPath;
    1.75 -import org.netbeans.api.java.classpath.GlobalPathRegistry;
    1.76 -import org.netbeans.api.java.source.ClasspathInfo;
    1.77 -import org.netbeans.api.java.source.ClasspathInfo.PathKind;
    1.78 -import org.netbeans.api.java.source.CompilationController;
    1.79 -import org.netbeans.api.java.source.CompilationInfo;
    1.80 -import org.netbeans.api.java.source.JavaSource;
    1.81 -import org.netbeans.api.java.source.JavaSource.Phase;
    1.82 -import org.netbeans.api.java.source.Task;
    1.83 -import org.netbeans.api.queries.FileEncodingQuery;
    1.84 -import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
    1.85 -import org.netbeans.modules.java.hints.spiimpl.Utilities;
    1.86 -import org.netbeans.modules.java.hints.spiimpl.hints.HintsInvoker;
    1.87 -import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch;
    1.88 -import org.netbeans.modules.java.hints.spiimpl.pm.BulkSearch.BulkPattern;
    1.89 -import org.netbeans.modules.java.hints.providers.spi.HintDescription.AdditionalQueryConstraints;
    1.90 -import org.netbeans.modules.java.hints.providers.spi.Trigger.PatternDescription;
    1.91 -import org.netbeans.spi.editor.hints.ErrorDescription;
    1.92 -import org.netbeans.api.java.source.matching.Matcher;
    1.93 -import org.netbeans.api.java.source.matching.Pattern;
    1.94 -import org.netbeans.modules.java.hints.providers.spi.Trigger.DecisionTrigger;
    1.95 -import org.netbeans.modules.java.hints.spiimpl.SPIAccessor;
    1.96 -import org.netbeans.modules.java.hints.spiimpl.hints.GlobalProcessingContext;
    1.97 -import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
    1.98 -import org.netbeans.spi.java.hints.Decision;
    1.99 -import org.netbeans.spi.java.hints.HintContext;
   1.100 -import org.openide.filesystems.FileObject;
   1.101 -import org.openide.filesystems.FileUtil;
   1.102 -import org.openide.util.Exceptions;
   1.103 -
   1.104 -/**
   1.105 - *
   1.106 - * @author lahvac
   1.107 - */
   1.108 -public class BatchSearch {
   1.109 -
   1.110 -    private static final Logger LOG = Logger.getLogger(BatchSearch.class.getName());
   1.111 -
   1.112 -    public static BatchResult findOccurrences(Iterable<? extends HintDescription> patterns, Scope scope) {
   1.113 -        return findOccurrences(patterns, scope, new ProgressHandleWrapper(null), HintsSettings.getGlobalSettings());
   1.114 -    }
   1.115 -
   1.116 -    public static BatchResult findOccurrences(final Iterable<? extends HintDescription> patterns, final Scope scope, final ProgressHandleWrapper progress, @NullAllowed HintsSettings settingsProvider) {
   1.117 -        return findOccurrencesLocal(patterns, scope.getIndexMapper(patterns), scope.getTodo(), progress, settingsProvider);
   1.118 -    }
   1.119 -
   1.120 -    private static BatchResult findOccurrencesLocal(final Iterable<? extends HintDescription> patterns, final MapIndices indexMapper, final Collection<? extends Folder> todo, final ProgressHandleWrapper progress, final @NullAllowed HintsSettings settingsProvider) {
   1.121 -        final BatchResult[] result = new BatchResult[1];
   1.122 -
   1.123 -        try {
   1.124 -            JavaSource.create(Utilities.createUniversalCPInfo()).runUserActionTask(new Task<CompilationController>() {
   1.125 -                public void run(CompilationController parameter) throws Exception {
   1.126 -                    result[0] = findOccurrencesLocalImpl(parameter, patterns, indexMapper, todo, progress, settingsProvider);
   1.127 -                }
   1.128 -            }, true);
   1.129 -        } catch (IOException ex) {
   1.130 -            throw new IllegalStateException(ex);
   1.131 -        }
   1.132 -
   1.133 -        return result[0];
   1.134 -    }
   1.135 -    
   1.136 -    private static BatchResult findOccurrencesLocalImpl(final CompilationInfo info, final Iterable<? extends HintDescription> patterns, MapIndices indexMapper, Collection<? extends Folder> todo, ProgressHandleWrapper progress, HintsSettings settingsProvider) {
   1.137 -        boolean hasKindPatterns = false;
   1.138 -
   1.139 -        for (HintDescription pattern : patterns) {
   1.140 -            if (!(pattern.getTrigger() instanceof PatternDescription)) {
   1.141 -                hasKindPatterns = true;
   1.142 -                break;
   1.143 -            }
   1.144 -        }
   1.145 -
   1.146 -        final Callable<BulkPattern> bulkPattern = hasKindPatterns ? null : new Callable<BulkPattern>() {
   1.147 -            private final AtomicReference<BulkPattern> pattern = new AtomicReference<BulkPattern>();
   1.148 -            public BulkPattern call() {
   1.149 -                if (pattern.get() == null) {
   1.150 -                    pattern.set(preparePattern(patterns, info));
   1.151 -                }
   1.152 -
   1.153 -                return pattern.get();
   1.154 -            }
   1.155 -        };
   1.156 -        final Map<IndexEnquirer, Collection<? extends Resource>> result = new HashMap<IndexEnquirer, Collection<? extends Resource>>();
   1.157 -        final Collection<MessageImpl> problems = new LinkedList<MessageImpl>();
   1.158 -        ProgressHandleWrapper innerForAll = progress.startNextPartWithEmbedding(ProgressHandleWrapper.prepareParts(2 * todo.size()));
   1.159 -        
   1.160 -        for (final Folder src : todo) {
   1.161 -            LOG.log(Level.FINE, "Processing: {0}", FileUtil.getFileDisplayName(src.getFileObject()));
   1.162 -            
   1.163 -            IndexEnquirer indexEnquirer;// = indexMapper.findIndex(src.getFileObject(), innerForAll, src.isRecursive());
   1.164 -
   1.165 -//            if (indexEnquirer == null) {
   1.166 -                indexEnquirer = new FileSystemBasedIndexEnquirer(src.getFileObject(), src.isRecursive());
   1.167 -//            }
   1.168 -
   1.169 -            Collection<? extends Resource> occurrences = indexEnquirer.findResources(patterns, innerForAll, bulkPattern, problems, settingsProvider);
   1.170 -
   1.171 -            if (!occurrences.isEmpty()) {
   1.172 -                result.put(indexEnquirer, occurrences);
   1.173 -            }
   1.174 -
   1.175 -            innerForAll.tick();
   1.176 -        }
   1.177 -
   1.178 -        return new BatchResult(result, patterns, problems);
   1.179 -    }
   1.180 -
   1.181 -    private static BulkPattern preparePattern(final Iterable<? extends HintDescription> patterns, CompilationInfo info) {
   1.182 -        Collection<String> code = new LinkedList<String>();
   1.183 -        Collection<Tree> trees = new LinkedList<Tree>();
   1.184 -        Collection<AdditionalQueryConstraints> additionalConstraints = new LinkedList<AdditionalQueryConstraints>();
   1.185 -
   1.186 -        for (HintDescription pattern : patterns) {
   1.187 -            String textPattern = ((PatternDescription) pattern.getTrigger()).getPattern();
   1.188 -
   1.189 -            code.add(textPattern);
   1.190 -            trees.add(Utilities.parseAndAttribute(info, textPattern, null));
   1.191 -            additionalConstraints.add(pattern.getAdditionalConstraints());
   1.192 -        }
   1.193 -
   1.194 -        return BulkSearch.getDefault().create(code, trees, additionalConstraints, new AtomicBoolean());
   1.195 -    }
   1.196 -
   1.197 -    public static void getVerifiedSpans(BatchResult candidates, @NonNull ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, final Collection<? super MessageImpl> problems, AtomicBoolean cancel) {
   1.198 -        getVerifiedSpans(candidates, progress, callback, false, problems, cancel);
   1.199 -    }
   1.200 -
   1.201 -    public static void getVerifiedSpans(BatchResult candidates, @NonNull ProgressHandleWrapper progress, final VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, final Collection<? super MessageImpl> problems, AtomicBoolean cancel) {
   1.202 -        int[] parts = new int[candidates.projectId2Resources.size()];
   1.203 -        int   index = 0;
   1.204 -
   1.205 -        for (Entry<? extends IndexEnquirer, ? extends Collection<? extends Resource>> e : candidates.projectId2Resources.entrySet()) {
   1.206 -            parts[index++] = e.getValue().size();
   1.207 -        }
   1.208 -
   1.209 -        ProgressHandleWrapper inner = progress.startNextPartWithEmbedding(parts);
   1.210 -
   1.211 -        for (Entry<? extends IndexEnquirer, ? extends Collection<? extends Resource>> e : candidates.projectId2Resources.entrySet()) {
   1.212 -            if (cancel.get()) 
   1.213 -                return;
   1.214 -            inner.startNextPart(e.getValue().size());
   1.215 -
   1.216 -            e.getKey().validateResource(e.getValue(), inner, callback, doNotRegisterClassPath, problems, cancel);
   1.217 -        }
   1.218 -    }
   1.219 -
   1.220 -    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) {
   1.221 -        Collection<FileObject> files = new LinkedList<FileObject>();
   1.222 -        final Map<FileObject, Resource> file2Resource = new HashMap<FileObject, Resource>();
   1.223 -
   1.224 -        for (Resource r : resources) {
   1.225 -            FileObject file = r.getResolvedFile();
   1.226 -
   1.227 -            if (file != null) {
   1.228 -                files.add(file);
   1.229 -                file2Resource.put(file, r);
   1.230 -            } else {
   1.231 -                callback.cannotVerifySpan(r);
   1.232 -                progress.tick();
   1.233 -            }
   1.234 -        }
   1.235 -
   1.236 -        Map<ClasspathInfo, Collection<FileObject>> cp2Files = BatchUtilities.sortFiles(files);
   1.237 -        ClassPath[] toRegister = null;
   1.238 -
   1.239 -        if (!doNotRegisterClassPath) {
   1.240 -            Set<ClassPath> toRegisterSet = new HashSet<ClassPath>();
   1.241 -
   1.242 -            for (ClasspathInfo cpInfo : cp2Files.keySet()) {
   1.243 -                toRegisterSet.add(cpInfo.getClassPath(PathKind.SOURCE));
   1.244 -            }
   1.245 -
   1.246 -            toRegister = !toRegisterSet.isEmpty() ? toRegisterSet.toArray(new ClassPath[0]) : null;
   1.247 -
   1.248 -            if (toRegister != null) {
   1.249 -                GlobalPathRegistry.getDefault().register(ClassPath.SOURCE, toRegister);
   1.250 -                try {
   1.251 -                    Utilities.waitScanFinished();
   1.252 -                } catch (InterruptedException ex) {
   1.253 -                    Exceptions.printStackTrace(ex);
   1.254 -                }
   1.255 -            }
   1.256 -        }
   1.257 -
   1.258 -        callback.groupStarted();
   1.259 -
   1.260 -        try {
   1.261 -            final GlobalProcessingContext gpc = new GlobalProcessingContext();
   1.262 -            for (Entry<ClasspathInfo, Collection<FileObject>> e : cp2Files.entrySet()) {
   1.263 -                try {
   1.264 -                    List<FileObject> toProcess = new ArrayList<FileObject>(e.getValue());
   1.265 -                    final AtomicInteger currentPointer = new AtomicInteger();
   1.266 -
   1.267 -//                    for (FileObject f : toProcess) {
   1.268 -                    while (currentPointer.get() < toProcess.size()) {
   1.269 -                        if (cancel.get())
   1.270 -                            return;
   1.271 -                        final AtomicBoolean stop = new AtomicBoolean();
   1.272 -//                        JavaSource js = JavaSource.create(e.getKey(), f);
   1.273 -                        JavaSource js = JavaSource.create(e.getKey(), toProcess.subList(currentPointer.get(), toProcess.size()));
   1.274 -
   1.275 -                        js.runUserActionTask(new Task<CompilationController>() {
   1.276 -                            public void run(CompilationController parameter) throws Exception {
   1.277 -                                if (stop.get()) return;
   1.278 -                                if (cancel.get()) return;
   1.279 -
   1.280 -                                boolean cont = true;
   1.281 -
   1.282 -                                try {
   1.283 -                                    if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0)
   1.284 -                                        return ;
   1.285 -
   1.286 -                                    progress.setMessage("processing: " + FileUtil.getFileDisplayName(parameter.getFileObject()));
   1.287 -                                    Resource r = file2Resource.get(parameter.getFileObject());
   1.288 -
   1.289 -                                    HintsSettings settings = r.settings;
   1.290 -                                    Iterable<? extends HintDescription> enabledHints;
   1.291 -                                    
   1.292 -                                    if (settings == null) {
   1.293 -                                        settings = HintsSettings.getSettingsFor(parameter.getFileObject());
   1.294 -                                        List<HintDescription> hintsCopy = new ArrayList<>();
   1.295 -                                        for (HintDescription hd : r.hints) {
   1.296 -                                            if (settings.isEnabled(hd.getMetadata())) {
   1.297 -                                                hintsCopy.add(hd);
   1.298 -                                            }
   1.299 -                                        }
   1.300 -                                        enabledHints = hintsCopy;
   1.301 -                                    } else {
   1.302 -                                        enabledHints = r.hints;
   1.303 -                                    }
   1.304 -                                    
   1.305 -                                    List<ErrorDescription> hints = new HintsInvoker(settings, gpc, new AtomicBoolean()).computeHints(parameter, r.hints, problems);
   1.306 -
   1.307 -                                    assert hints != null;
   1.308 -                                    
   1.309 -                                    cont = callback.spansVerified(parameter, r, hints);
   1.310 -                                } catch (ThreadDeath td) {
   1.311 -                                    throw td;
   1.312 -                                } catch (Throwable t) {
   1.313 -                                    LOG.log(Level.INFO, "Exception while performing batch processing in " + FileUtil.getFileDisplayName(parameter.getFileObject()), t);
   1.314 -                                    problems.add(new MessageImpl(MessageKind.WARNING, "An exception occurred while processing file: " + FileUtil.getFileDisplayName(parameter.getFileObject()) + " (" + t.getLocalizedMessage() + ")."));
   1.315 -                                }
   1.316 -                                
   1.317 -                                if (cont) {
   1.318 -                                    progress.tick();
   1.319 -                                    currentPointer.incrementAndGet();
   1.320 -                                } else {
   1.321 -                                    stop.set(true);
   1.322 -                                }
   1.323 -                            }
   1.324 -                        }, true);
   1.325 -                    }
   1.326 -                } catch (IOException ex) {
   1.327 -                    Exceptions.printStackTrace(ex);
   1.328 -                }
   1.329 -            }
   1.330 -            
   1.331 -            final Map<FileObject, List<Decision>> file2Decision = new HashMap<FileObject, List<Decision>>();
   1.332 -            for (List<Decision<?, ?>> decisions : gpc.decisions.values()) {
   1.333 -                for (Decision<?, ?> d : decisions) {
   1.334 -                    if (d.makeDecision()) {
   1.335 -                        List<Decision> fileDecisions = file2Decision.get(d.root.getFileObject());
   1.336 -                        
   1.337 -                        if (fileDecisions == null) {
   1.338 -                            file2Decision.put(d.root.getFileObject(), fileDecisions = new ArrayList<Decision>());
   1.339 -                        }
   1.340 -                        
   1.341 -                        fileDecisions.add(d);
   1.342 -                    }
   1.343 -                }
   1.344 -            }
   1.345 -
   1.346 -            Map<ClasspathInfo, Collection<FileObject>> cp2FilesAfterDecision = BatchUtilities.sortFiles(file2Decision.keySet());
   1.347 -            
   1.348 -            for (Entry<ClasspathInfo, Collection<FileObject>> e : cp2FilesAfterDecision.entrySet()) {
   1.349 -                JavaSource js = JavaSource.create(e.getKey(), e.getValue());
   1.350 -                
   1.351 -                try {
   1.352 -                    js.runUserActionTask(new Task<CompilationController>() {
   1.353 -                        @Override public void run(CompilationController parameter) throws Exception {
   1.354 -                            if (parameter.toPhase(Phase.RESOLVED).compareTo(Phase.RESOLVED) < 0)
   1.355 -                                return ;
   1.356 -                            
   1.357 -                            Resource r = file2Resource.get(parameter.getFileObject());
   1.358 -
   1.359 -                            HintsSettings settings = r.settings;
   1.360 -
   1.361 -                            if (settings == null) {
   1.362 -                                settings = HintsSettings.getSettingsFor(parameter.getFileObject());
   1.363 -                            }
   1.364 -
   1.365 -                            for (Decision<?, ?> d : file2Decision.get(parameter.getFileObject())) {
   1.366 -                            for (HintDescription hd : r.hints) {
   1.367 -                                if (!(hd.getTrigger() instanceof DecisionTrigger)) continue;
   1.368 -                                if (r.settings == null && !settings.isEnabled(hd.getMetadata())) continue;
   1.369 -                                DecisionTrigger dt = (DecisionTrigger) hd.getTrigger();
   1.370 -                                if (dt.getDecisionClass() != d.getClass()) continue;
   1.371 -                                TreePath tp = d.root.resolve(parameter);
   1.372 -                                HintContext ctx = SPIAccessor.getINSTANCE().createHintContext(parameter, settings, hd.getMetadata(), new GlobalProcessingContext(), tp, Collections.<String, TreePath>emptyMap(), Collections.<String, Collection<? extends TreePath>>emptyMap(), Collections.<String, String>emptyMap());
   1.373 -                                ctx.decision = d;
   1.374 -                                Collection<? extends ErrorDescription> errors = hd.getWorker().createErrors(ctx);
   1.375 -                                
   1.376 -                                if (errors != null) {
   1.377 -                                    callback.spansVerified(parameter, file2Resource.get(parameter.getFileObject()), errors);
   1.378 -                                }
   1.379 -                            }
   1.380 -                            }
   1.381 -                        }
   1.382 -                    }, true);
   1.383 -                } catch (IOException ex) {
   1.384 -                    Exceptions.printStackTrace(ex);
   1.385 -                }
   1.386 -            }
   1.387 -        } finally {
   1.388 -            callback.groupFinished();
   1.389 -            
   1.390 -            if (toRegister != null) {
   1.391 -                GlobalPathRegistry.getDefault().unregister(ClassPath.SOURCE, toRegister);
   1.392 -            }
   1.393 -            progress.finish();
   1.394 -        }
   1.395 -    }
   1.396 -
   1.397 -    public interface VerifiedSpansCallBack {
   1.398 -        public void groupStarted();
   1.399 -        public boolean spansVerified(CompilationController wc, Resource r, Collection<? extends ErrorDescription> hints) throws Exception;
   1.400 -        public void groupFinished();
   1.401 -        public void cannotVerifySpan(Resource r);
   1.402 -    }
   1.403 -
   1.404 -    
   1.405 -    public static class Folder {
   1.406 -
   1.407 -        private FileObject file;
   1.408 -        private NonRecursiveFolder folder;
   1.409 -        
   1.410 -        public Folder(FileObject file) {
   1.411 -            this.file = file;
   1.412 -        }
   1.413 -        
   1.414 -        public Folder(NonRecursiveFolder folder) {
   1.415 -            this.folder = folder;
   1.416 -        }
   1.417 -        
   1.418 -        public FileObject getFileObject() {
   1.419 -            if (file!=null) {
   1.420 -                return file;
   1.421 -            }
   1.422 -            return folder.getFolder();
   1.423 -            
   1.424 -        }
   1.425 -        
   1.426 -        private boolean isRecursive() {
   1.427 -            if (file!=null) {
   1.428 -                return file.isFolder();
   1.429 -            }
   1.430 -            return false;
   1.431 -        }
   1.432 -
   1.433 -        public static Folder[] convert(FileObject... files) {
   1.434 -            Folder[] result = new Folder[files.length];
   1.435 -            for (int i=0;i<files.length;i++) {
   1.436 -                result[i] = new Folder(files[i]);
   1.437 -            }
   1.438 -            return result;
   1.439 -        }
   1.440 -
   1.441 -        public static Folder[] convert(Collection list) {
   1.442 -            Folder[] result = new Folder[list.size()];
   1.443 -            int i=0;
   1.444 -            for (Object item:list) {
   1.445 -                if (item instanceof FileObject)
   1.446 -                    result[i] = new Folder((FileObject) item);
   1.447 -                else 
   1.448 -                    result[i] = new Folder((NonRecursiveFolder) item);
   1.449 -                i++;
   1.450 -            }
   1.451 -            return result;
   1.452 -        }
   1.453 -
   1.454 -        @Override
   1.455 -        public String toString() {
   1.456 -            return !isRecursive()?"Non":"" + "Recursive file " + getFileObject().getPath();
   1.457 -        }
   1.458 -        
   1.459 -        
   1.460 -    }
   1.461 -    
   1.462 -    public abstract static class Scope {
   1.463 -
   1.464 -        public abstract String getDisplayName();
   1.465 -        public abstract Collection<? extends Folder> getTodo();
   1.466 -        public abstract MapIndices getIndexMapper(Iterable<? extends HintDescription> hints);
   1.467 -        
   1.468 -    }
   1.469 -    
   1.470 -    public static final class BatchResult {
   1.471 -        
   1.472 -        private final Map<? extends IndexEnquirer, ? extends Collection<? extends Resource>> projectId2Resources;
   1.473 -        private final Iterable<? extends HintDescription> patterns;
   1.474 -        public final Collection<? extends MessageImpl> problems;
   1.475 -        
   1.476 -        public BatchResult(Map<? extends IndexEnquirer, ? extends Collection<? extends Resource>> projectId2Resources, Iterable<? extends HintDescription> patterns, Collection<? extends MessageImpl> problems) {
   1.477 -            this.projectId2Resources = projectId2Resources;
   1.478 -            this.patterns = patterns;
   1.479 -            this.problems = problems;
   1.480 -        }
   1.481 -
   1.482 -        public Collection<? extends Collection<? extends Resource>> getResources() {
   1.483 -            return projectId2Resources.values();
   1.484 -        }
   1.485 -
   1.486 -        public Map<FileObject, Collection<? extends Resource>> getResourcesWithRoots() {
   1.487 -            Map<FileObject, Collection<? extends Resource>> result = new HashMap<FileObject, Collection<? extends Resource>>();
   1.488 -
   1.489 -            for (Entry<? extends IndexEnquirer, ? extends Collection<? extends Resource>> e : projectId2Resources.entrySet()) {
   1.490 -                result.put(e.getKey().src, e.getValue());
   1.491 -            }
   1.492 -
   1.493 -            return result;
   1.494 -        }
   1.495 -
   1.496 -        public Iterable<? extends HintDescription> getPatterns() {
   1.497 -            return patterns;
   1.498 -        }
   1.499 -    }
   1.500 -
   1.501 -    public static final class Resource {
   1.502 -        private final IndexEnquirer indexEnquirer;
   1.503 -        private final String relativePath;
   1.504 -        final Iterable<? extends HintDescription> hints;
   1.505 -        private final BulkPattern pattern;
   1.506 -        final HintsSettings settings;
   1.507 -
   1.508 -        public Resource(IndexEnquirer indexEnquirer, String relativePath, Iterable<? extends HintDescription> hints, BulkPattern pattern, HintsSettings settings) {
   1.509 -            this.indexEnquirer = indexEnquirer;
   1.510 -            this.relativePath = relativePath;
   1.511 -            this.hints = hints;
   1.512 -            this.pattern = pattern;
   1.513 -            this.settings = settings;
   1.514 -        }
   1.515 -
   1.516 -        public String getRelativePath() {
   1.517 -            return relativePath;
   1.518 -        }
   1.519 -        
   1.520 -        public Iterable<int[]> getCandidateSpans() {
   1.521 -            FileObject file = getResolvedFile();
   1.522 -            JavaSource js;
   1.523 -
   1.524 -            if (file != null) {
   1.525 -                js = JavaSource.forFileObject(file);
   1.526 -            } else {
   1.527 -                CharSequence text = getSourceCode();
   1.528 -
   1.529 -                if (text == null) {
   1.530 -                    return null;
   1.531 -                }
   1.532 -
   1.533 -                Writer out = null;
   1.534 -
   1.535 -                try {
   1.536 -                    file = FileUtil.createData(FileUtil.createMemoryFileSystem().getRoot(), relativePath);
   1.537 -                    out = new OutputStreamWriter(file.getOutputStream());
   1.538 -
   1.539 -                    out.write(text.toString());
   1.540 -                } catch (IOException ex) {
   1.541 -                    Exceptions.printStackTrace(ex);
   1.542 -                    return null;
   1.543 -                } finally {
   1.544 -                    if (out != null) {
   1.545 -                        try {
   1.546 -                            out.close();
   1.547 -                        } catch (IOException ex) {
   1.548 -                            Exceptions.printStackTrace(ex);
   1.549 -                        }
   1.550 -                    }
   1.551 -                }
   1.552 -
   1.553 -                js = JavaSource.create(Utilities.createUniversalCPInfo(), file);
   1.554 -            }
   1.555 -
   1.556 -            final List<int[]> span = new LinkedList<int[]>();
   1.557 -
   1.558 -            try {
   1.559 -                js.runUserActionTask(new Task<CompilationController>() {
   1.560 -                    public void run(CompilationController cc) throws Exception {
   1.561 -                        cc.toPhase(Phase.PARSED);
   1.562 -
   1.563 -                        span.addAll(doComputeSpans(cc));
   1.564 -                    }
   1.565 -                }, true);
   1.566 -            } catch (IOException ex) {
   1.567 -                Exceptions.printStackTrace(ex);
   1.568 -            }
   1.569 -
   1.570 -            return span;
   1.571 -        }
   1.572 -
   1.573 -        private Collection<int[]> doComputeSpans(CompilationInfo ci) {
   1.574 -            Collection<int[]> result = new LinkedList<int[]>();
   1.575 -            Map<String, Collection<TreePath>> found = BulkSearch.getDefault().match(ci, new AtomicBoolean(), new TreePath(ci.getCompilationUnit()), pattern);
   1.576 -            
   1.577 -            for (Entry<String, Collection<TreePath>> e : found.entrySet()) {
   1.578 -                Tree treePattern = Utilities.parseAndAttribute(ci, e.getKey(), null);
   1.579 -                
   1.580 -                for (TreePath tp : e.getValue()) {
   1.581 -                    //XXX: this pass will not be performed on the web!!!
   1.582 -                    if (   BulkSearch.getDefault().requiresLightweightVerification()
   1.583 -                        && !Matcher.create(ci).setCancel(new AtomicBoolean()).setSearchRoot(tp).setTreeTopSearch().setUntypedMatching().match(Pattern.createSimplePattern(new TreePath(new TreePath(ci.getCompilationUnit()), treePattern))).iterator().hasNext()) {
   1.584 -                        continue;
   1.585 -                    }
   1.586 -                    int[] span = new int[] {
   1.587 -                        (int) ci.getTrees().getSourcePositions().getStartPosition(ci.getCompilationUnit(), tp.getLeaf()),
   1.588 -                        (int) ci.getTrees().getSourcePositions().getEndPosition(ci.getCompilationUnit(), tp.getLeaf())
   1.589 -                    };
   1.590 -
   1.591 -                    result.add(span);
   1.592 -                }
   1.593 -            }
   1.594 -
   1.595 -            return result;
   1.596 -        }
   1.597 -        
   1.598 -        public FileObject getResolvedFile() {
   1.599 -            return indexEnquirer.src.getFileObject(relativePath);
   1.600 -        }
   1.601 -
   1.602 -        public String getDisplayName() {
   1.603 -            FileObject file = getResolvedFile();
   1.604 -
   1.605 -            if (file != null) {
   1.606 -                return FileUtil.getFileDisplayName(file);
   1.607 -            } else {
   1.608 -                return relativePath; //TODO:+container
   1.609 -            }
   1.610 -        }
   1.611 -        
   1.612 -        public CharSequence getSourceCode() {
   1.613 -            try {
   1.614 -                FileObject file = getResolvedFile();
   1.615 -                ByteBuffer bb = ByteBuffer.wrap(file.asBytes());
   1.616 -
   1.617 -                return FileEncodingQuery.getEncoding(file).decode(bb);
   1.618 -            } catch (IOException ex) {
   1.619 -                Exceptions.printStackTrace(ex);
   1.620 -                return null;
   1.621 -            }
   1.622 -        }
   1.623 -
   1.624 -        public FileObject getRoot() {
   1.625 -            return indexEnquirer.src;
   1.626 -        }
   1.627 -    }
   1.628 -
   1.629 -    public static interface MapIndices {
   1.630 -        public IndexEnquirer findIndex(FileObject root, ProgressHandleWrapper progress, boolean recursive);
   1.631 -    }
   1.632 -
   1.633 -    public static abstract class IndexEnquirer {
   1.634 -        final FileObject src;
   1.635 -        public IndexEnquirer(FileObject src) {
   1.636 -            this.src = src;
   1.637 -        }
   1.638 -        public abstract Collection<? extends Resource> findResources(Iterable<? extends HintDescription> hints, ProgressHandleWrapper progress, @NullAllowed Callable<BulkPattern> bulkPattern, Collection<? super MessageImpl> problems, HintsSettings settingsProvider);
   1.639 -        public abstract void validateResource(Collection<? extends Resource> resources, ProgressHandleWrapper progress, VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, Collection<? super MessageImpl> problems, AtomicBoolean cancel);
   1.640 -//        public int[] getEstimatedSpan(Resource r);
   1.641 -    }
   1.642 -
   1.643 -    public static abstract class LocalIndexEnquirer extends IndexEnquirer {
   1.644 -        public LocalIndexEnquirer(FileObject src) {
   1.645 -            super(src);
   1.646 -        }
   1.647 -        public void validateResource(Collection<? extends Resource> resources, ProgressHandleWrapper progress, VerifiedSpansCallBack callback, boolean doNotRegisterClassPath, Collection<? super MessageImpl> problems, AtomicBoolean cancel) {
   1.648 -            getLocalVerifiedSpans(resources, progress, callback, doNotRegisterClassPath, problems, cancel);
   1.649 -        }
   1.650 -    }
   1.651 -
   1.652 -    public static final class FileSystemBasedIndexEnquirer extends LocalIndexEnquirer {
   1.653 -        private boolean recursive;
   1.654 -        public FileSystemBasedIndexEnquirer(FileObject src, boolean recursive) {
   1.655 -            super(src);
   1.656 -            this.recursive = recursive;
   1.657 -        }
   1.658 -        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) {
   1.659 -            Collection<FileObject> files = new LinkedList<FileObject>();
   1.660 -
   1.661 -            final ProgressHandleWrapper innerProgress = progress.startNextPartWithEmbedding(30, 70);
   1.662 -
   1.663 -            BatchUtilities.recursive(src, src, files, innerProgress, 0, null, null, recursive);
   1.664 -
   1.665 -            LOG.log(Level.FINE, "files: {0}", files);
   1.666 -
   1.667 -            innerProgress.startNextPart(files.size());
   1.668 -
   1.669 -            final Collection<Resource> result = new ArrayList<Resource>();
   1.670 -
   1.671 -            if (!files.isEmpty()) {
   1.672 -                try {
   1.673 -                    if (bulkPattern != null) {
   1.674 -                        long start = System.currentTimeMillis();
   1.675 -
   1.676 -                        JavaSource.create(Utilities.createUniversalCPInfo(), files).runUserActionTask(new Task<CompilationController>() {
   1.677 -                            public void run(CompilationController cc) throws Exception {
   1.678 -                                if (cc.toPhase(Phase.PARSED).compareTo(Phase.PARSED) <0) {
   1.679 -                                    return ;
   1.680 -                                }
   1.681 -
   1.682 -                                try {
   1.683 -                                    boolean matches = BulkSearch.getDefault().matches(cc, new AtomicBoolean(), new TreePath(cc.getCompilationUnit()), bulkPattern.call());
   1.684 -
   1.685 -                                    if (matches) {
   1.686 -                                        result.add(new Resource(FileSystemBasedIndexEnquirer.this, FileUtil.getRelativePath(src, cc.getFileObject()), hints, bulkPattern.call(), settingsProvider));
   1.687 -                                    }
   1.688 -                                } catch (ThreadDeath td) {
   1.689 -                                    throw td;
   1.690 -                                } catch (Throwable t) {
   1.691 -                                    LOG.log(Level.INFO, "Exception while performing batch search in " + FileUtil.getFileDisplayName(cc.getFileObject()), t);
   1.692 -                                    problems.add(new MessageImpl(MessageKind.WARNING, "An exception occurred while testing file: " + FileUtil.getFileDisplayName(cc.getFileObject()) + " (" + t.getLocalizedMessage() + ")."));
   1.693 -                                }
   1.694 -
   1.695 -                                innerProgress.tick();
   1.696 -                            }
   1.697 -                        }, true);
   1.698 -
   1.699 -                        long end = System.currentTimeMillis();
   1.700 -
   1.701 -                        LOG.log(Level.FINE, "took: {0}, per file: {1}", new Object[]{end - start, (end - start) / files.size()});
   1.702 -                    } else {
   1.703 -                        for (FileObject file : files) {
   1.704 -                            result.add(new Resource(this, FileUtil.getRelativePath(src, file), hints, null, settingsProvider));
   1.705 -                        }
   1.706 -                    }
   1.707 -                } catch (IOException ex) {
   1.708 -                    Exceptions.printStackTrace(ex);
   1.709 -                }
   1.710 -            }
   1.711 -
   1.712 -            return result;
   1.713 -        }
   1.714 -
   1.715 -    }
   1.716 -
   1.717 -}