Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(31)

Side by Side Diff: lib/src/bootloader.dart

Issue 1373953002: Basic analyzer `main()` isolate bootloader. (Closed) Base URL: https://github.com/dart-lang/analyzer_cli.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | test/data/plugin_options.yaml » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library analyzer_cli.src.bootloader;
6
7 import 'dart:io';
8 import 'dart:isolate';
9
10 import 'package:analyzer/file_system/physical_file_system.dart';
11 import 'package:analyzer/plugin/options.dart';
12 import 'package:analyzer/source/analysis_options_provider.dart';
13 import 'package:analyzer/src/generated/engine.dart';
14 import 'package:analyzer/src/plugin/plugin_configuration.dart';
15 import 'package:analyzer_cli/src/driver.dart';
16 import 'package:analyzer_cli/src/options.dart';
17 import 'package:analyzer_cli/src/plugin/plugin_config_processor_plugin.dart';
18 import 'package:plugin/manager.dart';
19 import 'package:plugin/plugin.dart';
20 import 'package:source_span/source_span.dart';
21 import 'package:yaml/src/yaml_node.dart';
22
23 const _analyzerPackageName = 'analyzer';
24
25 /// Source code assembler.
26 class Assembler {
27 /// Plugin configuration info.
28 final PluginConfig _config;
29
30 /// Create an assembler for the given plugin [config].
31 Assembler(this._config);
32
33 /// A string enumerating required package `import`s.
34 String get enumerateImports =>
35 plugins.map((PluginInfo p) => "import '${p.libraryUri}';").join('\n');
36
37 /// A string listing initialized plugin instances.
38 String get pluginList =>
39 plugins.map((PluginInfo p) => 'new ${p.className}()').join(', ');
40
41 /// Plugins to configure.
42 List<PluginInfo> get plugins => _config.plugins;
43
44 /// Create a file containing a `main()` suitable for loading in spawned
45 /// isolate.
46 String createMain() => _generateMain();
47
48 String _generateMain() => """
49 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
50 // for details. All rights reserved. Use of this source code is governed by a
51 // BSD-style license that can be found in the LICENSE file.
52
53 // This code was auto-generated, is not intended to be edited, and is subject to
54 // significant change. Please see the README file for more information.
55
56 import 'package:analyzer_cli/src/driver.dart';
57
58 $enumerateImports
59
60 void main(List<String> args) {
61 var starter = new Driver();
62 starter.userDefinedPlugins = [$pluginList];
63 starter.start(args);
64 }
65 """;
66 }
67
68 /// Given environment information extracted from command-line `args`, creates a
69 /// a loadable analyzer "image".
70 class BootLoader {
71 /// Emits an error message to [errorSink] if plugin config can't be read.
72 static final ErrorHandler _pluginConfigErrorHandler = (Exception e) {
73 String details;
74 if (e is PluginConfigFormatException) {
75 details = e.message;
76 var node = e.yamlNode;
77 if (node is YamlNode) {
78 SourceLocation location = node.span.start;
79 details += ' (line ${location.line}, column ${location.column})';
80 }
81 } else {
82 details = e.toString();
83 }
84
85 errorSink.writeln('Plugin configuration skipped: $details');
86 };
87
88 /// Reads plugin config info from `.analysis_options`.
89 PluginConfigProcessorPlugin _pluginConfigProcessorPlugin =
90 new PluginConfigProcessorPlugin(_pluginConfigErrorHandler);
91
92 /// Create a loadable analyzer image confifgured with plugins derived from
Brian Wilkerson 2015/09/28 17:48:11 nit: "confifgured" --> "configured"
pquitslund 2015/09/28 18:01:29 Thanks!
93 /// the given analyzer command-line `args`.
94 Image createImage(List<String> args) {
95 _processPlugins();
96
97 // Parse commandline options.
98 CommandLineOptions options = CommandLineOptions.parse(args);
99
100 // Process analysis options file (and notify all interested parties).
101 _processAnalysisOptions(options);
102
103 // TODO(pquitslund): Pass in .packages info
104 return new Image(_pluginConfigProcessorPlugin.pluginConfig,
105 args: args, packageRootPath: options.packageRootPath);
106 }
107
108 void _processAnalysisOptions(CommandLineOptions options) {
109 // Determine options file path.
110 var filePath = options.analysisOptionsFile != null
111 ? options.analysisOptionsFile
112 : AnalysisOptionsProvider.ANALYSIS_OPTIONS_NAME;
113 List<OptionsProcessor> optionsProcessors =
Brian Wilkerson 2015/09/28 17:48:11 I don't think there will be any processors until a
pquitslund 2015/09/28 18:01:29 Actually, that's exactly what our PluginConfigOpti
Brian Wilkerson 2015/09/28 18:29:20 So it's an explicitly installed "plugin" that can
pquitslund 2015/09/28 21:15:03 I agree. Addressed here: https://codereview.chro
114 AnalysisEngine.instance.optionsPlugin.optionsProcessors;
115 try {
116 var file = PhysicalResourceProvider.INSTANCE.getFile(filePath);
117 AnalysisOptionsProvider analysisOptionsProvider =
118 new AnalysisOptionsProvider();
119 Map<String, YamlNode> options =
120 analysisOptionsProvider.getOptionsFromFile(file);
121 optionsProcessors
122 .forEach((OptionsProcessor p) => p.optionsProcessed(options));
123 } on Exception catch (e) {
124 optionsProcessors.forEach((OptionsProcessor p) => p.onError(e));
125 }
126 }
127
128 void _processPlugins() {
129 List<Plugin> plugins = <Plugin>[];
130 plugins.add(_pluginConfigProcessorPlugin);
131 plugins.addAll(AnalysisEngine.instance.supportedPlugins);
132 ExtensionManager manager = new ExtensionManager();
133 manager.processPlugins(plugins);
134 }
135 }
136
137 /// A loadable "image" of a a configured analyzer instance.
138 class Image {
139 /// (Optional) package root path.
140 final String packageRootPath;
141
142 /// (Optional) package map.
143 final Map<String, Uri> packages;
144
145 /// Args to be passed on to the loaded main.
146 final List<String> args;
147
148 /// Plugin configuration.
149 final PluginConfig config;
150
151 /// Create an image with the given [config] and optionally [packages],
152 /// [packageRootPath], and command line [args].
153 Image(this.config, {this.packages, this.packageRootPath, this.args});
154
155 /// Load this image.
156 ///
157 /// Loading an image consists in assembling an analyzer `main()`, configured
158 /// to include the appropriate analyzer plugins as specified in
159 /// `.analyzer_options` which is then run in a spawned isolate.
160 void load() {
161 String mainSource = new Assembler(config).createMain();
162
163 Uri uri =
164 Uri.parse('data:application/dart;charset=utf-8,${Uri.encodeComponent(
165 mainSource)}');
166
167 ReceivePort errorListener = new ReceivePort();
168 errorListener.listen((data) {
169 //TODO(pquitslund): handle errors.
170 print('>>> ERROR: $data');
171 });
172
173 ReceivePort exitListener = new ReceivePort();
174 exitListener.listen((data) {
175 // Propagate exit code.
176 exit(exitCode);
177 });
178
179 // TODO(pquitslund): update once .packages are supported.
180 String packageRoot =
181 packageRootPath != null ? packageRootPath : './packages';
182 Uri packageUri = new Uri.file(packageRoot);
183
184 // TODO(pquitslund): add .packages support once the VM implements it.
185 Isolate.spawnUri(uri, args, null /* msg */,
186 packageRoot: packageUri,
187 onError: errorListener.sendPort,
188 onExit: exitListener.sendPort);
189
190 // TODO(pquitslund): consider starting paused
191 // http://stackoverflow.com/questions/29247374/what-is-the-best-way-to-track -the-state-of-an-isolate-in-dart
192 }
193 }
OLDNEW
« no previous file with comments | « no previous file | test/data/plugin_options.yaml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698