drift icon indicating copy to clipboard operation
drift copied to clipboard

InconsistentAnalysisException - The getter 'resolvedImports' was called on null.

Open kuhnroyal opened this issue 5 years ago • 14 comments

I am getting this generation error a lot lately as the projects grow in complexity/tables/queries.

Before this happens there is usually a mistake in some queries.moor file, like a forgotten import, duplicate query name due to copy/paste etc. After fixing the error, the only way to rebuild is cleaning everything and possibly manually deleting .g.dart/.moor.dart files.

When not cleaning this will consistently fail.

I have run with verbose and tried to add some debug logging myself.

[WARNING] moor_generator:moor_generator_not_shared on lib/db/handover/proposal_dao.dart:
############# uhm ??? proposal_queries.moor
[WARNING] moor_generator:moor_generator_not_shared on lib/db/handover/proposal_dao.dart:
There were some errors while running moor_generator on package:app/db/handover/proposal_dao.dart:
[WARNING] moor_generator:moor_generator_not_shared on lib/db/handover/proposal_dao.dart:
Could not parse file: InconsistentAnalysisException: Requested result might be inconsistent with previously returned results

[SEVERE] moor_generator:moor_generator_not_shared on lib/db/handover/proposal_dao.dart:
Error running MoorGenerator
NoSuchMethodError: The getter 'resolvedImports' was called on null.
Receiver: null
Tried calling: resolvedImports
dart:core                                                                       Object.noSuchMethod
package:moor_generator/src/analyzer/runner/task.dart 201:57                     Task.crawlImports
dart:core                                                                       Iterable.toList
package:moor_generator/src/analyzer/runner/steps/analyze_moor.dart 15:63        AnalyzeMoorStep.analyze
package:moor_generator/src/analyzer/runner/task.dart 223:45                     Task._analyze
package:moor_generator/src/analyzer/runner/task.dart 61:13                      Task.runTask
package:moor_generator/src/backends/build/moor_builder.dart 28:18               MoorBuilder.analyzeDartFile
package:moor_generator/src/backends/build/generators/moor_generator.dart 27:34  MoorGenerator.generate
package:source_gen/src/builder.dart 298:35                                      _generate
package:source_gen/src/builder.dart 79:15                                       _Builder._generateForLibrary
package:source_gen/src/builder.dart 71:11                                       _Builder.build
package:build                                                                   runBuilder
package:build_runner_core/src/generate/build_impl.dart 486:19                   _SingleBuild._runForInput.<fn>.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 302:15          _NoOpBuilderActionTracker.trackStage
package:build_runner_core/src/generate/build_impl.dart 484:23                   _SingleBuild._runForInput.<fn>.<fn>
package:build_runner_core/src/generate/build_impl.dart                          _SingleBuild._runForInput.<fn>.<fn>
package:timing/src/timing.dart 222:44                                           NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 441:22                   _SingleBuild._runForInput.<fn>
package:pool/pool.dart 127:28                                                   Pool.withResource
package:build_runner_core/src/generate/build_impl.dart 437:17                   _SingleBuild._runForInput
package:build_runner_core/src/generate/build_impl.dart 375:38                   _SingleBuild._runBuilder.<fn>
dart:async                                                                      Future.wait
package:build_runner_core/src/generate/build_impl.dart 374:36                   _SingleBuild._runBuilder
package:build_runner_core/src/generate/build_impl.dart 320:20                   _SingleBuild._runPhases.<fn>.<fn>
dart:async                                                                      _completeOnAsyncReturn
package:build_runner_core/src/generate/build_impl.dart                          _SingleBuild._matchingPrimaryInputs

[FINE] moor_generator:moor_generator_not_shared on lib/db/handover/proposal_dao.dart:Running DaoGenerator - 2 of 2
[WARNING] moor_generator:moor_generator_not_shared on lib/db/handover/handover_dao.dart:
############# uhm ??? handover_queries.moor
[WARNING] moor_generator:moor_generator_not_shared on lib/db/handover/handover_dao.dart:
There were some errors while running moor_generator on package:app/db/handover/handover_dao.dart:
[WARNING] moor_generator:moor_generator_not_shared on lib/db/handover/handover_dao.dart:
Could not parse file: InconsistentAnalysisException: Requested result might be inconsistent with previously returned results

[SEVERE] moor_generator:moor_generator_not_shared on lib/db/handover/handover_dao.dart:
Error running MoorGenerator
NoSuchMethodError: The getter 'resolvedImports' was called on null.
Receiver: null
Tried calling: resolvedImports
dart:core                                                                       Object.noSuchMethod
package:moor_generator/src/analyzer/runner/task.dart 201:57                     Task.crawlImports
dart:core                                                                       Iterable.toList
package:moor_generator/src/analyzer/runner/steps/analyze_moor.dart 15:63        AnalyzeMoorStep.analyze
package:moor_generator/src/analyzer/runner/task.dart 223:45                     Task._analyze
package:moor_generator/src/analyzer/runner/task.dart 61:13                      Task.runTask
package:moor_generator/src/backends/build/moor_builder.dart 28:18               MoorBuilder.analyzeDartFile
package:moor_generator/src/backends/build/generators/moor_generator.dart 27:34  MoorGenerator.generate
package:source_gen/src/builder.dart 298:35                                      _generate
package:source_gen/src/builder.dart 79:15                                       _Builder._generateForLibrary
package:source_gen/src/builder.dart 71:11                                       _Builder.build
package:build                                                                   runBuilder
package:build_runner_core/src/generate/build_impl.dart 486:19                   _SingleBuild._runForInput.<fn>.<fn>.<fn>
package:build_runner_core/src/generate/performance_tracker.dart 302:15          _NoOpBuilderActionTracker.trackStage
package:build_runner_core/src/generate/build_impl.dart 484:23                   _SingleBuild._runForInput.<fn>.<fn>
package:build_runner_core/src/generate/build_impl.dart                          _SingleBuild._runForInput.<fn>.<fn>
package:timing/src/timing.dart 222:44                                           NoOpTimeTracker.track
package:build_runner_core/src/generate/build_impl.dart 441:22                   _SingleBuild._runForInput.<fn>
package:pool/pool.dart 127:28                                                   Pool.withResource
package:build_runner_core/src/generate/build_impl.dart 437:17                   _SingleBuild._runForInput
package:build_runner_core/src/generate/build_impl.dart 375:38                   _SingleBuild._runBuilder.<fn>
dart:async                                                                      Future.wait
package:build_runner_core/src/generate/build_impl.dart 374:36                   _SingleBuild._runBuilder
package:build_runner_core/src/generate/build_impl.dart 320:20                   _SingleBuild._runPhases.<fn>.<fn>
dart:async                                                                      _completeOnAsyncReturn
package:build_runner_core/src/generate/build_impl.dart                          _SingleBuild._matchingPrimaryInputs

I have added some debug logging to AnalyzeMoorStep:

  void analyze() {
    final parseResult = file.currentResult as ParsedMoorFile;

    log.warning('############# uhm ??? ${file.shortName}');
    if (parseResult == null) {
      // this is never true but parseResult.resolvedImports is the source of the NoSuchMethodException
      log.severe('############# ${file.shortName}');
      log.severe(task);
    }
    final transitiveImports =
        task.crawlImports(parseResult.resolvedImports.values).toList();
   ...
}

What I don't understand is, that the null pointer is the parseResult.resolvedImports, however my logging indicates, that parsedResults is never null.

Also these 2 DAOs that fail to generate are not related to the queries file which contained the original error which was fixed by now.

kuhnroyal avatar Jul 14 '20 15:07 kuhnroyal

It looks like the NoSuchMethodError actually comes from here: https://github.com/simolus3/moor/blob/ba987b57b1a324fd0594037fe60c6a81ab2db8a9/moor_generator/lib/src/analyzer/runner/task.dart#L200-L201

If you want to help debugging, the following would really help to see where the null is coming from:

  • print(roots.toList()) at the beginning of crawlImports.
  • print('$available -> ${importsFromHere.toList()}') after line 201 from the snippet above

So far I don't see how a null value could ever end up there, since we already guard against that here: https://github.com/simolus3/moor/blob/ba987b57b1a324fd0594037fe60c6a81ab2db8a9/moor_generator/lib/src/analyzer/runner/task.dart#L110-L114


I assume the InconsistentAnalysisException comes from serialized_types.dart . You could print the stack trace to verify this: https://github.com/simolus3/moor/blob/ba987b57b1a324fd0594037fe60c6a81ab2db8a9/moor_generator/lib/src/analyzer/runner/task.dart#L85-L91

I think I already know how to fix this though - it should work with 6922ae040966f0812d602dc9feb2f94e35da691a.

simolus3 avatar Jul 14 '20 17:07 simolus3

Trying to recreate with the debug logs now.

kuhnroyal avatar Jul 14 '20 18:07 kuhnroyal

Ok I think I found the problem, your change looks like it could help in other cases but not here because this is somewhat a user error.

I am using a lot of built_value, for built_value enums and there is a moor converter. Then I wanted to use some generated moor classes inside other built_value classes and moved to the non-shared moor builder and run the built_value generator after moor.

This somehow works on a clean generation but when using things from the cache, it can not find the built_value enum classes.

Now I have a chicken/egg problem it seems :) Not sure how to proceed other than moving the enums to a separat library/project or maybe try different builder targets with excluded sources.

Btw, there seems to be a problem with latest analyzer versions (>=0.39.12 I think), seems to need an upper bound.

kuhnroyal avatar Jul 15 '20 09:07 kuhnroyal

I am using the built_value enums because I need Strings in the database. So for me this would also be solved if moor could automatically support String <-> enum conversion if the database type is TEXT.

kuhnroyal avatar Jul 15 '20 13:07 kuhnroyal

maybe try different builder targets with excluded sources

Yeah, that should work. Setting that up doesn't sound like fun though.

This somehow works on a clean generation but when using things from the cache, it can not find the built_value enum classes.

That's probably a bug, but it's hard to tell if it's a bug in moor, built_value or the build system.

The String <-> enum converter also came up in a private conversation recently, I might give it another look. Note that you can use a single converter converter class for all your enums:

class EnumToTextConverter<T> extends TypeConverter<T, String> {
  final List<T> values;
  final Map<String, T> _byName;

  EnumToTextConverter(this.values)
      : _byName = {
          for (final entry in values) entry.toString(): entry,
        };

  @override
  String mapToSql(T value) {
    return value.toString();
  }

  @override
  T mapToDart(String fromDb) {
    return _byName[fromDb];
  }
}

Then you can use MAPPED BY `EnumToTextConverter(MyEnumClass.values)` .

simolus3 avatar Jul 15 '20 14:07 simolus3

Yea, I implemented something similar with static const instances and making use of the small enum_to_string package. The stock enum.toString() is pretty bad and also changed between Dart versions which broke some previous implementations. Thats why I started with built_value enums in the first place.

I also restructured builder targets from one default to 4 separate targets with explicit sources and got generation time down to 54s from 2:20m - didn't expect this much improvement tbh.

I consider this issue closed unless you want to keep it open for the string enum conversion. So please close at your discretion.

kuhnroyal avatar Jul 15 '20 16:07 kuhnroyal

Nvm... just ran into this again with just plain moor and a non-generated enum converter.

I still have a guard block here: https://github.com/simolus3/moor/blob/ba987b57b1a324fd0594037fe60c6a81ab2db8a9/moor_generator/lib/src/analyzer/runner/task.dart#L200-L201

And it now logs and fails with the same exception as before. Simply made some unrelated changes.

### available.currentResult is null! FoundFile(package:app/db/appointment.moor, FileType.moor) -> []

The appointment.moor file makes use of the converter.

The appointment.temp.dart looks correct.

import 'package:app/db/converters/enum_converter.dart';
var expr_0 = EnumConverter.syncState;
var expr_1 = EnumConverter.syncState;
var expr_2 = EnumConverter.localState;

kuhnroyal avatar Jul 15 '20 16:07 kuhnroyal

So it seem this is somehow related to converters not found in the cache or something.

kuhnroyal avatar Jul 15 '20 16:07 kuhnroyal

Could this somehow be causes by using the library builder instead of the shared part builder?

kuhnroyal avatar Jul 17 '20 09:07 kuhnroyal

I don't think so - both builders should behave identically in how they use the analyzer.

Maybe the multi-target setup causes an issue like https://github.com/dart-lang/build/issues/2634, but I think moor's guards should prevent that.

simolus3 avatar Jul 18 '20 12:07 simolus3

The error occurred before I split the targets and created plain simple enum converters as well as after. But it always fails with .moor files that use converters.

kuhnroyal avatar Jul 20 '20 14:07 kuhnroyal

Thanks, I'll try to properly debug this on the weekend.

To reproduce this, is it enough if I use more than one target and type converters? It sounds like you have a repro that's immune to build_runner clean. If you can find a small repro (or some general outline of a build setup that fails) I'll take a look at that and see where exactly it goes wrong.

simolus3 avatar Jul 21 '20 18:07 simolus3

I'll try to create a repro.

kuhnroyal avatar Jul 21 '20 21:07 kuhnroyal

Ok, I think I found the problem after trying for 3 hours to create a reproducible sample, not fully sure but I can't get it to fail anymore for the moment.

I created a dart file bundling all the converters by using export; converter.dart

export 'enum_converter.dart';
export 'date_converter.dart';
...

Then I always imported this file in other moor files that needed one or more of the converters. This works on a clean build but not from cache.

kuhnroyal avatar Jul 27 '20 10:07 kuhnroyal