Index: packages/glob/lib/src/ast.dart |
diff --git a/packages/glob/lib/src/ast.dart b/packages/glob/lib/src/ast.dart |
index 191347734238d536fa50ae04940b5447e7029f75..5e24e2b9020467255acdc0a65fbf5c12f95e5087 100644 |
--- a/packages/glob/lib/src/ast.dart |
+++ b/packages/glob/lib/src/ast.dart |
@@ -2,8 +2,6 @@ |
// 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. |
-library glob.ast; |
- |
import 'package:path/path.dart' as p; |
import 'package:collection/collection.dart'; |
@@ -16,15 +14,20 @@ abstract class AstNode { |
/// The cached regular expression that this AST was compiled into. |
RegExp _regExp; |
+ /// Whether this node matches case-sensitively or not. |
+ final bool caseSensitive; |
+ |
/// Whether this glob could match an absolute path. |
/// |
/// Either this or [canMatchRelative] or both will be true. |
- final bool canMatchAbsolute = false; |
+ bool get canMatchAbsolute => false; |
/// Whether this glob could match a relative path. |
/// |
/// Either this or [canMatchRelative] or both will be true. |
- final bool canMatchRelative = true; |
+ bool get canMatchRelative => true; |
+ |
+ AstNode._(this.caseSensitive); |
/// Returns a new glob with all the options bubbled to the top level. |
/// |
@@ -35,11 +38,15 @@ abstract class AstNode { |
/// |
/// For example, given the glob `{foo,bar}/{click/clack}`, this would return |
/// `{foo/click,foo/clack,bar/click,bar/clack}`. |
- OptionsNode flattenOptions() => new OptionsNode([new SequenceNode([this])]); |
+ OptionsNode flattenOptions() => new OptionsNode( |
+ [new SequenceNode([this], caseSensitive: caseSensitive)], |
+ caseSensitive: caseSensitive); |
/// Returns whether this glob matches [string]. |
bool matches(String string) { |
- if (_regExp == null) _regExp = new RegExp('^${_toRegExp()}\$'); |
+ if (_regExp == null) { |
+ _regExp = new RegExp('^${_toRegExp()}\$', caseSensitive: caseSensitive); |
+ } |
return _regExp.hasMatch(string); |
} |
@@ -55,11 +62,14 @@ class SequenceNode extends AstNode { |
bool get canMatchAbsolute => nodes.first.canMatchAbsolute; |
bool get canMatchRelative => nodes.first.canMatchRelative; |
- SequenceNode(Iterable<AstNode> nodes) |
- : nodes = nodes.toList(); |
+ SequenceNode(Iterable<AstNode> nodes, {bool caseSensitive: true}) |
+ : nodes = nodes.toList(), |
+ super._(caseSensitive); |
OptionsNode flattenOptions() { |
- if (nodes.isEmpty) return new OptionsNode([this]); |
+ if (nodes.isEmpty) { |
+ return new OptionsNode([this], caseSensitive: caseSensitive); |
+ } |
var sequences = nodes.first.flattenOptions().options |
.map((sequence) => sequence.nodes); |
@@ -76,17 +86,19 @@ class SequenceNode extends AstNode { |
return new OptionsNode(sequences.map((sequence) { |
// Combine any adjacent LiteralNodes in [sequence]. |
- return new SequenceNode(sequence.fold([], (combined, node) { |
+ return new SequenceNode(sequence.fold/*<List<AstNode>>*/([], (combined, node) { |
if (combined.isEmpty || combined.last is! LiteralNode || |
node is! LiteralNode) { |
return combined..add(node); |
} |
- combined[combined.length - 1] = |
- new LiteralNode(combined.last.text + node.text); |
+ combined[combined.length - 1] = new LiteralNode( |
+ // TODO(nweiz): Avoid casting when sdk#25565 is fixed. |
+ (combined.last as LiteralNode).text + (node as LiteralNode).text, |
+ caseSensitive: caseSensitive); |
return combined; |
- })); |
- })); |
+ }), caseSensitive: caseSensitive); |
+ }), caseSensitive: caseSensitive); |
} |
/// Splits this glob into components along its path separators. |
@@ -101,27 +113,35 @@ class SequenceNode extends AstNode { |
/// [context] is used to determine what absolute roots look like for this |
/// glob. |
List<SequenceNode> split(p.Context context) { |
- var componentsToReturn = []; |
- var currentComponent; |
+ var componentsToReturn = <SequenceNode>[]; |
+ List<AstNode> currentComponent; |
- addNode(node) { |
+ addNode(AstNode node) { |
if (currentComponent == null) currentComponent = []; |
currentComponent.add(node); |
} |
finishComponent() { |
if (currentComponent == null) return; |
- componentsToReturn.add(new SequenceNode(currentComponent)); |
+ componentsToReturn.add( |
+ new SequenceNode(currentComponent, caseSensitive: caseSensitive)); |
currentComponent = null; |
} |
for (var node in nodes) { |
- if (node is! LiteralNode || !node.text.contains('/')) { |
+ if (node is! LiteralNode) { |
addNode(node); |
continue; |
} |
- var text = node.text; |
+ // TODO(nweiz): Avoid casting when sdk#25565 is fixed. |
+ var literal = node as LiteralNode; |
+ if (!literal.text.contains('/')) { |
+ addNode(literal); |
+ continue; |
+ } |
+ |
+ var text = literal.text; |
if (context.style == p.Style.windows) text = text.replaceAll("/", "\\"); |
var components = context.split(text); |
@@ -139,7 +159,7 @@ class SequenceNode extends AstNode { |
// So we switch it back here. |
root = root.replaceAll("\\", "/"); |
} |
- addNode(new LiteralNode(root)); |
+ addNode(new LiteralNode(root, caseSensitive: caseSensitive)); |
} |
finishComponent(); |
components = components.skip(1); |
@@ -149,14 +169,14 @@ class SequenceNode extends AstNode { |
// For each component except the last one, add a separate sequence to |
// [sequences] containing only that component. |
for (var component in components.take(components.length - 1)) { |
- addNode(new LiteralNode(component)); |
+ addNode(new LiteralNode(component, caseSensitive: caseSensitive)); |
finishComponent(); |
} |
// For the final component, only end its sequence (by adding a new empty |
// sequence) if it ends with a separator. |
- addNode(new LiteralNode(components.last)); |
- if (node.text.endsWith('/')) finishComponent(); |
+ addNode(new LiteralNode(components.last, caseSensitive: caseSensitive)); |
+ if (literal.text.endsWith('/')) finishComponent(); |
} |
finishComponent(); |
@@ -175,7 +195,7 @@ class SequenceNode extends AstNode { |
/// A node matching zero or more non-separator characters. |
class StarNode extends AstNode { |
- StarNode(); |
+ StarNode({bool caseSensitive: true}) : super._(caseSensitive); |
String _toRegExp() => '[^/]*'; |
@@ -193,7 +213,8 @@ class DoubleStarNode extends AstNode { |
/// This is used to determine what absolute paths look like. |
final p.Context _context; |
- DoubleStarNode(this._context); |
+ DoubleStarNode(this._context, {bool caseSensitive: true}) |
+ : super._(caseSensitive); |
String _toRegExp() { |
// Double star shouldn't match paths with a leading "../", since these paths |
@@ -229,7 +250,7 @@ class DoubleStarNode extends AstNode { |
/// A node matching a single non-separator character. |
class AnyCharNode extends AstNode { |
- AnyCharNode(); |
+ AnyCharNode({bool caseSensitive: true}) : super._(caseSensitive); |
String _toRegExp() => '[^/]'; |
@@ -250,8 +271,9 @@ class RangeNode extends AstNode { |
/// Whether this range was negated. |
final bool negated; |
- RangeNode(Iterable<Range> ranges, {this.negated}) |
- : ranges = ranges.toSet(); |
+ RangeNode(Iterable<Range> ranges, {this.negated, bool caseSensitive: true}) |
+ : ranges = ranges.toSet(), |
+ super._(caseSensitive); |
OptionsNode flattenOptions() { |
if (negated || ranges.any((range) => !range.isSingleton)) { |
@@ -262,9 +284,10 @@ class RangeNode extends AstNode { |
// a separate expansion. |
return new OptionsNode(ranges.map((range) { |
return new SequenceNode([ |
- new LiteralNode(new String.fromCharCodes([range.min])) |
- ]); |
- })); |
+ new LiteralNode(new String.fromCharCodes([range.min]), |
+ caseSensitive: caseSensitive) |
+ ], caseSensitive: caseSensitive); |
+ }), caseSensitive: caseSensitive); |
} |
String _toRegExp() { |
@@ -325,11 +348,13 @@ class OptionsNode extends AstNode { |
bool get canMatchAbsolute => options.any((node) => node.canMatchAbsolute); |
bool get canMatchRelative => options.any((node) => node.canMatchRelative); |
- OptionsNode(Iterable<SequenceNode> options) |
- : options = options.toList(); |
+ OptionsNode(Iterable<SequenceNode> options, {bool caseSensitive: true}) |
+ : options = options.toList(), |
+ super._(caseSensitive); |
OptionsNode flattenOptions() => new OptionsNode( |
- options.expand((option) => option.flattenOptions().options)); |
+ options.expand((option) => option.flattenOptions().options), |
+ caseSensitive: caseSensitive); |
String _toRegExp() => |
'(?:${options.map((option) => option._toRegExp()).join("|")})'; |
@@ -360,7 +385,9 @@ class LiteralNode extends AstNode { |
bool get canMatchRelative => !canMatchAbsolute; |
- LiteralNode(this.text, [this._context]); |
+ LiteralNode(this.text, {p.Context context, bool caseSensitive: true}) |
+ : _context = context, |
+ super._(caseSensitive); |
String _toRegExp() => regExpQuote(text); |