Support reading MoorOptions in CLI analyzer

This commit is contained in:
Simon Binder 2019-12-16 21:50:21 +01:00
parent 587e8fd1a9
commit d2864d6859
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
8 changed files with 138 additions and 19 deletions

View File

@ -7,6 +7,7 @@ import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
import 'package:analyzer/src/generated/source.dart' show SourceKind;
import 'package:logging/logging.dart';
import 'package:moor_generator/src/analyzer/options.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/analyzer/session.dart';
@ -29,10 +30,12 @@ class MoorDriver implements AnalysisDriverGeneric {
StreamSubscription _taskCompleteSubscription;
MoorDriver(this._tracker, this._scheduler, this.dartDriver,
this.contentOverlay, this._resourceProvider) {
this.contentOverlay, this._resourceProvider,
[MoorOptions options]) {
_scheduler.add(this);
final backend = CommonBackend(this);
session = MoorSession(backend);
session = MoorSession(backend, options: options ?? const MoorOptions());
_fileChangeSubscription =
session.changedFiles.listen(_tracker.notifyFilesChanged);

View File

@ -20,6 +20,7 @@ import 'package:analyzer_plugin/utilities/folding/folding.dart';
import 'package:analyzer_plugin/utilities/highlights/highlights.dart';
import 'package:analyzer_plugin/utilities/navigation/navigation.dart';
import 'package:analyzer_plugin/utilities/outline/outline.dart';
import 'package:moor_generator/src/analyzer/options.dart';
import 'package:moor_generator/src/analyzer/runner/file_graph.dart';
import 'package:moor_generator/src/backends/common/driver.dart';
import 'package:moor_generator/src/backends/common/file_tracker.dart';
@ -67,7 +68,8 @@ class MoorPlugin extends ServerPlugin
AnalysisDriverScheduler dartScheduler;
@override
MoorDriver createAnalysisDriver(plugin.ContextRoot contextRoot) {
MoorDriver createAnalysisDriver(plugin.ContextRoot contextRoot,
{MoorOptions options}) {
// create an analysis driver we can use to resolve Dart files
final analyzerRoot = ContextRoot(contextRoot.root, contextRoot.exclude,
pathContext: resourceProvider.pathContext)
@ -89,7 +91,7 @@ class MoorPlugin extends ServerPlugin
final errorService = ErrorService(this);
final driver = MoorDriver(tracker, analysisDriverScheduler, dartDriver,
fileContentOverlay, resourceProvider);
fileContentOverlay, resourceProvider, options);
driver.completedFiles().where((file) => file.isParsed).listen((file) {
sendNotificationsForFile(file.uri.path);

View File

@ -4,6 +4,7 @@ import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/memory_file_system.dart';
import 'package:analyzer_plugin/protocol/protocol_generated.dart';
import 'package:cli_util/cli_util.dart';
import 'package:moor_generator/src/analyzer/options.dart';
import 'package:moor_generator/src/backends/common/driver.dart';
import 'package:path/path.dart' as p;
@ -41,7 +42,10 @@ class StandaloneMoorAnalyzer {
}
}
MoorDriver createAnalysisDriver(String path) {
return _fakePlugin.createAnalysisDriver(ContextRoot(path, []));
MoorDriver createAnalysisDriver(String path, {MoorOptions options}) {
return _fakePlugin.createAnalysisDriver(
ContextRoot(path, []),
options: options,
);
}
}

View File

@ -1,22 +1,31 @@
import 'dart:async';
import 'dart:io';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:args/command_runner.dart';
import 'package:logging/logging.dart';
import 'package:moor_generator/src/backends/common/driver.dart';
import 'package:moor_generator/src/backends/standalone.dart';
import 'package:moor_generator/src/cli/commands/debug_plugin.dart';
import 'package:moor_generator/src/cli/project.dart';
import 'commands/debug_plugin.dart';
import 'commands/identify_databases.dart';
import 'logging.dart';
Future run(List<String> args) {
final cli = MoorCli();
return cli._runner.run(args);
return cli.run(args);
}
class MoorCli {
final StandaloneMoorAnalyzer _analyzer;
final Completer<void> _analyzerReadyCompleter = Completer();
Logger get logger => Logger.root;
CommandRunner _runner;
MoorProject project;
bool verbose;
Future<StandaloneMoorAnalyzer> get analyzer async {
await _analyzerReadyCompleter.future;
@ -32,8 +41,33 @@ class MoorCli {
..addCommand(IdentifyDatabases(this))
..addCommand(DebugPluginCommand(this));
_runner.argParser
.addFlag('verbose', abbr: 'v', defaultsTo: false, negatable: false);
_runner.argParser.addFlag(
'ansi',
abbr: 'a',
help: 'Whether to output colorful logs. Attempts to check whether this '
'is supported by the terminal by default.',
);
_analyzerReadyCompleter.complete(_analyzer.init());
}
Future<MoorDriver> createMoorDriver() async {
final analyzer = await this.analyzer;
return analyzer.createAnalysisDriver(project.directory.path,
options: project.moorOptions);
}
Future<void> run(Iterable<String> args) async {
final results = _runner.parse(args);
verbose = results['verbose'] as bool;
setupLogging(verbose: verbose);
project = await MoorProject.readFromDir(Directory.current);
await _runner.runCommand(results);
}
}
abstract class MoorCommand extends Command {

View File

@ -18,21 +18,17 @@ class IdentifyDatabases extends MoorCommand {
@override
Future run() async {
final analyzer = await cli.analyzer;
final directory = Directory.current;
print('Starting to scan in ${directory.path}...');
final driver = analyzer.createAnalysisDriver(directory.path);
final driver = await cli.createMoorDriver();
await for (final entity in directory.list(recursive: true)) {
if (entity is! File) continue;
final file = entity as File;
await for (final file in cli.project.sourceFiles) {
if (p.extension(file.path) != '.dart') continue;
print('scanning - $file');
cli.logger.fine('Scanning $file');
final parsed = await driver.waitFileParsed(entity.path);
final parsed = await driver.waitFileParsed(file.path);
final result = parsed.currentResult as ParsedDartFile;
// result can be null when we're running into a part of file
@ -45,7 +41,7 @@ class IdentifyDatabases extends MoorCommand {
.map((t) => t.declaration.fromClass.name)
.join(', ');
print('$displayName has moor databases or daos: $names');
cli.logger.info('$displayName has moor databases or daos: $names');
}
}
}

View File

@ -0,0 +1,28 @@
import 'package:cli_util/cli_logging.dart' as cli;
import 'package:logging/logging.dart' as log;
void setupLogging({bool verbose = false, bool useAnsi}) {
final ansi = cli.Ansi(useAnsi ?? cli.Ansi.terminalSupportsAnsi);
final cliLogger = verbose
? cli.Logger.verbose(ansi: ansi)
: cli.Logger.standard(ansi: ansi);
log.Logger.root.onRecord.listen((rec) {
final level = rec.level;
final msgBuffer = StringBuffer();
msgBuffer..write(rec.level.name)..write(': ')..write(rec.message);
if (rec.error != null) {
msgBuffer..write(rec.error)..write('\n')..write(rec.stackTrace);
}
if (level <= log.Level.CONFIG) {
cliLogger.trace(msgBuffer.toString());
} else if (level <= log.Level.INFO) {
cliLogger.stdout(msgBuffer.toString());
} else {
cliLogger.stderr(msgBuffer.toString());
}
});
}

View File

@ -0,0 +1,51 @@
import 'dart:io';
import 'package:build_config/build_config.dart';
import 'package:moor_generator/src/analyzer/options.dart';
import 'package:path/path.dart' as p;
import 'package:stream_transform/stream_transform.dart';
/// A project using moor. This is typically a dart project with a dependency on
/// moor and moor_generator.
class MoorProject {
/// The build configuration for this project.
final BuildConfig buildConfig;
final MoorOptions moorOptions;
final Directory directory;
MoorProject(this.buildConfig, this.directory)
: moorOptions = _readOptions(buildConfig);
Stream<File> get sourceFiles {
const topLevelDirs = {'lib', 'test', 'bin', 'example'};
return directory.list().asyncExpand((entity) {
// report all top-level files and all (recursive) content in topLevelDirs
if (entity is File) {
return Stream.value(entity);
} else if (entity is Directory) {
if (topLevelDirs.contains(p.basename(entity.path))) {
return entity.list(recursive: true);
}
}
return const Stream.empty();
}).whereType();
}
static MoorOptions _readOptions(BuildConfig config) {
final options = config.buildTargets.values
.map((t) => t.builders['moor_generator:moor_generator']?.options)
.where((t) => t != null)
.map((json) => MoorOptions.fromJson(json));
final iterator = options.iterator;
return iterator.moveNext() ? iterator.current : const MoorOptions();
}
static Future<MoorProject> readFromDir(Directory directory) async {
final config = await BuildConfig.fromPackageDir(directory.path);
return MoorProject(config, directory);
}
}

View File

@ -16,11 +16,13 @@ dependencies:
recase: ^2.0.1
meta: ^1.1.0
path: ^1.6.0
logging: '>=0.11.0 <1.0.0'
json_annotation: ^3.0.0
stream_transform: '>=0.0.20 <2.0.0'
# CLI
args: ^1.5.0
logging: '>=0.11.0 <1.0.0'
cli_util: ^0.1.0
# Moor-specific analysis
moor: ^2.0.1
@ -30,7 +32,6 @@ dependencies:
analyzer: '>=0.36.4 <0.40.0'
analyzer_plugin: '>=0.1.0 <0.3.0'
source_span: ^1.5.5
cli_util: ^0.1.0 # Used to locate the Dart SDK
# Build system
build: ^1.1.0