mirror of
https://github.com/dart-lang/sdk
synced 2024-10-06 14:49:43 +00:00
Add buildSdkSummary() to analyzer API.
R=brianwilkerson@google.com Bug: https://github.com/dart-lang/build/issues/2745#issuecomment-654441549 Change-Id: I144dd99be5e5a210e27f3b5b5b54951659479511 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/153384 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
431b57cbbb
commit
11632ff4d4
|
@ -1,3 +1,6 @@
|
|||
## 0.39.13-dev
|
||||
* Added 'dart/sdk/build_sdk_summary.dart' with `buildSdkSummary`.
|
||||
|
||||
## 0.39.12
|
||||
* Deprecated `canUseSummaries` in `DartSdkManager` constructor.
|
||||
Summaries are not supported this way for SDK.
|
||||
|
|
192
pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
Normal file
192
pkg/analyzer/lib/dart/sdk/build_sdk_summary.dart
Normal file
|
@ -0,0 +1,192 @@
|
|||
// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:_fe_analyzer_shared/src/sdk/allowed_experiments.dart';
|
||||
import 'package:analyzer/dart/analysis/features.dart';
|
||||
import 'package:analyzer/dart/analysis/utilities.dart';
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/src/dart/analysis/experiments.dart';
|
||||
import 'package:analyzer/src/dart/analysis/session.dart';
|
||||
import 'package:analyzer/src/dart/ast/ast.dart';
|
||||
import 'package:analyzer/src/dart/sdk/sdk.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart';
|
||||
import 'package:analyzer/src/generated/source.dart';
|
||||
import 'package:analyzer/src/summary/format.dart';
|
||||
import 'package:analyzer/src/summary/summarize_elements.dart';
|
||||
import 'package:analyzer/src/summary2/link.dart';
|
||||
import 'package:analyzer/src/summary2/linked_element_factory.dart';
|
||||
import 'package:analyzer/src/summary2/reference.dart';
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
/// Build summary for SDK at the given [sdkPath].
|
||||
///
|
||||
/// If [embedderYamlPath] is provided, then libraries from this file are
|
||||
/// appended to the libraries of the specified SDK.
|
||||
Uint8List buildSdkSummary({
|
||||
@required ResourceProvider resourceProvider,
|
||||
@required String sdkPath,
|
||||
String embedderYamlPath,
|
||||
}) {
|
||||
var sdk = FolderBasedDartSdk(
|
||||
resourceProvider,
|
||||
resourceProvider.getFolder(sdkPath),
|
||||
);
|
||||
sdk.analysisOptions = AnalysisOptionsImpl();
|
||||
|
||||
// Append libraries from the embedder.
|
||||
if (embedderYamlPath != null) {
|
||||
var file = resourceProvider.getFile(embedderYamlPath);
|
||||
var content = file.readAsStringSync();
|
||||
var map = loadYaml(content) as YamlMap;
|
||||
var embedderSdk = EmbedderSdk(resourceProvider, {file.parent: map});
|
||||
for (var library in embedderSdk.sdkLibraries) {
|
||||
var uriStr = library.shortName;
|
||||
if (sdk.libraryMap.getLibrary(uriStr) == null) {
|
||||
sdk.libraryMap.setLibrary(uriStr, library);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var librarySources = sdk.sdkLibraries.map((e) {
|
||||
return sdk.mapDartUri(e.shortName);
|
||||
}).toList();
|
||||
|
||||
return _Builder(
|
||||
sdk.context,
|
||||
sdk.allowedExperimentsJson,
|
||||
librarySources,
|
||||
).build();
|
||||
}
|
||||
|
||||
class _Builder {
|
||||
final AnalysisContext context;
|
||||
final String allowedExperimentsJson;
|
||||
final Iterable<Source> librarySources;
|
||||
|
||||
final Set<String> libraryUris = <String>{};
|
||||
final List<LinkInputLibrary> inputLibraries = [];
|
||||
|
||||
AllowedExperiments allowedExperiments;
|
||||
final PackageBundleAssembler bundleAssembler = PackageBundleAssembler();
|
||||
|
||||
_Builder(
|
||||
this.context,
|
||||
this.allowedExperimentsJson,
|
||||
this.librarySources,
|
||||
) {
|
||||
allowedExperiments = _parseAllowedExperiments(allowedExperimentsJson);
|
||||
}
|
||||
|
||||
/// Build the linked bundle and return its bytes.
|
||||
Uint8List build() {
|
||||
librarySources.forEach(_addLibrary);
|
||||
|
||||
var elementFactory = LinkedElementFactory(
|
||||
context,
|
||||
AnalysisSessionImpl(null),
|
||||
Reference.root(),
|
||||
);
|
||||
|
||||
var linkResult = link(elementFactory, inputLibraries);
|
||||
bundleAssembler.setBundle2(linkResult.bundle);
|
||||
|
||||
var buffer = PackageBundleBuilder(
|
||||
bundle2: linkResult.bundle,
|
||||
sdk: PackageBundleSdkBuilder(
|
||||
allowedExperimentsJson: allowedExperimentsJson,
|
||||
),
|
||||
).toBuffer();
|
||||
|
||||
return buffer is Uint8List ? buffer : Uint8List.fromList(buffer);
|
||||
}
|
||||
|
||||
void _addLibrary(Source source) {
|
||||
String uriStr = source.uri.toString();
|
||||
if (!libraryUris.add(uriStr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var inputUnits = <LinkInputUnit>[];
|
||||
|
||||
CompilationUnit definingUnit = _parse(source);
|
||||
inputUnits.add(
|
||||
LinkInputUnit(null, source, false, definingUnit),
|
||||
);
|
||||
|
||||
for (Directive directive in definingUnit.directives) {
|
||||
if (directive is NamespaceDirective) {
|
||||
String libUri = directive.uri.stringValue;
|
||||
Source libSource = context.sourceFactory.resolveUri(source, libUri);
|
||||
_addLibrary(libSource);
|
||||
} else if (directive is PartDirective) {
|
||||
String partUri = directive.uri.stringValue;
|
||||
Source partSource = context.sourceFactory.resolveUri(source, partUri);
|
||||
CompilationUnit partUnit = _parse(partSource);
|
||||
inputUnits.add(
|
||||
LinkInputUnit(partUri, partSource, false, partUnit),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
inputLibraries.add(
|
||||
LinkInputLibrary(source, inputUnits),
|
||||
);
|
||||
}
|
||||
|
||||
/// Return the [FeatureSet] for the given [uri], must be a `dart:` URI.
|
||||
FeatureSet _featureSet(Uri uri) {
|
||||
if (uri.isScheme('dart')) {
|
||||
var pathSegments = uri.pathSegments;
|
||||
if (pathSegments.isNotEmpty) {
|
||||
var libraryName = pathSegments.first;
|
||||
var experiments = allowedExperiments.forSdkLibrary(libraryName);
|
||||
return FeatureSet.fromEnableFlags(experiments);
|
||||
}
|
||||
}
|
||||
throw StateError('Expected a valid dart: URI: $uri');
|
||||
}
|
||||
|
||||
CompilationUnit _parse(Source source) {
|
||||
var result = parseString(
|
||||
content: source.contents.data,
|
||||
featureSet: _featureSet(source.uri),
|
||||
throwIfDiagnostics: false,
|
||||
);
|
||||
|
||||
if (result.errors.isNotEmpty) {
|
||||
var errorsStr = result.errors.map((e) {
|
||||
var location = result.lineInfo.getLocation(e.offset);
|
||||
return '${source.fullName}:$location - ${e.message}';
|
||||
}).join('\n');
|
||||
throw StateError(
|
||||
'Unexpected diagnostics:\n$errorsStr',
|
||||
);
|
||||
}
|
||||
|
||||
var unit = result.unit as CompilationUnitImpl;
|
||||
unit.languageVersion = LibraryLanguageVersion(
|
||||
package: ExperimentStatus.currentVersion,
|
||||
override: null,
|
||||
);
|
||||
|
||||
return result.unit;
|
||||
}
|
||||
|
||||
static AllowedExperiments _parseAllowedExperiments(String content) {
|
||||
if (content == null) {
|
||||
return AllowedExperiments(
|
||||
sdkDefaultExperiments: [],
|
||||
sdkLibraryExperiments: {},
|
||||
packageExperiments: {},
|
||||
);
|
||||
}
|
||||
|
||||
return parseAllowedExperiments(content);
|
||||
}
|
||||
}
|
|
@ -2,26 +2,12 @@
|
|||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:_fe_analyzer_shared/src/sdk/allowed_experiments.dart';
|
||||
import 'package:analyzer/dart/analysis/features.dart';
|
||||
import 'package:analyzer/dart/analysis/utilities.dart';
|
||||
import 'package:analyzer/dart/ast/ast.dart';
|
||||
import 'package:analyzer/dart/element/element.dart';
|
||||
@Deprecated('Use package:analyzer/dart/sdk/build_sdk_summary.dart instead')
|
||||
library summary_file_builder;
|
||||
|
||||
import 'package:analyzer/dart/sdk/build_sdk_summary.dart' as api;
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/file_system/physical_file_system.dart';
|
||||
import 'package:analyzer/src/dart/analysis/experiments.dart';
|
||||
import 'package:analyzer/src/dart/analysis/session.dart';
|
||||
import 'package:analyzer/src/dart/ast/ast.dart';
|
||||
import 'package:analyzer/src/dart/sdk/sdk.dart';
|
||||
import 'package:analyzer/src/generated/engine.dart';
|
||||
import 'package:analyzer/src/generated/source.dart';
|
||||
import 'package:analyzer/src/summary/format.dart';
|
||||
import 'package:analyzer/src/summary/summarize_elements.dart';
|
||||
import 'package:analyzer/src/summary2/link.dart' as summary2;
|
||||
import 'package:analyzer/src/summary2/linked_element_factory.dart' as summary2;
|
||||
import 'package:analyzer/src/summary2/reference.dart' as summary2;
|
||||
import 'package:meta/meta.dart';
|
||||
import 'package:yaml/yaml.dart';
|
||||
|
||||
/// Build summary for SDK the at the given [sdkPath].
|
||||
///
|
||||
|
@ -32,228 +18,9 @@ List<int> buildSdkSummary({
|
|||
@required String sdkPath,
|
||||
String embedderYamlPath,
|
||||
}) {
|
||||
var sdk = FolderBasedDartSdk(
|
||||
resourceProvider,
|
||||
resourceProvider.getFolder(sdkPath),
|
||||
return api.buildSdkSummary(
|
||||
resourceProvider: resourceProvider,
|
||||
sdkPath: sdkPath,
|
||||
embedderYamlPath: embedderYamlPath,
|
||||
);
|
||||
sdk.analysisOptions = AnalysisOptionsImpl();
|
||||
|
||||
// Append libraries from the embedder.
|
||||
if (embedderYamlPath != null) {
|
||||
var file = resourceProvider.getFile(embedderYamlPath);
|
||||
var content = file.readAsStringSync();
|
||||
var map = loadYaml(content) as YamlMap;
|
||||
var embedderSdk = EmbedderSdk(resourceProvider, {file.parent: map});
|
||||
for (var library in embedderSdk.sdkLibraries) {
|
||||
var uriStr = library.shortName;
|
||||
if (sdk.libraryMap.getLibrary(uriStr) == null) {
|
||||
sdk.libraryMap.setLibrary(uriStr, library);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var librarySources = sdk.sdkLibraries.map((e) {
|
||||
return sdk.mapDartUri(e.shortName);
|
||||
}).toList();
|
||||
|
||||
return _Builder(
|
||||
sdk.context,
|
||||
sdk.allowedExperimentsJson,
|
||||
librarySources,
|
||||
).build();
|
||||
}
|
||||
|
||||
@Deprecated('Use buildSdkSummary()')
|
||||
class SummaryBuilder {
|
||||
final ResourceProvider resourceProvider;
|
||||
final String sdkPath;
|
||||
|
||||
/// The list of SDK summaries, might also include Flutter libraries.
|
||||
/// Used for backward compatibility with `build_resolvers`.
|
||||
/// TODO(scheglov) Create a better API for this, and remove it.
|
||||
Iterable<Source> _librarySources;
|
||||
|
||||
/// The formal analysis context.
|
||||
/// Used for backward compatibility with `build_resolvers`.
|
||||
/// TODO(scheglov) Remove it.
|
||||
AnalysisContext _context;
|
||||
|
||||
/// Create a summary builder for these [librarySources] and [context].
|
||||
SummaryBuilder(Iterable<Source> librarySources, AnalysisContext context)
|
||||
: _librarySources = librarySources,
|
||||
_context = context,
|
||||
resourceProvider = PhysicalResourceProvider.INSTANCE,
|
||||
sdkPath = null;
|
||||
|
||||
factory SummaryBuilder.forSdk(String sdkPath) {
|
||||
return SummaryBuilder.forSdk2(
|
||||
resourceProvider: PhysicalResourceProvider.INSTANCE,
|
||||
sdkPath: sdkPath,
|
||||
);
|
||||
}
|
||||
|
||||
SummaryBuilder.forSdk2({
|
||||
@required this.resourceProvider,
|
||||
@required this.sdkPath,
|
||||
});
|
||||
|
||||
/// Build the linked bundle and return its bytes.
|
||||
List<int> build({@deprecated FeatureSet featureSet}) {
|
||||
if (_librarySources != null) {
|
||||
return _build();
|
||||
}
|
||||
|
||||
return buildSdkSummary(
|
||||
resourceProvider: resourceProvider,
|
||||
sdkPath: sdkPath,
|
||||
);
|
||||
}
|
||||
|
||||
/// The implementation that provides backward compatibility for
|
||||
/// `build_resolvers`.
|
||||
List<int> _build() {
|
||||
var dartCorePath = _librarySources
|
||||
.singleWhere((element) => '${element.uri}' == 'dart:core')
|
||||
.fullName;
|
||||
var sdkLib = resourceProvider.getFile(dartCorePath).parent.parent;
|
||||
|
||||
String allowedExperimentsJson;
|
||||
try {
|
||||
allowedExperimentsJson = sdkLib
|
||||
.getChildAssumingFolder('_internal')
|
||||
.getChildAssumingFile('allowed_experiments.json')
|
||||
.readAsStringSync();
|
||||
} catch (_) {}
|
||||
|
||||
return _Builder(
|
||||
_context,
|
||||
allowedExperimentsJson,
|
||||
_librarySources,
|
||||
).build();
|
||||
}
|
||||
}
|
||||
|
||||
class _Builder {
|
||||
final AnalysisContext context;
|
||||
final String allowedExperimentsJson;
|
||||
final Iterable<Source> librarySources;
|
||||
|
||||
final Set<String> libraryUris = <String>{};
|
||||
final List<summary2.LinkInputLibrary> inputLibraries = [];
|
||||
|
||||
AllowedExperiments allowedExperiments;
|
||||
final PackageBundleAssembler bundleAssembler = PackageBundleAssembler();
|
||||
|
||||
_Builder(
|
||||
this.context,
|
||||
this.allowedExperimentsJson,
|
||||
this.librarySources,
|
||||
) {
|
||||
allowedExperiments = _parseAllowedExperiments(allowedExperimentsJson);
|
||||
}
|
||||
|
||||
/// Build the linked bundle and return its bytes.
|
||||
List<int> build() {
|
||||
librarySources.forEach(_addLibrary);
|
||||
|
||||
var elementFactory = summary2.LinkedElementFactory(
|
||||
context,
|
||||
AnalysisSessionImpl(null),
|
||||
summary2.Reference.root(),
|
||||
);
|
||||
|
||||
var linkResult = summary2.link(elementFactory, inputLibraries);
|
||||
bundleAssembler.setBundle2(linkResult.bundle);
|
||||
|
||||
return PackageBundleBuilder(
|
||||
bundle2: linkResult.bundle,
|
||||
sdk: PackageBundleSdkBuilder(
|
||||
allowedExperimentsJson: allowedExperimentsJson,
|
||||
),
|
||||
).toBuffer();
|
||||
}
|
||||
|
||||
void _addLibrary(Source source) {
|
||||
String uriStr = source.uri.toString();
|
||||
if (!libraryUris.add(uriStr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var inputUnits = <summary2.LinkInputUnit>[];
|
||||
|
||||
CompilationUnit definingUnit = _parse(source);
|
||||
inputUnits.add(
|
||||
summary2.LinkInputUnit(null, source, false, definingUnit),
|
||||
);
|
||||
|
||||
for (Directive directive in definingUnit.directives) {
|
||||
if (directive is NamespaceDirective) {
|
||||
String libUri = directive.uri.stringValue;
|
||||
Source libSource = context.sourceFactory.resolveUri(source, libUri);
|
||||
_addLibrary(libSource);
|
||||
} else if (directive is PartDirective) {
|
||||
String partUri = directive.uri.stringValue;
|
||||
Source partSource = context.sourceFactory.resolveUri(source, partUri);
|
||||
CompilationUnit partUnit = _parse(partSource);
|
||||
inputUnits.add(
|
||||
summary2.LinkInputUnit(partUri, partSource, false, partUnit),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
inputLibraries.add(
|
||||
summary2.LinkInputLibrary(source, inputUnits),
|
||||
);
|
||||
}
|
||||
|
||||
/// Return the [FeatureSet] for the given [uri], must be a `dart:` URI.
|
||||
FeatureSet _featureSet(Uri uri) {
|
||||
if (uri.isScheme('dart')) {
|
||||
var pathSegments = uri.pathSegments;
|
||||
if (pathSegments.isNotEmpty) {
|
||||
var libraryName = pathSegments.first;
|
||||
var experiments = allowedExperiments.forSdkLibrary(libraryName);
|
||||
return FeatureSet.fromEnableFlags(experiments);
|
||||
}
|
||||
}
|
||||
throw StateError('Expected a valid dart: URI: $uri');
|
||||
}
|
||||
|
||||
CompilationUnit _parse(Source source) {
|
||||
var result = parseString(
|
||||
content: source.contents.data,
|
||||
featureSet: _featureSet(source.uri),
|
||||
throwIfDiagnostics: false,
|
||||
);
|
||||
|
||||
if (result.errors.isNotEmpty) {
|
||||
var errorsStr = result.errors.map((e) {
|
||||
var location = result.lineInfo.getLocation(e.offset);
|
||||
return '${source.fullName}:$location - ${e.message}';
|
||||
}).join('\n');
|
||||
throw StateError(
|
||||
'Unexpected diagnostics:\n$errorsStr',
|
||||
);
|
||||
}
|
||||
|
||||
var unit = result.unit as CompilationUnitImpl;
|
||||
unit.languageVersion = LibraryLanguageVersion(
|
||||
package: ExperimentStatus.currentVersion,
|
||||
override: null,
|
||||
);
|
||||
|
||||
return result.unit;
|
||||
}
|
||||
|
||||
static AllowedExperiments _parseAllowedExperiments(String content) {
|
||||
if (content == null) {
|
||||
return AllowedExperiments(
|
||||
sdkDefaultExperiments: [],
|
||||
sdkLibraryExperiments: {},
|
||||
packageExperiments: {},
|
||||
);
|
||||
}
|
||||
|
||||
return parseAllowedExperiments(content);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name: analyzer
|
||||
version: 0.39.12
|
||||
version: 0.39.13-dev
|
||||
description: This package provides a library that performs static analysis of Dart code.
|
||||
homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
|
||||
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:analyzer/dart/sdk/build_sdk_summary.dart';
|
||||
import 'package:analyzer/file_system/physical_file_system.dart';
|
||||
import 'package:analyzer/src/dart/sdk/sdk.dart';
|
||||
import 'package:analyzer/src/summary/summary_file_builder.dart';
|
||||
|
||||
void main(List<String> args) {
|
||||
String command;
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'dart:async';
|
|||
import 'dart:io' as io;
|
||||
import 'dart:isolate';
|
||||
|
||||
import 'package:analyzer/dart/sdk/build_sdk_summary.dart';
|
||||
import 'package:analyzer/error/error.dart';
|
||||
import 'package:analyzer/file_system/file_system.dart';
|
||||
import 'package:analyzer/file_system/physical_file_system.dart';
|
||||
|
@ -31,7 +32,6 @@ import 'package:analyzer/src/pubspec/pubspec_validator.dart';
|
|||
import 'package:analyzer/src/source/package_map_resolver.dart';
|
||||
import 'package:analyzer/src/source/path_filter.dart';
|
||||
import 'package:analyzer/src/summary/package_bundle_reader.dart';
|
||||
import 'package:analyzer/src/summary/summary_file_builder.dart';
|
||||
import 'package:analyzer/src/summary/summary_sdk.dart' show SummaryBasedDartSdk;
|
||||
import 'package:analyzer/src/task/options.dart';
|
||||
import 'package:analyzer/src/util/yaml.dart';
|
||||
|
|
Loading…
Reference in a new issue