| // Copyright (c) 2024, 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:analyzer/error/error.dart'; | 
 | import 'package:analyzer/error/listener.dart'; | 
 | import 'package:analyzer/file_system/file_system.dart' as file_system; | 
 | import 'package:analyzer/file_system/physical_file_system.dart' as file_system; | 
 | import 'package:analyzer/source/file_source.dart'; | 
 | import 'package:analyzer/source/source.dart'; | 
 | // ignore: implementation_imports | 
 | import 'package:analyzer/src/lint/io.dart'; | 
 | // ignore: implementation_imports | 
 | import 'package:analyzer/src/lint/pub.dart'; | 
 | import 'package:meta/meta.dart'; | 
 | import 'package:path/path.dart' as path; | 
 |  | 
 | import 'analysis_error_info.dart'; | 
 | import 'lint_driver.dart'; | 
 | import 'linter_options.dart'; | 
 |  | 
 | Source _createSource(Uri uri) { | 
 |   var filePath = uri.toFilePath(); | 
 |   var file = file_system.PhysicalResourceProvider.INSTANCE.getFile(filePath); | 
 |   return FileSource(file, uri); | 
 | } | 
 |  | 
 | /// Dart source linter, only for package:linter's tools and tests. | 
 | class TestLinter implements AnalysisErrorListener { | 
 |   final errors = <AnalysisError>[]; | 
 |  | 
 |   final LinterOptions options; | 
 |   final file_system.ResourceProvider _resourceProvider; | 
 |  | 
 |   TestLinter( | 
 |     this.options, { | 
 |     file_system.ResourceProvider? resourceProvider, | 
 |   }) : _resourceProvider = | 
 |             resourceProvider ?? file_system.PhysicalResourceProvider.INSTANCE; | 
 |  | 
 |   Future<List<AnalysisErrorInfo>> lintFiles(List<File> files) async { | 
 |     var errors = <AnalysisErrorInfo>[]; | 
 |     var lintDriver = LintDriver(options, _resourceProvider); | 
 |     errors.addAll(await lintDriver.analyze(files.where(isDartFile))); | 
 |     for (var file in files.where(isPubspecFile)) { | 
 |       lintPubspecSource( | 
 |         contents: file.readAsStringSync(), | 
 |         sourcePath: _resourceProvider.pathContext.normalize(file.absolute.path), | 
 |       ); | 
 |     } | 
 |     return errors; | 
 |   } | 
 |  | 
 |   @visibleForTesting | 
 |   void lintPubspecSource({required String contents, String? sourcePath}) { | 
 |     var sourceUrl = sourcePath == null ? null : path.toUri(sourcePath); | 
 |     var spec = Pubspec.parse(contents, sourceUrl: sourceUrl); | 
 |  | 
 |     for (var rule in options.enabledRules) { | 
 |       var visitor = rule.getPubspecVisitor(); | 
 |       if (visitor != null) { | 
 |         // Analyzer sets reporters; if this file is not being analyzed, | 
 |         // we need to set one ourselves.  (Needless to say, when pubspec | 
 |         // processing gets pushed down, this hack can go away.) | 
 |         if (sourceUrl != null) { | 
 |           var source = _createSource(sourceUrl); | 
 |           rule.reporter = ErrorReporter(this, source); | 
 |         } | 
 |         try { | 
 |           spec.accept(visitor); | 
 |         } on Exception catch (_) { | 
 |           // TODO(srawlins): Report the exception somewhere? | 
 |         } | 
 |       } | 
 |     } | 
 |   } | 
 |  | 
 |   @override | 
 |   void onError(AnalysisError error) => errors.add(error); | 
 | } |