blob: e65271003b0ba918c149cc85db54353b4d0a190e [file] [log] [blame]
// 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.
import 'package:analyzer/dart/analysis/context_root.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:path/path.dart';
/// An implementation of a context root.
class ContextRootImpl implements ContextRoot {
@override
final ResourceProvider resourceProvider;
@override
final Folder root;
@override
final List<Resource> included = <Resource>[];
@override
final List<Resource> excluded = <Resource>[];
@override
File optionsFile;
@override
File packagesFile;
/// Initialize a newly created context root.
ContextRootImpl(this.resourceProvider, this.root);
@override
Iterable<String> get excludedPaths =>
excluded.map((Resource folder) => folder.path);
@override
int get hashCode => root.path.hashCode;
@override
Iterable<String> get includedPaths =>
included.map((Resource folder) => folder.path);
@override
bool operator ==(Object other) {
return other is ContextRoot && root.path == other.root.path;
}
@override
Iterable<String> analyzedFiles() sync* {
for (String path in includedPaths) {
if (!_isExcluded(path)) {
Resource resource = resourceProvider.getResource(path);
if (resource is File) {
yield path;
} else if (resource is Folder) {
yield* _includedFilesInFolder(resource);
} else {
Type type = resource.runtimeType;
throw StateError('Unknown resource at path "$path" ($type)');
}
}
}
}
@override
bool isAnalyzed(String path) {
return _isIncluded(path) && !_isExcluded(path);
}
/// Return the absolute paths of all of the files that are included in the
/// given [folder].
Iterable<String> _includedFilesInFolder(Folder folder) sync* {
for (Resource resource in folder.getChildren()) {
String path = resource.path;
if (!_isExcluded(path)) {
if (resource is File) {
yield path;
} else if (resource is Folder) {
yield* _includedFilesInFolder(resource);
} else {
Type type = resource.runtimeType;
throw StateError('Unknown resource at path "$path" ($type)');
}
}
}
}
/// Return `true` if the given [path] is either the same as or inside of one
/// of the [excludedPaths].
bool _isExcluded(String path) {
Context context = resourceProvider.pathContext;
String name = context.basename(path);
if (name.startsWith('.')) {
return true;
}
for (String excludedPath in excludedPaths) {
if (context.isAbsolute(excludedPath)) {
if (path == excludedPath || context.isWithin(excludedPath, path)) {
return true;
}
} else {
// The documentation claims that [excludedPaths] only contains absolute
// paths, so we shouldn't be able to reach this point.
for (String includedPath in includedPaths) {
if (context.isWithin(
context.join(includedPath, excludedPath), path)) {
return true;
}
}
}
}
return false;
}
/// Return `true` if the given [path] is either the same as or inside of one
/// of the [includedPaths].
bool _isIncluded(String path) {
Context context = resourceProvider.pathContext;
for (String includedPath in includedPaths) {
if (path == includedPath || context.isWithin(includedPath, path)) {
return true;
}
}
return false;
}
}