b0d4ab8ef9
This was mostly a rename/move of the folder (and the analysis server updated all references), but I also had to:
- add `integration_test/analysis_options.yaml` to import from `../test` to get the same lint ignores
- update paths of exclusions in `verify_sorted_test.dart`
By moving all of the tests that start the server out-of-process out of test, we can:
1. Use "dart test" to just run the faster tests ("dart test test") and get functionality of the pkg:test runner (for example running tests concurrently and JSON output)
2. Allow VS Code to spawn different debug sessions for the "test" and "integration_test" folder, which means we can use a `preLaunchTask` to trigger compilation of the analysis server from source whenever running integration tests (avoiding having to compile manually, or run from source in a way that compiles a new server for each test suite)
Change-Id: I37cc03dc32d08c5b51a2eab79f6338bb079b32ac
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/434801
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
193 lines
5.2 KiB
Dart
193 lines
5.2 KiB
Dart
// Copyright (c) 2014, 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.
|
|
|
|
/// Code generation for the file "matchers.dart".
|
|
library;
|
|
|
|
import 'package:analyzer_utilities/tools.dart';
|
|
|
|
import 'api.dart';
|
|
import 'from_html.dart';
|
|
import 'implied_types.dart';
|
|
import 'to_html.dart';
|
|
|
|
final GeneratedFile target = GeneratedFile(
|
|
'integration_test/support/protocol_matchers.dart',
|
|
(String pkgPath) async {
|
|
var visitor = CodegenMatchersVisitor(readApi(pkgPath));
|
|
return visitor.collectCode(visitor.visitApi);
|
|
},
|
|
);
|
|
|
|
class CodegenMatchersVisitor extends HierarchicalApiVisitor with CodeGenerator {
|
|
/// Visitor used to produce doc comments.
|
|
final ToHtmlVisitor toHtmlVisitor;
|
|
|
|
/// Short human-readable string describing the context of the matcher being
|
|
/// created.
|
|
late String context;
|
|
|
|
CodegenMatchersVisitor(super.api) : toHtmlVisitor = ToHtmlVisitor(api) {
|
|
codeGeneratorSettings.commentLineLength = 79;
|
|
codeGeneratorSettings.docCommentStartMarker = null;
|
|
codeGeneratorSettings.docCommentLineLeader = '/// ';
|
|
codeGeneratorSettings.docCommentEndMarker = null;
|
|
codeGeneratorSettings.languageName = 'dart';
|
|
}
|
|
|
|
/// Create a matcher for the part of the API called [name], optionally
|
|
/// clarified by [nameSuffix]. The matcher should verify that its input
|
|
/// matches the given [type].
|
|
void makeMatcher(ImpliedType impliedType) {
|
|
context = impliedType.humanReadableName;
|
|
var impliedTypeType = impliedType.type;
|
|
docComment(
|
|
toHtmlVisitor.collectHtml(() {
|
|
toHtmlVisitor.p(() {
|
|
toHtmlVisitor.write(context);
|
|
});
|
|
if (impliedTypeType != null) {
|
|
toHtmlVisitor.showType(null, impliedTypeType);
|
|
}
|
|
}),
|
|
);
|
|
write('final Matcher ${camelJoin(['is', impliedType.camelName])} = ');
|
|
if (impliedTypeType == null) {
|
|
write('isNull');
|
|
} else {
|
|
visitTypeDecl(impliedTypeType);
|
|
}
|
|
writeln(';');
|
|
writeln();
|
|
}
|
|
|
|
/// Generate a map describing the given set of fields, for use as the
|
|
/// 'requiredFields' or 'optionalFields' argument to the [MatchesJsonObject]
|
|
/// constructor.
|
|
void outputObjectFields(Iterable<TypeObjectField> fields) {
|
|
if (fields.isEmpty) {
|
|
write('null');
|
|
return;
|
|
}
|
|
writeln('{');
|
|
indent(() {
|
|
var commaNeeded = false;
|
|
for (var field in fields) {
|
|
if (commaNeeded) {
|
|
writeln(',');
|
|
}
|
|
write("'${field.name}': ");
|
|
if (field.value != null) {
|
|
write("equals('${field.value}')");
|
|
} else {
|
|
visitTypeDecl(field.type);
|
|
}
|
|
commaNeeded = true;
|
|
}
|
|
writeln();
|
|
});
|
|
write('}');
|
|
}
|
|
|
|
@override
|
|
void visitApi() {
|
|
outputHeader(year: '2017');
|
|
writeln();
|
|
writeln('/// Matchers for data types defined in the analysis server API.');
|
|
writeln('library;');
|
|
writeln();
|
|
writeln("import 'package:test/test.dart';");
|
|
writeln();
|
|
writeln("import 'integration_tests.dart';");
|
|
writeln();
|
|
writeln('// ignore_for_file: flutter_style_todos');
|
|
writeln();
|
|
var impliedTypes = computeImpliedTypes(api).values.toList();
|
|
impliedTypes.sort(
|
|
(ImpliedType first, ImpliedType second) =>
|
|
first.camelName.compareTo(second.camelName),
|
|
);
|
|
for (var impliedType in impliedTypes) {
|
|
makeMatcher(impliedType);
|
|
}
|
|
}
|
|
|
|
@override
|
|
void visitTypeEnum(TypeEnum typeEnum) {
|
|
writeln("MatchesEnum('$context', [");
|
|
indent(() {
|
|
var commaNeeded = false;
|
|
for (var value in typeEnum.values) {
|
|
if (commaNeeded) {
|
|
writeln(',');
|
|
}
|
|
write("'${value.value}'");
|
|
commaNeeded = true;
|
|
}
|
|
writeln();
|
|
});
|
|
write('])');
|
|
}
|
|
|
|
@override
|
|
void visitTypeList(TypeList typeList) {
|
|
write('isListOf(');
|
|
visitTypeDecl(typeList.itemType);
|
|
write(')');
|
|
}
|
|
|
|
@override
|
|
void visitTypeMap(TypeMap typeMap) {
|
|
write('isMapOf(');
|
|
visitTypeDecl(typeMap.keyType);
|
|
write(', ');
|
|
visitTypeDecl(typeMap.valueType);
|
|
write(')');
|
|
}
|
|
|
|
@override
|
|
void visitTypeObject(TypeObject typeObject) {
|
|
writeln('LazyMatcher(() => MatchesJsonObject(');
|
|
indent(() {
|
|
write("'$context', ");
|
|
var requiredFields = typeObject.fields.where(
|
|
(TypeObjectField field) => !field.optional,
|
|
);
|
|
outputObjectFields(requiredFields);
|
|
var optionalFields =
|
|
typeObject.fields
|
|
.where((TypeObjectField field) => field.optional)
|
|
.toList();
|
|
if (optionalFields.isNotEmpty) {
|
|
write(', optionalFields: ');
|
|
outputObjectFields(optionalFields);
|
|
}
|
|
});
|
|
write('))');
|
|
}
|
|
|
|
@override
|
|
void visitTypeReference(TypeReference typeReference) {
|
|
var typeName = typeReference.typeName;
|
|
if (typeName == 'long') {
|
|
typeName = 'int';
|
|
}
|
|
write(camelJoin(['is', typeName]));
|
|
}
|
|
|
|
@override
|
|
void visitTypeUnion(TypeUnion typeUnion) {
|
|
var commaNeeded = false;
|
|
write('isOneOf([');
|
|
for (var choice in typeUnion.choices) {
|
|
if (commaNeeded) {
|
|
write(', ');
|
|
}
|
|
visitTypeDecl(choice);
|
|
commaNeeded = true;
|
|
}
|
|
write('])');
|
|
}
|
|
}
|