mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Bumps the Dart version to 3.8 across the repo (excluding engine/src/flutter/third_party) and applies formatting updates from Dart 3.8. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [ ] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
309 lines
8.6 KiB
Dart
309 lines
8.6 KiB
Dart
// Copyright 2014 The Flutter Authors. 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:file/file.dart';
|
|
import 'package:file/memory.dart';
|
|
import 'package:path/path.dart' as path;
|
|
import 'package:pub_semver/pub_semver.dart';
|
|
import 'package:snippets/snippets.dart';
|
|
import 'package:test/test.dart' hide TypeMatcher, isInstanceOf;
|
|
|
|
import 'filesystem_resource_provider.dart';
|
|
|
|
class FakeFlutterInformation extends FlutterInformation {
|
|
FakeFlutterInformation(this.flutterRoot);
|
|
|
|
final Directory flutterRoot;
|
|
|
|
@override
|
|
Directory getFlutterRoot() {
|
|
return flutterRoot;
|
|
}
|
|
|
|
@override
|
|
Map<String, dynamic> getFlutterInformation() {
|
|
return <String, dynamic>{
|
|
'flutterRoot': flutterRoot,
|
|
'frameworkVersion': Version(2, 10, 0),
|
|
'dartSdkVersion': Version(2, 12, 1),
|
|
};
|
|
}
|
|
}
|
|
|
|
void main() {
|
|
group('Parser', () {
|
|
late MemoryFileSystem memoryFileSystem = MemoryFileSystem();
|
|
late FlutterRepoSnippetConfiguration configuration;
|
|
late SnippetGenerator generator;
|
|
late Directory tmpDir;
|
|
late Directory flutterRoot;
|
|
|
|
void writeSkeleton(String type) {
|
|
switch (type) {
|
|
case 'dartpad':
|
|
configuration.getHtmlSkeletonFile('dartpad').writeAsStringSync('''
|
|
<div>HTML Bits (DartPad-style)</div>
|
|
<iframe class="snippet-dartpad" src="https://dartpad.dev/embed-flutter.html?split=60&run=true&sample_id={{id}}&sample_channel={{channel}}"></iframe>
|
|
<div>More HTML Bits</div>
|
|
''');
|
|
case 'sample':
|
|
case 'snippet':
|
|
configuration.getHtmlSkeletonFile(type).writeAsStringSync('''
|
|
<div>HTML Bits</div>
|
|
{{description}}
|
|
<pre>{{code}}</pre>
|
|
<pre>{{app}}</pre>
|
|
<div>More HTML Bits</div>
|
|
''');
|
|
}
|
|
}
|
|
|
|
setUp(() {
|
|
// Create a new filesystem.
|
|
memoryFileSystem = MemoryFileSystem();
|
|
tmpDir = memoryFileSystem.systemTempDirectory.createTempSync('flutter_snippets_test.');
|
|
flutterRoot = memoryFileSystem.directory(path.join(tmpDir.absolute.path, 'flutter'));
|
|
configuration = FlutterRepoSnippetConfiguration(
|
|
flutterRoot: flutterRoot,
|
|
filesystem: memoryFileSystem,
|
|
);
|
|
configuration.skeletonsDirectory.createSync(recursive: true);
|
|
<String>['dartpad', 'sample', 'snippet'].forEach(writeSkeleton);
|
|
FlutterInformation.instance = FakeFlutterInformation(flutterRoot);
|
|
generator = SnippetGenerator(
|
|
configuration: configuration,
|
|
filesystem: memoryFileSystem,
|
|
flutterRoot: configuration.skeletonsDirectory.parent,
|
|
);
|
|
});
|
|
|
|
test('parses from comments', () async {
|
|
final File inputFile = _createSnippetSourceFile(tmpDir, memoryFileSystem);
|
|
final Iterable<SourceElement> elements = getFileElements(
|
|
inputFile,
|
|
resourceProvider: FileSystemResourceProvider(memoryFileSystem),
|
|
);
|
|
expect(elements, isNotEmpty);
|
|
final SnippetDartdocParser sampleParser = SnippetDartdocParser(memoryFileSystem);
|
|
sampleParser.parseFromComments(elements);
|
|
sampleParser.parseAndAddAssumptions(elements, inputFile);
|
|
expect(elements.length, equals(7));
|
|
int sampleCount = 0;
|
|
for (final SourceElement element in elements) {
|
|
expect(element.samples.length, greaterThanOrEqualTo(1));
|
|
sampleCount += element.samples.length;
|
|
final String code = generator.generateCode(element.samples.first);
|
|
expect(code, contains('// Description'));
|
|
expect(
|
|
code,
|
|
contains(
|
|
RegExp('''^String elementName = '${element.elementName}';\$''', multiLine: true),
|
|
),
|
|
);
|
|
final String html = generator.generateHtml(element.samples.first);
|
|
expect(
|
|
html,
|
|
contains(
|
|
RegExp(
|
|
'''^<pre>String elementName = '${element.elementName}';.*\$''',
|
|
multiLine: true,
|
|
),
|
|
),
|
|
);
|
|
expect(
|
|
html,
|
|
contains(
|
|
'<div class="snippet-description">{@end-inject-html}Description{@inject-html}</div>\n',
|
|
),
|
|
);
|
|
}
|
|
expect(sampleCount, equals(8));
|
|
});
|
|
test('parses dartpad samples from linked file', () async {
|
|
final File inputFile = _createDartpadSourceFile(
|
|
tmpDir,
|
|
memoryFileSystem,
|
|
flutterRoot,
|
|
linked: true,
|
|
);
|
|
final Iterable<SourceElement> elements = getFileElements(
|
|
inputFile,
|
|
resourceProvider: FileSystemResourceProvider(memoryFileSystem),
|
|
);
|
|
expect(elements, isNotEmpty);
|
|
final SnippetDartdocParser sampleParser = SnippetDartdocParser(memoryFileSystem);
|
|
sampleParser.parseFromComments(elements);
|
|
expect(elements.length, equals(1));
|
|
int sampleCount = 0;
|
|
for (final SourceElement element in elements) {
|
|
expect(element.samples.length, greaterThanOrEqualTo(1));
|
|
sampleCount += element.samples.length;
|
|
final String code = generator.generateCode(element.samples.first);
|
|
expect(code, contains('// Description'));
|
|
expect(
|
|
code,
|
|
contains(RegExp('^void ${element.name}Sample\\(\\) \\{.*\$', multiLine: true)),
|
|
);
|
|
final String html = generator.generateHtml(element.samples.first);
|
|
expect(
|
|
html,
|
|
contains(
|
|
RegExp(
|
|
'''^<iframe class="snippet-dartpad" src="https://dartpad.dev/.*sample_id=${element.name}.0.*></iframe>.*\$''',
|
|
multiLine: true,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
expect(sampleCount, equals(1));
|
|
});
|
|
test('parses assumptions', () async {
|
|
final File inputFile = _createSnippetSourceFile(tmpDir, memoryFileSystem);
|
|
final SnippetDartdocParser sampleParser = SnippetDartdocParser(memoryFileSystem);
|
|
final List<SourceLine> assumptions = sampleParser.parseAssumptions(inputFile);
|
|
expect(assumptions.length, equals(1));
|
|
expect(assumptions.first.text, equals('int integer = 3;'));
|
|
});
|
|
});
|
|
}
|
|
|
|
File _createSnippetSourceFile(Directory tmpDir, FileSystem filesystem) {
|
|
return filesystem.file(path.join(tmpDir.absolute.path, 'snippet_in.dart'))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync(r'''
|
|
// Copyright
|
|
|
|
// @dart = 2.12
|
|
|
|
import 'foo.dart';
|
|
|
|
// Examples can assume:
|
|
// int integer = 3;
|
|
|
|
/// Top level variable comment
|
|
///
|
|
/// {@tool snippet}
|
|
/// Description
|
|
/// ```dart
|
|
/// String elementName = 'topLevelVariable';
|
|
/// ```
|
|
/// {@end-tool}
|
|
int topLevelVariable = 4;
|
|
|
|
/// Top level function comment
|
|
///
|
|
/// {@tool snippet}
|
|
/// Description
|
|
/// ```dart
|
|
/// String elementName = 'topLevelFunction';
|
|
/// ```
|
|
/// {@end-tool}
|
|
int topLevelFunction() {
|
|
return integer;
|
|
}
|
|
|
|
/// Class comment
|
|
///
|
|
/// {@tool snippet}
|
|
/// Description
|
|
/// ```dart
|
|
/// String elementName = 'DocumentedClass';
|
|
/// ```
|
|
/// {@end-tool}
|
|
///
|
|
/// {@tool snippet}
|
|
/// Description2
|
|
/// ```dart
|
|
/// String elementName = 'DocumentedClass';
|
|
/// ```
|
|
/// {@end-tool}
|
|
class DocumentedClass {
|
|
/// Constructor comment
|
|
/// {@tool snippet}
|
|
/// Description
|
|
/// ```dart
|
|
/// String elementName = 'DocumentedClass';
|
|
/// ```
|
|
/// {@end-tool}
|
|
const DocumentedClass();
|
|
|
|
/// Named constructor comment
|
|
/// {@tool snippet}
|
|
/// Description
|
|
/// ```dart
|
|
/// String elementName = 'DocumentedClass.name';
|
|
/// ```
|
|
/// {@end-tool}
|
|
const DocumentedClass.name();
|
|
|
|
/// Member variable comment
|
|
/// {@tool snippet}
|
|
/// Description
|
|
/// ```dart
|
|
/// String elementName = 'DocumentedClass.intMember';
|
|
/// ```
|
|
/// {@end-tool}
|
|
int intMember;
|
|
|
|
/// Member comment
|
|
/// {@tool snippet}
|
|
/// Description
|
|
/// ```dart
|
|
/// String elementName = 'DocumentedClass.member';
|
|
/// ```
|
|
/// {@end-tool}
|
|
void member() {}
|
|
}
|
|
''');
|
|
}
|
|
|
|
File _createDartpadSourceFile(
|
|
Directory tmpDir,
|
|
FileSystem filesystem,
|
|
Directory flutterRoot, {
|
|
bool linked = false,
|
|
}) {
|
|
final File linkedFile = filesystem.file(path.join(flutterRoot.absolute.path, 'linked_file.dart'))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('''
|
|
// Copyright
|
|
|
|
import 'foo.dart';
|
|
|
|
// Description
|
|
|
|
void DocumentedClassSample() {
|
|
String elementName = 'DocumentedClass';
|
|
}
|
|
''');
|
|
|
|
final String source = linked
|
|
? '''
|
|
/// ** See code in ${path.relative(linkedFile.path, from: flutterRoot.absolute.path)} **'''
|
|
: '''
|
|
/// ```dart
|
|
/// void DocumentedClassSample() {
|
|
/// String elementName = 'DocumentedClass';
|
|
/// }
|
|
/// ```''';
|
|
|
|
return filesystem.file(path.join(tmpDir.absolute.path, 'snippet_in.dart'))
|
|
..createSync(recursive: true)
|
|
..writeAsStringSync('''
|
|
// Copyright
|
|
|
|
// @dart = 2.12
|
|
|
|
import 'foo.dart';
|
|
|
|
/// Class comment
|
|
///
|
|
/// {@tool dartpad --template=template}
|
|
/// Description
|
|
$source
|
|
/// {@end-tool}
|
|
class DocumentedClass {}
|
|
''');
|
|
}
|