blob: 42ea3f1f3cc81b4156bcb3d6ecec08a5a75dfa0e [file] [log] [blame]
// Copyright (c) 2022, 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' as io;
import 'package:analyzer/dart/analysis/analysis_context.dart';
import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:path/path.dart' as path;
const bool _silent = true;
class Surveyor {
final SurveyorVisitor visitor;
final List<String> sourcePaths;
final List<String> excludedPaths;
Surveyor.fromDirs({
required this.visitor,
required List<io.Directory> directories,
this.excludedPaths = const [],
}) : sourcePaths = directories
.map((directory) => path.normalize(directory.absolute.path))
.toList() {
assert(sourcePaths.isNotEmpty);
}
Future<void> analyze() async {
for (var directory in sourcePaths) {
await _analyzeDirectory(directory);
}
}
Future<void> _analyzeDirectory(String directory) async {
var analysisContextCollection = AnalysisContextCollection(
includedPaths: [directory],
excludedPaths: excludedPaths,
resourceProvider: PhysicalResourceProvider.INSTANCE,
);
for (var analysisContext in analysisContextCollection.contexts) {
var dir = analysisContext.contextRoot.root.path;
var surveyorContext = SurveyorContext(analysisContext);
visitor.preAnalysis(surveyorContext, subDir: dir != directory);
for (var filePath in analysisContext.contextRoot.analyzedFiles()) {
if (!_isDartFileName(filePath)) continue;
surveyorContext._updateCurrentFilePath(filePath);
try {
var resolvedUnitResult = await analysisContext.currentSession
.getResolvedUnit(filePath) as ResolvedUnitResult;
resolvedUnitResult.unit.accept(visitor);
} catch (e) {
if (!_silent) {
print('Exception caught analyzing: $filePath\n$e');
}
}
surveyorContext._updateCurrentFilePath(null);
}
visitor.postAnalysis(surveyorContext);
}
}
}
abstract class SurveyorVisitor implements AstVisitor {
void preAnalysis(SurveyorContext context, {required bool subDir});
void postAnalysis(SurveyorContext context);
}
class SurveyorContext {
final AnalysisContext analysisContext;
String? _currentFilePath;
SurveyorContext(this.analysisContext);
String get currentFilePath => _currentFilePath!;
void _updateCurrentFilePath(String? filePath) {
_currentFilePath = filePath;
}
}
bool _isDartFileName(String filePath) => filePath.endsWith('.dart');