#204266: Adding fixes to missing return statement compilation error.
authorJan Lahoda <jlahoda@netbeans.org>
Sun, 06 Nov 2011 14:11:15 +0100
changeset 1766185103b897e7c
parent 17660 576257df2a4c
child 17662 6494a399b320
#204266: Adding fixes to missing return statement compilation error.
javahints/nbproject/project.properties
javahints/nbproject/project.xml
javahints/src/org/netbeans/modules/javahints/Bundle.properties
javahints/src/org/netbeans/modules/javahints/MissingReturn.java
javahints/src/org/netbeans/modules/javahints/resources/layer.xml
javahints/test/unit/src/org/netbeans/modules/javahints/Bundle_test.properties
javahints/test/unit/src/org/netbeans/modules/javahints/MissingReturnTest.java
     1.1 --- a/javahints/nbproject/project.properties	Sun Oct 30 22:14:10 2011 +0100
     1.2 +++ b/javahints/nbproject/project.properties	Sun Nov 06 14:11:15 2011 +0100
     1.3 @@ -50,7 +50,7 @@
     1.4  auxiliary.org-netbeans-modules-editor-indent.text.x-java.CodeStyle.project.text-limit-width=80
     1.5  javac.compilerargs=-Xlint:unchecked
     1.6  javac.source=1.5
     1.7 -spec.version.base=2.48.0
     1.8 +spec.version.base=2.49.0
     1.9  
    1.10  nbm.needs.restart=true
    1.11  requires.nb.javac=true
     2.1 --- a/javahints/nbproject/project.xml	Sun Oct 30 22:14:10 2011 +0100
     2.2 +++ b/javahints/nbproject/project.xml	Sun Nov 06 14:11:15 2011 +0100
     2.3 @@ -56,6 +56,15 @@
     2.4                      </run-dependency>
     2.5                  </dependency>
     2.6                  <dependency>
     2.7 +                    <code-name-base>org.netbeans.api.annotations.common</code-name-base>
     2.8 +                    <build-prerequisite/>
     2.9 +                    <compile-dependency/>
    2.10 +                    <run-dependency>
    2.11 +                        <release-version>1</release-version>
    2.12 +                        <specification-version>1.11</specification-version>
    2.13 +                    </run-dependency>
    2.14 +                </dependency>
    2.15 +                <dependency>
    2.16                      <code-name-base>org.netbeans.api.java</code-name-base>
    2.17                      <build-prerequisite/>
    2.18                      <compile-dependency/>
     3.1 --- a/javahints/src/org/netbeans/modules/javahints/Bundle.properties	Sun Oct 30 22:14:10 2011 +0100
     3.2 +++ b/javahints/src/org/netbeans/modules/javahints/Bundle.properties	Sun Nov 06 14:11:15 2011 +0100
     3.3 @@ -159,3 +159,6 @@
     3.4  DN_org.netbeans.modules.javahints.CheckReturnValueHint=@CheckReturnValue
     3.5  DESC_org.netbeans.modules.javahints.CheckReturnValueHint=Verifies that a result of method marked with @CheckReturnValue is really checked.
     3.6  ERR_org.netbeans.modules.javahints.CheckReturnValueHint=Should check the method return value
     3.7 +
     3.8 +DN_MissingReturn=Method Missing a Return Statement
     3.9 +FIX_AddReturn=Add return statement
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/javahints/src/org/netbeans/modules/javahints/MissingReturn.java	Sun Nov 06 14:11:15 2011 +0100
     4.3 @@ -0,0 +1,202 @@
     4.4 +/*
     4.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     4.6 + *
     4.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
     4.8 + *
     4.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    4.10 + * Other names may be trademarks of their respective owners.
    4.11 + *
    4.12 + * The contents of this file are subject to the terms of either the GNU
    4.13 + * General Public License Version 2 only ("GPL") or the Common
    4.14 + * Development and Distribution License("CDDL") (collectively, the
    4.15 + * "License"). You may not use this file except in compliance with the
    4.16 + * License. You can obtain a copy of the License at
    4.17 + * http://www.netbeans.org/cddl-gplv2.html
    4.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    4.19 + * specific language governing permissions and limitations under the
    4.20 + * License.  When distributing the software, include this License Header
    4.21 + * Notice in each file and include the License file at
    4.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    4.23 + * particular file as subject to the "Classpath" exception as provided
    4.24 + * by Oracle in the GPL Version 2 section of the License file that
    4.25 + * accompanied this code. If applicable, add the following below the
    4.26 + * License Header, with the fields enclosed by brackets [] replaced by
    4.27 + * your own identifying information:
    4.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    4.29 + *
    4.30 + * If you wish your version of this file to be governed by only the CDDL
    4.31 + * or only the GPL Version 2, indicate your decision by adding
    4.32 + * "[Contributor] elects to include this software in this distribution
    4.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    4.34 + * single choice of license, a recipient has the option to distribute
    4.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    4.36 + * to extend the choice of license to its licensees as provided above.
    4.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    4.38 + * Version 2 license, then the option applies only if the new code is
    4.39 + * made subject to such option by the copyright holder.
    4.40 + *
    4.41 + * Contributor(s):
    4.42 + *
    4.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
    4.44 + */
    4.45 +package org.netbeans.modules.javahints;
    4.46 +
    4.47 +import com.sun.source.tree.*;
    4.48 +import com.sun.source.tree.Tree.Kind;
    4.49 +import com.sun.source.util.TreePath;
    4.50 +import java.util.*;
    4.51 +import javax.lang.model.type.TypeKind;
    4.52 +import javax.lang.model.type.TypeMirror;
    4.53 +import org.netbeans.api.annotations.common.NonNull;
    4.54 +import org.netbeans.api.java.source.*;
    4.55 +import org.netbeans.api.java.source.JavaSource.Phase;
    4.56 +import org.netbeans.modules.java.hints.errors.ChangeMethodReturnType;
    4.57 +import org.netbeans.modules.java.hints.errors.Utilities;
    4.58 +import org.netbeans.modules.java.hints.jackpot.spi.JavaFix;
    4.59 +import org.netbeans.modules.java.hints.spi.ErrorRule;
    4.60 +import org.netbeans.spi.editor.hints.ChangeInfo;
    4.61 +import org.netbeans.spi.editor.hints.Fix;
    4.62 +import org.openide.filesystems.FileObject;
    4.63 +import org.openide.util.NbBundle;
    4.64 +
    4.65 +/**
    4.66 + *
    4.67 + * @author lahvac
    4.68 + */
    4.69 +public class MissingReturn implements ErrorRule<Void> {
    4.70 +
    4.71 +    private final static Set<String> CODES = new HashSet<String>(Arrays.asList(
    4.72 +            "compiler.err.missing.ret.stmt"
    4.73 +    ));
    4.74 +
    4.75 +    @Override
    4.76 +    public Set<String> getCodes() {
    4.77 +        return CODES;
    4.78 +    }
    4.79 +
    4.80 +    @Override
    4.81 +    public List<Fix> run(CompilationInfo info, String diagnosticKey, int offset, TreePath treePath, ErrorRule.Data<Void> data) {
    4.82 +        List<Fix> result = new ArrayList<Fix>();
    4.83 +
    4.84 +        treePath = info.getTreeUtilities().pathFor(offset - 1);
    4.85 +
    4.86 +        TreePath method = treePath.getParentPath();
    4.87 +        MethodTree mt = (MethodTree) method.getLeaf();
    4.88 +        TypeMirror type = info.getTrees().getTypeMirror(new TreePath(method, mt.getReturnType()));
    4.89 +
    4.90 +        result.add(createChangeToTypeFix(info, treePath.getParentPath(), info.getTypes().getNoType(TypeKind.VOID)));
    4.91 +
    4.92 +        if (type != null && treePath.getLeaf().getKind() == Kind.BLOCK) {
    4.93 +            result.add(new AddReturnFixImpl(info, treePath, type.getKind()));
    4.94 +        }
    4.95 +
    4.96 +        return result;
    4.97 +    }
    4.98 +
    4.99 +    @Override
   4.100 +    public String getId() {
   4.101 +        return MissingReturn.class.getName();
   4.102 +    }
   4.103 +
   4.104 +    @Override
   4.105 +    public String getDisplayName() {
   4.106 +        return NbBundle.getMessage(MissingReturn.class, "DN_MissingReturn");
   4.107 +    }
   4.108 +
   4.109 +    @Override
   4.110 +    public void cancel() {}
   4.111 +
   4.112 +    private static final class AddReturnFixImpl implements Fix {
   4.113 +
   4.114 +        private final TreePathHandle targetBlock;
   4.115 +        private final TypeKind targetKind;
   4.116 +
   4.117 +        public AddReturnFixImpl(CompilationInfo info, TreePath block, TypeKind kind) {
   4.118 +            this.targetBlock = TreePathHandle.create(block, info);
   4.119 +            this.targetKind = kind;
   4.120 +        }
   4.121 +
   4.122 +        @Override
   4.123 +        public String getText() {
   4.124 +            return NbBundle.getMessage(MissingReturn.class, "FIX_AddReturn");
   4.125 +        }
   4.126 +
   4.127 +        public ChangeInfo implement() throws Exception {
   4.128 +            FileObject file = targetBlock.getFileObject();
   4.129 +            JavaSource js = JavaSource.forFileObject(file);
   4.130 +
   4.131 +            ModificationResult mr = js.runModificationTask(new Task<WorkingCopy>() {
   4.132 +                public void run(WorkingCopy wc) throws Exception {
   4.133 +                    wc.toPhase(Phase.RESOLVED);
   4.134 +
   4.135 +                    TreePath block = targetBlock.resolve(wc);
   4.136 +
   4.137 +                    if (block == null) {
   4.138 +                        return ; //TODO: log
   4.139 +                    }
   4.140 +                    
   4.141 +                    //TODO:copied from NotInitializedVariable!
   4.142 +                    Object value;
   4.143 +                    if (targetKind.isPrimitive()) {
   4.144 +                        if (targetKind == TypeKind.BOOLEAN) {
   4.145 +                            value = false;
   4.146 +                        }
   4.147 +                        else {
   4.148 +                            value = 0;
   4.149 +                        }
   4.150 +                    }
   4.151 +                    else {
   4.152 +                        value = null;
   4.153 +                    }
   4.154 +
   4.155 +                    TreeMaker make = wc.getTreeMaker();
   4.156 +                    LiteralTree returnValue = make.Literal(value);
   4.157 +                    BlockTree blockTree = (BlockTree) block.getLeaf();
   4.158 +
   4.159 +                    wc.tag(returnValue, Utilities.TAG_SELECT);
   4.160 +                    wc.rewrite(blockTree, make.addBlockStatement(blockTree, make.Return(returnValue)));
   4.161 +                }
   4.162 +            });
   4.163 +
   4.164 +            return Utilities.commitAndComputeChangeInfo(file, mr);
   4.165 +        }
   4.166 +
   4.167 +    }
   4.168 +
   4.169 +    public static Fix createChangeToTypeFix(CompilationInfo info, TreePath method, @NonNull TypeMirror newType) {
   4.170 +        return JavaFix.toEditorFix(new FixImpl(info, method, TypeMirrorHandle.create(newType), info.getTypeUtilities().getTypeName(newType).toString()));
   4.171 +    }
   4.172 +
   4.173 +    private static final class FixImpl extends JavaFix {
   4.174 +
   4.175 +        private final TypeMirrorHandle targetTypeHandle;
   4.176 +        private final String targetTypeDN;
   4.177 +
   4.178 +        public FixImpl(CompilationInfo info, TreePath tp, TypeMirrorHandle targetTypeHandle, String targetTypeDN) {
   4.179 +            super(info, tp);
   4.180 +            this.targetTypeHandle = targetTypeHandle;
   4.181 +            this.targetTypeDN = targetTypeDN;
   4.182 +        }
   4.183 +
   4.184 +        @Override
   4.185 +        protected String getText() {
   4.186 +            return NbBundle.getMessage(ChangeMethodReturnType.class, "FIX_ChangeMethodReturnType", targetTypeDN);
   4.187 +        }
   4.188 +
   4.189 +        @Override
   4.190 +        protected void performRewrite(WorkingCopy wc, TreePath tp, boolean canShowUI) {
   4.191 +            TypeMirror targetType = targetTypeHandle.resolve(wc);
   4.192 +
   4.193 +            if (targetType == null) {
   4.194 +                //XXX: log
   4.195 +                return ;
   4.196 +            }
   4.197 +
   4.198 +            MethodTree mt = (MethodTree) tp.getLeaf();
   4.199 +            TreeMaker make = wc.getTreeMaker();
   4.200 +
   4.201 +            wc.rewrite(mt.getReturnType(), make.Type(targetType));
   4.202 +        }
   4.203 +
   4.204 +    }
   4.205 +}
     5.1 --- a/javahints/src/org/netbeans/modules/javahints/resources/layer.xml	Sun Oct 30 22:14:10 2011 +0100
     5.2 +++ b/javahints/src/org/netbeans/modules/javahints/resources/layer.xml	Sun Nov 06 14:11:15 2011 +0100
     5.3 @@ -50,6 +50,7 @@
     5.4                  <file name="org-netbeans-modules-javahints-TypoDetector.instance"/>
     5.5                  <file name="org-netbeans-modules-javahints-TypeInForEachLoop.instance"/>
     5.6                  <file name="org-netbeans-modules-javahints-MakeStatic.instance"/>
     5.7 +                <file name="org-netbeans-modules-javahints-MissingReturn.instance"/>
     5.8              </folder>
     5.9  
    5.10              <folder name="hints">
     6.1 --- a/javahints/test/unit/src/org/netbeans/modules/javahints/Bundle_test.properties	Sun Oct 30 22:14:10 2011 +0100
     6.2 +++ b/javahints/test/unit/src/org/netbeans/modules/javahints/Bundle_test.properties	Sun Nov 06 14:11:15 2011 +0100
     6.3 @@ -22,3 +22,4 @@
     6.4  ERR_POSSIBLENULL_TO_NON_NULL_ARG=ERR_POSSIBLENULL_TO_NON_NULL_ARG
     6.5  DN_NegateCondition=Negate condition
     6.6  ERR_org.netbeans.modules.javahints.CheckReturnValueHint=ERR_org.netbeans.modules.javahints.CheckReturnValueHint
     6.7 +FIX_AddReturn=FIX_AddReturn
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/javahints/test/unit/src/org/netbeans/modules/javahints/MissingReturnTest.java	Sun Nov 06 14:11:15 2011 +0100
     7.3 @@ -0,0 +1,89 @@
     7.4 +/*
     7.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     7.6 + *
     7.7 + * Copyright 2011 Oracle and/or its affiliates. All rights reserved.
     7.8 + *
     7.9 + * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
    7.10 + * Other names may be trademarks of their respective owners.
    7.11 + *
    7.12 + * The contents of this file are subject to the terms of either the GNU
    7.13 + * General Public License Version 2 only ("GPL") or the Common
    7.14 + * Development and Distribution License("CDDL") (collectively, the
    7.15 + * "License"). You may not use this file except in compliance with the
    7.16 + * License. You can obtain a copy of the License at
    7.17 + * http://www.netbeans.org/cddl-gplv2.html
    7.18 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
    7.19 + * specific language governing permissions and limitations under the
    7.20 + * License.  When distributing the software, include this License Header
    7.21 + * Notice in each file and include the License file at
    7.22 + * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
    7.23 + * particular file as subject to the "Classpath" exception as provided
    7.24 + * by Oracle in the GPL Version 2 section of the License file that
    7.25 + * accompanied this code. If applicable, add the following below the
    7.26 + * License Header, with the fields enclosed by brackets [] replaced by
    7.27 + * your own identifying information:
    7.28 + * "Portions Copyrighted [year] [name of copyright owner]"
    7.29 + *
    7.30 + * If you wish your version of this file to be governed by only the CDDL
    7.31 + * or only the GPL Version 2, indicate your decision by adding
    7.32 + * "[Contributor] elects to include this software in this distribution
    7.33 + * under the [CDDL or GPL Version 2] license." If you do not indicate a
    7.34 + * single choice of license, a recipient has the option to distribute
    7.35 + * your version of this file under either the CDDL, the GPL Version 2 or
    7.36 + * to extend the choice of license to its licensees as provided above.
    7.37 + * However, if you add GPL Version 2 code and therefore, elected the GPL
    7.38 + * Version 2 license, then the option applies only if the new code is
    7.39 + * made subject to such option by the copyright holder.
    7.40 + *
    7.41 + * Contributor(s):
    7.42 + *
    7.43 + * Portions Copyrighted 2011 Sun Microsystems, Inc.
    7.44 + */
    7.45 +package org.netbeans.modules.javahints;
    7.46 +
    7.47 +import com.sun.source.util.TreePath;
    7.48 +import java.util.List;
    7.49 +import org.netbeans.api.java.source.CompilationInfo;
    7.50 +import org.netbeans.modules.java.hints.infrastructure.ErrorHintsTestBase;
    7.51 +import org.netbeans.spi.editor.hints.Fix;
    7.52 +import org.openide.util.NbBundle;
    7.53 +
    7.54 +/**
    7.55 + *
    7.56 + * @author lahvac
    7.57 + */
    7.58 +public class MissingReturnTest extends ErrorHintsTestBase {
    7.59 +
    7.60 +    public MissingReturnTest(String name) {
    7.61 +        super(name);
    7.62 +    }
    7.63 +
    7.64 +    public void testReturnTypeToVoid() throws Exception {
    7.65 +        performFixTest("test/Test.java",
    7.66 +                       "package test; public class Test { private String t() { }| }",
    7.67 +                       "FIX_ChangeMethodReturnType void",
    7.68 +                       "package test; public class Test { private void t() { } }");
    7.69 +    }
    7.70 +
    7.71 +    public void testAddReturn() throws Exception {
    7.72 +        performFixTest("test/Test.java",
    7.73 +                       "package test; public class Test { private String t() {\n}| }",
    7.74 +                       "FIX_AddReturn",
    7.75 +                       "package test; public class Test { private String t() { return null; } }");
    7.76 +    }
    7.77 +
    7.78 +    @Override
    7.79 +    protected List<Fix> computeFixes(CompilationInfo info, int pos, TreePath path) throws Exception {
    7.80 +        return new MissingReturn().run(info, null, pos, path, null);
    7.81 +    }
    7.82 +
    7.83 +    @Override
    7.84 +    protected String toDebugString(CompilationInfo info, Fix f) {
    7.85 +        return f.getText();
    7.86 +    }
    7.87 +
    7.88 +    static {
    7.89 +        NbBundle.setBranding("test");
    7.90 +    }
    7.91 +
    7.92 +}