sandbox/java.hints/spi.java.hints/src/org/netbeans/spi/java/hints/JavaFix.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/JavaFix.java	Mon Dec 19 11:37:36 2016 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,309 +0,0 @@
     1.4 -/*
     1.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.6 - *
     1.7 - * Copyright 2008-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 2008-2012 Sun Microsystems, Inc.
    1.44 - */
    1.45 -
    1.46 -package org.netbeans.spi.java.hints;
    1.47 -
    1.48 -import com.sun.source.util.TreePath;
    1.49 -import java.io.ByteArrayInputStream;
    1.50 -import java.io.ByteArrayOutputStream;
    1.51 -import java.io.IOException;
    1.52 -import java.io.InputStream;
    1.53 -import java.io.OutputStream;
    1.54 -import java.nio.ByteBuffer;
    1.55 -import java.util.Collection;
    1.56 -import java.util.Collections;
    1.57 -import java.util.HashMap;
    1.58 -import java.util.List;
    1.59 -import java.util.Map;
    1.60 -import java.util.logging.Level;
    1.61 -import java.util.logging.Logger;
    1.62 -import javax.lang.model.type.TypeMirror;
    1.63 -import javax.swing.text.BadLocationException;
    1.64 -import javax.swing.text.Document;
    1.65 -import org.netbeans.api.annotations.common.NonNull;
    1.66 -import org.netbeans.api.java.source.CompilationInfo;
    1.67 -import org.netbeans.api.java.source.TreePathHandle;
    1.68 -import org.netbeans.api.java.source.WorkingCopy;
    1.69 -import org.netbeans.api.queries.FileEncodingQuery;
    1.70 -import org.netbeans.modules.java.hints.spiimpl.JavaFixImpl;
    1.71 -import org.netbeans.modules.java.hints.spiimpl.batch.BatchUtilities;
    1.72 -import org.netbeans.modules.refactoring.spi.RefactoringElementImplementation;
    1.73 -import org.netbeans.spi.editor.hints.ChangeInfo;
    1.74 -import org.netbeans.spi.editor.hints.Fix;
    1.75 -import org.openide.filesystems.FileObject;
    1.76 -import org.openide.util.Exceptions;
    1.77 -import org.openide.util.Parameters;
    1.78 -
    1.79 -/**A base class for fixes that modify Java source code. Using this class
    1.80 - * as a base class makes creating the fix somewhat simpler, but also supports
    1.81 - * running the hint in the Inspect&Transform dialog. The fix can be converted
    1.82 - * to {@link Fix} by means of the {@link #toEditorFix() } method.
    1.83 - *
    1.84 - * @see JavaFixUtilities for various predefined fixes.
    1.85 - * @author Jan Lahoda
    1.86 - */
    1.87 -public abstract class JavaFix {
    1.88 -
    1.89 -    private final TreePathHandle handle;
    1.90 -    private final Map<String, String> options;
    1.91 -
    1.92 -    /**Create JavaFix with the given base {@link TreePath}. The base {@link TreePath}
    1.93 -     * will be passed back to the real implementation of the fix.
    1.94 -     *
    1.95 -     * @param info a {@link CompilationInfo} from which the given {@link TreePath} originates
    1.96 -     * @param tp a {@link TreePath} that will be passed back to the
    1.97 -     *           {@link #performRewrite(org.netbeans.spi.java.hints.JavaFix.TransformationContext) } method
    1.98 -     */
    1.99 -    protected JavaFix(@NonNull CompilationInfo info, @NonNull TreePath tp) {
   1.100 -        this(info, tp, Collections.<String, String>emptyMap());
   1.101 -    }
   1.102 -
   1.103 -    JavaFix(CompilationInfo info, TreePath tp, Map<String, String> options) {
   1.104 -        this.handle = TreePathHandle.create(tp, info);
   1.105 -        this.options = Collections.unmodifiableMap(new HashMap<String, String>(options));
   1.106 -    }
   1.107 -
   1.108 -    /**Create JavaFix with the given base {@link TreePathHandle}. The base {@link TreePathHandle}
   1.109 -     * will be resolved and passed back to the real implementation of the fix.
   1.110 -     *
   1.111 -     * @param handle a {@link TreePathHandle} that will be resolved and passed back to the
   1.112 -     *              {@link #performRewrite(org.netbeans.spi.java.hints.JavaFix.TransformationContext) } method
   1.113 -     */
   1.114 -    protected JavaFix(@NonNull TreePathHandle handle) {
   1.115 -        this(handle, Collections.<String, String>emptyMap());
   1.116 -    }
   1.117 -
   1.118 -    JavaFix(TreePathHandle handle, Map<String, String> options) {
   1.119 -        this.handle = handle;
   1.120 -        this.options = Collections.unmodifiableMap(new HashMap<String, String>(options));
   1.121 -    }
   1.122 -
   1.123 -    /**The display text of the fix.
   1.124 -     *
   1.125 -     * @return the display text of the fix.
   1.126 -     */
   1.127 -    protected abstract @NonNull String getText();
   1.128 -
   1.129 -    /**Do the transformations needed to implement the hint's function.
   1.130 -     *
   1.131 -     * @param ctx a context over which the fix should operate
   1.132 -     * @throws Exception if something goes wrong while performing the transformation
   1.133 -     *                   - will be logged by the infrastructure
   1.134 -     */
   1.135 -    protected abstract void performRewrite(@NonNull TransformationContext ctx) throws Exception;
   1.136 -
   1.137 -    /**Convert this {@link JavaFix} into the Editor Hints {@link Fix}.
   1.138 -     *
   1.139 -     * @return a {@link Fix}, that when invoked, will invoke {@link #performRewrite(org.netbeans.spi.java.hints.JavaFix.TransformationContext) }
   1.140 -     * method on this {@link JavaFix}.
   1.141 -     */
   1.142 -    public final Fix toEditorFix() {
   1.143 -        return new JavaFixImpl(this);
   1.144 -    }
   1.145 -
   1.146 -    static {
   1.147 -        JavaFixImpl.Accessor.INSTANCE = new JavaFixImpl.Accessor() {
   1.148 -            @Override
   1.149 -            public String getText(JavaFix jf) {
   1.150 -                return jf.getText();
   1.151 -            }
   1.152 -            @Override
   1.153 -            public ChangeInfo process(JavaFix jf, WorkingCopy wc, boolean canShowUI, Map<FileObject, byte[]> resourceContent, Collection<? super RefactoringElementImplementation> fileChanges) throws Exception {
   1.154 -                TreePath tp = jf.handle.resolve(wc);
   1.155 -
   1.156 -                if (tp == null) {
   1.157 -                    Logger.getLogger(JavaFix.class.getName()).log(Level.SEVERE, "Cannot resolve handle={0}", jf.handle);
   1.158 -                    return null;
   1.159 -                }
   1.160 -
   1.161 -                jf.performRewrite(new TransformationContext(wc, tp, canShowUI, resourceContent, fileChanges));
   1.162 -
   1.163 -                return null;
   1.164 -            }
   1.165 -            @Override
   1.166 -            public FileObject getFile(JavaFix jf) {
   1.167 -                return jf.handle.getFileObject();
   1.168 -            }
   1.169 -            @Override
   1.170 -            public Map<String, String> getOptions(JavaFix jf) {
   1.171 -                return jf.options;
   1.172 -            }
   1.173 -
   1.174 -            @Override
   1.175 -            public Fix rewriteFix(CompilationInfo info, String displayName, TreePath what, String to, Map<String, TreePath> parameters, Map<String, Collection<? extends TreePath>> parametersMulti, Map<String, String> parameterNames, Map<String, TypeMirror> constraints, Map<String, String> options, String... imports) {
   1.176 -                return JavaFixUtilities.rewriteFix(info, displayName, what, to, parameters, parametersMulti, parameterNames, constraints, options, imports);
   1.177 -            }
   1.178 -
   1.179 -            @Override
   1.180 -            public Fix createSuppressWarningsFix(CompilationInfo compilationInfo, TreePath treePath, String... keys) {
   1.181 -                return ErrorDescriptionFactory.createSuppressWarningsFix(compilationInfo, treePath, keys);
   1.182 -            }
   1.183 -
   1.184 -            @Override
   1.185 -            public List<Fix> createSuppressWarnings(CompilationInfo compilationInfo, TreePath treePath, String... keys) {
   1.186 -                return ErrorDescriptionFactory.createSuppressWarnings(compilationInfo, treePath, keys);
   1.187 -            }
   1.188 -
   1.189 -            @Override
   1.190 -            public List<Fix> resolveDefaultFixes(HintContext ctx, Fix... provided) {
   1.191 -                return ErrorDescriptionFactory.resolveDefaultFixes(ctx, provided);
   1.192 -            }
   1.193 -        };
   1.194 -    }
   1.195 -
   1.196 -    /**A context that contains a reference to a {@link WorkingCopy} through which
   1.197 -     * modifications of Java source code can be made.
   1.198 -     *
   1.199 -     */
   1.200 -    public static final class TransformationContext {
   1.201 -        private final WorkingCopy workingCopy;
   1.202 -        private final TreePath path;
   1.203 -        private final boolean canShowUI;
   1.204 -        private final Map<FileObject, byte[]> resourceContentChanges;
   1.205 -        private final Collection<? super RefactoringElementImplementation> fileChanges;
   1.206 -        TransformationContext(WorkingCopy workingCopy, TreePath path, boolean canShowUI, Map<FileObject, byte[]> resourceContentChanges, Collection<? super RefactoringElementImplementation> fileChanges) {
   1.207 -            this.workingCopy = workingCopy;
   1.208 -            this.path = path;
   1.209 -            this.canShowUI = canShowUI;
   1.210 -            this.resourceContentChanges = resourceContentChanges;
   1.211 -            this.fileChanges = fileChanges;
   1.212 -        }
   1.213 -
   1.214 -        boolean isCanShowUI() {
   1.215 -            return canShowUI;
   1.216 -        }
   1.217 -
   1.218 -        /**Returns the {@link TreePath} that was passed to a {@link JavaFix} constructor.
   1.219 -         *
   1.220 -         * @return the {@link TreePath} that was passed to a {@link JavaFix} constructor.
   1.221 -         */
   1.222 -        public @NonNull TreePath getPath() {
   1.223 -            return path;
   1.224 -        }
   1.225 -
   1.226 -        /**A {@link WorkingCopy} over which the transformation should operate.
   1.227 -         * @return {@link WorkingCopy} over which the transformation should operate.
   1.228 -         */
   1.229 -        public @NonNull WorkingCopy getWorkingCopy() {
   1.230 -            return workingCopy;
   1.231 -        }
   1.232 -
   1.233 -        /**Allows access to non-Java resources. The content of this InputStream will
   1.234 -         * include all changes done through {@link #getResourceOutput(org.openide.filesystems.FileObject) }
   1.235 -         * before calling this method.
   1.236 -         *
   1.237 -         * @param file whose content should be returned
   1.238 -         * @return the file's content
   1.239 -         * @throws IOException if something goes wrong while opening the file
   1.240 -         * @throws IllegalArgumentException if {@code file} parameter is null, or
   1.241 -         *                                  if it represents a Java file
   1.242 -         */
   1.243 -        public @NonNull InputStream getResourceContent(@NonNull FileObject file) throws IOException, IllegalArgumentException {
   1.244 -            Parameters.notNull("file", file);
   1.245 -            if ("text/x-java".equals(file.getMIMEType("text/x-java")))
   1.246 -                throw new IllegalArgumentException("Cannot access Java files");
   1.247 -
   1.248 -            byte[] newContent = resourceContentChanges != null ? resourceContentChanges.get(file) : null;
   1.249 -
   1.250 -            if (newContent == null) {
   1.251 -                final Document doc = BatchUtilities.getDocument(file);
   1.252 -
   1.253 -                if (doc != null) {
   1.254 -                    final String[] result = new String[1];
   1.255 -
   1.256 -                    doc.render(new Runnable() {
   1.257 -                        @Override public void run() {
   1.258 -                            try {
   1.259 -                                result[0] = doc.getText(0, doc.getLength());
   1.260 -                            } catch (BadLocationException ex) {
   1.261 -                                Exceptions.printStackTrace(ex);
   1.262 -                            }
   1.263 -                        }
   1.264 -                    });
   1.265 -
   1.266 -                    if (result[0] != null) {
   1.267 -                        ByteBuffer encoded = FileEncodingQuery.getEncoding(file).encode(result[0]);
   1.268 -                        byte[] encodedBytes = new byte[encoded.remaining()];
   1.269 -
   1.270 -                        encoded.get(encodedBytes);
   1.271 -
   1.272 -                        return new ByteArrayInputStream(encodedBytes);
   1.273 -                    }
   1.274 -                }
   1.275 -                
   1.276 -                return file.getInputStream();
   1.277 -            } else {
   1.278 -                return new ByteArrayInputStream(newContent);
   1.279 -            }
   1.280 -        }
   1.281 -
   1.282 -        /**Record a changed version of a file. The changes will be applied altogether with
   1.283 -         * changes to the Java file. In Inspect&Transform, changes done through this
   1.284 -         * method will be part of the preview.
   1.285 -         *
   1.286 -         * @param file whose content should be changed
   1.287 -         * @return an {@link java.io.OutputStream} into which the new content of the file should be written
   1.288 -         * @throws IOException if something goes wrong while opening the file
   1.289 -         * @throws IllegalArgumentException if {@code file} parameter is null, or
   1.290 -         *                                  if it represents a Java file
   1.291 -         */
   1.292 -        public @NonNull OutputStream getResourceOutput(@NonNull final FileObject file) throws IOException {
   1.293 -            Parameters.notNull("file", file);
   1.294 -            if ("text/x-java".equals(file.getMIMEType("text/x-java")))
   1.295 -                throw new IllegalArgumentException("Cannot access Java files");
   1.296 -            if (resourceContentChanges == null) return file.getOutputStream();
   1.297 -
   1.298 -            return new ByteArrayOutputStream() {
   1.299 -                @Override public void close() throws IOException {
   1.300 -                    super.close();
   1.301 -                    resourceContentChanges.put(file, toByteArray());
   1.302 -                }
   1.303 -            };
   1.304 -        }
   1.305 -
   1.306 -        Collection<? super RefactoringElementImplementation> getFileChanges() {
   1.307 -            return fileChanges;
   1.308 -        }
   1.309 -
   1.310 -    }
   1.311 -
   1.312 -}