sandbox/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/support/TransformationSupport.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/spi/java/hints/support/TransformationSupport.java	Mon Dec 19 11:37:36 2016 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,311 +0,0 @@
     1.4 -/*
     1.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.6 - *
     1.7 - * Copyright 2012 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 2012 Sun Microsystems, Inc.
    1.44 - */
    1.45 -package org.netbeans.spi.java.hints.support;
    1.46 -
    1.47 -import com.sun.source.util.TreePath;
    1.48 -import java.util.*;
    1.49 -import java.util.Map.Entry;
    1.50 -import java.util.concurrent.atomic.AtomicBoolean;
    1.51 -import javax.lang.model.type.TypeMirror;
    1.52 -import org.netbeans.api.annotations.common.NonNull;
    1.53 -import org.netbeans.api.java.source.CompilationInfo;
    1.54 -import org.netbeans.api.java.source.ModificationResult;
    1.55 -import org.netbeans.api.java.source.TypeMirrorHandle;
    1.56 -import org.netbeans.api.java.source.WorkingCopy;
    1.57 -import org.netbeans.api.java.source.matching.Matcher;
    1.58 -import org.netbeans.api.java.source.matching.Occurrence;
    1.59 -import org.netbeans.api.java.source.matching.Pattern;
    1.60 -import org.netbeans.api.project.Project;
    1.61 -import org.netbeans.modules.java.hints.jackpot.spi.PatternConvertor;
    1.62 -import org.netbeans.modules.java.hints.providers.spi.HintDescription;
    1.63 -import org.netbeans.modules.java.hints.providers.spi.HintDescriptionFactory;
    1.64 -import org.netbeans.modules.java.hints.providers.spi.Trigger;
    1.65 -import org.netbeans.modules.java.hints.spiimpl.JavaFixImpl;
    1.66 -import org.netbeans.modules.java.hints.spiimpl.MessageImpl;
    1.67 -import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch;
    1.68 -import org.netbeans.modules.java.hints.spiimpl.batch.BatchSearch.BatchResult;
    1.69 -import org.netbeans.modules.java.hints.spiimpl.batch.BatchUtilities;
    1.70 -import org.netbeans.modules.java.hints.spiimpl.batch.ProgressHandleWrapper;
    1.71 -import org.netbeans.modules.java.hints.spiimpl.batch.Scopes;
    1.72 -import org.netbeans.modules.java.hints.spiimpl.hints.HintsInvoker;
    1.73 -import org.netbeans.modules.java.hints.spiimpl.options.HintsSettings;
    1.74 -import org.netbeans.modules.java.hints.spiimpl.pm.PatternCompiler;
    1.75 -import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
    1.76 -import org.netbeans.spi.editor.hints.*;
    1.77 -import org.netbeans.spi.java.hints.HintContext;
    1.78 -import org.netbeans.spi.java.hints.JavaFix;
    1.79 -import org.openide.util.Exceptions;
    1.80 -
    1.81 -/**
    1.82 - * Static utility classes for processing jackpot patterns.
    1.83 - * <a href="https://bitbucket.org/jlahoda/jackpot30/wiki/RulesLanguage">Rules Language</a>
    1.84 - * @author Jan Becicka
    1.85 - * @since 1.1
    1.86 - */
    1.87 -public final class TransformationSupport {
    1.88 -
    1.89 -    private String jackpotPattern;
    1.90 -    private Transformer transformer;
    1.91 -    private AtomicBoolean cancel = new AtomicBoolean();
    1.92 -
    1.93 -    private TransformationSupport(String jackpotPattern, Transformer transformer) {
    1.94 -        this.jackpotPattern = jackpotPattern;
    1.95 -        this.transformer = transformer;
    1.96 -    }
    1.97 -    
    1.98 -    /**
    1.99 -     * Creates new TransformationSupport representing given jackpotPattern.
   1.100 -     * @param jackpotPattern
   1.101 -     * @return
   1.102 -     */
   1.103 -    public static @NonNull TransformationSupport create(@NonNull String jackpotPattern) {
   1.104 -        return new TransformationSupport(jackpotPattern, null);
   1.105 -    }
   1.106 -
   1.107 -    /**
   1.108 -     * Creates new TransformationSupport representing given jackpotPattern with custom Transformer.
   1.109 -     * @param inputJackpotPattern
   1.110 -     * @param t
   1.111 -     * @see Transformer
   1.112 -     * @return
   1.113 -     */
   1.114 -    public static @NonNull TransformationSupport create(@NonNull String inputJackpotPattern, @NonNull Transformer t) {
   1.115 -        return new TransformationSupport(inputJackpotPattern, t);
   1.116 -    }
   1.117 -
   1.118 -    /**
   1.119 -     * Option to cancel query.
   1.120 -     * @param cancel
   1.121 -     * @return
   1.122 -     */
   1.123 -    public @NonNull TransformationSupport setCancel(@NonNull AtomicBoolean cancel) {
   1.124 -        this.cancel = cancel;
   1.125 -        return this;
   1.126 -    }
   1.127 -
   1.128 -
   1.129 -    /**
   1.130 -     * Run current transformation on all projects and collect results.
   1.131 -     * @return collection of {@link ModificationResult}
   1.132 -     */
   1.133 -    public @NonNull Collection<? extends ModificationResult> processAllProjects() {
   1.134 -        if (transformer!=null) {
   1.135 -            return performTransformation(jackpotPattern, transformer, cancel);
   1.136 -        } else {
   1.137 -            return performTransformation(jackpotPattern, cancel);
   1.138 -        }
   1.139 -    }
   1.140 -
   1.141 -    
   1.142 -    /**
   1.143 -     * Process current transformation on given treePath and performs rewrite on
   1.144 -     * workingCopy.
   1.145 -     * @param workingCopy
   1.146 -     * @param treePath 
   1.147 -     */
   1.148 -    public void transformTreePath(@NonNull WorkingCopy workingCopy, @NonNull TreePath treePath) {
   1.149 -        if (transformer!=null) {
   1.150 -            throw new UnsupportedOperationException("Not implemented yet");
   1.151 -        } else {
   1.152 -            performTransformation(workingCopy, treePath, jackpotPattern, cancel);
   1.153 -        }
   1.154 -    }
   1.155 -
   1.156 -
   1.157 -    /**
   1.158 -     * Transformer callback which is called for each occurrence during processing 
   1.159 -     * of {@link #performTransformation(java.lang.String, org.netbeans.spi.java.hints.support.JackpotSupport.Transformer, java.util.concurrent.atomic.AtomicBoolean)    
   1.160 -     */
   1.161 -    public interface Transformer {
   1.162 -
   1.163 -        /**
   1.164 -         * Implement custom transformation of occurrence here.
   1.165 -         * @param copy
   1.166 -         * @param occurrence
   1.167 -         */
   1.168 -        public void transform(WorkingCopy copy, Occurrence occurrence);
   1.169 -
   1.170 -    }
   1.171 -    
   1.172 -    
   1.173 -    
   1.174 -    /**
   1.175 -     * Performs transformation described by jackpotPattern on given workingCopy.
   1.176 -     * @param workingCopy
   1.177 -     * @param jackpotPattern
   1.178 -     * @param cancel
   1.179 -     */
   1.180 -    private static void performTransformation(WorkingCopy workingCopy, TreePath on, String jackpotPattern, AtomicBoolean cancel) {
   1.181 -        Iterable<? extends HintDescription> hints = PatternConvertor.create(jackpotPattern);
   1.182 -        HintsInvoker inv = new HintsInvoker(HintsSettings.getSettingsFor(workingCopy.getFileObject()), cancel);
   1.183 -        Map<HintDescription, List<ErrorDescription>> computeHints = inv.computeHints(workingCopy, on, false, hints, new ArrayList<MessageImpl>());
   1.184 -        
   1.185 -        if (computeHints == null || cancel.get()) return ;
   1.186 -        
   1.187 -        List<ErrorDescription> errs = new ArrayList<ErrorDescription>();
   1.188 -        for (Entry<HintDescription, List<ErrorDescription>> entry: computeHints.entrySet()) {
   1.189 -            errs.addAll(entry.getValue());
   1.190 -        }
   1.191 -        List<MessageImpl> problems = new LinkedList<MessageImpl>();
   1.192 -
   1.193 -        try {
   1.194 -            if (BatchUtilities.applyFixes(workingCopy, Collections.<Project, Set<String>>emptyMap(), errs, null, new ArrayList<RefactoringElementImplementation>(), problems)) {
   1.195 -                throw new IllegalStateException();
   1.196 -            }
   1.197 -        } catch (IllegalStateException ex) {
   1.198 -            Exceptions.printStackTrace(ex);
   1.199 -        } catch (Exception ex) {
   1.200 -            Exceptions.printStackTrace(ex);
   1.201 -        }
   1.202 -
   1.203 -        if (!problems.isEmpty()) {
   1.204 -            throw new IllegalStateException(problems.get(0).text);
   1.205 -        }
   1.206 -    }
   1.207 -    
   1.208 -    /**
   1.209 -     * Performs jackpotPattern transformation in all open projects.
   1.210 -     * @param jackpotPattern
   1.211 -     * @param cancel
   1.212 -     * @return
   1.213 -     */
   1.214 -    private static  Collection<? extends ModificationResult> performTransformation(String jackpotPattern, AtomicBoolean cancel) {
   1.215 -        Collection<MessageImpl> problems = new LinkedList<MessageImpl>();
   1.216 -        BatchResult batchResult = BatchSearch.findOccurrences(PatternConvertor.create(jackpotPattern), Scopes.allOpenedProjectsScope());
   1.217 -        return BatchUtilities.applyFixes(batchResult, new ProgressHandleWrapper(1, 1), cancel, problems);
   1.218 -    }
   1.219 -    
   1.220 -    /**
   1.221 -     * Performs transformation defined by transformer on all occurrences, which matches inputJackpotPattern.
   1.222 -     * @param inputJackpotPattern
   1.223 -     * @param transformer
   1.224 -     * @return collection of ModificationResults.
   1.225 -     */
   1.226 -    private static Collection<? extends ModificationResult> performTransformation(final String inputJackpotPattern, final Transformer transformer, AtomicBoolean cancel) {
   1.227 -        List<HintDescription> descriptions = new ArrayList<HintDescription>();
   1.228 -
   1.229 -        for (HintDescription hd : PatternConvertor.create(inputJackpotPattern)) {
   1.230 -            final String triggerPattern = ((Trigger.PatternDescription) hd.getTrigger()).getPattern();
   1.231 -            descriptions.add(HintDescriptionFactory.create().setTrigger(hd.getTrigger()).setWorker(new HintDescription.Worker() {
   1.232 -                @Override public Collection<? extends ErrorDescription> createErrors(HintContext ctx) {
   1.233 -                    final Map<String, TypeMirrorHandle<?>> constraintsHandles = new HashMap<String, TypeMirrorHandle<?>>();
   1.234 -
   1.235 -                    for (Map.Entry<String, TypeMirror> c : ctx.getConstraints().entrySet()) {
   1.236 -                        constraintsHandles.put(c.getKey(), TypeMirrorHandle.create(c.getValue()));
   1.237 -                    }
   1.238 -
   1.239 -                    Fix fix = new JavaFix(ctx.getInfo(), ctx.getPath()) {
   1.240 -                        @Override protected String getText() {
   1.241 -                            return "";
   1.242 -                        }
   1.243 -                        @Override protected void performRewrite(JavaFix.TransformationContext ctx) {
   1.244 -                            WorkingCopy wc = ctx.getWorkingCopy();
   1.245 -                            Map<String, TypeMirror> constraints = new HashMap<String, TypeMirror>();
   1.246 -
   1.247 -                            for (Map.Entry<String, TypeMirrorHandle<?>> c : constraintsHandles.entrySet()) {
   1.248 -                                constraints.put(c.getKey(), c.getValue().resolve(wc));
   1.249 -                            }
   1.250 -
   1.251 -                            Pattern pattern = PatternCompiler.compile(wc, triggerPattern, constraints, Collections.<String>emptyList());
   1.252 -                            Collection<? extends Occurrence> occurrence = Matcher.create(wc).setTreeTopSearch().setSearchRoot(ctx.getPath()).match(pattern);
   1.253 -
   1.254 -                            assert occurrence.size() == 1;
   1.255 -
   1.256 -                            transformer.transform(wc, occurrence.iterator().next());
   1.257 -                        }
   1.258 -                    }.toEditorFix();
   1.259 -                    
   1.260 -                    return Collections.singletonList(ErrorDescriptionFactory.createErrorDescription(Severity.WARNING, "", Collections.singletonList(fix), ctx.getInfo().getFileObject(), 0, 0));
   1.261 -                }
   1.262 -            }).produce());
   1.263 -
   1.264 -        }
   1.265 -        
   1.266 -        BatchSearch.BatchResult batchResult = BatchSearch.findOccurrences(descriptions, Scopes.allOpenedProjectsScope());
   1.267 -        return BatchUtilities.applyFixes(batchResult, new ProgressHandleWrapper(1, 1), cancel, new ArrayList<MessageImpl>());
   1.268 -    }
   1.269 -    
   1.270 -    /**
   1.271 -     * Performs transformation described by transformationJackpotPattern on all occurences described by inputJackpotPattern.
   1.272 -     * @param inputJackpotPattern
   1.273 -     * @param transformationJackpotPattern
   1.274 -     * @param cancel 
   1.275 -     * @return
   1.276 -     */
   1.277 -    private static Collection<? extends ModificationResult> performTransformation(String inputJackpotPattern, final String transformationJackpotPattern, AtomicBoolean cancel) {
   1.278 -        return performTransformation(inputJackpotPattern, new Transformer() {
   1.279 -
   1.280 -            @Override
   1.281 -            public void transform(WorkingCopy copy, Occurrence occurrence) {
   1.282 -                try {
   1.283 -                    Fix toFix = TransformationSupport.rewriteFix(copy, "whatever", occurrence.getOccurrenceRoot(), transformationJackpotPattern, occurrence.getVariables(), occurrence.getMultiVariables(), occurrence.getVariables2Names(), Collections.<String, TypeMirror>emptyMap(), Collections.<String, String>emptyMap());
   1.284 -                    TransformationSupport.process(((JavaFixImpl) toFix).jf, copy, false, null, new ArrayList<RefactoringElementImplementation>());
   1.285 -                } catch (Exception ex) {
   1.286 -                    Exceptions.printStackTrace(ex);
   1.287 -                }
   1.288 -            }
   1.289 -        }, cancel);
   1.290 -    }
   1.291 -
   1.292 -    private static ChangeInfo process(JavaFix jf, WorkingCopy wc, boolean canShowUI, Map<org.openide.filesystems.FileObject, byte[]> resourceContent, Collection<? super RefactoringElementImplementation> fileChanges) throws Exception {
   1.293 -        return JavaFixImpl.Accessor.INSTANCE.process(jf, wc, canShowUI, resourceContent, fileChanges);
   1.294 -    }
   1.295 -
   1.296 -    /**
   1.297 -     * 
   1.298 -     * @param info
   1.299 -     * @param displayName
   1.300 -     * @param what
   1.301 -     * @param to
   1.302 -     * @param parameters
   1.303 -     * @param parametersMulti
   1.304 -     * @param parameterNames
   1.305 -     * @param constraints
   1.306 -     * @param options
   1.307 -     * @param imports
   1.308 -     * @return
   1.309 -     */
   1.310 -    private static Fix rewriteFix(CompilationInfo info, String displayName, TreePath what, final String to, Map<String, TreePath> parameters, Map<String, Collection<? extends TreePath>> parametersMulti, final Map<String, String> parameterNames, Map<String, TypeMirror> constraints, Map<String, String> options, String... imports) {
   1.311 -        return JavaFixImpl.Accessor.INSTANCE.rewriteFix(info, displayName, what, to, parameters, parametersMulti, parameterNames, constraints, options, imports);
   1.312 -    }
   1.313 -    
   1.314 -}