|  | // Copyright (c) 2018, 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. | 
|  |  | 
|  | /// @docImport 'package:analyzer/dart/analysis/session.dart'; | 
|  | library; | 
|  |  | 
|  | import 'package:analyzer/dart/analysis/analysis_context.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/element/element.dart'; | 
|  | import 'package:analyzer/error/listener.dart'; | 
|  | import 'package:analyzer/file_system/file_system.dart'; | 
|  | import 'package:analyzer/file_system/physical_file_system.dart'; | 
|  | import 'package:analyzer/source/line_info.dart'; | 
|  | import 'package:analyzer/src/dart/analysis/experiments.dart'; | 
|  | import 'package:analyzer/src/dart/analysis/results.dart'; | 
|  | import 'package:analyzer/src/dart/scanner/reader.dart'; | 
|  | import 'package:analyzer/src/dart/scanner/scanner.dart'; | 
|  | import 'package:analyzer/src/generated/parser.dart'; | 
|  | import 'package:analyzer/src/string_source.dart'; | 
|  |  | 
|  | /// Return the result of parsing the file at the given [path]. | 
|  | /// | 
|  | /// If a [resourceProvider] is given, it will be used to access the file system. | 
|  | /// | 
|  | /// [featureSet] determines what set of features will be assumed by the parser. | 
|  | /// This parameter is required because the analyzer does not yet have a | 
|  | /// performant way of computing the correct feature set for a single file to be | 
|  | /// parsed.  Callers that need the feature set to be strictly correct must | 
|  | /// create an [AnalysisContextCollection], query it to get an [AnalysisContext], | 
|  | /// query it to get an [AnalysisSession], and then call `getParsedUnit`. | 
|  | /// | 
|  | /// Callers that don't need the feature set to be strictly correct can pass in | 
|  | /// `FeatureSet.latestLanguageVersion()` to enable the default set of features; | 
|  | /// this is much more performant than using an analysis session, because it | 
|  | /// doesn't require the analyzer to process the SDK. | 
|  | /// | 
|  | /// If [throwIfDiagnostics] is `true` (the default), then if any diagnostics are | 
|  | /// produced because of syntactic errors in the file an `ArgumentError` will be | 
|  | /// thrown. If the parameter is `false`, then the caller can check the result | 
|  | /// to see whether there are any errors. | 
|  | ParseStringResult parseFile({ | 
|  | required String path, | 
|  | ResourceProvider? resourceProvider, | 
|  | required FeatureSet featureSet, | 
|  | bool throwIfDiagnostics = true, | 
|  | }) { | 
|  | resourceProvider ??= PhysicalResourceProvider.INSTANCE; | 
|  | var content = (resourceProvider.getResource(path) as File).readAsStringSync(); | 
|  | return parseString( | 
|  | content: content, | 
|  | path: path, | 
|  | featureSet: featureSet, | 
|  | throwIfDiagnostics: throwIfDiagnostics, | 
|  | ); | 
|  | } | 
|  |  | 
|  | /// Returns the result of parsing the given [content] as a compilation unit. | 
|  | /// | 
|  | /// If a [featureSet] is provided, it will be the default set of features that | 
|  | /// will be assumed by the parser. | 
|  | /// | 
|  | /// If a [path] is provided, it will be used as the name of the file when | 
|  | /// reporting errors. | 
|  | /// | 
|  | /// If [throwIfDiagnostics] is `true` (the default), then if any diagnostics are | 
|  | /// produced because of syntactic errors in the [content] an `ArgumentError` | 
|  | /// will be thrown.  This behavior is not intended as a way for the client to | 
|  | /// find out about errors--it is intended to avoid causing problems for naive | 
|  | /// clients that might not be thinking about the possibility of parse errors | 
|  | /// (and might therefore make assumptions about the returned AST that don't hold | 
|  | /// in the presence of parse errors).  Clients interested in details about parse | 
|  | /// errors should pass `false` and check `result.errors` to determine what parse | 
|  | /// errors, if any, have occurred. | 
|  | ParseStringResult parseString({ | 
|  | required String content, | 
|  | FeatureSet? featureSet, | 
|  | String? path, | 
|  | bool throwIfDiagnostics = true, | 
|  | }) { | 
|  | featureSet ??= FeatureSet.latestLanguageVersion(); | 
|  | var source = StringSource(content, path ?? ''); | 
|  | var reader = CharSequenceReader(content); | 
|  | var diagnosticCollector = RecordingDiagnosticListener(); | 
|  | var scanner = Scanner(source, reader, diagnosticCollector) | 
|  | ..configureFeatures( | 
|  | featureSetForOverriding: featureSet, | 
|  | featureSet: featureSet, | 
|  | ); | 
|  | var token = scanner.tokenize(); | 
|  | var languageVersion = LibraryLanguageVersion( | 
|  | package: ExperimentStatus.currentVersion, | 
|  | override: scanner.overrideVersion, | 
|  | ); | 
|  | var lineInfo = LineInfo(scanner.lineStarts); | 
|  | var parser = Parser( | 
|  | source, | 
|  | diagnosticCollector, | 
|  | featureSet: scanner.featureSet, | 
|  | languageVersion: languageVersion, | 
|  | lineInfo: lineInfo, | 
|  | ); | 
|  | var unit = parser.parseCompilationUnit(token); | 
|  | ParseStringResult result = ParseStringResultImpl( | 
|  | content, | 
|  | unit, | 
|  | diagnosticCollector.diagnostics, | 
|  | ); | 
|  | if (throwIfDiagnostics && result.errors.isNotEmpty) { | 
|  | var buffer = StringBuffer(); | 
|  | for (var error in result.errors) { | 
|  | var location = lineInfo.getLocation(error.offset); | 
|  | buffer.writeln( | 
|  | '  ${error.diagnosticCode.name}: ${error.message} - ' | 
|  | '${location.lineNumber}:${location.columnNumber}', | 
|  | ); | 
|  | } | 
|  | throw ArgumentError('Content produced diagnostics when parsed:\n$buffer'); | 
|  | } | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /// Return the result of resolving the file at the given [path]. | 
|  | /// | 
|  | /// If a [resourceProvider] is given, it will be used to access the file system. | 
|  | /// | 
|  | /// Note that if more than one file is going to be resolved then this function | 
|  | /// is inefficient. Clients should instead use [AnalysisContextCollection] to | 
|  | /// create one or more contexts and use those contexts to resolve the files. | 
|  | Future<SomeResolvedUnitResult> resolveFile({ | 
|  | required String path, | 
|  | ResourceProvider? resourceProvider, | 
|  | }) async { | 
|  | AnalysisContext context = _createAnalysisContext( | 
|  | path: path, | 
|  | resourceProvider: resourceProvider, | 
|  | ); | 
|  | return await context.currentSession.getResolvedUnit(path); | 
|  | } | 
|  |  | 
|  | /// Return the result of resolving the file at the given [path]. | 
|  | /// | 
|  | /// If a [resourceProvider] is given, it will be used to access the file system. | 
|  | /// | 
|  | /// Note that if more than one file is going to be resolved then this function | 
|  | /// is inefficient. Clients should instead use [AnalysisContextCollection] to | 
|  | /// create one or more contexts and use those contexts to resolve the files. | 
|  | @Deprecated('Use resolveFile instead') | 
|  | Future<SomeResolvedUnitResult> resolveFile2({ | 
|  | required String path, | 
|  | ResourceProvider? resourceProvider, | 
|  | }) async { | 
|  | AnalysisContext context = _createAnalysisContext( | 
|  | path: path, | 
|  | resourceProvider: resourceProvider, | 
|  | ); | 
|  | return await context.currentSession.getResolvedUnit(path); | 
|  | } | 
|  |  | 
|  | /// Return a newly create analysis context in which the file at the given [path] | 
|  | /// can be analyzed. | 
|  | /// | 
|  | /// If a [resourceProvider] is given, it will be used to access the file system. | 
|  | AnalysisContext _createAnalysisContext({ | 
|  | required String path, | 
|  | ResourceProvider? resourceProvider, | 
|  | }) { | 
|  | AnalysisContextCollection collection = AnalysisContextCollection( | 
|  | includedPaths: <String>[path], | 
|  | resourceProvider: resourceProvider ?? PhysicalResourceProvider.INSTANCE, | 
|  | ); | 
|  | List<AnalysisContext> contexts = collection.contexts; | 
|  | if (contexts.length != 1) { | 
|  | throw ArgumentError('path must be an absolute path to a single file'); | 
|  | } | 
|  | return contexts[0]; | 
|  | } |