diff --git a/packages/_you_dart_internal/lib/analyzer.dart b/packages/_you_dart_internal/lib/analyzer.dart index 3b7c362c..7836365e 100644 --- a/packages/_you_dart_internal/lib/analyzer.dart +++ b/packages/_you_dart_internal/lib/analyzer.dart @@ -1,2 +1,3 @@ export 'package:_you_dart_internal/src/analyzer.dart' show CompilationUnitReader, AnnotationReader; +export 'package:_you_dart_internal/src/analyzer.dart' show MemoryFsAnalyzer; export 'package:_you_dart_internal/src/pubspec.dart' show Pubspec; diff --git a/packages/_you_dart_internal/lib/src/analyzer.dart b/packages/_you_dart_internal/lib/src/analyzer.dart index 90d77d83..c4840ff4 100644 --- a/packages/_you_dart_internal/lib/src/analyzer.dart +++ b/packages/_you_dart_internal/lib/src/analyzer.dart @@ -1,22 +1,88 @@ /// 本包与应用逻辑无关的common analyzer逻辑 library; +import 'package:analyzer/dart/analysis/analysis_context_collection.dart'; import 'package:analyzer/dart/analysis/results.dart'; import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/constant/value.dart'; import 'package:analyzer/dart/element/element.dart'; import 'package:analyzer/dart/element/type.dart'; +import 'package:analyzer/file_system/file_system.dart' as file_system; +import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:code_builder/code_builder.dart'; -import 'package:file/file.dart'; -import 'package:path/path.dart' as path; + +import 'package:path/path.dart' as path_; + +// ignore: implementation_imports, there is no other way i don t want to copy it . +import 'package:analyzer/src/test_utilities/mock_sdk.dart'; + +/// 实验mock sdk 看能否用element模式而不是ast,未成功暂放 +class MemoryFsAnalyzer { + MemoryFsAnalyzer() { + _ensureFile("/pkg/pubspec.yaml", ''' +name: mock_lib +version: 0.1.0 + +environment: + sdk: '>=3.4.0 <4.0.0' +'''); + + file_system.File initLibFile = _ensureFile("/pkg/lib/__init__.dart", """ +var v="first file use by create session"; +"""); + ; + + String sdkPath = '/sdk'; + createMockSdk( + resourceProvider: _resourceProvider, + root: _ensureFolder(sdkPath), + ); + + var collection = AnalysisContextCollection( + includedPaths: [initLibFile.path], + resourceProvider: _resourceProvider, + sdkPath: sdkPath, + ); + session = collection.contexts[0].currentSession; + } + + final MemoryResourceProvider _resourceProvider = MemoryResourceProvider(); + late final AnalysisSession session; + /// 测试页即简单的测试:500次 7s + Future getResolvedLibrary({required String path, required String content}) async { + var file = _ensureFile(path_.absolute(path), content); + return CompilationUnitReader.resolve(session, file.path); + } + + static Iterable toList(file_system.Resource resource) sync* { + if (resource is file_system.File) { + yield resource; + } + if (resource is file_system.Folder) { + for (var x in resource.getChildren()) { + yield* toList(x); + } + } + } + + file_system.Folder _ensureFolder(String path) { + String convertedPath = _resourceProvider.convertPath(path); + return _resourceProvider.getFolder(convertedPath)..create(); + } + + file_system.File _ensureFile(String path, String content) { + String convertedPath = _resourceProvider.convertPath(path); + return _resourceProvider.getFile(convertedPath)..writeAsStringSync(content); + } +} class CompilationUnitReader { CompilationUnitReader(this.unit); - static Future resolve(AnalysisSession analysisSession, File file) async { - assert(await file.exists(), "file:$file"); - var result = (await analysisSession.getResolvedUnit(path.normalize(path.absolute(file.path))) as ResolvedUnitResult); + static Future resolve(AnalysisSession analysisSession, String file) async { + var result = (await analysisSession.getResolvedUnit(path_.normalize(path_.absolute(file))) as ResolvedUnitResult); + assert(result.errors.isEmpty, "expect no error, but:${result.errors}"); return CompilationUnitReader(result.unit); } @@ -48,7 +114,7 @@ class CompilationUnitReader { if (t == null) continue; if (t is! InterfaceType) continue; - var findAnnoType = [t, ...t.allSupertypes].where((e) => e.getDisplayString(withNullability:true) == annoType).firstOrNull; + var findAnnoType = [t, ...t.allSupertypes].where((e) => e.getDisplayString(withNullability: true) == annoType).firstOrNull; if (findAnnoType == null) continue; if (annoUrl != null) { var publicExportFrom = findPublicExportLib(findAnnoType, library); @@ -104,13 +170,12 @@ class AnnotationReader { Reference? getFieldTypeAsRef(String name) { var type = getField(name)?.toTypeValue(); if (type == null) return null; - var symbol = type.getDisplayString(withNullability:true); + var symbol = type.getDisplayString(withNullability: true); if (symbol == "") return null; var publicExportFrom = findPublicExportLib(type, unit.library); var url = publicExportFrom?.identifier; return refer(symbol, url); } - } /// given a internal lib: package:you_flutter/src/router.dart diff --git a/packages/you_cli/lib/src/cli_core.dart b/packages/you_cli/lib/src/cli_core.dart index dd2baecb..e8666d09 100644 --- a/packages/you_cli/lib/src/cli_core.dart +++ b/packages/you_cli/lib/src/cli_core.dart @@ -72,7 +72,7 @@ class YouCli { return null; } - CompilationUnitReader unit = await CompilationUnitReader.resolve(analysisSession, file); + CompilationUnitReader unit = await CompilationUnitReader.resolve(analysisSession, file.path); return unit.topFunction(layoutFunctionName); } @@ -80,7 +80,7 @@ class YouCli { if (!await file.exists()) { return null; } - CompilationUnitReader unit = await CompilationUnitReader.resolve(analysisSession, file); + CompilationUnitReader unit = await CompilationUnitReader.resolve(analysisSession, file.path); return unit.topFunction(pageFunctionName); } @@ -88,7 +88,7 @@ class YouCli { if (!await file.exists()) { return null; } - CompilationUnitReader unit = await CompilationUnitReader.resolve(analysisSession, file); + CompilationUnitReader unit = await CompilationUnitReader.resolve(analysisSession, file.path); return PageAnnotation.find(unit); } } diff --git a/packages/you_cli/pubspec.yaml b/packages/you_cli/pubspec.yaml index 9803f307..0af7bb31 100644 --- a/packages/you_cli/pubspec.yaml +++ b/packages/you_cli/pubspec.yaml @@ -26,6 +26,7 @@ dependencies: # you_* you_dart: ^0.0.6-dev.3 + _you_dart_internal: ^0.0.6-dev.3 dev_dependencies: lints: ^3.0.0 test: diff --git a/packages/you_cli/test/src/analyzer_test.dart b/packages/you_cli/test/src/analyzer_test.dart index 1305bfc9..bad437f7 100644 --- a/packages/you_cli/test/src/analyzer_test.dart +++ b/packages/you_cli/test/src/analyzer_test.dart @@ -11,11 +11,11 @@ void main() { File notePage = fs.file("../../notes/flutter_web/lib/routes/notes/page.dart"); group("AnalyzedUnit element", () { test('class_', () async { - var result = await CompilationUnitReader.resolve(cli.analysisSession, fs.file("lib/src/cli_core.dart")); + var result = await CompilationUnitReader.resolve(cli.analysisSession, "lib/src/cli_core.dart"); check(result.class_("YouCli")!.displayName).equals("YouCli"); }); test('annotation', () async { - var result = await CompilationUnitReader.resolve(cli.analysisSession, notePage); + var result = await CompilationUnitReader.resolve(cli.analysisSession, notePage.path); var pageMeta = result.annotationOnTopFunction(funcName: "build", annoType: "PageAnnotation")!; check(pageMeta.ast.toSource()).equals('@NoteAnnotation(label: "笔记")'); }); diff --git a/packages/you_flutter/lib/src/note/source_code.dart b/packages/you_flutter/lib/src/note/source_code.dart index 85518463..01c06f8d 100644 --- a/packages/you_flutter/lib/src/note/source_code.dart +++ b/packages/you_flutter/lib/src/note/source_code.dart @@ -1,20 +1,12 @@ import 'package:_you_dart_internal/utils.dart'; -import 'package:analyzer/dart/analysis/analysis_context_collection.dart'; import 'package:analyzer/dart/analysis/features.dart'; -import 'package:analyzer/dart/analysis/results.dart'; -import 'package:analyzer/dart/analysis/session.dart'; import 'package:analyzer/dart/analysis/utilities.dart'; import 'package:analyzer/dart/ast/ast.dart'; import 'package:analyzer/dart/ast/visitor.dart'; -import 'package:analyzer/file_system/file_system.dart'; -import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:flutter/foundation.dart'; import 'package:http/http.dart' as http; import 'package:meta/meta.dart'; -import 'package:path/path.dart' as path_; -// ignore: implementation_imports, there is no other way i don t want to copy it . -import 'package:analyzer/src/test_utilities/mock_sdk.dart'; import 'package:source_map_stack_trace/source_map_stack_trace.dart'; import 'package:stack_trace/stack_trace.dart'; import 'package:path/path.dart' as path; @@ -127,89 +119,6 @@ class _CodeVisitor extends GeneralizingAstVisitor { } } -/// 实验mock sdk 看能否用element模式而不是ast,未成功暂放 -@internal -class MemoryCodeAnalyzer { - @visibleForTesting - final resourceProvider = MemoryResourceProvider(); - late final AnalysisSession session; - final ({String path, String content}) _defaultInitLib = ( - path: "/pkg/lib/note.dart", - content: """ -class Cell{ - void call(Object? content) {} - Cell addCell() => Cell(); - Cell addCellWith() => Cell(); -} - """ - ); - - MemoryCodeAnalyzer() { - var libs = [_defaultInitLib]; - for (var lib in libs) { - _newFile(lib.path, lib.content); - } - _newFile("/pkg/pubspec.yaml", ''' -name: mock_lib -version: 0.1.0 - -environment: - sdk: '>=3.4.0 <4.0.0' -'''); - - String sdkPath = '/sdk'; - createMockSdk( - resourceProvider: resourceProvider, - root: _newFolder(sdkPath), - ); - - var collection = AnalysisContextCollection( - includedPaths: libs.map((e) => e.path).toList(), - resourceProvider: resourceProvider, - sdkPath: sdkPath, - ); - session = collection.contexts[0].currentSession; - } - - Future getResolvedLibrary({required String path, required String content}) async { - var file = _newFile(resourceProvider.convertPath(path_.absolute(path)), content); - return session.getResolvedLibrary(file.path) as ResolvedLibraryResult; - } - - SomeParsedUnitResult getParsedUnit({required String path, required String content}) { - var file = _newFile(resourceProvider.convertPath(path_.absolute(path)), content); - return session.getParsedUnit(file.path); - } - - /// 测试页即简单的测试:500次 7s - Future getResolvedUnit({required String path, required String content}) async { - var file = _newFile(resourceProvider.convertPath(path_.absolute(path)), content); - var result= await session.getResolvedUnit(file.path); - return result as ResolvedUnitResult; - } - - static Iterable toList(Resource resource) sync* { - if (resource is File) { - yield resource; - } - if (resource is Folder) { - for (var x in resource.getChildren()) { - yield* toList(x); - } - } - } - - Folder _newFolder(String path) { - String convertedPath = resourceProvider.convertPath(path); - return resourceProvider.getFolder(convertedPath)..create(); - } - - File _newFile(String path, String content) { - String convertedPath = resourceProvider.convertPath(path); - return resourceProvider.getFile(convertedPath)..writeAsStringSync(content); - } -} - class CellCallerResult { final StackTrace originTrace; final StackTrace dartTrace; diff --git a/packages/you_flutter/test/src/note/note_code_benchmark.dart b/packages/you_flutter/test/src/note/note_code_benchmark.dart index ed6507cf..e0e90394 100644 --- a/packages/you_flutter/test/src/note/note_code_benchmark.dart +++ b/packages/you_flutter/test/src/note/note_code_benchmark.dart @@ -1,12 +1,12 @@ +import 'package:_you_dart_internal/analyzer.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:you_flutter/src/note/source_code.dart'; void main() { group("CodeAnalyzer", () { test('resolve', () async { - MemoryCodeAnalyzer analyzer = MemoryCodeAnalyzer(); + MemoryFsAnalyzer analyzer = MemoryFsAnalyzer(); for (int i = 0; i < 500; i++) { - var resolveUnitResult = await analyzer.getResolvedUnit(path: "/pkg/lib/routes/notes/page.dart", content: ''' + var resolveUnitResult = await analyzer.getResolvedLibrary(path: "/pkg/lib/routes/notes/page.dart", content: ''' import 'package:flutter/widgets.dart'; import 'package:you_flutter/note.dart'; diff --git a/packages/you_flutter/test/src/note/note_code_test.dart b/packages/you_flutter/test/src/note/note_code_test.dart index 4acc0a27..9689a721 100644 --- a/packages/you_flutter/test/src/note/note_code_test.dart +++ b/packages/you_flutter/test/src/note/note_code_test.dart @@ -1,3 +1,4 @@ +import 'package:_you_dart_internal/analyzer.dart'; import 'package:checks/checks.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:you_flutter/src/note/source_code.dart'; @@ -51,8 +52,8 @@ class TextExamples { group("CodeAnalyzer", () { test('resolve', () async { - MemoryCodeAnalyzer analyzer = MemoryCodeAnalyzer(); - var resolveUnitResult = await analyzer.getResolvedUnit(path: "/pkg/lib/routes/notes/page.dart", content: ''' + MemoryFsAnalyzer analyzer = MemoryFsAnalyzer(); + var r = await analyzer.getResolvedLibrary(path: "/pkg/lib/routes/notes/page.dart", content: ''' import 'package:flutter/widgets.dart'; import 'package:you_flutter/note.dart'; @@ -67,7 +68,7 @@ class TextExamples { } } '''); - check(resolveUnitResult); + check(r.unit).isNotNull(); }); }); }