d7f200b97d
(Part of https://github.com/dart-lang/sdk/issues/63288) This change migrates the kernel package to use the new constructor declaration syntax, described in https://github.com/dart-lang/language/blob/main/accepted/future-releases/primary-constructors/feature-specification.md#abbreviations-of-in-body-constructor-declarations. This change was performed in an automated fashion, by (a) bumping the package's SDK constraint to `3.13.0-0`, (b) enabling the lints `unnecessary_type_name_in_constructor` and `unnecessary_const_in_enum_constructor`, (c) fixing the resulting lint failures using `dart fix`, and then (d) reformatting the affected files. To ease code review, I've reverted unrelated formatting changes. Change-Id: I8d32a0b26450a44dfa2ebd9fe2dff9df6a6a6964 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/508426 Reviewed-by: Konstantin Shcheglov <scheglov@google.com> Commit-Queue: Paul Berry <paulberry@google.com>
183 lines
5.4 KiB
Dart
183 lines
5.4 KiB
Dart
#!/usr/bin/env dart
|
|
// Copyright (c) 2022, 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:io';
|
|
|
|
import 'package:kernel/class_hierarchy.dart';
|
|
import 'package:kernel/core_types.dart';
|
|
import 'package:kernel/kernel.dart';
|
|
import 'package:kernel/src/tool/command_line_util.dart';
|
|
|
|
void usage() {
|
|
print("Compares the hierarchies of two dill files.");
|
|
print("");
|
|
print(
|
|
"Usage: dart <script> dillFile1.dill dillFile2.dill "
|
|
"[import:uri#classToIgnore|another:uri#andClassToIgnore]",
|
|
);
|
|
exit(1);
|
|
}
|
|
|
|
void main(List<String> args) {
|
|
CommandLineHelper.requireVariableArgumentCount([2, 3], args, usage);
|
|
CommandLineHelper.requireFileExists(args[0]);
|
|
CommandLineHelper.requireFileExists(args[1]);
|
|
Component binary1 = CommandLineHelper.tryLoadDill(args[0]);
|
|
Component binary2 = CommandLineHelper.tryLoadDill(args[1]);
|
|
Map<Uri, Set<String>> ignoresMap = {};
|
|
if (args.length >= 3) {
|
|
List<String> ignores = args[2].split("|");
|
|
for (String ignore in ignores) {
|
|
List<String> uriClassName = ignore.split("#");
|
|
if (uriClassName.length != 2) {
|
|
print(
|
|
"Ignoring '$ignore' as it doesn't conform to "
|
|
"'importUri#className'",
|
|
);
|
|
continue;
|
|
}
|
|
Uri uri = Uri.parse(uriClassName[0]);
|
|
String className = uriClassName[1];
|
|
(ignoresMap[uri] ??= {}).add(className);
|
|
}
|
|
}
|
|
|
|
print("(1): ${args[0]}");
|
|
print("(2): ${args[1]}");
|
|
print("");
|
|
|
|
ClosedWorldClassHierarchy ch1 =
|
|
new ClassHierarchy(binary1, new CoreTypes(binary1))
|
|
as ClosedWorldClassHierarchy;
|
|
ClosedWorldClassHierarchy ch2 =
|
|
new ClassHierarchy(binary2, new CoreTypes(binary2))
|
|
as ClosedWorldClassHierarchy;
|
|
|
|
Map<Uri, Library> libMap1 = createLibMap(binary1);
|
|
Map<Uri, Library> libMap2 = createLibMap(binary2);
|
|
Set<Uri> agreeingImportUris = new Set<Uri>.from(libMap1.keys)
|
|
..retainAll(libMap2.keys);
|
|
|
|
for (Uri uri in agreeingImportUris) {
|
|
Library lib1 = libMap1[uri]!;
|
|
Library lib2 = libMap2[uri]!;
|
|
Map<String, Class> libClass1 = createPublicClassMap(
|
|
lib1,
|
|
ignored: ignoresMap[uri],
|
|
);
|
|
Map<String, Class> libClass2 = createPublicClassMap(
|
|
lib2,
|
|
ignored: ignoresMap[uri],
|
|
);
|
|
Set<String> agreeingClasses = new Set<String>.from(libClass1.keys)
|
|
..retainAll(libClass2.keys);
|
|
if (agreeingClasses.length != libClass1.length ||
|
|
libClass1.length != libClass2.length) {
|
|
print("Missing classes in lib $uri");
|
|
Set<String> missing = new Set<String>.from(libClass1.keys)
|
|
..removeAll(libClass2.keys);
|
|
if (missing.isNotEmpty) {
|
|
print("In (1) but not in (2): ${missing.toList()}");
|
|
}
|
|
missing = new Set<String>.from(libClass2.keys)..removeAll(libClass1.keys);
|
|
if (missing.isNotEmpty) {
|
|
print("In (2) but not in (1): ${missing.toList()}");
|
|
}
|
|
print("");
|
|
}
|
|
|
|
for (String className in agreeingClasses) {
|
|
Class c1 = libClass1[className]!;
|
|
Class c2 = libClass2[className]!;
|
|
Set<ClassReference> c1Supertypes = createClassReferenceSet(
|
|
ch1.getAllSupertypeClassesForTesting(c1),
|
|
onlyPublic: true,
|
|
ignoresMap: ignoresMap,
|
|
);
|
|
Set<ClassReference> c2Supertypes = createClassReferenceSet(
|
|
ch2.getAllSupertypeClassesForTesting(c2),
|
|
onlyPublic: true,
|
|
ignoresMap: ignoresMap,
|
|
);
|
|
Set<ClassReference> missing = new Set<ClassReference>.from(c1Supertypes)
|
|
..removeAll(c2Supertypes);
|
|
if (missing.isNotEmpty) {
|
|
print(
|
|
"$c1 in $lib1 from (1) has these extra supertypes: "
|
|
"${missing.toList()}",
|
|
);
|
|
}
|
|
missing = new Set<ClassReference>.from(c2Supertypes)
|
|
..removeAll(c1Supertypes);
|
|
if (missing.isNotEmpty) {
|
|
print(
|
|
"$c2 in $lib2 from (2) has these extra supertypes: "
|
|
"${missing.toList()}",
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
Map<Uri, Library> createLibMap(Component c) {
|
|
Map<Uri, Library> map = {};
|
|
for (Library lib in c.libraries) {
|
|
map[lib.importUri] = lib;
|
|
}
|
|
return map;
|
|
}
|
|
|
|
Map<String, Class> createPublicClassMap(
|
|
Library lib, {
|
|
required Set<String>? ignored,
|
|
}) {
|
|
Map<String, Class> map = {};
|
|
for (Class c in lib.classes) {
|
|
if (c.name.startsWith("_")) continue;
|
|
if (ignored?.contains(c.name) ?? false) continue;
|
|
map[c.name] = c;
|
|
}
|
|
return map;
|
|
}
|
|
|
|
Set<ClassReference> createClassReferenceSet(
|
|
List<Class> classes, {
|
|
required bool onlyPublic,
|
|
required Map<Uri, Set<String>> ignoresMap,
|
|
}) {
|
|
Set<ClassReference> result = {};
|
|
for (Class c in classes) {
|
|
if (onlyPublic && c.name.startsWith("_")) continue;
|
|
Set<String>? ignored = ignoresMap[c.enclosingLibrary.importUri];
|
|
if (ignored?.contains(c.name) ?? false) continue;
|
|
result.add(new ClassReference(c.name, c.enclosingLibrary.importUri));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
class ClassReference {
|
|
final String name;
|
|
final Uri libImportUri;
|
|
|
|
const new(this.name, this.libImportUri);
|
|
|
|
@override
|
|
int get hashCode => name.hashCode * 13 + libImportUri.hashCode * 17;
|
|
|
|
@override
|
|
bool operator ==(Object other) {
|
|
if (identical(this, other)) return true;
|
|
if (other is! ClassReference) return false;
|
|
if (name != other.name) return false;
|
|
if (libImportUri != other.libImportUri) return false;
|
|
return true;
|
|
}
|
|
|
|
@override
|
|
String toString() {
|
|
return "$name ($libImportUri)";
|
|
}
|
|
}
|