From 68f5b2a8535003af67d17970feff69fffdd7f716 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Thu, 25 Feb 2021 11:32:02 -0800 Subject: [PATCH 01/10] nullsafety --- lib/src/executable.dart | 39 +++++++++++++------- lib/src/executor.dart | 57 +++++++++++++++++------------ lib/src/source_generator.dart | 34 ++++++++++++------ pubspec.yaml | 4 +-- test/isolate_executor_test.dart | 63 ++++++++++++++++++++++----------- test/test_package/lib/lib.dart | 4 +-- test/test_package/pubspec.yaml | 2 +- 7 files changed, 132 insertions(+), 71 deletions(-) diff --git a/lib/src/executable.dart b/lib/src/executable.dart index cf982d9..b71c081 100644 --- a/lib/src/executable.dart +++ b/lib/src/executable.dart @@ -8,30 +8,43 @@ abstract class Executable { Future execute(); final Map message; - final SendPort _sendPort; + final SendPort? _sendPort; U instanceOf(String typeName, - {List positionalArguments: const [], Map namedArguments, Symbol constructorName}) { - ClassMirror typeMirror = currentMirrorSystem().isolate.rootLibrary.declarations[new Symbol(typeName)]; + {List positionalArguments: const [], + Map namedArguments = const {}, + Symbol? constructorName}) { + ClassMirror? typeMirror = currentMirrorSystem() + .isolate + .rootLibrary + .declarations[Symbol(typeName)] as ClassMirror?; if (typeMirror == null) { typeMirror = currentMirrorSystem() - .libraries - .values - .where((lib) => lib.uri.scheme == "package" || lib.uri.scheme == "file") - .expand((lib) => lib.declarations.values) - .firstWhere((decl) => decl is ClassMirror && MirrorSystem.getName(decl.simpleName) == typeName, - orElse: () => throw new ArgumentError("Unknown type '$typeName'. Did you forget to import it?")); + .libraries + .values + .where((lib) => + lib.uri.scheme == "package" || lib.uri.scheme == "file") + .expand((lib) => lib.declarations.values) + .firstWhere( + (decl) => + decl is ClassMirror && + MirrorSystem.getName(decl.simpleName) == typeName, + orElse: () => throw ArgumentError( + "Unknown type '$typeName'. Did you forget to import it?")) + as ClassMirror?; } - return typeMirror.newInstance(constructorName ?? const Symbol(""), positionalArguments, namedArguments).reflectee - as U; + return typeMirror! + .newInstance(constructorName ?? const Symbol(""), positionalArguments, + namedArguments) + .reflectee as U; } void send(dynamic message) { - _sendPort.send(message); + _sendPort!.send(message); } void log(String message) { - _sendPort.send({"_line_": message}); + _sendPort!.send({"_line_": message}); } } diff --git a/lib/src/executor.dart b/lib/src/executor.dart index 9367b23..4b92dd4 100644 --- a/lib/src/executor.dart +++ b/lib/src/executor.dart @@ -6,39 +6,43 @@ import 'package:isolate_executor/src/executable.dart'; import 'package:isolate_executor/src/source_generator.dart'; class IsolateExecutor { - IsolateExecutor(this.generator, {this.packageConfigURI, Map message}) : this.message = message ?? {}; + IsolateExecutor(this.generator, + {this.packageConfigURI, this.message = const {}}); final SourceGenerator generator; final Map message; - final Uri packageConfigURI; - final Completer completer = new Completer(); + final Uri? packageConfigURI; + final Completer completer = Completer(); Stream get events => _eventListener.stream; Stream get console => _logListener.stream; - final StreamController _logListener = new StreamController(); - final StreamController _eventListener = new StreamController(); + final StreamController _logListener = StreamController(); + final StreamController _eventListener = StreamController(); Future execute() async { - if (packageConfigURI != null && !(new File.fromUri(packageConfigURI).existsSync())) { - throw new StateError("Package file '$packageConfigURI' not found. Run 'pub get' and retry."); + if (packageConfigURI != null && + !(File.fromUri(packageConfigURI!).existsSync())) { + throw StateError( + "Package file '$packageConfigURI' not found. Run 'pub get' and retry."); } final scriptSource = Uri.encodeComponent(await generator.scriptSource); - var onErrorPort = new ReceivePort() + var onErrorPort = ReceivePort() ..listen((err) async { if (err is List) { - final stack = new StackTrace.fromString(err.last.replaceAll(scriptSource, "")); + final stack = + StackTrace.fromString(err.last.replaceAll(scriptSource, "")); - completer.completeError(new StateError(err.first), stack); + completer.completeError(StateError(err.first), stack); } else { completer.completeError(err); } }); - var controlPort = new ReceivePort() + var controlPort = ReceivePort() ..listen((results) { if (results is Map && results.length == 1) { if (results.containsKey("_result")) { @@ -55,13 +59,18 @@ class IsolateExecutor { try { message["_sendPort"] = controlPort.sendPort; - final dataUri = Uri.parse("data:application/dart;charset=utf-8,${scriptSource}"); + final dataUri = + Uri.parse("data:application/dart;charset=utf-8,${scriptSource}"); if (packageConfigURI != null) { await Isolate.spawnUri(dataUri, [], message, - errorsAreFatal: true, onError: onErrorPort.sendPort, packageConfig: packageConfigURI); + errorsAreFatal: true, + onError: onErrorPort.sendPort, + packageConfig: packageConfigURI); } else { await Isolate.spawnUri(dataUri, [], message, - errorsAreFatal: true, onError: onErrorPort.sendPort, automaticPackageResolution: true); + errorsAreFatal: true, + onError: onErrorPort.sendPort, + automaticPackageResolution: true); } return await completer.future; @@ -74,14 +83,18 @@ class IsolateExecutor { } static Future run(Executable executable, - {Uri packageConfigURI, - List imports, - String additionalContents, - void eventHandler(dynamic event), - void logHandler(String line), - List additionalTypes}) async { - final source = new SourceGenerator(executable.runtimeType, imports: imports, additionalContents: additionalContents, additionalTypes: additionalTypes); - var executor = new IsolateExecutor(source, packageConfigURI: packageConfigURI, message: executable.message); + {Uri? packageConfigURI, + List? imports, + String? additionalContents, + void eventHandler(dynamic event)?, + void logHandler(String line)?, + List? additionalTypes}) async { + final source = SourceGenerator(executable.runtimeType, + imports: imports, + additionalContents: additionalContents, + additionalTypes: additionalTypes); + var executor = IsolateExecutor(source, + packageConfigURI: packageConfigURI, message: executable.message); if (eventHandler != null) { executor.events.listen(eventHandler); diff --git a/lib/src/source_generator.dart b/lib/src/source_generator.dart index 3793957..67d3286 100644 --- a/lib/src/source_generator.dart +++ b/lib/src/source_generator.dart @@ -3,22 +3,27 @@ import 'dart:isolate'; import 'dart:mirrors'; import 'dart:async'; -import 'package:analyzer/analyzer.dart'; +import 'package:analyzer/dart/analysis/analysis_context_collection.dart'; +import 'package:analyzer/dart/analysis/features.dart'; +import 'package:analyzer/dart/analysis/utilities.dart'; +import 'package:analyzer/dart/ast/ast.dart'; import 'package:isolate_executor/src/executable.dart'; class SourceGenerator { - SourceGenerator(this.executableType, {this.imports, this.additionalContents, this.additionalTypes}); + SourceGenerator(this.executableType, + {this.imports, this.additionalContents, this.additionalTypes}); Type executableType; - String get typeName => MirrorSystem.getName(reflectType(executableType).simpleName); - final List imports; - final String additionalContents; - final List additionalTypes; + String get typeName => + MirrorSystem.getName(reflectType(executableType).simpleName); + final List? imports; + final String? additionalContents; + final List? additionalTypes; Future get scriptSource async { final typeSource = (await _getClass(executableType)).toSource(); - var builder = new StringBuffer(); + var builder = StringBuffer(); builder.writeln("import 'dart:async';"); builder.writeln("import 'dart:isolate';"); @@ -29,7 +34,7 @@ class SourceGenerator { builder.writeln(""" Future main (List args, Map message) async { final sendPort = message['_sendPort']; - final executable = new $typeName(message); + final executable = $typeName(message); final result = await executable.execute(); sendPort.send({"_result": result}); } @@ -50,11 +55,18 @@ Future main (List args, Map message) async { } static Future _getClass(Type type) async { - final uri = await Isolate.resolvePackageUri(reflectClass(type).location.sourceUri); - final fileUnit = parseDartFile(uri.toFilePath(windows: Platform.isWindows)); + final uri = + await Isolate.resolvePackageUri(reflectClass(type).location!.sourceUri); + final path = uri!.toFilePath(windows: Platform.isWindows); + + final analysisContextCollection = + AnalysisContextCollection(includedPaths: [path]); + final context = analysisContextCollection.contextFor(path); + final session = context.currentSession; + final unit = session.getParsedUnit(path); final typeName = MirrorSystem.getName(reflectClass(type).simpleName); - return fileUnit.declarations + return unit.unit.declarations .where((u) => u is ClassDeclaration) .map((cu) => cu as ClassDeclaration) .firstWhere((classDecl) => classDecl.name.name == typeName); diff --git a/pubspec.yaml b/pubspec.yaml index a963ba2..5e17338 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -5,10 +5,10 @@ homepage: https://github.com/stablekernel/dart-isolate-executor author: stable|kernel environment: - sdk: ">=2.0.0 <3.0.0" + sdk: ">=2.12.0-0 <3.0.0" dependencies: - analyzer: '>=0.32.0 <0.50.0' + analyzer: ^1.0.0 dev_dependencies: test: ^1.3.0 diff --git a/test/isolate_executor_test.dart b/test/isolate_executor_test.dart index 6284641..051b7bc 100644 --- a/test/isolate_executor_test.dart +++ b/test/isolate_executor_test.dart @@ -5,43 +5,56 @@ import 'package:isolate_executor/isolate_executor.dart'; import 'package:test/test.dart'; void main() { - final projDir = Directory.current.uri.resolve("test/").resolve("test_package/"); + final projDir = + Directory.current.uri.resolve("test/").resolve("test_package/"); setUpAll(() async { await getDependencies(projDir); }); test("Can run an Executable and get its return value", () async { - final result = - await IsolateExecutor.run(SimpleReturner({}), packageConfigURI: projDir.resolve(".packages")); + final result = await IsolateExecutor.run(SimpleReturner({}), + packageConfigURI: projDir.resolve(".packages")); expect(result, 1); }); test("Logged messages are available through logger stream", () async { final msgs = []; await IsolateExecutor.run(SimpleReturner({}), - logHandler: (msg) => msgs.add(msg), packageConfigURI: projDir.resolve(".packages")); + logHandler: (msg) => msgs.add(msg), + packageConfigURI: projDir.resolve(".packages")); expect(msgs, ["hello"]); }); test("Send values to Executable and use them", () async { - final result = await IsolateExecutor.run(Echo({'echo': 'hello'}), packageConfigURI: projDir.resolve(".packages")); + final result = await IsolateExecutor.run(Echo({'echo': 'hello'}), + packageConfigURI: projDir.resolve(".packages")); expect(result, 'hello'); }); test("Run from another package", () async { final result = await IsolateExecutor.run(InPackage({}), - packageConfigURI: projDir.resolve(".packages"), imports: ["package:test_package/lib.dart"]); - - expect(result, {"def": "default", "pos": "positionalArgs", "nam": "namedArgs", "con": "fromID"}); + packageConfigURI: projDir.resolve(".packages"), + imports: ["package:test_package/lib.dart"]); + + expect(result, { + "def": "default", + "pos": "positionalArgs", + "nam": "namedArgs", + "con": "fromID" + }); }); test("Can get messages thru stream", () async { var completers = [new Completer(), new Completer(), new Completer()]; - var futures = [completers[0].future, completers[1].future, completers[2].future]; - - final result = await IsolateExecutor.run(Streamer({}), packageConfigURI: projDir.resolve(".packages"), - eventHandler: (event) { + var futures = [ + completers[0].future, + completers[1].future, + completers[2].future + ]; + + final result = await IsolateExecutor.run(Streamer({}), + packageConfigURI: projDir.resolve(".packages"), eventHandler: (event) { completers.last.complete(event); completers.removeLast(); }); @@ -50,7 +63,10 @@ void main() { final completed = await Future.wait(futures); expect(completed.any((i) => i == 1), true); expect(completed.any((i) => i is Map && i["key"] == "value"), true); - expect(completed.any((i) => i is Map && i["key1"] == "value1" && i["key2"] == "value2"), true); + expect( + completed.any( + (i) => i is Map && i["key1"] == "value1" && i["key2"] == "value2"), + true); }); test("Can instantiate types including in additionalContents", () async { @@ -62,9 +78,12 @@ class AdditionalContents { int get id => 10; } expect(result, 10); }); - test("If error is thrown, it is made available to consumer and the stack trace has been trimmed of script source", () async { + test( + "If error is thrown, it is made available to consumer and the stack trace has been trimmed of script source", + () async { try { - await IsolateExecutor.run(Thrower({}), packageConfigURI: projDir.resolve(".packages")); + await IsolateExecutor.run(Thrower({}), + packageConfigURI: projDir.resolve(".packages")); fail('unreachable'); } on StateError catch (e, st) { expect(e.toString(), contains("thrower-error")); @@ -105,10 +124,13 @@ class InPackage extends Executable> { @override Future> execute() async { - SomeObjectBaseClass def = instanceOf("DefaultObject"); - SomeObjectBaseClass pos = instanceOf("PositionalArgumentsObject", positionalArguments: ["positionalArgs"]); - SomeObjectBaseClass nam = instanceOf("NamedArgumentsObject", namedArguments: {#id: "namedArgs"}); - SomeObjectBaseClass con = instanceOf("NamedConstructorObject", constructorName: #fromID); + SomeObjectBaseClass def = instanceOf("DefaultObject", namedArguments: {}); + SomeObjectBaseClass pos = instanceOf("PositionalArgumentsObject", + positionalArguments: ["positionalArgs"], namedArguments: {}); + SomeObjectBaseClass nam = + instanceOf("NamedArgumentsObject", namedArguments: {#id: "namedArgs"}); + SomeObjectBaseClass con = + instanceOf("NamedConstructorObject", constructorName: #fromID); return {"def": def.id, "pos": pos.id, "nam": nam.id, "con": con.id}; } } @@ -146,5 +168,6 @@ class AdditionalContentsInstantiator extends Executable { Future getDependencies(Uri projectDir) async { final cmd = Platform.isWindows ? "pub.bat" : "pub"; - return Process.run(cmd, ["get"], workingDirectory: projectDir.toFilePath(windows: Platform.isWindows)); + return Process.run(cmd, ["get"], + workingDirectory: projectDir.toFilePath(windows: Platform.isWindows)); } diff --git a/test/test_package/lib/lib.dart b/test/test_package/lib/lib.dart index 79d2007..ba6e319 100644 --- a/test/test_package/lib/lib.dart +++ b/test/test_package/lib/lib.dart @@ -13,7 +13,7 @@ class PositionalArgumentsObject implements SomeObjectBaseClass { } class NamedArgumentsObject implements SomeObjectBaseClass { - NamedArgumentsObject({this.id}); + NamedArgumentsObject({this.id = ''}); String id; } @@ -21,4 +21,4 @@ class NamedArgumentsObject implements SomeObjectBaseClass { class NamedConstructorObject implements SomeObjectBaseClass { NamedConstructorObject.fromID(); String get id => "fromID"; -} \ No newline at end of file +} diff --git a/test/test_package/pubspec.yaml b/test/test_package/pubspec.yaml index 252f232..7faa01e 100644 --- a/test/test_package/pubspec.yaml +++ b/test/test_package/pubspec.yaml @@ -3,4 +3,4 @@ description: test dependency version: 1.0.0 environment: - sdk: '>=2.0.0 <3.0.0' + sdk: '>=2.12.0-0 <3.0.0' From 619ce981cb290183265f8dfc7979af3ee36acde3 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Thu, 25 Feb 2021 11:33:58 -0800 Subject: [PATCH 02/10] update travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b4b912d..12070f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: dart dart: - - stable + - beta jobs: include: From 8b38833119195c4e854dd6e423c1ea2e47c0525f Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Thu, 25 Feb 2021 14:19:33 -0800 Subject: [PATCH 03/10] update appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index be0c50d..3b769dd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -3,7 +3,7 @@ branches: - master install: - - ps: wget https://storage.googleapis.com/dart-archive/channels/stable/release/latest/sdk/dartsdk-windows-x64-release.zip -OutFile dart-sdk.zip + - ps: wget https://storage.googleapis.com/dart-archive/channels/beta/release/latest/sdk/dartsdk-windows-x64-release.zip -OutFile dart-sdk.zip - cmd: echo "Unzipping dart-sdk..." - cmd: 7z x dart-sdk.zip -o"C:\tools" -y > nul - set PATH=%PATH%;C:\tools\dart-sdk\bin From f4dafdfad8c8a2f635c1bb68d30aeb45510d6375 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sun, 14 Mar 2021 00:01:19 -0800 Subject: [PATCH 04/10] this is how context building shouldve been --- lib/src/source_generator.dart | 26 ++++++++++++++++++++------ pubspec.yaml | 5 +++-- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/lib/src/source_generator.dart b/lib/src/source_generator.dart index 67d3286..48c5828 100644 --- a/lib/src/source_generator.dart +++ b/lib/src/source_generator.dart @@ -3,9 +3,12 @@ import 'dart:isolate'; import 'dart:mirrors'; import 'dart:async'; -import 'package:analyzer/dart/analysis/analysis_context_collection.dart'; -import 'package:analyzer/dart/analysis/features.dart'; -import 'package:analyzer/dart/analysis/utilities.dart'; +import 'package:analyzer/dart/analysis/analysis_context.dart'; +import 'package:analyzer/dart/analysis/context_builder.dart'; +import 'package:analyzer/dart/analysis/context_locator.dart'; +import 'package:analyzer/file_system/file_system.dart'; +import 'package:analyzer/file_system/physical_file_system.dart'; +import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:isolate_executor/src/executable.dart'; @@ -59,9 +62,7 @@ Future main (List args, Map message) async { await Isolate.resolvePackageUri(reflectClass(type).location!.sourceUri); final path = uri!.toFilePath(windows: Platform.isWindows); - final analysisContextCollection = - AnalysisContextCollection(includedPaths: [path]); - final context = analysisContextCollection.contextFor(path); + final context = _createContext(path); final session = context.currentSession; final unit = session.getParsedUnit(path); final typeName = MirrorSystem.getName(reflectClass(type).simpleName); @@ -72,3 +73,16 @@ Future main (List args, Map message) async { .firstWhere((classDecl) => classDecl.name.name == typeName); } } + +AnalysisContext _createContext(String path, + {ResourceProvider? resourceProvider}) { + resourceProvider ??= PhysicalResourceProvider.INSTANCE; + final builder = ContextBuilder(resourceProvider: resourceProvider); + final contextLocator = ContextLocator( + resourceProvider: resourceProvider, + ); + final root = contextLocator.locateRoots( + includedPaths: [path], + ); + return builder.createContext(contextRoot: root.first); +} diff --git a/pubspec.yaml b/pubspec.yaml index 5e17338..8d19d3d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,9 +8,10 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - analyzer: ^1.0.0 + analyzer: ^1.1.0 + glob: ^2.0.0 dev_dependencies: - test: ^1.3.0 + test: ^1.6.5 test_package: path: test/test_package From 850078ccba125c017b4d3343f344acde362cde89 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Sun, 21 Mar 2021 19:24:09 -0700 Subject: [PATCH 05/10] change packages name --- lib/src/executor.dart | 4 ++-- lib/src/source_generator.dart | 3 +-- pubspec.yaml | 4 ++-- test/isolate_executor_test.dart | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/lib/src/executor.dart b/lib/src/executor.dart index 4b92dd4..961f3b6 100644 --- a/lib/src/executor.dart +++ b/lib/src/executor.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'dart:io'; import 'dart:isolate'; -import 'package:isolate_executor/src/executable.dart'; -import 'package:isolate_executor/src/source_generator.dart'; +import 'package:conduit_isolate_executor/src/executable.dart'; +import 'package:conduit_isolate_executor/src/source_generator.dart'; class IsolateExecutor { IsolateExecutor(this.generator, diff --git a/lib/src/source_generator.dart b/lib/src/source_generator.dart index 48c5828..bc53bb3 100644 --- a/lib/src/source_generator.dart +++ b/lib/src/source_generator.dart @@ -8,9 +8,8 @@ import 'package:analyzer/dart/analysis/context_builder.dart'; import 'package:analyzer/dart/analysis/context_locator.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/physical_file_system.dart'; -import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:isolate_executor/src/executable.dart'; +import 'package:conduit_isolate_executor/src/executable.dart'; class SourceGenerator { SourceGenerator(this.executableType, diff --git a/pubspec.yaml b/pubspec.yaml index 8d19d3d..1cf154b 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ -name: isolate_executor +name: conduit_isolate_executor description: This library contains types that allow for executing code in a spawned isolate, perhaps with additional imports. -version: 2.0.2+3 +version: 0.1.0 homepage: https://github.com/stablekernel/dart-isolate-executor author: stable|kernel diff --git a/test/isolate_executor_test.dart b/test/isolate_executor_test.dart index 051b7bc..f935af1 100644 --- a/test/isolate_executor_test.dart +++ b/test/isolate_executor_test.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'dart:io'; -import 'package:isolate_executor/isolate_executor.dart'; +import 'package:conduit_isolate_executor/isolate_executor.dart'; import 'package:test/test.dart'; void main() { From fa518f8b0ceaba8d3917dc211408389322d5315d Mon Sep 17 00:00:00 2001 From: Reductions Date: Tue, 30 Mar 2021 07:01:12 +0300 Subject: [PATCH 06/10] Added lint package and fixed warnings --- .gitignore | 3 +- .travis.yml | 15 ------- analysis_options.yaml | 18 ++------ appveyor.yml | 19 -------- lib/isolate_executor.dart | 4 +- lib/src/executable.dart | 45 ++++++++++--------- lib/src/executor.dart | 77 ++++++++++++++++++++------------- lib/src/source_generator.dart | 32 ++++++++------ pubspec.yaml | 3 +- test/isolate_executor_test.dart | 37 +++++++++++----- test/test_package/lib/lib.dart | 6 +++ 11 files changed, 131 insertions(+), 128 deletions(-) delete mode 100644 .travis.yml delete mode 100644 appveyor.yml diff --git a/.gitignore b/.gitignore index 1586ec0..886b8ae 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ pubspec.lock # Directory created by dartdoc doc/api/ -*.iml \ No newline at end of file +*.iml +.tool-versions \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 12070f8..0000000 --- a/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: dart -dart: - - beta - -jobs: - include: - - stage: test - script: pub get && pub run test -j1 - -stages: -- test - -branches: - only: - - master diff --git a/analysis_options.yaml b/analysis_options.yaml index 97f0908..f4b1672 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1,15 +1,5 @@ -analyzer: - strong-mode: true -# exclude: -# - path/to/excluded/files/** +include: package:lint/analysis_options.yaml -# Lint rules and documentation, see http://dart-lang.github.io/linter/lints -linter: - rules: - - cancel_subscriptions - - hash_and_equals - - iterable_contains_unrelated_type - - list_remove_unrelated_type - - test_types_in_equals - - unrelated_type_equality_checks - - valid_regexps +analyzer: + strong-mode: + implicit-casts: true diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 3b769dd..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,19 +0,0 @@ -branches: - only: - - master - -install: - - ps: wget https://storage.googleapis.com/dart-archive/channels/beta/release/latest/sdk/dartsdk-windows-x64-release.zip -OutFile dart-sdk.zip - - cmd: echo "Unzipping dart-sdk..." - - cmd: 7z x dart-sdk.zip -o"C:\tools" -y > nul - - set PATH=%PATH%;C:\tools\dart-sdk\bin - - set PATH=%PATH%;%APPDATA%\Pub\Cache\bin - -build: off - -test_script: - - pub get - - pub run test -j1 - -cache: - - C:\Users\appveyor\AppData\Roaming\Pub\Cache \ No newline at end of file diff --git a/lib/isolate_executor.dart b/lib/isolate_executor.dart index e24d4aa..9b621b5 100644 --- a/lib/isolate_executor.dart +++ b/lib/isolate_executor.dart @@ -3,6 +3,6 @@ /// library isolate_executor; -export 'src/source_generator.dart'; -export 'src/executor.dart'; export 'src/executable.dart'; +export 'src/executor.dart'; +export 'src/source_generator.dart'; diff --git a/lib/src/executable.dart b/lib/src/executable.dart index b71c081..260d063 100644 --- a/lib/src/executable.dart +++ b/lib/src/executable.dart @@ -10,33 +10,36 @@ abstract class Executable { final Map message; final SendPort? _sendPort; - U instanceOf(String typeName, - {List positionalArguments: const [], - Map namedArguments = const {}, - Symbol? constructorName}) { + U instanceOf( + String typeName, { + List positionalArguments = const [], + Map namedArguments = const {}, + Symbol constructorName = const Symbol(""), + }) { ClassMirror? typeMirror = currentMirrorSystem() .isolate .rootLibrary .declarations[Symbol(typeName)] as ClassMirror?; - if (typeMirror == null) { - typeMirror = currentMirrorSystem() - .libraries - .values - .where((lib) => - lib.uri.scheme == "package" || lib.uri.scheme == "file") - .expand((lib) => lib.declarations.values) - .firstWhere( - (decl) => - decl is ClassMirror && - MirrorSystem.getName(decl.simpleName) == typeName, - orElse: () => throw ArgumentError( - "Unknown type '$typeName'. Did you forget to import it?")) - as ClassMirror?; - } + + typeMirror ??= currentMirrorSystem() + .libraries + .values + .where((lib) => lib.uri.scheme == "package" || lib.uri.scheme == "file") + .expand((lib) => lib.declarations.values) + .firstWhere( + (decl) => + decl is ClassMirror && + MirrorSystem.getName(decl.simpleName) == typeName, + orElse: () => throw ArgumentError( + "Unknown type '$typeName'. Did you forget to import it?"), + ) as ClassMirror?; return typeMirror! - .newInstance(constructorName ?? const Symbol(""), positionalArguments, - namedArguments) + .newInstance( + constructorName, + positionalArguments, + namedArguments, + ) .reflectee as U; } diff --git a/lib/src/executor.dart b/lib/src/executor.dart index 961f3b6..6635ca2 100644 --- a/lib/src/executor.dart +++ b/lib/src/executor.dart @@ -6,8 +6,11 @@ import 'package:conduit_isolate_executor/src/executable.dart'; import 'package:conduit_isolate_executor/src/source_generator.dart'; class IsolateExecutor { - IsolateExecutor(this.generator, - {this.packageConfigURI, this.message = const {}}); + IsolateExecutor( + this.generator, { + this.packageConfigURI, + this.message = const {}, + }); final SourceGenerator generator; final Map message; @@ -23,14 +26,15 @@ class IsolateExecutor { Future execute() async { if (packageConfigURI != null && - !(File.fromUri(packageConfigURI!).existsSync())) { + !File.fromUri(packageConfigURI!).existsSync()) { throw StateError( - "Package file '$packageConfigURI' not found. Run 'pub get' and retry."); + "Package file '$packageConfigURI' not found. Run 'pub get' and retry.", + ); } final scriptSource = Uri.encodeComponent(await generator.scriptSource); - var onErrorPort = ReceivePort() + final onErrorPort = ReceivePort() ..listen((err) async { if (err is List) { final stack = @@ -42,7 +46,7 @@ class IsolateExecutor { } }); - var controlPort = ReceivePort() + final controlPort = ReceivePort() ..listen((results) { if (results is Map && results.length == 1) { if (results.containsKey("_result")) { @@ -59,18 +63,25 @@ class IsolateExecutor { try { message["_sendPort"] = controlPort.sendPort; - final dataUri = - Uri.parse("data:application/dart;charset=utf-8,${scriptSource}"); + final dataUri = Uri.parse( + "data:application/dart;charset=utf-8,$scriptSource", + ); if (packageConfigURI != null) { - await Isolate.spawnUri(dataUri, [], message, - errorsAreFatal: true, - onError: onErrorPort.sendPort, - packageConfig: packageConfigURI); + await Isolate.spawnUri( + dataUri, + [], + message, + onError: onErrorPort.sendPort, + packageConfig: packageConfigURI, + ); } else { - await Isolate.spawnUri(dataUri, [], message, - errorsAreFatal: true, - onError: onErrorPort.sendPort, - automaticPackageResolution: true); + await Isolate.spawnUri( + dataUri, + [], + message, + onError: onErrorPort.sendPort, + automaticPackageResolution: true, + ); } return await completer.future; @@ -82,19 +93,27 @@ class IsolateExecutor { } } - static Future run(Executable executable, - {Uri? packageConfigURI, - List? imports, - String? additionalContents, - void eventHandler(dynamic event)?, - void logHandler(String line)?, - List? additionalTypes}) async { - final source = SourceGenerator(executable.runtimeType, - imports: imports, - additionalContents: additionalContents, - additionalTypes: additionalTypes); - var executor = IsolateExecutor(source, - packageConfigURI: packageConfigURI, message: executable.message); + static Future run( + Executable executable, { + List imports = const [], + Uri? packageConfigURI, + String? additionalContents, + List additionalTypes = const [], + void Function(dynamic event)? eventHandler, + void Function(String line)? logHandler, + }) async { + final source = SourceGenerator( + executable.runtimeType, + imports: imports, + additionalContents: additionalContents, + additionalTypes: additionalTypes, + ); + + final executor = IsolateExecutor( + source, + packageConfigURI: packageConfigURI, + message: executable.message, + ); if (eventHandler != null) { executor.events.listen(eventHandler); diff --git a/lib/src/source_generator.dart b/lib/src/source_generator.dart index bc53bb3..9dcb7b8 100644 --- a/lib/src/source_generator.dart +++ b/lib/src/source_generator.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'dart:isolate'; import 'dart:mirrors'; -import 'dart:async'; import 'package:analyzer/dart/analysis/analysis_context.dart'; import 'package:analyzer/dart/analysis/context_builder.dart'; @@ -12,27 +11,31 @@ import 'package:analyzer/dart/ast/ast.dart'; import 'package:conduit_isolate_executor/src/executable.dart'; class SourceGenerator { - SourceGenerator(this.executableType, - {this.imports, this.additionalContents, this.additionalTypes}); + SourceGenerator( + this.executableType, { + this.imports = const [], + this.additionalTypes = const [], + this.additionalContents, + }); Type executableType; String get typeName => MirrorSystem.getName(reflectType(executableType).simpleName); - final List? imports; + final List imports; final String? additionalContents; - final List? additionalTypes; + final List additionalTypes; Future get scriptSource async { final typeSource = (await _getClass(executableType)).toSource(); - var builder = StringBuffer(); + final builder = StringBuffer(); builder.writeln("import 'dart:async';"); builder.writeln("import 'dart:isolate';"); builder.writeln("import 'dart:mirrors';"); - imports?.forEach((import) { - builder.writeln("import '$import';"); - }); + for (final anImport in imports) { + builder.writeln("import '$anImport';"); + } builder.writeln(""" Future main (List args, Map message) async { final sendPort = message['_sendPort']; @@ -44,7 +47,7 @@ Future main (List args, Map message) async { builder.writeln(typeSource); builder.writeln((await _getClass(Executable)).toSource()); - for (var type in additionalTypes ?? []) { + for (final type in additionalTypes) { final source = await _getClass(type); builder.writeln(source.toSource()); } @@ -67,14 +70,15 @@ Future main (List args, Map message) async { final typeName = MirrorSystem.getName(reflectClass(type).simpleName); return unit.unit.declarations - .where((u) => u is ClassDeclaration) - .map((cu) => cu as ClassDeclaration) + .whereType() .firstWhere((classDecl) => classDecl.name.name == typeName); } } -AnalysisContext _createContext(String path, - {ResourceProvider? resourceProvider}) { +AnalysisContext _createContext( + String path, { + ResourceProvider? resourceProvider, +}) { resourceProvider ??= PhysicalResourceProvider.INSTANCE; final builder = ContextBuilder(resourceProvider: resourceProvider); final contextLocator = ContextLocator( diff --git a/pubspec.yaml b/pubspec.yaml index 1cf154b..fe8f88c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -8,10 +8,11 @@ environment: sdk: ">=2.12.0-0 <3.0.0" dependencies: - analyzer: ^1.1.0 + analyzer: ^1.3.0 glob: ^2.0.0 dev_dependencies: + lint: ^1.5.3 test: ^1.6.5 test_package: path: test/test_package diff --git a/test/isolate_executor_test.dart b/test/isolate_executor_test.dart index f935af1..a08f2e0 100644 --- a/test/isolate_executor_test.dart +++ b/test/isolate_executor_test.dart @@ -27,8 +27,10 @@ void main() { }); test("Send values to Executable and use them", () async { - final result = await IsolateExecutor.run(Echo({'echo': 'hello'}), - packageConfigURI: projDir.resolve(".packages")); + final result = await IsolateExecutor.run( + Echo({'echo': 'hello'}), + packageConfigURI: projDir.resolve(".packages"), + ); expect(result, 'hello'); }); @@ -46,8 +48,8 @@ void main() { }); test("Can get messages thru stream", () async { - var completers = [new Completer(), new Completer(), new Completer()]; - var futures = [ + final completers = [Completer(), Completer(), Completer()]; + final futures = [ completers[0].future, completers[1].future, completers[2].future @@ -85,6 +87,8 @@ class AdditionalContents { int get id => 10; } await IsolateExecutor.run(Thrower({}), packageConfigURI: projDir.resolve(".packages")); fail('unreachable'); + + //ignore: avoid_catching_errors } on StateError catch (e, st) { expect(e.toString(), contains("thrower-error")); expect(st.toString().contains("import"), false); @@ -104,7 +108,7 @@ class SimpleReturner extends Executable { class Echo extends Executable { Echo(Map message) - : echoMessage = message['echo'], + : echoMessage = message['echo']!.toString(), super(message); final String echoMessage; @@ -124,13 +128,22 @@ class InPackage extends Executable> { @override Future> execute() async { - SomeObjectBaseClass def = instanceOf("DefaultObject", namedArguments: {}); - SomeObjectBaseClass pos = instanceOf("PositionalArgumentsObject", - positionalArguments: ["positionalArgs"], namedArguments: {}); - SomeObjectBaseClass nam = - instanceOf("NamedArgumentsObject", namedArguments: {#id: "namedArgs"}); - SomeObjectBaseClass con = - instanceOf("NamedConstructorObject", constructorName: #fromID); + final SomeObjectBaseClass def = instanceOf( + "DefaultObject", + namedArguments: {}, + ); + final SomeObjectBaseClass pos = instanceOf( + "PositionalArgumentsObject", + positionalArguments: ["positionalArgs"], + namedArguments: {}, + ); + final SomeObjectBaseClass nam = instanceOf( + "NamedArgumentsObject", + namedArguments: {#id: "namedArgs"}, + ); + final SomeObjectBaseClass con = + instanceOf("NamedConstructorObject", constructorName: #fromID) + as SomeObjectBaseClass; return {"def": def.id, "pos": pos.id, "nam": nam.id, "con": con.id}; } } diff --git a/test/test_package/lib/lib.dart b/test/test_package/lib/lib.dart index ba6e319..9c3b55b 100644 --- a/test/test_package/lib/lib.dart +++ b/test/test_package/lib/lib.dart @@ -4,21 +4,27 @@ export 'package:test_package/src/src.dart'; String libFunction() => "libFunction"; class DefaultObject implements SomeObjectBaseClass { + @override String get id => "default"; } class PositionalArgumentsObject implements SomeObjectBaseClass { PositionalArgumentsObject(this.id); + + @override String id; } class NamedArgumentsObject implements SomeObjectBaseClass { NamedArgumentsObject({this.id = ''}); + @override String id; } class NamedConstructorObject implements SomeObjectBaseClass { NamedConstructorObject.fromID(); + + @override String get id => "fromID"; } From 87c56f1cdd9c1381063be6c83e7f412abc9b1521 Mon Sep 17 00:00:00 2001 From: j4qfrost Date: Tue, 30 Mar 2021 00:19:20 -0700 Subject: [PATCH 07/10] Create dart.yml --- dart.yml | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 dart.yml diff --git a/dart.yml b/dart.yml new file mode 100644 index 0000000..5bcd712 --- /dev/null +++ b/dart.yml @@ -0,0 +1,41 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Dart + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + + - uses: dart-lang/setup-dart@stable + + - name: Install dependencies + run: dart pub get + + - name: Test + run: pub get && pub run test -j1 + + # Uncomment this step to verify the use of 'dart format' on each commit. + # - name: Verify formatting + # run: dart format --output=none --set-exit-if-changed . + + # Consider passing '--fatal-infos' for slightly stricter analysis. + - name: Analyze project source + run: dart analyze + + # Your project will need to have tests in test/ and a dependency on + # package:test for this step to succeed. Note that Flutter projects will + # want to change this to 'flutter test'. + - name: Run tests + run: dart test From a4f9492482b2d2ba1eb915b9f4594cedb504c62d Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 30 Mar 2021 00:58:25 -0700 Subject: [PATCH 08/10] move workflow --- dart.yml => .github/workflow/test.yml | 3 --- 1 file changed, 3 deletions(-) rename dart.yml => .github/workflow/test.yml (93%) diff --git a/dart.yml b/.github/workflow/test.yml similarity index 93% rename from dart.yml rename to .github/workflow/test.yml index 5bcd712..946c551 100644 --- a/dart.yml +++ b/.github/workflow/test.yml @@ -22,9 +22,6 @@ jobs: - name: Install dependencies run: dart pub get - - - name: Test - run: pub get && pub run test -j1 # Uncomment this step to verify the use of 'dart format' on each commit. # - name: Verify formatting From a32d500e4c32b5682be980192dac9331f3f362e0 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 30 Mar 2021 01:35:15 -0700 Subject: [PATCH 09/10] package rename --- lib/src/executor.dart | 4 ++-- lib/src/source_generator.dart | 2 +- pubspec.yaml | 4 ++-- test/isolate_executor_test.dart | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/src/executor.dart b/lib/src/executor.dart index 6635ca2..0e3b999 100644 --- a/lib/src/executor.dart +++ b/lib/src/executor.dart @@ -2,8 +2,8 @@ import 'dart:async'; import 'dart:io'; import 'dart:isolate'; -import 'package:conduit_isolate_executor/src/executable.dart'; -import 'package:conduit_isolate_executor/src/source_generator.dart'; +import 'package:conduit_isolate_exec/src/executable.dart'; +import 'package:conduit_isolate_exec/src/source_generator.dart'; class IsolateExecutor { IsolateExecutor( diff --git a/lib/src/source_generator.dart b/lib/src/source_generator.dart index 9dcb7b8..6fb9bcf 100644 --- a/lib/src/source_generator.dart +++ b/lib/src/source_generator.dart @@ -8,7 +8,7 @@ import 'package:analyzer/dart/analysis/context_locator.dart'; import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/physical_file_system.dart'; import 'package:analyzer/dart/ast/ast.dart'; -import 'package:conduit_isolate_executor/src/executable.dart'; +import 'package:conduit_isolate_exec/src/executable.dart'; class SourceGenerator { SourceGenerator( diff --git a/pubspec.yaml b/pubspec.yaml index fe8f88c..a1c3a57 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ -name: conduit_isolate_executor +name: conduit_isolate_exec description: This library contains types that allow for executing code in a spawned isolate, perhaps with additional imports. -version: 0.1.0 +version: 1.0.0-b1 homepage: https://github.com/stablekernel/dart-isolate-executor author: stable|kernel diff --git a/test/isolate_executor_test.dart b/test/isolate_executor_test.dart index a08f2e0..a094b51 100644 --- a/test/isolate_executor_test.dart +++ b/test/isolate_executor_test.dart @@ -1,7 +1,7 @@ import 'dart:async'; import 'dart:io'; -import 'package:conduit_isolate_executor/isolate_executor.dart'; +import 'package:conduit_isolate_exec/isolate_executor.dart'; import 'package:test/test.dart'; void main() { From 2972c6effe5e7f5a3680af809e3ec903f6af1460 Mon Sep 17 00:00:00 2001 From: AnhQuan Nguyen Date: Tue, 30 Mar 2021 01:36:54 -0700 Subject: [PATCH 10/10] change homepage --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index a1c3a57..5afcbb3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: conduit_isolate_exec description: This library contains types that allow for executing code in a spawned isolate, perhaps with additional imports. version: 1.0.0-b1 -homepage: https://github.com/stablekernel/dart-isolate-executor +homepage: https://github.com/conduit-dart/isolate-exec author: stable|kernel environment: