Skip to content

Commit

Permalink
Macro. Apply code optimizer, update constants.
Browse files Browse the repository at this point in the history
Change-Id: I3d7958121d4b3dbdd32b5b960b55baa2632b54ad
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/352723
Reviewed-by: Brian Wilkerson <[email protected]>
Commit-Queue: Konstantin Shcheglov <[email protected]>
  • Loading branch information
scheglov authored and Commit Queue committed Feb 15, 2024
1 parent 6a5d541 commit 6b6f782
Show file tree
Hide file tree
Showing 9 changed files with 1,205 additions and 235 deletions.
71 changes: 41 additions & 30 deletions pkg/analyzer/lib/src/dart/analysis/file_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ class FileState {
///
/// This feature set is then restricted, with the [packageLanguageVersion],
/// or with a `@dart` language override token in the file header.
final FeatureSet _featureSet;
final FeatureSet featureSet;

/// The language version for the package that contains this file.
final Version packageLanguageVersion;
Expand Down Expand Up @@ -438,7 +438,7 @@ class FileState {
this.uri,
this.source,
this.workspacePackage,
this._featureSet,
this.featureSet,
this.packageLanguageVersion,
this.analysisOptions,
) : uriProperties = FileUriProperties(uri);
Expand Down Expand Up @@ -515,6 +515,41 @@ class FileState {
}
}

/// Parses given [code] with the same features as this file.
CompilationUnitImpl parseCode({
required String code,
required AnalysisErrorListener errorListener,
}) {
CharSequenceReader reader = CharSequenceReader(code);
Scanner scanner = Scanner(source, reader, errorListener)
..configureFeatures(
featureSetForOverriding: featureSet,
featureSet: featureSet.restrictToVersion(
packageLanguageVersion,
),
);
Token token = scanner.tokenize(reportScannerErrors: false);
LineInfo lineInfo = LineInfo(scanner.lineStarts);

Parser parser = Parser(
source,
errorListener,
featureSet: scanner.featureSet,
lineInfo: lineInfo,
);

var unit = parser.parseCompilationUnit(token);
unit.languageVersion = LibraryLanguageVersion(
package: packageLanguageVersion,
override: scanner.overrideVersion,
);

// Ensure the string canonicalization cache size is reasonable.
pruneStringCanonicalizationCache();

return unit;
}

/// Read the file content and ensure that all of the file properties are
/// consistent with the read content, including API signature.
///
Expand All @@ -540,7 +575,7 @@ class FileState {
{
var signature = ApiSignature();
signature.addUint32List(_fsState._saltForUnlinked);
signature.addFeatureSet(_featureSet);
signature.addFeatureSet(featureSet);
signature.addLanguageVersion(packageLanguageVersion);
signature.addString(contentHash);
signature.addBool(exists);
Expand Down Expand Up @@ -733,34 +768,10 @@ class FileState {
}

CompilationUnitImpl _parse(AnalysisErrorListener errorListener) {
CharSequenceReader reader = CharSequenceReader(content);
Scanner scanner = Scanner(source, reader, errorListener)
..configureFeatures(
featureSetForOverriding: _featureSet,
featureSet: _featureSet.restrictToVersion(
packageLanguageVersion,
),
);
Token token = scanner.tokenize(reportScannerErrors: false);
LineInfo lineInfo = LineInfo(scanner.lineStarts);

Parser parser = Parser(
source,
errorListener,
featureSet: scanner.featureSet,
lineInfo: lineInfo,
return parseCode(
code: content,
errorListener: errorListener,
);

var unit = parser.parseCompilationUnit(token);
unit.languageVersion = LibraryLanguageVersion(
package: packageLanguageVersion,
override: scanner.overrideVersion,
);

// Ensure the string canonicalization cache size is reasonable.
pruneStringCanonicalizationCache();

return unit;
}

// TODO(scheglov): write tests
Expand Down
57 changes: 54 additions & 3 deletions pkg/analyzer/lib/src/summary2/library_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:_fe_analyzer_shared/src/field_promotability.dart';
import 'package:_fe_analyzer_shared/src/macros/code_optimizer.dart' as macro;
import 'package:_fe_analyzer_shared/src/macros/executor.dart' as macro;
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/listener.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart' as file_state;
import 'package:analyzer/src/dart/analysis/file_state.dart' hide DirectiveUri;
import 'package:analyzer/src/dart/analysis/info_declaration_store.dart';
Expand All @@ -16,13 +18,15 @@ import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/dart/element/field_name_non_promotability_info.dart'
as element_model;
import 'package:analyzer/src/dart/resolver/scope.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/summary2/combinator.dart';
import 'package:analyzer/src/summary2/constructor_initializer_resolver.dart';
import 'package:analyzer/src/summary2/default_value_resolver.dart';
import 'package:analyzer/src/summary2/element_builder.dart';
import 'package:analyzer/src/summary2/export.dart';
import 'package:analyzer/src/summary2/informative_data.dart';
import 'package:analyzer/src/summary2/link.dart';
import 'package:analyzer/src/summary2/linked_element_factory.dart';
import 'package:analyzer/src/summary2/macro_application.dart';
import 'package:analyzer/src/summary2/macro_merge.dart';
import 'package:analyzer/src/summary2/metadata_resolver.dart';
Expand Down Expand Up @@ -459,13 +463,18 @@ class LibraryBuilder {
return;
}

final augmentationCode = macroApplier.buildAugmentationLibraryCode(
var augmentationCode = macroApplier.buildAugmentationLibraryCode(
_macroResults.flattenedToList2,
);
if (augmentationCode == null) {
return;
}

var mergedUnit = kind.file.parseCode(
code: augmentationCode,
errorListener: AnalysisErrorListener.NULL_LISTENER,
);

kind.disposeMacroAugmentations(disposeFiles: true);

// Remove import for partial macro augmentations.
Expand All @@ -477,8 +486,23 @@ class LibraryBuilder {
final partialUnits = units.sublist(units.length - _macroResults.length);
units.length -= _macroResults.length;

final importState = kind.addMacroAugmentation(
var optimizedCodeEdits = _CodeOptimizer(
elementFactory: linker.elementFactory,
).optimize(
augmentationCode,
libraryDeclarationNames: element.definingCompilationUnit.children
.map((e) => e.name)
.nonNulls
.toSet(),
scannerConfiguration: Scanner.buildConfig(kind.file.featureSet),
);
var optimizedCode = macro.Edit.applyList(
optimizedCodeEdits.reversed.toList(),
augmentationCode,
);

final importState = kind.addMacroAugmentation(
optimizedCode,
addLibraryAugmentDirective: true,
partialIndex: null,
);
Expand Down Expand Up @@ -521,7 +545,13 @@ class LibraryBuilder {
unitNode: unitNode,
unitElement: unitElement,
augmentation: augmentation,
).perform();
).perform(updateConstants: () {
MacroUpdateConstantsForOptimizedCode(
unitNode: mergedUnit,
codeEdits: optimizedCodeEdits,
unitElement: unitElement,
).perform();
});

// Set offsets the same way as when reading from summary.
InformativeDataApplier(
Expand Down Expand Up @@ -1216,6 +1246,27 @@ enum MacroDeclarationsPhaseStepResult {
topDeclaration,
}

class _CodeOptimizer extends macro.CodeOptimizer {
final LinkedElementFactory elementFactory;
final Map<Uri, Set<String>> exportedNames = {};

_CodeOptimizer({
required this.elementFactory,
});

@override
Set<String> getImportedNames(String uriStr) {
var uri = Uri.parse(uriStr);
var libraryElement = elementFactory.libraryOfUri(uri);
if (libraryElement != null) {
return exportedNames[uri] ??= libraryElement.exportedReferences
.map((exported) => exported.reference.name)
.toSet();
}
return const <String>{};
}
}

/// This class examines all the [InterfaceElement]s in a library and determines
/// which fields are promotable within that library.
class _FieldPromotability extends FieldPromotability<InterfaceElement,
Expand Down
Loading

0 comments on commit 6b6f782

Please sign in to comment.