Skip to content

Commit 11632ff

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Add buildSdkSummary() to analyzer API.
[email protected] Bug: dart-lang/build#2745 (comment) Change-Id: I144dd99be5e5a210e27f3b5b5b54951659479511 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153384 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent 431b57c commit 11632ff

File tree

6 files changed

+206
-244
lines changed

6 files changed

+206
-244
lines changed

pkg/analyzer/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 0.39.13-dev
2+
* Added 'dart/sdk/build_sdk_summary.dart' with `buildSdkSummary`.
3+
14
## 0.39.12
25
* Deprecated `canUseSummaries` in `DartSdkManager` constructor.
36
Summaries are not supported this way for SDK.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
// Copyright (c) 2020, 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+
import 'dart:typed_data';
6+
7+
import 'package:_fe_analyzer_shared/src/sdk/allowed_experiments.dart';
8+
import 'package:analyzer/dart/analysis/features.dart';
9+
import 'package:analyzer/dart/analysis/utilities.dart';
10+
import 'package:analyzer/dart/ast/ast.dart';
11+
import 'package:analyzer/dart/element/element.dart';
12+
import 'package:analyzer/file_system/file_system.dart';
13+
import 'package:analyzer/src/dart/analysis/experiments.dart';
14+
import 'package:analyzer/src/dart/analysis/session.dart';
15+
import 'package:analyzer/src/dart/ast/ast.dart';
16+
import 'package:analyzer/src/dart/sdk/sdk.dart';
17+
import 'package:analyzer/src/generated/engine.dart';
18+
import 'package:analyzer/src/generated/source.dart';
19+
import 'package:analyzer/src/summary/format.dart';
20+
import 'package:analyzer/src/summary/summarize_elements.dart';
21+
import 'package:analyzer/src/summary2/link.dart';
22+
import 'package:analyzer/src/summary2/linked_element_factory.dart';
23+
import 'package:analyzer/src/summary2/reference.dart';
24+
import 'package:meta/meta.dart';
25+
import 'package:yaml/yaml.dart';
26+
27+
/// Build summary for SDK at the given [sdkPath].
28+
///
29+
/// If [embedderYamlPath] is provided, then libraries from this file are
30+
/// appended to the libraries of the specified SDK.
31+
Uint8List buildSdkSummary({
32+
@required ResourceProvider resourceProvider,
33+
@required String sdkPath,
34+
String embedderYamlPath,
35+
}) {
36+
var sdk = FolderBasedDartSdk(
37+
resourceProvider,
38+
resourceProvider.getFolder(sdkPath),
39+
);
40+
sdk.analysisOptions = AnalysisOptionsImpl();
41+
42+
// Append libraries from the embedder.
43+
if (embedderYamlPath != null) {
44+
var file = resourceProvider.getFile(embedderYamlPath);
45+
var content = file.readAsStringSync();
46+
var map = loadYaml(content) as YamlMap;
47+
var embedderSdk = EmbedderSdk(resourceProvider, {file.parent: map});
48+
for (var library in embedderSdk.sdkLibraries) {
49+
var uriStr = library.shortName;
50+
if (sdk.libraryMap.getLibrary(uriStr) == null) {
51+
sdk.libraryMap.setLibrary(uriStr, library);
52+
}
53+
}
54+
}
55+
56+
var librarySources = sdk.sdkLibraries.map((e) {
57+
return sdk.mapDartUri(e.shortName);
58+
}).toList();
59+
60+
return _Builder(
61+
sdk.context,
62+
sdk.allowedExperimentsJson,
63+
librarySources,
64+
).build();
65+
}
66+
67+
class _Builder {
68+
final AnalysisContext context;
69+
final String allowedExperimentsJson;
70+
final Iterable<Source> librarySources;
71+
72+
final Set<String> libraryUris = <String>{};
73+
final List<LinkInputLibrary> inputLibraries = [];
74+
75+
AllowedExperiments allowedExperiments;
76+
final PackageBundleAssembler bundleAssembler = PackageBundleAssembler();
77+
78+
_Builder(
79+
this.context,
80+
this.allowedExperimentsJson,
81+
this.librarySources,
82+
) {
83+
allowedExperiments = _parseAllowedExperiments(allowedExperimentsJson);
84+
}
85+
86+
/// Build the linked bundle and return its bytes.
87+
Uint8List build() {
88+
librarySources.forEach(_addLibrary);
89+
90+
var elementFactory = LinkedElementFactory(
91+
context,
92+
AnalysisSessionImpl(null),
93+
Reference.root(),
94+
);
95+
96+
var linkResult = link(elementFactory, inputLibraries);
97+
bundleAssembler.setBundle2(linkResult.bundle);
98+
99+
var buffer = PackageBundleBuilder(
100+
bundle2: linkResult.bundle,
101+
sdk: PackageBundleSdkBuilder(
102+
allowedExperimentsJson: allowedExperimentsJson,
103+
),
104+
).toBuffer();
105+
106+
return buffer is Uint8List ? buffer : Uint8List.fromList(buffer);
107+
}
108+
109+
void _addLibrary(Source source) {
110+
String uriStr = source.uri.toString();
111+
if (!libraryUris.add(uriStr)) {
112+
return;
113+
}
114+
115+
var inputUnits = <LinkInputUnit>[];
116+
117+
CompilationUnit definingUnit = _parse(source);
118+
inputUnits.add(
119+
LinkInputUnit(null, source, false, definingUnit),
120+
);
121+
122+
for (Directive directive in definingUnit.directives) {
123+
if (directive is NamespaceDirective) {
124+
String libUri = directive.uri.stringValue;
125+
Source libSource = context.sourceFactory.resolveUri(source, libUri);
126+
_addLibrary(libSource);
127+
} else if (directive is PartDirective) {
128+
String partUri = directive.uri.stringValue;
129+
Source partSource = context.sourceFactory.resolveUri(source, partUri);
130+
CompilationUnit partUnit = _parse(partSource);
131+
inputUnits.add(
132+
LinkInputUnit(partUri, partSource, false, partUnit),
133+
);
134+
}
135+
}
136+
137+
inputLibraries.add(
138+
LinkInputLibrary(source, inputUnits),
139+
);
140+
}
141+
142+
/// Return the [FeatureSet] for the given [uri], must be a `dart:` URI.
143+
FeatureSet _featureSet(Uri uri) {
144+
if (uri.isScheme('dart')) {
145+
var pathSegments = uri.pathSegments;
146+
if (pathSegments.isNotEmpty) {
147+
var libraryName = pathSegments.first;
148+
var experiments = allowedExperiments.forSdkLibrary(libraryName);
149+
return FeatureSet.fromEnableFlags(experiments);
150+
}
151+
}
152+
throw StateError('Expected a valid dart: URI: $uri');
153+
}
154+
155+
CompilationUnit _parse(Source source) {
156+
var result = parseString(
157+
content: source.contents.data,
158+
featureSet: _featureSet(source.uri),
159+
throwIfDiagnostics: false,
160+
);
161+
162+
if (result.errors.isNotEmpty) {
163+
var errorsStr = result.errors.map((e) {
164+
var location = result.lineInfo.getLocation(e.offset);
165+
return '${source.fullName}:$location - ${e.message}';
166+
}).join('\n');
167+
throw StateError(
168+
'Unexpected diagnostics:\n$errorsStr',
169+
);
170+
}
171+
172+
var unit = result.unit as CompilationUnitImpl;
173+
unit.languageVersion = LibraryLanguageVersion(
174+
package: ExperimentStatus.currentVersion,
175+
override: null,
176+
);
177+
178+
return result.unit;
179+
}
180+
181+
static AllowedExperiments _parseAllowedExperiments(String content) {
182+
if (content == null) {
183+
return AllowedExperiments(
184+
sdkDefaultExperiments: [],
185+
sdkLibraryExperiments: {},
186+
packageExperiments: {},
187+
);
188+
}
189+
190+
return parseAllowedExperiments(content);
191+
}
192+
}

0 commit comments

Comments
 (0)