| Index: lib/src/ast.dart
|
| diff --git a/lib/src/ast.dart b/lib/src/ast.dart
|
| index 191347734238d536fa50ae04940b5447e7029f75..a003c499ae0f3eb1ae8d13dfb44ef49b7542c375 100644
|
| --- a/lib/src/ast.dart
|
| +++ b/lib/src/ast.dart
|
| @@ -16,6 +16,9 @@ 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.
|
| @@ -26,6 +29,8 @@ abstract class AstNode {
|
| /// Either this or [canMatchRelative] or both will be true.
|
| final bool canMatchRelative = true;
|
|
|
| + AstNode._(this.caseSensitive);
|
| +
|
| /// Returns a new glob with all the options bubbled to the top level.
|
| ///
|
| /// In particular, this returns a glob AST with two guarantees:
|
| @@ -35,11 +40,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 +64,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);
|
| @@ -82,11 +94,11 @@ class SequenceNode extends AstNode {
|
| return combined..add(node);
|
| }
|
|
|
| - combined[combined.length - 1] =
|
| - new LiteralNode(combined.last.text + node.text);
|
| + combined[combined.length - 1] = new LiteralNode(
|
| + combined.last.text + node.text, caseSensitive: caseSensitive);
|
| return combined;
|
| - }));
|
| - }));
|
| + }), caseSensitive: caseSensitive);
|
| + }), caseSensitive: caseSensitive);
|
| }
|
|
|
| /// Splits this glob into components along its path separators.
|
| @@ -111,7 +123,8 @@ class SequenceNode extends AstNode {
|
|
|
| finishComponent() {
|
| if (currentComponent == null) return;
|
| - componentsToReturn.add(new SequenceNode(currentComponent));
|
| + componentsToReturn.add(
|
| + new SequenceNode(currentComponent, caseSensitive: caseSensitive));
|
| currentComponent = null;
|
| }
|
|
|
| @@ -139,7 +152,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,13 +162,13 @@ 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));
|
| + addNode(new LiteralNode(components.last, caseSensitive: caseSensitive));
|
| if (node.text.endsWith('/')) finishComponent();
|
| }
|
|
|
| @@ -175,7 +188,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 +206,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 +243,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 +264,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 +277,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 +341,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 +378,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);
|
|
|
|
|