Updating NPECheck hint to current hint SPI.
authorJan Lahoda <jlahoda@netbeans.org>
Thu, 19 Apr 2012 22:19:53 +0200
changeset 17819c912ef634638
parent 17818 361013e4690a
child 17820 76be0d576837
Updating NPECheck hint to current hint SPI.
javahints/src/org/netbeans/modules/javahints/Bundle.properties
javahints/src/org/netbeans/modules/javahints/NPECheck.java
javahints/test/unit/src/org/netbeans/modules/javahints/NPECheckTest.java
     1.1 --- a/javahints/src/org/netbeans/modules/javahints/Bundle.properties	Thu Apr 19 21:04:16 2012 +0200
     1.2 +++ b/javahints/src/org/netbeans/modules/javahints/Bundle.properties	Thu Apr 19 22:19:53 2012 +0200
     1.3 @@ -130,6 +130,8 @@
     1.4  FIX_ConvertAnonymousToInner=Convert Anonymous to Inner
     1.5  
     1.6  
     1.7 +DN_NPECheck=Null Dereference
     1.8 +DESC_NPECheck=Checks various problems related to dereferencing nulls
     1.9  ERR_DereferencingNull=Dereferencing null
    1.10  ERR_PossiblyDereferencingNull=Possibly Dereferencing null
    1.11  ERR_AssigningNullToNotNull=Assigning Null to NotNull Variable
     2.1 --- a/javahints/src/org/netbeans/modules/javahints/NPECheck.java	Thu Apr 19 21:04:16 2012 +0200
     2.2 +++ b/javahints/src/org/netbeans/modules/javahints/NPECheck.java	Thu Apr 19 22:19:53 2012 +0200
     2.3 @@ -1,7 +1,7 @@
     2.4  /*
     2.5   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     2.6   * 
     2.7 - * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
     2.8 + * Copyright 1997-2012 Sun Microsystems, Inc. All rights reserved.
     2.9   * 
    2.10   * The contents of this file are subject to the terms of either the GNU
    2.11   * General Public License Version 2 only ("GPL") or the Common
    2.12 @@ -23,36 +23,20 @@
    2.13   * 
    2.14   * Contributor(s):
    2.15   * 
    2.16 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
    2.17 + * Portions Copyrighted 2007-2012 Sun Microsystems, Inc.
    2.18   */
    2.19  
    2.20  package org.netbeans.modules.javahints;
    2.21  
    2.22 -import com.sun.source.tree.AssignmentTree;
    2.23 -import com.sun.source.tree.BinaryTree;
    2.24 -import com.sun.source.tree.BreakTree;
    2.25 -import com.sun.source.tree.ClassTree;
    2.26 -import com.sun.source.tree.ConditionalExpressionTree;
    2.27 -import com.sun.source.tree.ContinueTree;
    2.28 -import com.sun.source.tree.IdentifierTree;
    2.29 -import com.sun.source.tree.IfTree;
    2.30 -import com.sun.source.tree.LiteralTree;
    2.31 -import com.sun.source.tree.MemberSelectTree;
    2.32 -import com.sun.source.tree.MethodInvocationTree;
    2.33 -import com.sun.source.tree.NewClassTree;
    2.34 -import com.sun.source.tree.ReturnTree;
    2.35 -import com.sun.source.tree.ThrowTree;
    2.36 -import com.sun.source.tree.Tree;
    2.37 +import com.sun.source.tree.*;
    2.38  import com.sun.source.tree.Tree.Kind;
    2.39 -import com.sun.source.tree.VariableTree;
    2.40 -import com.sun.source.tree.WhileLoopTree;
    2.41  import com.sun.source.util.TreePath;
    2.42  import com.sun.source.util.TreePathScanner;
    2.43  import java.util.ArrayList;
    2.44  import java.util.EnumSet;
    2.45  import java.util.HashMap;
    2.46  import java.util.HashSet;
    2.47 -import java.util.LinkedList;
    2.48 +import java.util.IdentityHashMap;
    2.49  import java.util.List;
    2.50  import java.util.Map;
    2.51  import java.util.Map.Entry;
    2.52 @@ -64,75 +48,172 @@
    2.53  import javax.lang.model.element.TypeElement;
    2.54  import javax.lang.model.element.VariableElement;
    2.55  import org.netbeans.api.java.source.CompilationInfo;
    2.56 -import org.netbeans.modules.java.hints.spi.AbstractHint;
    2.57 -import org.netbeans.modules.java.hints.spi.support.FixFactory;
    2.58  import org.netbeans.spi.editor.hints.ErrorDescription;
    2.59 -import org.netbeans.spi.editor.hints.ErrorDescriptionFactory;
    2.60 -import org.netbeans.spi.editor.hints.Fix;
    2.61  import org.openide.util.NbBundle;
    2.62  
    2.63  import static org.netbeans.modules.javahints.NPECheck.State.*;
    2.64 +import org.netbeans.spi.java.hints.*;
    2.65  
    2.66 -/**
    2.67 +/**XXX: null initializer to a non-null variable!
    2.68   *
    2.69   * @author lahvac
    2.70   */
    2.71 -public class NPECheck extends AbstractHint {
    2.72 +@Hint(displayName="#DN_NPECheck", description="#DESC_NPECheck", category="bugs", enabled=false)
    2.73 +public class NPECheck {
    2.74  
    2.75 -    public NPECheck() {
    2.76 -        super(false, true, HintSeverity.WARNING, "null");
    2.77 +    @TriggerPattern("$var = $expr")
    2.78 +    public static ErrorDescription assignment(HintContext ctx) {
    2.79 +        Element e = ctx.getInfo().getTrees().getElement(ctx.getVariables().get("$var"));
    2.80 +
    2.81 +        if (e == null || !VARIABLE_ELEMENT.contains(e.getKind())) {
    2.82 +            return null;
    2.83 +        }
    2.84 +        
    2.85 +        TreePath expr = ctx.getVariables().get("$expr");
    2.86 +        State r = computeExpressionsState(ctx.getInfo()).get(expr.getLeaf());
    2.87 +
    2.88 +        State elementState = getStateFromAnnotations(e);
    2.89 +
    2.90 +        if (elementState != null && elementState.isNotNull()) {
    2.91 +            String key = null;
    2.92 +
    2.93 +            if (r == NULL) {
    2.94 +                key = "ERR_AssigningNullToNotNull";
    2.95 +            }
    2.96 +
    2.97 +            if (r == POSSIBLE_NULL_REPORT) {
    2.98 +                key = "ERR_PossibleAssigingNullToNotNull";
    2.99 +            }
   2.100 +
   2.101 +            if (key != null) {
   2.102 +                return ErrorDescriptionFactory.forTree(ctx, ctx.getPath(), NbBundle.getMessage(NPECheck.class, key));
   2.103 +            }
   2.104 +        }
   2.105 +
   2.106 +        return null;
   2.107 +    }
   2.108 +    
   2.109 +    @TriggerPattern("$select.$variable")
   2.110 +    public static ErrorDescription memberSelect(HintContext ctx) {
   2.111 +        TreePath select = ctx.getVariables().get("$select");
   2.112 +        State r = computeExpressionsState(ctx.getInfo()).get(select.getLeaf());
   2.113 +        
   2.114 +        if (r == State.NULL) {
   2.115 +            String displayName = NbBundle.getMessage(NPECheck.class, "ERR_DereferencingNull");
   2.116 +            
   2.117 +            return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), displayName);
   2.118 +        }
   2.119 +
   2.120 +        if (r == State.POSSIBLE_NULL_REPORT) {
   2.121 +            String displayName = NbBundle.getMessage(NPECheck.class, "ERR_PossiblyDereferencingNull");
   2.122 +            
   2.123 +            return ErrorDescriptionFactory.forName(ctx, ctx.getPath(), displayName);
   2.124 +        }
   2.125 +        
   2.126 +        return null;
   2.127 +    }
   2.128 +    
   2.129 +    @TriggerTreeKind(Kind.METHOD_INVOCATION)
   2.130 +    public static List<ErrorDescription> methodInvocation(HintContext ctx) {
   2.131 +        MethodInvocationTree mit = (MethodInvocationTree) ctx.getPath().getLeaf();
   2.132 +        List<State> paramStates = new ArrayList<State>(mit.getArguments().size());
   2.133 +        Map<Tree, State> expressionsState = computeExpressionsState(ctx.getInfo());
   2.134 +
   2.135 +        for (Tree param : mit.getArguments()) {
   2.136 +            State r = expressionsState.get(param);
   2.137 +            paramStates.add(r != null ? r : State.POSSIBLE_NULL);
   2.138 +        }
   2.139 +
   2.140 +        Element e = ctx.getInfo().getTrees().getElement(ctx.getPath());
   2.141 +
   2.142 +        if (e == null || e.getKind() != ElementKind.METHOD) {
   2.143 +            return null;
   2.144 +        }
   2.145 +
   2.146 +        ExecutableElement ee = (ExecutableElement) e;
   2.147 +        int index = 0;
   2.148 +        List<ErrorDescription> result = new ArrayList<ErrorDescription>();
   2.149 +
   2.150 +        for (VariableElement param : ee.getParameters()) {
   2.151 +            if (getStateFromAnnotations(param) == NOT_NULL) {
   2.152 +                switch (paramStates.get(index)) {
   2.153 +                    case NULL:
   2.154 +                        result.add(ErrorDescriptionFactory.forTree(ctx, mit.getArguments().get(index), NbBundle.getMessage(NPECheck.class, "ERR_NULL_TO_NON_NULL_ARG")));
   2.155 +                        break;
   2.156 +                    case POSSIBLE_NULL_REPORT:
   2.157 +                        result.add(ErrorDescriptionFactory.forTree(ctx, mit.getArguments().get(index), NbBundle.getMessage(NPECheck.class, "ERR_POSSIBLENULL_TO_NON_NULL_ARG")));
   2.158 +                        break;
   2.159 +                }
   2.160 +            }
   2.161 +        }
   2.162 +        
   2.163 +        return result;
   2.164 +    } 
   2.165 +    
   2.166 +    private static final Object KEY_EXPRESSION_STATE = new Object();
   2.167 +    //Cancelling:
   2.168 +    private static Map<Tree, State> computeExpressionsState(CompilationInfo info) {
   2.169 +        Map<Tree, State> result = (Map<Tree, State>) info.getCachedValue(KEY_EXPRESSION_STATE);
   2.170 +        
   2.171 +        if (result != null) {
   2.172 +            return result;
   2.173 +        }
   2.174 +        
   2.175 +        VisitorImpl v = new VisitorImpl(info);
   2.176 +        
   2.177 +        v.scan(info.getCompilationUnit(), null);
   2.178 +        
   2.179 +        info.putCachedValue(KEY_EXPRESSION_STATE, result = v.expressionState, CompilationInfo.CacheClearPolicy.ON_TASK_END);
   2.180 +        
   2.181 +        return result;
   2.182 +    }
   2.183 +    
   2.184 +    private static State getStateFromAnnotations(Element e) {
   2.185 +        return getStateFromAnnotations(e, State.POSSIBLE_NULL);
   2.186      }
   2.187  
   2.188 -    @Override
   2.189 -    public String getDescription() {
   2.190 -        return "NPE";
   2.191 +    private static State getStateFromAnnotations(Element e, State def) {
   2.192 +        for (AnnotationMirror am : e.getAnnotationMirrors()) {
   2.193 +            String simpleName = ((TypeElement) am.getAnnotationType().asElement()).getSimpleName().toString();
   2.194 +
   2.195 +            if ("Nullable".equals(simpleName) || "NullAllowed".equals(simpleName)) {
   2.196 +                return State.POSSIBLE_NULL_REPORT;
   2.197 +            }
   2.198 +
   2.199 +            if ("CheckForNull".equals(simpleName)) {
   2.200 +                return State.POSSIBLE_NULL_REPORT;
   2.201 +            }
   2.202 +
   2.203 +            if ("NotNull".equals(simpleName) || "NonNull".equals(simpleName)) {
   2.204 +                return State.NOT_NULL;
   2.205 +            }
   2.206 +        }
   2.207 +
   2.208 +        return def;
   2.209      }
   2.210 -
   2.211 -    public Set<Kind> getTreeKinds() {
   2.212 -        return EnumSet.of(Kind.METHOD);
   2.213 -    }
   2.214 -
   2.215 -    public List<ErrorDescription> run(CompilationInfo compilationInfo, TreePath treePath) {
   2.216 -        VisitorImpl v = new VisitorImpl(compilationInfo);
   2.217          
   2.218 -        v.scan(treePath, null);
   2.219 +    private static final class VisitorImpl extends TreePathScanner<State, Void> {
   2.220          
   2.221 -        return v.warnings;
   2.222 -    }
   2.223 -
   2.224 -    public String getId() {
   2.225 -        return NPECheck.class.getName();
   2.226 -    }
   2.227 -
   2.228 -    public String getDisplayName() {
   2.229 -        return "NPE";
   2.230 -    }
   2.231 -
   2.232 -    public void cancel() {
   2.233 -    }
   2.234 -
   2.235 -    private final class VisitorImpl extends TreePathScanner<State, Void> {
   2.236 -        
   2.237 -        private CompilationInfo info;
   2.238 -        private List<ErrorDescription> warnings;
   2.239 -        
   2.240 +        private final CompilationInfo info;
   2.241          private Map<VariableElement, State> variable2State = new HashMap<VariableElement, NPECheck.State>();
   2.242          private Map<VariableElement, State> testedTo = new HashMap<VariableElement, NPECheck.State>();
   2.243 +        private final Map<Tree, State> expressionState = new IdentityHashMap<Tree, State>();
   2.244  
   2.245          public VisitorImpl(CompilationInfo info) {
   2.246              this.info = info;
   2.247 -            this.warnings = new LinkedList<ErrorDescription>();
   2.248          }
   2.249  
   2.250 -        private void report(TreePath path, String key) {
   2.251 -            long start = info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), path.getLeaf());
   2.252 -            long end = info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), path.getLeaf());
   2.253 +        @Override
   2.254 +        public State scan(Tree tree, Void p) {
   2.255 +            State r = super.scan(tree, p);
   2.256 +            
   2.257 +            if (r != null) {
   2.258 +                expressionState.put(tree, r);
   2.259 +            }
   2.260 +            
   2.261 +            return r;
   2.262 +        }
   2.263  
   2.264 -            String displayName = NbBundle.getMessage(NPECheck.class, key);
   2.265 -            List<Fix> fixes = FixFactory.createSuppressWarnings(info, path, "null");
   2.266 -            warnings.add(ErrorDescriptionFactory.createErrorDescription(getSeverity().toEditorSeverity(), displayName, fixes, info.getFileObject(), (int) start, (int) end));
   2.267 -        }
   2.268 -        
   2.269          @Override
   2.270          public State visitAssignment(AssignmentTree node, Void p) {
   2.271              Element e = info.getTrees().getElement(new TreePath(getCurrentPath(), node.getVariable()));
   2.272 @@ -147,24 +228,6 @@
   2.273              
   2.274              scan(node.getVariable(), p);
   2.275              
   2.276 -            State elementState = getStateFromAnnotations(e);
   2.277 -            
   2.278 -            if (elementState != null && elementState.isNotNull()) {
   2.279 -                String key = null;
   2.280 -
   2.281 -                if (r == NULL) {
   2.282 -                    key = "ERR_AssigningNullToNotNull";
   2.283 -                }
   2.284 -
   2.285 -                if (r == POSSIBLE_NULL_REPORT) {
   2.286 -                    key = "ERR_PossibleAssigingNullToNotNull";
   2.287 -                }
   2.288 -            
   2.289 -                if (key != null) {
   2.290 -                    report(getCurrentPath(), key);
   2.291 -                }
   2.292 -            }
   2.293 -            
   2.294              return r;
   2.295          }
   2.296  
   2.297 @@ -186,37 +249,29 @@
   2.298          @Override
   2.299          public State visitMemberSelect(MemberSelectTree node, Void p) {
   2.300              State expr = scan(node.getExpression(), p);
   2.301 -            
   2.302 -            long start = info.getTrees().getSourcePositions().getStartPosition(info.getCompilationUnit(), node);
   2.303 -            long end = info.getTrees().getSourcePositions().getEndPosition(info.getCompilationUnit(), node);
   2.304 -
   2.305              boolean wasNPE = false;
   2.306              
   2.307              if (expr == State.NULL) {
   2.308 -                String displayName = NbBundle.getMessage(NPECheck.class, "ERR_DereferencingNull");
   2.309 -                List<Fix> fixes = FixFactory.createSuppressWarnings(info, getCurrentPath(), "null");
   2.310 -                warnings.add(ErrorDescriptionFactory.createErrorDescription(getSeverity().toEditorSeverity(), displayName, fixes, info.getFileObject(), (int) start, (int) end));
   2.311 -                
   2.312                  wasNPE = true;
   2.313              }
   2.314  
   2.315              if (expr == State.POSSIBLE_NULL_REPORT) {
   2.316 -                String displayName = NbBundle.getMessage(NPECheck.class, "ERR_PossiblyDereferencingNull");
   2.317 -                List<Fix> fixes = FixFactory.createSuppressWarnings(info, getCurrentPath(), "null");
   2.318 -                warnings.add(ErrorDescriptionFactory.createErrorDescription(getSeverity().toEditorSeverity(), displayName, fixes, info.getFileObject(), (int) start, (int) end));
   2.319 -                
   2.320                  wasNPE = true;
   2.321              }
   2.322              
   2.323 -            if (wasNPE) {
   2.324 -                Element e = info.getTrees().getElement(new TreePath(getCurrentPath(), node.getExpression()));
   2.325 +            Element e = info.getTrees().getElement(new TreePath(getCurrentPath(), node.getExpression()));
   2.326 +            
   2.327 +            if (isVariableElement(e)) {
   2.328 +                State r = getStateFromAnnotations(e);
   2.329                  
   2.330 -                if (isVariableElement(e)) {
   2.331 +                if (wasNPE) {
   2.332                      variable2State.put((VariableElement) e, NOT_NULL_BE_NPE);
   2.333                  }
   2.334 +                
   2.335 +                return r;
   2.336              }
   2.337              
   2.338 -            return super.visitMemberSelect(node, p);
   2.339 +            return State.POSSIBLE_NULL;
   2.340          }
   2.341  
   2.342          @Override
   2.343 @@ -474,12 +529,10 @@
   2.344          @Override
   2.345          public State visitMethodInvocation(MethodInvocationTree node, Void p) {
   2.346              scan(node.getTypeArguments(), p);
   2.347 -            
   2.348 -            State methodSelectState = scan(node.getMethodSelect(), p);
   2.349 -            List<State> paramStates = new ArrayList<State>(node.getArguments().size());
   2.350 +            scan(node.getMethodSelect(), p);
   2.351              
   2.352              for (Tree param : node.getArguments()) {
   2.353 -                paramStates.add(scan(param, p));
   2.354 +                scan(param, p);
   2.355              }
   2.356              
   2.357              Element e = info.getTrees().getElement(getCurrentPath());
   2.358 @@ -488,22 +541,6 @@
   2.359                  return State.POSSIBLE_NULL;
   2.360              }
   2.361              
   2.362 -            ExecutableElement ee = (ExecutableElement) e;
   2.363 -            int index = 0;
   2.364 -            
   2.365 -            for (VariableElement param : ee.getParameters()) {
   2.366 -                if (getStateFromAnnotations(param) == NOT_NULL) {
   2.367 -                    switch (paramStates.get(index)) {
   2.368 -                        case NULL:
   2.369 -                            report(new TreePath(getCurrentPath(), node.getArguments().get(index)), "ERR_NULL_TO_NON_NULL_ARG");
   2.370 -                            break;
   2.371 -                        case POSSIBLE_NULL_REPORT:
   2.372 -                            report(new TreePath(getCurrentPath(), node.getArguments().get(index)), "ERR_POSSIBLENULL_TO_NON_NULL_ARG");
   2.373 -                            break;
   2.374 -                    }
   2.375 -                }
   2.376 -            }
   2.377 -            
   2.378              return getStateFromAnnotations(e);
   2.379          }
   2.380  
   2.381 @@ -559,29 +596,6 @@
   2.382              return null;
   2.383          }
   2.384          
   2.385 -        private State getStateFromAnnotations(Element e) {
   2.386 -            return getStateFromAnnotations(e, State.POSSIBLE_NULL);
   2.387 -        }
   2.388 -        
   2.389 -        private State getStateFromAnnotations(Element e, State def) {
   2.390 -            for (AnnotationMirror am : e.getAnnotationMirrors()) {
   2.391 -                String simpleName = ((TypeElement) am.getAnnotationType().asElement()).getSimpleName().toString();
   2.392 -
   2.393 -                if ("Nullable".equals(simpleName) || "NullAllowed".equals(simpleName)) {
   2.394 -                    return State.POSSIBLE_NULL_REPORT;
   2.395 -                }
   2.396 -
   2.397 -                if ("CheckForNull".equals(simpleName)) {
   2.398 -                    return State.POSSIBLE_NULL_REPORT;
   2.399 -                }
   2.400 -
   2.401 -                if ("NotNull".equals(simpleName) || "NonNull".equals(simpleName)) {
   2.402 -                    return State.NOT_NULL;
   2.403 -                }
   2.404 -            }
   2.405 -
   2.406 -            return def;
   2.407 -        }
   2.408      }
   2.409      
   2.410      static enum State {
     3.1 --- a/javahints/test/unit/src/org/netbeans/modules/javahints/NPECheckTest.java	Thu Apr 19 21:04:16 2012 +0200
     3.2 +++ b/javahints/test/unit/src/org/netbeans/modules/javahints/NPECheckTest.java	Thu Apr 19 22:19:53 2012 +0200
     3.3 @@ -1,7 +1,7 @@
     3.4  /*
     3.5   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     3.6   * 
     3.7 - * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
     3.8 + * Copyright 1997-2012 Sun Microsystems, Inc. All rights reserved.
     3.9   * 
    3.10   * The contents of this file are subject to the terms of either the GNU
    3.11   * General Public License Version 2 only ("GPL") or the Common
    3.12 @@ -23,88 +23,92 @@
    3.13   * 
    3.14   * Contributor(s):
    3.15   * 
    3.16 - * Portions Copyrighted 2007 Sun Microsystems, Inc.
    3.17 + * Portions Copyrighted 2007-2012 Sun Microsystems, Inc.
    3.18   */
    3.19  
    3.20  package org.netbeans.modules.javahints;
    3.21  
    3.22 -import com.sun.source.util.TreePath;
    3.23 -import java.util.List;
    3.24 -import org.netbeans.api.java.source.CompilationInfo;
    3.25 -import org.netbeans.modules.java.hints.infrastructure.TreeRuleTestBase;
    3.26 -import org.netbeans.spi.editor.hints.ErrorDescription;
    3.27 -import org.openide.util.NbBundle;
    3.28 +import org.netbeans.junit.NbTestCase;
    3.29 +import org.netbeans.modules.java.hints.test.api.HintTest;
    3.30  
    3.31  /**
    3.32   *
    3.33   * @author lahvac
    3.34   */
    3.35 -public class NPECheckTest extends TreeRuleTestBase {
    3.36 +public class NPECheckTest extends NbTestCase {
    3.37      
    3.38      public NPECheckTest(String testName) {
    3.39          super(testName);
    3.40      }
    3.41  
    3.42      public void testSimpleNull1() throws Exception {
    3.43 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {Object o; o = null; o.toString();}}", "0:67-0:77:verifier:DN");
    3.44 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {Object o; o = null; o.toString();}}", "0:69-0:77:verifier:DN");
    3.45      }
    3.46      
    3.47      public void testSimpleNull2() throws Exception {
    3.48 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {Object o = null; o.toString();}}", "0:64-0:74:verifier:DN");
    3.49 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {Object o = null; o.toString();}}", "0:66-0:74:verifier:DN");
    3.50      }
    3.51      
    3.52      public void testIf1() throws Exception {
    3.53 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st(Object o) {if (o == null) {o.toString();}}}", "0:71-0:81:verifier:DN");
    3.54 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test(Object o) {if (o == null) {o.toString();}}}", "0:73-0:81:verifier:DN");
    3.55      }
    3.56      
    3.57      public void testIf2() throws Exception {
    3.58 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st(Object o) {if (o == null) {o = \"\";} o.length();}}");
    3.59 +        HintTest.create()
    3.60 +                .input("package test; class Test {private void test(Object o) {if (o == null) {o = \"\";} o.length();}}", false)
    3.61 +                .run(NPECheck.class)
    3.62 +                .assertWarnings();
    3.63      }
    3.64      
    3.65      public void testIf3() throws Exception {
    3.66 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {String s = null; if (s == null) {s = \"\";} s.length();}}");
    3.67 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s == null) {s = \"\";} s.length();}}");
    3.68      }
    3.69      
    3.70      public void testIf4() throws Exception {
    3.71 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {String s = null; if (s == null) {s = \"\";} else {s = \"\";} s.length();}}");
    3.72 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s == null) {s = \"\";} else {s = \"\";} s.length();}}");
    3.73      }
    3.74      
    3.75      public void testIf5() throws Exception {
    3.76 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {String s = null; if (s == null) {s = \"\";} else {s = null;} s.length();}}", "0:106-0:114:verifier:Possibly Dereferencing null");
    3.77 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s == null) {s = \"\";} else {s = null;} s.length();}}", "0:108-0:114:verifier:Possibly Dereferencing null");
    3.78      }
    3.79      
    3.80      public void testIf6() throws Exception {
    3.81 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st(Object o) {if (null == o) {o.toString();}}}", "0:71-0:81:verifier:DN");
    3.82 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test(Object o) {if (null == o) {o.toString();}}}", "0:73-0:81:verifier:DN");
    3.83      }
    3.84      
    3.85      public void testIf7() throws Exception {
    3.86 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {String o = null; if (o != null) {o.toString();}}}");
    3.87 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String o = null; if (o != null) {o.toString();}}}");
    3.88      }
    3.89      
    3.90      public void testIf8() throws Exception {
    3.91 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {String o = null; if (null != o) {o.toString();}}}");
    3.92 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String o = null; if (null != o) {o.toString();}}}");
    3.93      }
    3.94      
    3.95      public void testIf9() throws Exception {
    3.96 -        performAnalysisTest("test/Test.java",
    3.97 -                            "package test; class Test {private void te|st(String s) {if (s == null) {} s.length();}}}",
    3.98 -                            "0:73-0:81:verifier:Possibly Dereferencing null");
    3.99 +        HintTest.create()
   3.100 +                .input("package test; class Test {private void test(String s) {if (s == null) {} s.length();}}")
   3.101 +                .run(NPECheck.class)
   3.102 +                .assertWarnings("0:75-0:81:verifier:Possibly Dereferencing null");
   3.103      }
   3.104      
   3.105      public void testIfa() throws Exception {
   3.106 -        performAnalysisTest("test/Test.java",
   3.107 -                            "package test; class Test {private void te|st(String s1, String s2) {if (s1 == null) {s1 = s2;} s1.length();}}}");
   3.108 +        HintTest.create()
   3.109 +                .input("package test; class Test {private void test(String s1, String s2) {if (s1 == null) {s1 = s2;} s1.length();}}")
   3.110 +                .run(NPECheck.class)
   3.111 +                .assertWarnings();
   3.112      }
   3.113      
   3.114      public void testIfb() throws Exception {
   3.115 -        performAnalysisTest("test/Test.java",
   3.116 -                            "package test; class Test {private void te|st(@Null String s) {if (s == null) {throw new UnsupportedOperationException();} s.length();}} @interface Null {}}");
   3.117 +        HintTest.create()
   3.118 +                .input("package test; class Test {private void test(@Null String s) {if (s == null) {throw new UnsupportedOperationException();} s.length();}} @interface Null {}")
   3.119 +                .run(NPECheck.class)
   3.120 +                .assertWarnings();
   3.121      }
   3.122      
   3.123      public void testIfc() throws Exception {
   3.124          performAnalysisTest("test/Test.java",
   3.125                              "package test; class Test {\n"+
   3.126 -                            "    private void te|st(int i, @CheckForNull String o) {\n" +
   3.127 +                            "    private void test(int i, @CheckForNull String o) {\n" +
   3.128                              "        if (i > 2 && o != null && o.length() > 2) {\n" +
   3.129                              "        }\n" +
   3.130                              "    }\n" +
   3.131 @@ -119,24 +123,24 @@
   3.132                              "        }\n" +
   3.133                              "    }\n" +
   3.134                              "    @interface CheckForNull{}\n" +
   3.135 -                            "}\n", 42);
   3.136 +                            "}\n");
   3.137      }
   3.138      
   3.139      public void testTernary1() throws Exception {
   3.140 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st(int i) {String s = i == 0 ? \"\" : null; s.length();}}");
   3.141 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test(int i) {String s = i == 0 ? \"\" : null; s.length();}}");
   3.142      }
   3.143      
   3.144      public void testTernary2() throws Exception {
   3.145          performAnalysisTest("test/Test.java",
   3.146 -                            "package test; class Test {private void te|st(String s) {Object o = s == null ? \"\" : s; s = s.toString();}}",
   3.147 -                            "0:90-0:100:verifier:Possibly Dereferencing null");
   3.148 +                            "package test; class Test {private void test(String s) {Object o = s == null ? \"\" : s; s = s.toString();}}",
   3.149 +                            "0:92-0:100:verifier:Possibly Dereferencing null");
   3.150      }
   3.151      
   3.152      public void testTernary3() throws Exception {
   3.153          performAnalysisTest("test/Test.java",
   3.154                              "package test;\n" +
   3.155                              "class Test {\n" +
   3.156 -                            "    public void te|st() {" +
   3.157 +                            "    public void test() {" +
   3.158                              "        String e = null;" +
   3.159                              "        String f = e == null ? \"\" : e.trim();" +
   3.160                              "    }" +
   3.161 @@ -144,66 +148,66 @@
   3.162      }
   3.163      
   3.164      public void testNewClass() throws Exception {
   3.165 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {String s = null; if (s == null) {s = new String(\"\");} s.length();}}");
   3.166 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s == null) {s = new String(\"\");} s.length();}}");
   3.167      }
   3.168      
   3.169      public void testCheckForNull1() throws Exception {
   3.170 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {String s = get(); s.length();} @Nullable private String get() {return \"\";} @interface Nullable {}}", "0:65-0:73:verifier:Possibly Dereferencing null");
   3.171 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = get(); s.length();} @Nullable private String get() {return \"\";} @interface Nullable {}}", "0:67-0:73:verifier:Possibly Dereferencing null");
   3.172      }
   3.173      
   3.174      public void testCheckForNull2() throws Exception {
   3.175 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {s.length();} @Nullable private String s; @interface Nullable {}}", "0:47-0:55:verifier:Possibly Dereferencing null");
   3.176 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {s.length();} @Nullable private String s; @interface Nullable {}}", "0:49-0:55:verifier:Possibly Dereferencing null");
   3.177      }
   3.178      
   3.179      public void testAssignNullToNotNull() throws Exception {
   3.180 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {s = null;} @NotNull private String s; @interface NotNull {}}", "0:47-0:55:verifier:ANNNV");
   3.181 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {s = null;} @NotNull private String s; @interface NotNull {}}", "0:47-0:55:verifier:ANNNV");
   3.182      }
   3.183      
   3.184      public void testPossibleAssignNullToNotNull() throws Exception {
   3.185 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st(int i) {String s2 = null; if (i == 0) {s2 = \"\";} s = s2;} @NotNull private String s; @interface NotNull {}}", "0:93-0:99:verifier:PANNNV");
   3.186 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test(int i) {String s2 = null; if (i == 0) {s2 = \"\";} s = s2;} @NotNull private String s; @interface NotNull {}}", "0:93-0:99:verifier:PANNNV");
   3.187      }
   3.188      
   3.189      public void testNullCheckAnd1() throws Exception {
   3.190 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {String s = null; if (s != null && s.length() > 0) {}}}");
   3.191 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s != null && s.length() > 0) {}}}");
   3.192      }
   3.193      
   3.194      public void testNullCheckAnd2() throws Exception {
   3.195 -        performAnalysisTest("test/Test.java", "package test; class Test {private void te|st() {String s = null; if (s == null && s.length() > 0) {}}}", "0:81-0:89:verifier:DN");
   3.196 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s == null && s.length() > 0) {}}}", "0:83-0:89:verifier:DN");
   3.197      }
   3.198      
   3.199      public void testNullCheckOr1() throws Exception {
   3.200 -        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s != null || s.length() > 0) {}}}", 89 - 48, "0:81-0:89:verifier:DN");
   3.201 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s != null || s.length() > 0) {}}}", "0:83-0:89:verifier:DN");
   3.202      }
   3.203      
   3.204      public void testNullCheckOr2() throws Exception {
   3.205 -        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s == null || s.length() > 0) {}}}", 89 - 48);
   3.206 +        performAnalysisTest("test/Test.java", "package test; class Test {private void test() {String s = null; if (s == null || s.length() > 0) {}}}");
   3.207      }
   3.208      
   3.209      public void testContinue1() throws Exception {
   3.210          performAnalysisTest("test/Test.java",
   3.211 -                            "package test; class Test {private void te|st(String[] sa) {for (String s : sa) {if (s == null) continue; s.length();}}}");
   3.212 +                            "package test; class Test {private void test(String[] sa) {for (String s : sa) {if (s == null) continue; s.length();}}}");
   3.213      }
   3.214      
   3.215      public void testCondition1() throws Exception {
   3.216          performAnalysisTest("test/Test.java",
   3.217 -                            "package test; class Test {private void test(String sa) {boolean b = sa != null && (sa.length() == 0 || sa.length() == 1);}}", 71 - 30);
   3.218 +                            "package test; class Test {private void test(String sa) {boolean b = sa != null && (sa.length() == 0 || sa.length() == 1);}}");
   3.219      }
   3.220      
   3.221      public void testCondition2() throws Exception {
   3.222          performAnalysisTest("test/Test.java",
   3.223 -                            "package test; class Test {private void test(String sa) {boolean b = sa == null || (sa.length() == 0 && sa.length() == 1);}}", 71 - 30);
   3.224 +                            "package test; class Test {private void test(String sa) {boolean b = sa == null || (sa.length() == 0 && sa.length() == 1);}}");
   3.225      }
   3.226      
   3.227      public void testCondition3() throws Exception {
   3.228          performAnalysisTest("test/Test.java",
   3.229 -                            "package test; class Test {private void te|st(int i) {Object o2 = i < 1 ? null : \"\"; boolean b = true && o2 != null && o2.toString() != \"\";}}");
   3.230 +                            "package test; class Test {private void test(int i) {Object o2 = i < 1 ? null : \"\"; boolean b = true && o2 != null && o2.toString() != \"\";}}");
   3.231      }
   3.232      
   3.233      public void testWhileAndIf() throws Exception {
   3.234          performAnalysisTest("test/Test.java",
   3.235                              "package test;\n" +
   3.236                              "class Test {\n" +
   3.237 -                            "    private void tes|t(int i, boolean b, Object o2) {\n" +
   3.238 +                            "    private void test(int i, boolean b, Object o2) {\n" +
   3.239                              "        Object o = null;\n" +
   3.240                              "        while (--i > 0) {\n" +
   3.241                              "            if (b) {\n" +
   3.242 @@ -213,28 +217,28 @@
   3.243                              "        o.toString();\n" +
   3.244                              "    }" +
   3.245                              "}",
   3.246 -                            "9:8-9:18:verifier:DN");
   3.247 +                            "9:10-9:18:verifier:DN");
   3.248      }
   3.249      
   3.250      public void testWhile1() throws Exception {
   3.251          performAnalysisTest("test/Test.java",
   3.252                              "package test;\n" +
   3.253                              "class Test {\n" +
   3.254 -                            "    private void tes|t(String o) {\n" +
   3.255 +                            "    private void test(String o) {\n" +
   3.256                              "        while (o != null && o.length() > 1) {\n" +
   3.257                              "            o = o.substring(1);\n" +
   3.258                              "        }\n" +
   3.259                              "        o.toString();\n" +
   3.260                              "    }" +
   3.261                              "}",
   3.262 -                            "6:8-6:18:verifier:Possibly Dereferencing null");
   3.263 +                            "6:10-6:18:verifier:Possibly Dereferencing null");
   3.264      }
   3.265      
   3.266      public void testWhile2() throws Exception {
   3.267          performAnalysisTest("test/Test.java",
   3.268                              "package test;\n" +
   3.269                              "class Test {\n" +
   3.270 -                            "    private void tes|t(@CheckForNull String o) {\n" +
   3.271 +                            "    private void test(@CheckForNull String o) {\n" +
   3.272                              "        while (o != null) {\n" +
   3.273                              "            o = o.substring(1);\n" +
   3.274                              "        }\n" +
   3.275 @@ -245,13 +249,13 @@
   3.276      
   3.277      public void testParameter1() throws Exception {
   3.278          performAnalysisTest("test/Test.java",
   3.279 -                            "package test; class Test {private void te|st(int i) {String s = null; ttt(s);} private void ttt(@NotNull String s){}} @interface NotNull {}",
   3.280 +                            "package test; class Test {private void test(int i) {String s = null; ttt(s);} private void ttt(@NotNull String s){}} @interface NotNull {}",
   3.281                              "0:73-0:74:verifier:ERR_NULL_TO_NON_NULL_ARG");
   3.282      }
   3.283      
   3.284      public void testParameter2() throws Exception {
   3.285          performAnalysisTest("test/Test.java",
   3.286 -                            "package test; class Test {private void te|st(int i) {ttt(t());} private void ttt(@NotNull String s){} private @CheckForNull String t() {return \"\";} } @interface NotNull {} @interface CheckForNull {}",
   3.287 +                            "package test; class Test {private void test(int i) {ttt(t());} private void ttt(@NotNull String s){} private @CheckForNull String t() {return \"\";} } @interface NotNull {} @interface CheckForNull {}",
   3.288                              "0:56-0:59:verifier:ERR_POSSIBLENULL_TO_NON_NULL_ARG");
   3.289      }
   3.290      
   3.291 @@ -259,64 +263,64 @@
   3.292          performAnalysisTest("test/Test.java",
   3.293                              "package test;\n" +
   3.294                              "class Test {\n" +
   3.295 -                            "    private void tes|t(@CheckForNull String o) {\n" +
   3.296 +                            "    private void test(@CheckForNull String o) {\n" +
   3.297                              "        o.toString();\n" +
   3.298                              "        o.toString();\n" +
   3.299                              "        o.toString();\n" +
   3.300                              "    }" +
   3.301                              "    @interface CheckForNull {}\n" +
   3.302 -                            "}", "3:8-3:18:verifier:Possibly Dereferencing null");
   3.303 +                            "}", "3:10-3:18:verifier:Possibly Dereferencing null");
   3.304      }
   3.305      
   3.306      public void testNoMultipleReports2() throws Exception {
   3.307          performAnalysisTest("test/Test.java",
   3.308                              "package test;\n" +
   3.309                              "class Test {\n" +
   3.310 -                            "    private void tes|t(@CheckForNull String o) {\n" +
   3.311 +                            "    private void test(@CheckForNull String o) {\n" +
   3.312                              "        if (o.length() > 1 && o.length() > 2);\n" +
   3.313                              "    }" +
   3.314                              "    @interface CheckForNull {}\n" +
   3.315 -                            "}", "3:12-3:20:verifier:Possibly Dereferencing null");
   3.316 +                            "}", "3:14-3:20:verifier:Possibly Dereferencing null");
   3.317      }
   3.318      
   3.319      public void testNoMultipleReports3() throws Exception {
   3.320          performAnalysisTest("test/Test.java",
   3.321                              "package test;\n" +
   3.322                              "class Test {\n" +
   3.323 -                            "    private void tes|t(@CheckForNull String o) {\n" +
   3.324 +                            "    private void test(@CheckForNull String o) {\n" +
   3.325                              "        boolean b = o.length() > 1 && o.length() > 2;\n" +
   3.326                              "    }" +
   3.327                              "    @interface CheckForNull {}\n" +
   3.328 -                            "}", "3:20-3:28:verifier:Possibly Dereferencing null");
   3.329 +                            "}", "3:22-3:28:verifier:Possibly Dereferencing null");
   3.330      }
   3.331      
   3.332      public void testNoMultipleReports4() throws Exception {
   3.333          performAnalysisTest("test/Test.java",
   3.334                              "package test;\n" +
   3.335                              "class Test {\n" +
   3.336 -                            "    private void tes|t(@CheckForNull String o) {\n" +
   3.337 +                            "    private void test(@CheckForNull String o) {\n" +
   3.338                              "        boolean b = o.length() > 1 && o.length() > 2 ? false : true;\n" +
   3.339                              "    }" +
   3.340                              "    @interface CheckForNull {}\n" +
   3.341 -                            "}", "3:20-3:28:verifier:Possibly Dereferencing null");
   3.342 +                            "}", "3:22-3:28:verifier:Possibly Dereferencing null");
   3.343      }
   3.344      
   3.345      public void testCCE() throws Exception {
   3.346 -        performAnalysisTest("test/Test.java",
   3.347 -                            "package test;\n" +
   3.348 -                            "class Test {\n" +
   3.349 -                            "    private void tes|t() {\n" +
   3.350 -                            "        c.s Object method = new Object();\n" +
   3.351 -                            "    }" +
   3.352 -                            "}"/*, "3:20-3:28:verifier:Possibly Dereferencing null"*/);
   3.353 +        HintTest.create()
   3.354 +                .input("package test;\n" +
   3.355 +                       "class Test {\n" +
   3.356 +                       "    private void test() {\n" +
   3.357 +                       "        c.s Object method = new Object();\n" +
   3.358 +                       "    }" +
   3.359 +                       "}", false)
   3.360 +                .run(NPECheck.class)
   3.361 +                .assertWarnings(/*"3:20-3:28:verifier:Possibly Dereferencing null"*/);
   3.362      }
   3.363      
   3.364 -    @Override
   3.365 -    protected List<ErrorDescription> computeErrors(CompilationInfo info, TreePath path) {
   3.366 -        return new NPECheck().run(info, path);
   3.367 -    }
   3.368 -
   3.369 -    static {
   3.370 -        NbBundle.setBranding("test");
   3.371 +    private void performAnalysisTest(String fileName, String code, String... golden) throws Exception {
   3.372 +        HintTest.create()
   3.373 +                .input(fileName, code)
   3.374 +                .run(NPECheck.class)
   3.375 +                .assertWarnings(golden);
   3.376      }
   3.377  }