HaxeFoundation / intellij-haxe

Haxe plugin for IntelliJ Platform based IDEs (IDEA, Android-Studio)
http://intellij-haxe.org
Apache License 2.0
219 stars 100 forks source link

Regression: fullyResolveTypedef produces NullPointerException #904

Open mayakwd opened 5 years ago

mayakwd commented 5 years ago
    at com.intellij.plugins.haxe.lang.psi.HaxeResolver.fullyResolveTypedef(HaxeResolver.java:389)
    at com.intellij.plugins.haxe.lang.psi.HaxeResolver.tryResolveHelperClass(HaxeResolver.java:346)
    at com.intellij.plugins.haxe.lang.psi.HaxeResolver.resolveChain(HaxeResolver.java:280)
    at com.intellij.plugins.haxe.lang.psi.HaxeResolver.checkIsChain(HaxeResolver.java:185)
    at com.intellij.plugins.haxe.lang.psi.HaxeResolver.doResolve(HaxeResolver.java:115)
    at com.intellij.psi.impl.source.resolve.ResolveCache.lambda$resolve$0(ResolveCache.java:150)
    at com.intellij.openapi.util.RecursionManager$2.doPreventingRecursion(RecursionManager.java:98)
    at com.intellij.psi.impl.source.resolve.ResolveCache.resolve(ResolveCache.java:149)
    at com.intellij.psi.impl.source.resolve.ResolveCache.resolveWithCaching(ResolveCache.java:239)
    at com.intellij.plugins.haxe.lang.psi.HaxeResolver.resolve(HaxeResolver.java:76)
    at com.intellij.plugins.haxe.lang.psi.impl.HaxeReferenceImpl.multiResolve(HaxeReferenceImpl.java:216)
    at com.intellij.plugins.haxe.lang.psi.impl.HaxeReferenceImpl.resolveToComponentName(HaxeReferenceImpl.java:233)
    at com.intellij.plugins.haxe.ide.annotator.HaxeColorAnnotator.annotate(HaxeColorAnnotator.java:65)
    at com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.runAnnotators(DefaultHighlightVisitor.java:120)
    at com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.visit(DefaultHighlightVisitor.java:87)
    at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.runVisitors(GeneralHighlightingPass.java:353)
    at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.lambda$collectHighlights$5(GeneralHighlightingPass.java:292)
    at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.analyzeByVisitors(GeneralHighlightingPass.java:313)
    at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.lambda$analyzeByVisitors$6(GeneralHighlightingPass.java:316)
    at com.intellij.codeInsight.daemon.impl.DefaultHighlightVisitor.analyze(DefaultHighlightVisitor.java:71)
    at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.analyzeByVisitors(GeneralHighlightingPass.java:316)
    at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.collectHighlights(GeneralHighlightingPass.java:283)
    at com.intellij.codeInsight.daemon.impl.GeneralHighlightingPass.collectInformationWithProgress(GeneralHighlightingPass.java:227)
    at com.intellij.codeInsight.daemon.impl.ProgressableTextEditorHighlightingPass.doCollectInformation(ProgressableTextEditorHighlightingPass.java:84)
    at com.intellij.codeHighlighting.TextEditorHighlightingPass.collectInformation(TextEditorHighlightingPass.java:69)
    at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$null$1(PassExecutorService.java:423)
    at com.intellij.openapi.application.impl.ApplicationImpl.tryRunReadAction(ApplicationImpl.java:1168)
    at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$doRun$2(PassExecutorService.java:416)
    at com.intellij.openapi.progress.impl.CoreProgressManager.registerIndicatorAndRun(CoreProgressManager.java:582)
    at com.intellij.openapi.progress.impl.CoreProgressManager.executeProcessUnderProgress(CoreProgressManager.java:532)
    at com.intellij.openapi.progress.impl.ProgressManagerImpl.executeProcessUnderProgress(ProgressManagerImpl.java:87)
    at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.doRun(PassExecutorService.java:415)
    at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.lambda$run$0(PassExecutorService.java:391)
    at com.intellij.openapi.application.impl.ReadMostlyRWLock.executeByImpatientReader(ReadMostlyRWLock.java:147)
    at com.intellij.openapi.application.impl.ApplicationImpl.executeByImpatientReader(ApplicationImpl.java:222)
    at com.intellij.codeInsight.daemon.impl.PassExecutorService$ScheduledPass.run(PassExecutorService.java:389)
    at com.intellij.concurrency.JobLauncherImpl$VoidForkJoinTask$1.exec(JobLauncherImpl.java:161)
    at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
    at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1056)
    at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1692)
    at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)
EricBishton commented 5 years ago

Fixing this NPE is easy, if we just test for null, but that's not the underlying problem, I think. Do you have any example code that triggered the error, so I can figure out why there is no underlying type in the model?

The model is made from a HaxeClass, so I don't know why the type model wouldn't be able to reference it:

  @NotNull
  private static HaxeClassResolveResult fullyResolveTypedef(@Nullable HaxeClass typedef, @Nullable HaxeGenericSpecialization specialization) {
    if (null == typedef) return HaxeClassResolveResult.EMPTY;

    HashSet<String> recursionGuard = new HashSet<>(); // Track which typedefs we've already resolved so we don't end up in an infinite loop.

    HaxeClassResolveResult result = HaxeClassResolveResult.EMPTY;
    HaxeClassModel model = typedef.getModel();
    while (null != model && model.isTypedef() && !recursionGuard.contains(model.getName())) {
      recursionGuard.add(model.getName());

      final HaxeTypeOrAnonymous toa = model.getUnderlyingType();  // <<<<----- NPE occurs here.
      final HaxeType type = toa.getType();
      if (null == type) {
        // Anonymous structure
        result = HaxeClassResolveResult.create(toa.getAnonymousType(), specialization);
        break;
      }

      // If the reference is to a type parameter, resolve that instead.
      HaxeClassResolveResult nakedResult = specialization.get(type, type.getReferenceExpression().getIdentifier().getText());
      if (null == nakedResult) {
        nakedResult = type.getReferenceExpression().resolveHaxeClass();
      }
      result = HaxeClassResolveResult.create(nakedResult.getHaxeClass(), specialization);
      model = null != result.getHaxeClass() ? result.getHaxeClass().getModel() : null;
    }
    return result;
  }

[EDIT: Add the rest of the function for context.]

mayakwd commented 5 years ago

I'll try to extract pure sample to reproduce.