diff --git a/README.md b/README.md index 836806b..d9af806 100644 --- a/README.md +++ b/README.md @@ -1,37 +1,25 @@ # Flutter工程条件编译打包脚本 ## 原理 -通过将 flutter run/build [--option] 命令替换为 bash flutter.sh run/build [--option] ,在原有flutter运行/打包流程前后执行内置及用户自定义脚本,从而实现对打包流程的自定义控制,默认内置功能为根据命令参数中的 --debug/release 以及 --flavor 渠道名,对代码和资源文件的条件编译 + +通过将 flutter run/build [--option] 命令替换为 bash flutter.sh run/build [--option] ,在原有flutter运行/打包流程前后执行内置及用户自定义脚本,从而实现对打包流程的自定义控制,默认内置功能为根据命令参数中的 +--debug/release 以及 --flavor 渠道名,对代码条件编译. ## 用法语法 + ### 代码: + 代码中使用形如以下的注释来进行代码块的条件标记 + ```dart void main(List arguments) { print(1); - // #[release[google]] + // #{{exp}} // print(2); - // #[release[!asd]] - // print(3); - // #[debug] - // print(4); - // #[release[test]] - // print(5); - // #[[test asd]] - // print(6); - // #[[]] - // print(7) - // #[[]] + // #{{default}} + print(7); + // #{{end}} } ``` -基本注释标记语法为 **// #[debug/release[flavorName1 flavorName2 ...]]** ,外层方括号内填写debug模式或release模式,可以留空表示同时匹配两种模式;内层方括号内填写flavor名的列表,打包命令中 --flavor flavorName 参数传递进来的渠道名在列表中则匹配成功。 - - 特殊的,如果渠道名列表中的名称前加'!'表示取反,命令参数中传入的渠道名不在该列表中时匹配成功(ps: 注意普通渠道名条件列表与带取反的列表不能同时存在) - -注释标记后紧跟该条件下的代码,并注意用 '// ' 进行代码注释,脚本解析时从上到下,某个注释标记的条件匹配成功,就会将紧跟的代码片段覆盖最近的默认代码块,并忽略掉两者之间的其他条件代码块。 -默认代码块的前后需要用 '// #[[]]' 注释作为标记。 - -### 文件: -类似代码中注释条件标记的语法,文件名中使用形如 'abc[debug/release[flavorName1 flavorName2 ...]].xxx' 的形式进行文件命名,并用对应的 'abc.xxx' 文件名作为默认情况下使用的文件,即可在编译运行的时候自动根据传入参数将合适的文件替换为实际使用的文件,并在编译完成后自动还原。 -# **WIP** \ No newline at end of file +基本注释标记语法为 **// #{{exp | default | end}}** \ No newline at end of file diff --git a/bin/after_script.dart b/bin/after_script.dart index 4959228..0b1a0c8 100644 --- a/bin/after_script.dart +++ b/bin/after_script.dart @@ -8,9 +8,5 @@ void main(List arguments) { File(p.path.substring(0, p.path.length - 4)).deleteSync(); p.renameSync(p.path.substring(0, p.path.length - 4)); } - if (p.path.endsWith('.default')) { - File(p.path.substring(0, p.path.length - 8)).deleteSync(); - p.renameSync(p.path.substring(0, p.path.length - 8)); - } }); } diff --git a/bin/expressions/LICENSE b/bin/expressions/LICENSE new file mode 100644 index 0000000..76b4ef1 --- /dev/null +++ b/bin/expressions/LICENSE @@ -0,0 +1,24 @@ +Copyright (c) 2018, Rik Bellens. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/bin/expressions/expressions.dart b/bin/expressions/expressions.dart new file mode 100644 index 0000000..2e9e362 --- /dev/null +++ b/bin/expressions/expressions.dart @@ -0,0 +1,4 @@ +library expressions; + +export 'src/expressions.dart'; +export 'src/evaluator.dart'; diff --git a/bin/expressions/src/deps/petitparser/LICENSE b/bin/expressions/src/deps/petitparser/LICENSE new file mode 100644 index 0000000..c523916 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/LICENSE @@ -0,0 +1,22 @@ +The MIT License + +Copyright (c) 2006-2021 Lukas Renggli. +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/bin/expressions/src/deps/petitparser/core.dart b/bin/expressions/src/deps/petitparser/core.dart new file mode 100644 index 0000000..60e6cf9 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/core.dart @@ -0,0 +1,4 @@ +/// This package contains the core classes of the framework. +export 'src/core/exception.dart'; +export 'src/core/parser.dart'; +export 'src/core/token.dart'; diff --git a/bin/expressions/src/deps/petitparser/parser.dart b/bin/expressions/src/deps/petitparser/parser.dart new file mode 100644 index 0000000..d30ef74 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/parser.dart @@ -0,0 +1,45 @@ +/// This package contains the standard parser implementations. +export 'src/parser/action/cast.dart'; +export 'src/parser/action/cast_list.dart'; +export 'src/parser/action/continuation.dart'; +export 'src/parser/action/flatten.dart'; +export 'src/parser/action/map.dart'; +export 'src/parser/action/permute.dart'; +export 'src/parser/action/pick.dart'; +export 'src/parser/action/token.dart'; +export 'src/parser/action/trimming.dart'; +export 'src/parser/character/any_of.dart'; +export 'src/parser/character/char.dart'; +export 'src/parser/character/digit.dart'; +export 'src/parser/character/letter.dart'; +export 'src/parser/character/lowercase.dart'; +export 'src/parser/character/none_of.dart'; +export 'src/parser/character/parser.dart'; +export 'src/parser/character/pattern.dart'; +export 'src/parser/character/predicate.dart'; +export 'src/parser/character/range.dart'; +export 'src/parser/character/uppercase.dart'; +export 'src/parser/character/whitespace.dart'; +export 'src/parser/character/word.dart'; +export 'src/parser/combinator/and.dart'; +export 'src/parser/combinator/choice.dart'; +export 'src/parser/combinator/delegate.dart'; +export 'src/parser/combinator/list.dart'; +export 'src/parser/combinator/not.dart'; +export 'src/parser/combinator/optional.dart'; +export 'src/parser/combinator/sequence.dart'; +export 'src/parser/combinator/settable.dart'; +export 'src/parser/misc/eof.dart'; +export 'src/parser/misc/epsilon.dart'; +export 'src/parser/misc/failure.dart'; +export 'src/parser/misc/position.dart'; +export 'src/parser/predicate/any.dart'; +export 'src/parser/predicate/predicate.dart'; +export 'src/parser/predicate/string.dart'; +export 'src/parser/repeater/greedy.dart'; +export 'src/parser/repeater/lazy.dart'; +export 'src/parser/repeater/limited.dart'; +export 'src/parser/repeater/possessive.dart'; +export 'src/parser/repeater/repeating.dart'; +export 'src/parser/repeater/separated_by.dart'; +export 'src/parser/repeater/unbounded.dart'; diff --git a/bin/expressions/src/deps/petitparser/petitparser.dart b/bin/expressions/src/deps/petitparser/petitparser.dart new file mode 100644 index 0000000..8bff4f6 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/petitparser.dart @@ -0,0 +1,5 @@ +/// This package exports the core library of PetitParser, a dynamic parser +/// combinator framework. + +export 'core.dart'; +export 'parser.dart'; diff --git a/bin/expressions/src/deps/petitparser/src/context/context.dart b/bin/expressions/src/deps/petitparser/src/context/context.dart new file mode 100644 index 0000000..1a43b07 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/context/context.dart @@ -0,0 +1,32 @@ +import '../meta/lib/meta.dart'; + +import '../core/token.dart'; +import 'failure.dart'; +import 'result.dart'; +import 'success.dart'; + +/// An immutable parse context. +@immutable +class Context { + const Context(this.buffer, this.position); + + /// The buffer we are working on. + final String buffer; + + /// The current position in the [buffer]. + final int position; + + /// Returns a result indicating a parse success. + Result success(R result, [int? position]) => + Success(buffer, position ?? this.position, result); + + /// Returns a result indicating a parse failure. + Result failure(String message, [int? position]) => + Failure(buffer, position ?? this.position, message); + + /// Returns the current line:column position in the [buffer]. + String toPositionString() => Token.positionString(buffer, position); + + @override + String toString() => 'Context[${toPositionString()}]'; +} diff --git a/bin/expressions/src/deps/petitparser/src/context/failure.dart b/bin/expressions/src/deps/petitparser/src/context/failure.dart new file mode 100644 index 0000000..121440d --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/context/failure.dart @@ -0,0 +1,23 @@ +import '../core/exception.dart'; +import 'result.dart'; + +/// An immutable parse result in case of a failed parse. +class Failure extends Result { + const Failure(String buffer, int position, this.message) + : super(buffer, position); + + @override + bool get isFailure => true; + + @override + R get value => throw ParserException(this); + + @override + final String message; + + @override + Result map(T Function(R element) callback) => failure(message); + + @override + String toString() => 'Failure[${toPositionString()}]: $message'; +} diff --git a/bin/expressions/src/deps/petitparser/src/context/result.dart b/bin/expressions/src/deps/petitparser/src/context/result.dart new file mode 100644 index 0000000..6c59f78 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/context/result.dart @@ -0,0 +1,24 @@ +import '../core/exception.dart'; +import 'context.dart'; + +/// An immutable parse result. +abstract class Result extends Context { + const Result(String buffer, int position) : super(buffer, position); + + /// Returns `true` if this result indicates a parse success. + bool get isSuccess => false; + + /// Returns `true` if this result indicates a parse failure. + bool get isFailure => false; + + /// Returns the parsed value of this result, or throws a [ParserException] + /// if this is a parse failure. + R get value; + + /// Returns the error message of this result, or throws an [UnsupportedError] + /// if this is a parse success. + String get message; + + /// Transforms the result with a [callback]. + Result map(T Function(R element) callback); +} diff --git a/bin/expressions/src/deps/petitparser/src/context/success.dart b/bin/expressions/src/deps/petitparser/src/context/success.dart new file mode 100644 index 0000000..dfede39 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/context/success.dart @@ -0,0 +1,23 @@ +import 'result.dart'; + +/// An immutable parse result in case of a successful parse. +class Success extends Result { + const Success(String buffer, int position, this.value) + : super(buffer, position); + + @override + bool get isSuccess => true; + + @override + final R value; + + @override + String get message => + throw UnsupportedError('Successful parse results do not have a message.'); + + @override + Result map(T Function(R element) callback) => success(callback(value)); + + @override + String toString() => 'Success[${toPositionString()}]: $value'; +} diff --git a/bin/expressions/src/deps/petitparser/src/core/exception.dart b/bin/expressions/src/deps/petitparser/src/core/exception.dart new file mode 100644 index 0000000..39759e8 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/core/exception.dart @@ -0,0 +1,20 @@ +import '../context/failure.dart'; + +/// An exception raised in case of a parse error. +class ParserException implements FormatException { + final Failure failure; + + ParserException(this.failure); + + @override + String get message => failure.message; + + @override + int get offset => failure.position; + + @override + String get source => failure.buffer; + + @override + String toString() => '${failure.message} at ${failure.toPositionString()}'; +} diff --git a/bin/expressions/src/deps/petitparser/src/core/parser.dart b/bin/expressions/src/deps/petitparser/src/core/parser.dart new file mode 100644 index 0000000..1652230 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/core/parser.dart @@ -0,0 +1,131 @@ +import '../meta/lib/meta.dart'; + +import '../context/context.dart'; +import '../context/failure.dart'; +import '../context/result.dart'; +import '../context/success.dart'; + +/// Abstract base class of all parsers. +@optionalTypeArgs +abstract class Parser { + Parser(); + + /// Primitive method doing the actual parsing. + /// + /// The method is overridden in concrete subclasses to implement the + /// parser specific logic. The methods takes a parse [context] and + /// returns the resulting context, which is either a [Success] or + /// [Failure] context. + Result parseOn(Context context); + + /// Primitive method doing the actual parsing. + /// + /// This method is an optimized version of [Parser.parseOn] that is getting + /// its speed advantage by avoiding any unnecessary memory allocations. + /// + /// The method is overridden in most concrete subclasses to implement the + /// optimized logic. As an input the method takes a [buffer] and the current + /// [position] in that buffer. It returns a new (positive) position in case + /// of a successful parse, or `-1` in case of a failure. + /// + /// Subclasses don't necessarily have to override this method, since it is + /// emulated using its slower brother. + int fastParseOn(String buffer, int position) { + final result = parseOn(Context(buffer, position)); + return result.isSuccess ? result.position : -1; + } + + /// Returns the parse result of the [input]. + /// + /// The implementation creates a default parse context on the input and calls + /// the internal parsing logic of the receiving parser. + /// + /// For example, `letter().plus().parse('abc')` results in an instance of + /// [Success], where [Context.position] is `3` and [Success.value] is + /// `[a, b, c]`. + /// + /// Similarly, `letter().plus().parse('123')` results in an instance of + /// [Failure], where [Context.position] is `0` and [Failure.message] is + /// ['letter expected']. + Result parse(String input) => parseOn(Context(input, 0)); + + /// Returns a shallow copy of the receiver. + /// + /// Override this method in all subclasses, return its own type. + Parser copy(); + + /// Recursively tests for structural equality of two parsers. + /// + /// The code automatically deals with recursive parsers and parsers that + /// refer to other parsers. Do not override this method, instead customize + /// [Parser.hasEqualProperties] and [Parser.children]. + @nonVirtual + bool isEqualTo(Parser other, [Set? seen]) { + if (this == other) { + return true; + } + if (runtimeType != other.runtimeType || !hasEqualProperties(other)) { + return false; + } + seen ??= {}; + return !seen.add(this) || hasEqualChildren(other, seen); + } + + /// Compare the properties of two parsers. + /// + /// Override this method in all subclasses that add new state. + @protected + @mustCallSuper + bool hasEqualProperties(covariant Parser other) => true; + + /// Compare the children of two parsers. + /// + /// Normally this method does not need to be overridden, as this method works + /// generically on the returned [Parser.children]. + @protected + @mustCallSuper + bool hasEqualChildren(covariant Parser other, Set seen) { + final thisChildren = children, otherChildren = other.children; + if (thisChildren.length != otherChildren.length) { + return false; + } + for (var i = 0; i < thisChildren.length; i++) { + if (!thisChildren[i].isEqualTo(otherChildren[i], seen)) { + return false; + } + } + return true; + } + + /// Returns a list of directly referenced parsers. + /// + /// For example, `letter().children` returns the empty collection `[]`, + /// because the letter parser is a primitive or leaf parser that does not + /// depend or call any other parser. + /// + /// In contrast, `letter().or(digit()).children` returns a collection + /// containing both the `letter()` and `digit()` parser. + /// + /// Override this method and [Parser.replace] in all subclasses that + /// reference other parsers. + List get children => const []; + + /// Changes the receiver by replacing [source] with [target]. Does nothing + /// if [source] does not exist in [Parser.children]. + /// + /// The following example creates a letter parser and then defines a parser + /// called `example` that accepts one or more letters. Eventually the parser + /// `example` is modified by replacing the `letter` parser with a new + /// parser that accepts a digit. The resulting `example` parser accepts one + /// or more digits. + /// + /// final letter = letter(); + /// final example = letter.plus(); + /// example.replace(letter, digit()); + /// + /// Override this method and [Parser.children] in all subclasses that + /// reference other parsers. + void replace(Parser source, Parser target) { + // no children, nothing to do + } +} diff --git a/bin/expressions/src/deps/petitparser/src/core/token.dart b/bin/expressions/src/deps/petitparser/src/core/token.dart new file mode 100644 index 0000000..16facf8 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/core/token.dart @@ -0,0 +1,85 @@ +import '../meta/lib/meta.dart'; + +import '../matcher/matches_skipping.dart'; +import '../parser/action/token.dart'; +import '../parser/character/char.dart'; +import '../parser/combinator/choice.dart'; +import '../parser/combinator/optional.dart'; +import '../parser/combinator/sequence.dart'; +import 'parser.dart'; + +/// A token represents a parsed part of the input stream. +/// +/// The token holds the resulting value of the input, the input buffer, +/// and the start and stop position in the input buffer. It provides many +/// convenience methods to access the state of the token. +@immutable +class Token { + /// Constructs a token from the parsed value, the input buffer, and the + /// start and stop position in the input buffer. + const Token(this.value, this.buffer, this.start, this.stop); + + /// The parsed value of the token. + final T value; + + /// The parsed buffer of the token. + final String buffer; + + /// The start position of the token in the buffer. + final int start; + + /// The stop position of the token in the buffer. + final int stop; + + /// The consumed input of the token. + String get input => buffer.substring(start, stop); + + /// The length of the token. + int get length => stop - start; + + /// The line number of the token (only works for [String] buffers). + int get line => Token.lineAndColumnOf(buffer, start)[0]; + + /// The column number of this token (only works for [String] buffers). + int get column => Token.lineAndColumnOf(buffer, start)[1]; + + @override + String toString() => 'Token[${positionString(buffer, start)}]: $value'; + + @override + bool operator ==(Object other) { + return other is Token && + value == other.value && + start == other.start && + stop == other.stop; + } + + @override + int get hashCode => value.hashCode + start.hashCode + stop.hashCode; + + /// Returns a parser for that detects newlines platform independently. + static Parser newlineParser() => _newlineParser; + + static final Parser _newlineParser = + char('\n') | (char('\r') & char('\n').optional()); + + /// Converts the [position] index in a [buffer] to a line and column tuple. + static List lineAndColumnOf(String buffer, int position) { + var line = 1, offset = 0; + for (final token in newlineParser().token().matchesSkipping(buffer)) { + if (position < token.stop) { + return [line, position - offset + 1]; + } + line++; + offset = token.stop; + } + return [line, position - offset + 1]; + } + + /// Returns a human readable string representing the [position] index in a + /// [buffer]. + static String positionString(String buffer, int position) { + final lineAndColumn = lineAndColumnOf(buffer, position); + return '${lineAndColumn[0]}:${lineAndColumn[1]}'; + } +} diff --git a/bin/expressions/src/deps/petitparser/src/matcher/accept.dart b/bin/expressions/src/deps/petitparser/src/matcher/accept.dart new file mode 100644 index 0000000..8b6b3ee --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/matcher/accept.dart @@ -0,0 +1,9 @@ +import '../core/parser.dart'; + +extension AcceptParser on Parser { + /// Tests if the [input] can be successfully parsed. + /// + /// For example, `letter().plus().accept('abc')` returns `true`, and + /// `letter().plus().accept('123')` returns `false`. + bool accept(String input) => fastParseOn(input, 0) >= 0; +} diff --git a/bin/expressions/src/deps/petitparser/src/matcher/matches.dart b/bin/expressions/src/deps/petitparser/src/matcher/matches.dart new file mode 100644 index 0000000..ff5b02a --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/matcher/matches.dart @@ -0,0 +1,26 @@ +import '../core/parser.dart'; +import '../parser/action/map.dart'; +import '../parser/combinator/and.dart'; +import '../parser/combinator/choice.dart'; +import '../parser/combinator/sequence.dart'; +import '../parser/predicate/any.dart'; +import '../parser/repeater/possessive.dart'; +import 'matches_skipping.dart'; + +extension MatchesParser on Parser { + /// Returns a list of all successful overlapping parses of the [input]. + /// + /// For example, `letter().plus().matches('abc de')` results in the list + /// `[['a', 'b', 'c'], ['b', 'c'], ['c'], ['d', 'e'], ['e']]`. See + /// [matchesSkipping] to retrieve non-overlapping parse results. + List matches(String input) { + final list = []; + and() + .map(list.add, hasSideEffects: true) + .seq(any()) + .or(any()) + .star() + .fastParseOn(input, 0); + return list; + } +} diff --git a/bin/expressions/src/deps/petitparser/src/matcher/matches_skipping.dart b/bin/expressions/src/deps/petitparser/src/matcher/matches_skipping.dart new file mode 100644 index 0000000..f7b93b2 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/matcher/matches_skipping.dart @@ -0,0 +1,19 @@ +import '../core/parser.dart'; +import '../parser/action/map.dart'; +import '../parser/combinator/choice.dart'; +import '../parser/predicate/any.dart'; +import '../parser/repeater/possessive.dart'; +import 'matches.dart'; + +extension MatchesSkippingParser on Parser { + /// Returns a list of all successful non-overlapping parses of the input. + /// + /// For example, `letter().plus().matchesSkipping('abc de')` results in the + /// list `[['a', 'b', 'c'], ['d', 'e']]`. See [matches] to retrieve + /// overlapping parse results. + List matchesSkipping(String input) { + final list = []; + map(list.add, hasSideEffects: true).or(any()).star().fastParseOn(input, 0); + return list; + } +} diff --git a/bin/expressions/src/deps/petitparser/src/matcher/pattern.dart b/bin/expressions/src/deps/petitparser/src/matcher/pattern.dart new file mode 100644 index 0000000..18e247b --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/matcher/pattern.dart @@ -0,0 +1,7 @@ +import '../core/parser.dart'; +import 'pattern/parser_pattern.dart'; + +extension PatternParser on Parser { + /// Converts this [Parser] into a [Pattern] for basic searches within strings. + Pattern toPattern() => ParserPattern(this); +} diff --git a/bin/expressions/src/deps/petitparser/src/matcher/pattern/parser_match.dart b/bin/expressions/src/deps/petitparser/src/matcher/pattern/parser_match.dart new file mode 100644 index 0000000..0d77f2e --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/matcher/pattern/parser_match.dart @@ -0,0 +1,33 @@ +import '../../meta/lib/meta.dart'; +import 'parser_pattern.dart'; + +@immutable +class ParserMatch implements Match { + @override + final ParserPattern pattern; + + @override + final String input; + + @override + final int start; + + @override + final int end; + + const ParserMatch(this.pattern, this.input, this.start, this.end); + + @override + String? group(int group) => this[group]; + + @override + String? operator [](int group) => + group == 0 ? input.substring(start, end) : null; + + @override + List groups(List groupIndices) => + groupIndices.map(group).toList(growable: false); + + @override + int get groupCount => 0; +} diff --git a/bin/expressions/src/deps/petitparser/src/matcher/pattern/parser_pattern.dart b/bin/expressions/src/deps/petitparser/src/matcher/pattern/parser_pattern.dart new file mode 100644 index 0000000..3f66801 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/matcher/pattern/parser_pattern.dart @@ -0,0 +1,37 @@ +import '../../meta/lib/meta.dart'; + +import '../../core/parser.dart'; +import 'parser_match.dart'; +import 'pattern_iterable.dart'; + +@immutable +class ParserPattern implements Pattern { + final Parser parser; + + const ParserPattern(this.parser); + + /// Matches this parser against [string] repeatedly. + /// + /// If [start] is provided, matching will start at that index. The returned + /// iterable lazily computes all the non-overlapping matches of the parser on + /// the string, ordered by start index. + /// + /// If the pattern matches the empty string at some point, the next match is + /// found by starting at the previous match's end plus one. + @override + Iterable allMatches(String string, [int start = 0]) => + PatternIterable(this, string, start); + + /// Match this pattern against the start of [string]. + /// + /// If [start] is provided, this parser is tested against the string at the + /// [start] position. That is, a [Match] is returned if the pattern can match + /// a part of the string starting from position [start]. + /// + /// Returns `null` if the pattern doesn't match. + @override + ParserMatch? matchAsPrefix(String string, [int start = 0]) { + final end = parser.fastParseOn(string, start); + return end < 0 ? null : ParserMatch(this, string, start, end); + } +} diff --git a/bin/expressions/src/deps/petitparser/src/matcher/pattern/pattern_iterable.dart b/bin/expressions/src/deps/petitparser/src/matcher/pattern/pattern_iterable.dart new file mode 100644 index 0000000..a98b474 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/matcher/pattern/pattern_iterable.dart @@ -0,0 +1,20 @@ +import 'dart:collection'; + +import '../../meta/lib/meta.dart'; + +import 'parser_match.dart'; +import 'parser_pattern.dart'; +import 'pattern_iterator.dart'; + +@immutable +class PatternIterable extends IterableBase { + final ParserPattern pattern; + final String input; + final int start; + + const PatternIterable(this.pattern, this.input, this.start); + + @override + Iterator get iterator => + PatternIterator(pattern, pattern.parser, input, start); +} diff --git a/bin/expressions/src/deps/petitparser/src/matcher/pattern/pattern_iterator.dart b/bin/expressions/src/deps/petitparser/src/matcher/pattern/pattern_iterator.dart new file mode 100644 index 0000000..88ea8ba --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/matcher/pattern/pattern_iterator.dart @@ -0,0 +1,34 @@ +import '../../core/parser.dart'; +import 'parser_match.dart'; +import 'parser_pattern.dart'; + +class PatternIterator extends Iterator { + final ParserPattern pattern; + final Parser parser; + final String input; + int start; + + PatternIterator(this.pattern, this.parser, this.input, this.start); + + @override + late ParserMatch current; + + @override + bool moveNext() { + while (start <= input.length) { + final end = parser.fastParseOn(input, start); + if (end < 0) { + start++; + } else { + current = ParserMatch(pattern, input, start, end); + if (start == end) { + start++; + } else { + start = end; + } + return true; + } + } + return false; + } +} diff --git a/bin/expressions/src/deps/petitparser/src/meta/LICENSE b/bin/expressions/src/deps/petitparser/src/meta/LICENSE new file mode 100644 index 0000000..4ded3fa --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/meta/LICENSE @@ -0,0 +1,26 @@ +Copyright 2016, the Dart project authors. All rights reserved. +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + * Neither the name of Google Inc. nor the names of its + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/bin/expressions/src/deps/petitparser/src/meta/lib/meta.dart b/bin/expressions/src/deps/petitparser/src/meta/lib/meta.dart new file mode 100644 index 0000000..becc195 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/meta/lib/meta.dart @@ -0,0 +1,390 @@ +// Copyright (c) 2016, 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. + +/// Annotations that developers can use to express the intentions that otherwise +/// can't be deduced by statically analyzing the source code. +/// +/// See also `@deprecated` and `@override` in the `dart:core` library. +/// +/// Annotations provide semantic information that tools can use to provide a +/// better user experience. For example, an IDE might not autocomplete the name +/// of a function that's been marked `@deprecated`, or it might display the +/// function's name differently. +/// +/// For information on installing and importing this library, see the [meta +/// package on pub.dev](https://pub.dev/packages/meta). For examples of using +/// annotations, see +/// [Metadata](https://dart.dev/guides/language/language-tour#metadata) in the +/// language tour. +library meta; + +import 'meta_meta.dart'; + +/// Used to annotate a function `f`. Indicates that `f` always throws an +/// exception. Any functions that override `f`, in class inheritance, are also +/// expected to conform to this contract. +/// +/// Tools, such as the analyzer, can use this to understand whether a block of +/// code "exits". For example: +/// +/// ```dart +/// @alwaysThrows toss() { throw 'Thrown'; } +/// +/// int fn(bool b) { +/// if (b) { +/// return 0; +/// } else { +/// toss(); +/// print("Hello."); +/// } +/// } +/// ``` +/// +/// Without the annotation on `toss`, it would look as though `fn` doesn't +/// always return a value. The annotation shows that `fn` does always exit. In +/// addition, the annotation reveals that any statements following a call to +/// `toss` (like the `print` call) are dead code. +/// +/// Tools, such as the analyzer, can also expect this contract to be enforced; +/// that is, tools may emit warnings if a function with this annotation +/// _doesn't_ always throw. +const _AlwaysThrows alwaysThrows = _AlwaysThrows(); + +/// Used to annotate a parameter of an instance method that overrides another +/// method. +/// +/// Indicates that this parameter may have a tighter type than the parameter on +/// its superclass. The actual argument will be checked at runtime to ensure it +/// is a subtype of the overridden parameter type. +/// +@Deprecated('Use the `covariant` modifier instead') +const _Checked checked = _Checked(); + +/// Used to annotate a method, getter or top-level getter or function to +/// indicate that the value obtained by invoking it should not be stored in a +/// field or top-level variable. The annotation can also be applied to a class +/// to implicitly annotate all of the valid members of the class, or applied to +/// a library to annotate all of the valid members of the library, including +/// classes. If a value returned by an element marked as `doNotStore` is returned +/// from a function or getter, that function or getter should be similarly +/// annotated. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than a library, class, +/// method or getter, top-level getter or function, or +/// * an invocation of a member that has this annotation is returned by a method, +/// getter or function that is not similarly annotated as `doNotStore`, or +/// * an invocation of a member that has this annotation is assigned to a field +/// or top-level variable. +const _DoNotStore doNotStore = _DoNotStore(); + +/// Used to annotate a library, or any declaration that is part of the public +/// interface of a library (such as top-level members, class members, and +/// function parameters) to indicate that the annotated API is experimental and +/// may be removed or changed at any-time without updating the version of the +/// containing package, despite the fact that it would otherwise be a breaking +/// change. +/// +/// If the annotation is applied to a library then it is equivalent to applying +/// the annotation to all of the top-level members of the library. Applying the +/// annotation to a class does *not* apply the annotation to subclasses, but +/// does apply the annotation to members of the class. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with a declaration that is not part of the +/// public interface of a library (such as a local variable or a declaration +/// that is private) or a directive other than the first directive in the +/// library, or +/// * the declaration is referenced by a package that has not explicitly +/// indicated its intention to use experimental APIs (details TBD). +const _Experimental experimental = _Experimental(); + +/// Used to annotate an instance or static method `m`. Indicates that `m` must +/// either be abstract or must return a newly allocated object or `null`. In +/// addition, every method that either implements or overrides `m` is implicitly +/// annotated with this same annotation. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than a method, or +/// * a method that has this annotation can return anything other than a newly +/// allocated object or `null`. +const _Factory factory = _Factory(); + +/// Used to annotate a class `C`. Indicates that `C` and all subtypes of `C` +/// must be immutable. +/// +/// A class is immutable if all of the instance fields of the class, whether +/// defined directly or inherited, are `final`. +/// +/// Tools, such as the analyzer, can provide feedback if +/// * the annotation is associated with anything other than a class, or +/// * a class that has this annotation or extends, implements or mixes in a +/// class that has this annotation is not immutable. +const Immutable immutable = Immutable(); + +/// Used to annotate a declaration which should only be used from within the +/// package in which it is declared, and which should not be exposed from said +/// package's public API. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the declaration is declared in a package's public API, or is exposed from +/// a package's public API, or +/// * the declaration is private, an unnamed extension, a static member of a +/// private class, mixin, or extension, a value of a private enum, or a +/// constructor of a private class, or +/// * the declaration is referenced outside the package in which it is declared. +const _Internal internal = _Internal(); + +/// Used to annotate a test framework function that runs a single test. +/// +/// Tools, such as IDEs, can show invocations of such function in a file +/// structure view to help the user navigating in large test files. +/// +/// The first parameter of the function must be the description of the test. +const _IsTest isTest = _IsTest(); + +/// Used to annotate a test framework function that runs a group of tests. +/// +/// Tools, such as IDEs, can show invocations of such function in a file +/// structure view to help the user navigating in large test files. +/// +/// The first parameter of the function must be the description of the group. +const _IsTestGroup isTestGroup = _IsTestGroup(); + +/// Used to annotate a const constructor `c`. Indicates that any invocation of +/// the constructor must use the keyword `const` unless one or more of the +/// arguments to the constructor is not a compile-time constant. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than a const constructor, +/// or +/// * an invocation of a constructor that has this annotation is not invoked +/// using the `const` keyword unless one or more of the arguments to the +/// constructor is not a compile-time constant. +const _Literal literal = _Literal(); + +/// Used to annotate an instance method `m`. Indicates that every invocation of +/// a method that overrides `m` must also invoke `m`. In addition, every method +/// that overrides `m` is implicitly annotated with this same annotation. +/// +/// Note that private methods with this annotation cannot be validly overridden +/// outside of the library that defines the annotated method. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than an instance method, +/// or +/// * a method that overrides a method that has this annotation can return +/// without invoking the overridden method. +const _MustCallSuper mustCallSuper = _MustCallSuper(); + +/// Used to annotate an instance member (method, getter, setter, operator, or +/// field) `m` in a class `C` or mixin `M`. Indicates that `m` should not be +/// overridden in any classes that extend or mixin `C` or `M`. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than an instance member, +/// * the annotation is associated with an abstract member (because subclasses +/// are required to override the member), +/// * the annotation is associated with an extension method, +/// * the annotation is associated with a member `m` in class `C`, and there is +/// a class `D` or mixin `M`, that extends or mixes in `C`, that declares an +/// overriding member `m`. +const _NonVirtual nonVirtual = _NonVirtual(); + +/// Used to annotate a class, mixin, or extension declaration `C`. Indicates +/// that any type arguments declared on `C` are to be treated as optional. +/// Tools such as the analyzer and linter can use this information to suppress +/// warnings that would otherwise require type arguments on `C` to be provided. +const _OptionalTypeArgs optionalTypeArgs = _OptionalTypeArgs(); + +/// Used to annotate an instance member (method, getter, setter, operator, or +/// field) `m` in a class `C`. If the annotation is on a field it applies to the +/// getter, and setter if appropriate, that are induced by the field. Indicates +/// that `m` should only be invoked from instance methods of `C` or classes that +/// extend, implement or mix in `C`, either directly or indirectly. Additionally +/// indicates that `m` should only be invoked on `this`, whether explicitly or +/// implicitly. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than an instance member, +/// or +/// * an invocation of a member that has this annotation is used outside of an +/// instance member defined on a class that extends or mixes in (or a mixin +/// constrained to) the class in which the protected member is defined. +/// * an invocation of a member that has this annotation is used within an +/// instance method, but the receiver is something other than `this`. +const _Protected protected = _Protected(); + +/// Used to annotate a named parameter `p` in a method or function `f`. +/// Indicates that every invocation of `f` must include an argument +/// corresponding to `p`, despite the fact that `p` would otherwise be an +/// optional parameter. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than a named parameter, +/// * the annotation is associated with a named parameter in a method `m1` that +/// overrides a method `m0` and `m0` defines a named parameter with the same +/// name that does not have this annotation, or +/// * an invocation of a method or function does not include an argument +/// corresponding to a named parameter that has this annotation. +const Required required = Required(); + +/// Annotation marking a class as not allowed as a super-type. +/// +/// Classes in the same package as the marked class may extend, implement or +/// mix-in the annotated class. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than a class, +/// * the annotation is associated with a class `C`, and there is a class or +/// mixin `D`, which extends, implements, mixes in, or constrains to `C`, and +/// `C` and `D` are declared in different packages. +const _Sealed sealed = _Sealed(); + +/// Used to annotate a field that is allowed to be overridden in Strong Mode. +/// +/// Deprecated: Most of strong mode is now the default in 2.0, but the notion of +/// virtual fields was dropped, so this annotation no longer has any meaning. +/// Uses of the annotation should be removed. +@Deprecated('No longer has meaning') +const _Virtual virtual = _Virtual(); + +/// Used to annotate an instance member that was made public so that it could be +/// overridden but that is not intended to be referenced from outside the +/// defining library. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with a declaration other than a public +/// instance member in a class or mixin, or +/// * the member is referenced outside of the defining library. +const _VisibleForOverriding visibleForOverriding = _VisibleForOverriding(); + +/// Used to annotate a declaration that was made public, so that it is more +/// visible than otherwise necessary, to make code testable. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with a declaration not in the `lib` folder +/// of a package, or a private declaration, or a declaration in an unnamed +/// static extension, or +/// * the declaration is referenced outside of its defining library or a +/// library which is in the `test` folder of the defining package. +const _VisibleForTesting visibleForTesting = _VisibleForTesting(); + +/// Used to annotate a class. +/// +/// See [immutable] for more details. +class Immutable { + /// A human-readable explanation of the reason why the class is immutable. + final String reason; + + /// Initialize a newly created instance to have the given [reason]. + const Immutable([this.reason = '']); +} + +/// Used to annotate a named parameter `p` in a method or function `f`. +/// +/// See [required] for more details. +class Required { + /// A human-readable explanation of the reason why the annotated parameter is + /// required. For example, the annotation might look like: + /// + /// ButtonWidget({ + /// Function onHover, + /// @Required('Buttons must do something when pressed') + /// Function onPressed, + /// ... + /// }) ... + final String reason; + + /// Initialize a newly created instance to have the given [reason]. + const Required([this.reason = '']); +} + +class _AlwaysThrows { + const _AlwaysThrows(); +} + +class _Checked { + const _Checked(); +} + +@Target({ + TargetKind.classType, + TargetKind.function, + TargetKind.getter, + TargetKind.library, + TargetKind.method, +}) +class _DoNotStore { + const _DoNotStore(); +} + +class _Experimental { + const _Experimental(); +} + +class _Factory { + const _Factory(); +} + +class _Internal { + const _Internal(); +} + +class _IsTest { + const _IsTest(); +} + +class _IsTestGroup { + const _IsTestGroup(); +} + +class _Literal { + const _Literal(); +} + +class _MustCallSuper { + const _MustCallSuper(); +} + +class _NonVirtual { + const _NonVirtual(); +} + +class _OptionalTypeArgs { + const _OptionalTypeArgs(); +} + +class _Protected { + const _Protected(); +} + +class _Sealed { + const _Sealed(); +} + +@Deprecated('No longer has meaning') +class _Virtual { + const _Virtual(); +} + +class _VisibleForOverriding { + const _VisibleForOverriding(); +} + +class _VisibleForTesting { + const _VisibleForTesting(); +} \ No newline at end of file diff --git a/bin/expressions/src/deps/petitparser/src/meta/lib/meta_meta.dart b/bin/expressions/src/deps/petitparser/src/meta/lib/meta_meta.dart new file mode 100644 index 0000000..6974f07 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/meta/lib/meta_meta.dart @@ -0,0 +1,83 @@ +// Copyright (c) 2020, 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. + +/// Annotations that describe the intended use of other annotations. +library meta_meta; + +/// An annotation used on classes that are intended to be used as annotations +/// to indicate the kinds of declarations and directives for which the +/// annotation is appropriate. +/// +/// The kinds are represented by the constants defined in [TargetKind]. +/// +/// Tools, such as the analyzer, can provide feedback if +/// +/// * the annotation is associated with anything other than a class, where the +/// class must be usable as an annotation (that is, contain at least one +/// `const` constructor). +/// * the annotated annotation is associated with anything other than the kinds +/// of declarations listed as valid targets. +@Target({TargetKind.classType}) +class Target { + /// The kinds of declarations with which the annotated annotation can be + /// associated. + final Set kinds; + + const Target(this.kinds); +} + +/// An enumeration of the kinds of targets to which an annotation can be +/// applied. +enum TargetKind { + /// Indicates that an annotation is valid on any class declaration. + classType, + + /// Indicates that an annotation is valid on any enum declaration. + enumType, + + /// Indicates that an annotation is valid on any extension declaration. + extension, + + /// Indicates that an annotation is valid on any field declaration, both + /// instance and static fields, whether it's in a class, mixin or extension. + field, + + /// Indicates that an annotation is valid on any top-level function + /// declaration. + function, + + /// Indicates that an annotation is valid on the first directive in a library, + /// whether that's a `library`, `import`, `export` or `part` directive. This + /// doesn't include the `part of` directive in a part file. + library, + + /// Indicates that an annotation is valid on any getter declaration, both + /// instance or static getters, whether it's in a class, mixin, extension, or + /// at the top-level of a library. + getter, + + /// Indicates that an annotation is valid on any method declaration, both + /// instance and static methods, whether it's in a class, mixin or extension. + method, + + /// Indicates that an annotation is valid on any mixin declaration. + mixinType, + + /// Indicates that an annotation is valid on any formal parameter declaration, + /// whether it's in a function, method, constructor, or closure. + parameter, + + /// Indicates that an annotation is valid on any setter declaration, both + /// instance or static setters, whether it's in a class, mixin, extension, or + /// at the top-level of a library. + setter, + + /// Indicates that an annotation is valid on any declaration that introduces a + /// type. This includes classes, enums, mixins and typedefs, but does not + /// include extensions because extensions don't introduce a type. + type, + + /// Indicates that an annotation is valid on any typedef declaration. + typedefType, +} \ No newline at end of file diff --git a/bin/expressions/src/deps/petitparser/src/parser/action/cast.dart b/bin/expressions/src/deps/petitparser/src/parser/action/cast.dart new file mode 100644 index 0000000..7d999bb --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/action/cast.dart @@ -0,0 +1,31 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../combinator/delegate.dart'; + +extension CastParserExtension on Parser { + /// Returns a parser that casts itself to `Parser`. + Parser cast() => CastParser(this); +} + +/// A parser that casts a `Result` to a `Result`. +class CastParser extends DelegateParser { + CastParser(Parser delegate) : super(delegate); + + @override + Result parseOn(Context context) { + final result = delegate.parseOn(context); + if (result.isSuccess) { + return result.success(result.value); + } else { + return result.failure(result.message); + } + } + + @override + int fastParseOn(String buffer, int position) => + delegate.fastParseOn(buffer, position); + + @override + CastParser copy() => CastParser(delegate); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/action/cast_list.dart b/bin/expressions/src/deps/petitparser/src/parser/action/cast_list.dart new file mode 100644 index 0000000..15b8b61 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/action/cast_list.dart @@ -0,0 +1,32 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../combinator/delegate.dart'; + +extension CastListParserExtension on Parser { + /// Returns a parser that casts itself to `Parser>`. Assumes this + /// parser to be of type `Parser`. + Parser> castList() => CastListParser(this); +} + +/// A parser that casts a `Result` to a `Result>`. +class CastListParser extends DelegateParser> { + CastListParser(Parser delegate) : super(delegate); + + @override + Result> parseOn(Context context) { + final result = delegate.parseOn(context); + if (result.isSuccess) { + return result.success(result.value.cast()); + } else { + return result.failure(result.message); + } + } + + @override + int fastParseOn(String buffer, int position) => + delegate.fastParseOn(buffer, position); + + @override + CastListParser copy() => CastListParser(delegate); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/action/continuation.dart b/bin/expressions/src/deps/petitparser/src/parser/action/continuation.dart new file mode 100644 index 0000000..0ec5d71 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/action/continuation.dart @@ -0,0 +1,55 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../../parser/combinator/delegate.dart'; + +/// Handler function for the [ContinuationParser]. +typedef ContinuationHandler = Result Function( + ContinuationCallback continuation, Context context); + +/// Callback function for the [ContinuationHandler]. +typedef ContinuationCallback = Result Function(Context context); + +extension ContinuationParserExtension on Parser { + /// Returns a parser that when activated captures a continuation function + /// and passes it together with the current context into the handler. + /// + /// Handlers are not required to call the continuation, but can completely + /// ignore it, call it multiple times, and/or store it away for later use. + /// Similarly handlers can modify the current context and/or modify the + /// returned result. + /// + /// The following example shows a simple wrapper. Messages are printed before + /// and after the `digit()` parser is activated: + /// + /// final parser = digit().callCC((continuation, context) { + /// print('Parser will be activated, the context is $context.'); + /// final result = continuation(context); + /// print('Parser was activated, the result is $result.'); + /// return result; + /// }); + Parser callCC(ContinuationHandler handler) => + ContinuationParser(this, handler); +} + +/// Continuation parser that when activated captures a continuation function +/// and passes it together with the current context into the handler. +class ContinuationParser extends DelegateParser { + final ContinuationHandler handler; + + ContinuationParser(Parser delegate, this.handler) : super(delegate); + + @override + Result parseOn(Context context) => handler(_parseDelegateOn, context); + + Result _parseDelegateOn(Context context) => + delegate.parseOn(context) as Result; + + @override + ContinuationParser copy() => + ContinuationParser(delegate as Parser, handler); + + @override + bool hasEqualProperties(ContinuationParser other) => + super.hasEqualProperties(other) && handler == other.handler; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/action/flatten.dart b/bin/expressions/src/deps/petitparser/src/parser/action/flatten.dart new file mode 100644 index 0000000..1431297 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/action/flatten.dart @@ -0,0 +1,59 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../combinator/delegate.dart'; + +extension FlattenParserExtension on Parser { + /// Returns a parser that discards the result of the receiver, and returns + /// a sub-string of the consumed range in the string/list being parsed. + /// + /// If a [message] is provided, the flatten parser can switch to a fast mode + /// where error tracking within the receiver is suppressed and in case of a + /// problem [message] is reported instead. + /// + /// For example, the parser `letter().plus().flatten()` returns `'abc'` + /// for the input `'abc'`. In contrast, the parser `letter().plus()` would + /// return `['a', 'b', 'c']` for the same input instead. + Parser flatten([String? message]) => FlattenParser(this, message); +} + +/// A parser that answers a substring of the range its delegate +/// parses. +class FlattenParser extends DelegateParser { + FlattenParser(Parser delegate, [this.message]) : super(delegate); + + final String? message; + + @override + Result parseOn(Context context) { + if (message == null) { + final result = delegate.parseOn(context); + if (result.isSuccess) { + final output = + context.buffer.substring(context.position, result.position); + return result.success(output); + } + return result.failure(result.message); + } else { + // If we have a message we can switch to fast mode. + final position = delegate.fastParseOn(context.buffer, context.position); + if (position < 0) { + return context.failure(message!); + } + final output = context.buffer.substring(context.position, position); + return context.success(output, position); + } + } + + @override + int fastParseOn(String buffer, int position) { + return delegate.fastParseOn(buffer, position); + } + + @override + bool hasEqualProperties(FlattenParser other) => + super.hasEqualProperties(other) && message == other.message; + + @override + FlattenParser copy() => FlattenParser(delegate, message); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/action/map.dart b/bin/expressions/src/deps/petitparser/src/parser/action/map.dart new file mode 100644 index 0000000..8d5f163 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/action/map.dart @@ -0,0 +1,60 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../combinator/delegate.dart'; + +/// Typed action callback. +typedef MapCallback = R Function(T value); + +extension MapParserExtension on Parser { + /// Returns a parser that evaluates a [callback] as the production action + /// on success of the receiver. + /// + /// By default we assume the [callback] to be side-effect free. Unless + /// [hasSideEffects] is set to `true`, the execution might be skipped if there + /// are no direct dependencies. + /// + /// For example, the parser `digit().map((char) => int.parse(char))` returns + /// the number `1` for the input string `'1'`. If the delegate fails, the + /// production action is not executed and the failure is passed on. + Parser map(MapCallback callback, {bool hasSideEffects = false}) => + MapParser(this, callback, hasSideEffects); +} + +/// A parser that performs a transformation with a given function on the +/// successful parse result of the delegate. +class MapParser extends DelegateParser { + final MapCallback callback; + final bool hasSideEffects; + + MapParser(Parser delegate, this.callback, [this.hasSideEffects = false]) + : super(delegate); + + @override + Result parseOn(Context context) { + final result = delegate.parseOn(context); + if (result.isSuccess) { + return result.success(callback(result.value)); + } else { + return result.failure(result.message); + } + } + + @override + int fastParseOn(String buffer, int position) { + // If we know to have side-effects, we have to fall back to the slow mode. + return hasSideEffects + ? super.fastParseOn(buffer, position) + : delegate.fastParseOn(buffer, position); + } + + @override + MapParser copy() => + MapParser(delegate as Parser, callback, hasSideEffects); + + @override + bool hasEqualProperties(MapParser other) => + super.hasEqualProperties(other) && + callback == other.callback && + hasSideEffects == other.hasSideEffects; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/action/permute.dart b/bin/expressions/src/deps/petitparser/src/parser/action/permute.dart new file mode 100644 index 0000000..397835c --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/action/permute.dart @@ -0,0 +1,51 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../combinator/delegate.dart'; + +extension PermuteParserExtension on Parser { + /// Returns a parser that transforms a successful parse result by returning + /// the permuted elements at [indexes] of a list. Negative indexes can be + /// used to access the elements from the back of the list. + /// + /// For example, the parser `letter().star().permute([0, -1])` returns the + /// first and last letter parsed. For the input `'abc'` it returns + /// `['a', 'c']`. + Parser> permute(List indexes) => + PermuteParser(this, indexes); +} + +/// A parser that performs a transformation with a given function on the +/// successful parse result of the delegate. +class PermuteParser extends DelegateParser> { + final List indexes; + + PermuteParser(Parser delegate, this.indexes) : super(delegate); + + @override + Result> parseOn(Context context) { + final result = delegate.parseOn(context); + if (result.isSuccess) { + final value = result.value; + final values = indexes + .map((index) => value[index < 0 ? value.length + index : index]) + .cast() + .toList(growable: false); + return result.success(values); + } else { + return result.failure(result.message); + } + } + + @override + int fastParseOn(String buffer, int position) => + delegate.fastParseOn(buffer, position); + + @override + PermuteParser copy() => + PermuteParser(delegate as Parser, indexes); + + @override + bool hasEqualProperties(PermuteParser other) => + super.hasEqualProperties(other) && indexes == other.indexes; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/action/pick.dart b/bin/expressions/src/deps/petitparser/src/parser/action/pick.dart new file mode 100644 index 0000000..679556d --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/action/pick.dart @@ -0,0 +1,45 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../combinator/delegate.dart'; + +extension PickParserExtension on Parser { + /// Returns a parser that transforms a successful parse result by returning + /// the element at [index] of a list. A negative index can be used to access + /// the elements from the back of the list. + /// + /// For example, the parser `letter().star().pick(-1)` returns the last + /// letter parsed. For the input `'abc'` it returns `'c'`. + Parser pick(int index) => PickParser(this, index); +} + +/// A parser that performs a transformation with a given function on the +/// successful parse result of the delegate. +class PickParser extends DelegateParser { + final int index; + + PickParser(Parser delegate, this.index) : super(delegate); + + @override + Result parseOn(Context context) { + final result = delegate.parseOn(context); + if (result.isSuccess) { + final value = result.value; + final picked = value[index < 0 ? value.length + index : index]; + return result.success(picked); + } else { + return result.failure(result.message); + } + } + + @override + int fastParseOn(String buffer, int position) => + delegate.fastParseOn(buffer, position); + + @override + PickParser copy() => PickParser(delegate as Parser, index); + + @override + bool hasEqualProperties(PickParser other) => + super.hasEqualProperties(other) && index == other.index; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/action/token.dart b/bin/expressions/src/deps/petitparser/src/parser/action/token.dart new file mode 100644 index 0000000..2485cc3 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/action/token.dart @@ -0,0 +1,40 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../../core/token.dart'; +import '../combinator/delegate.dart'; + +extension TokenParserExtension on Parser { + /// Returns a parser that returns a [Token]. The token carries the parsed + /// value of the receiver [Token.value], as well as the consumed input + /// [Token.input] from [Token.start] to [Token.stop] of the input being + /// parsed. + /// + /// For example, the parser `letter().plus().token()` returns the token + /// `Token[start: 0, stop: 3, value: abc]` for the input `'abc'`. + Parser> token() => TokenParser(this); +} + +/// A parser that answers a token of the result its delegate parses. +class TokenParser extends DelegateParser> { + TokenParser(Parser delegate) : super(delegate); + + @override + Result> parseOn(Context context) { + final result = delegate.parseOn(context); + if (result.isSuccess) { + final token = Token( + result.value, context.buffer, context.position, result.position); + return result.success(token); + } else { + return result.failure(result.message); + } + } + + @override + int fastParseOn(String buffer, int position) => + delegate.fastParseOn(buffer, position); + + @override + TokenParser copy() => TokenParser(delegate); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/action/trimming.dart b/bin/expressions/src/deps/petitparser/src/parser/action/trimming.dart new file mode 100644 index 0000000..ed6e3f4 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/action/trimming.dart @@ -0,0 +1,84 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../character/whitespace.dart'; +import '../combinator/delegate.dart'; + +extension TrimmingParserExtension on Parser { + /// Returns a parser that consumes input before and after the receiver, + /// discards the excess input and only returns returns the result of the + /// receiver. The optional arguments are parsers that consume the excess + /// input. By default `whitespace()` is used. Up to two arguments can be + /// provided to have different parsers on the [left] and [right] side. + /// + /// For example, the parser `letter().plus().trim()` returns `['a', 'b']` + /// for the input `' ab\n'` and consumes the complete input string. + Parser trim([Parser? left, Parser? right]) => + TrimmingParser(this, left ??= whitespace(), right ??= left); +} + +/// A parser that silently consumes input of another parser around +/// its delegate. +class TrimmingParser extends DelegateParser { + Parser left; + Parser right; + + TrimmingParser(Parser delegate, this.left, this.right) : super(delegate); + + @override + Result parseOn(Context context) { + final buffer = context.buffer; + + // Trim the left part: + final before = trim_(left, buffer, context.position); + if (before != context.position) { + context = Context(buffer, before); + } + + // Consume the delegate: + final result = delegate.parseOn(context) as Result; + if (result.isFailure) { + return result; + } + + // Trim the right part: + final after = trim_(right, buffer, result.position); + return after == result.position + ? result + : result.success(result.value, after); + } + + @override + int fastParseOn(String buffer, int position) { + final result = delegate.fastParseOn(buffer, trim_(left, buffer, position)); + return result < 0 ? -1 : trim_(right, buffer, result); + } + + int trim_(Parser parser, String buffer, int position) { + for (;;) { + final result = parser.fastParseOn(buffer, position); + if (result < 0) { + return position; + } + position = result; + } + } + + @override + TrimmingParser copy() => + TrimmingParser(delegate as Parser, left, right); + + @override + List get children => [delegate, left, right]; + + @override + void replace(Parser source, Parser target) { + super.replace(source, target); + if (left == source) { + left = target; + } + if (right == source) { + right = target; + } + } +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/any_of.dart b/bin/expressions/src/deps/petitparser/src/parser/character/any_of.dart new file mode 100644 index 0000000..879e2fe --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/any_of.dart @@ -0,0 +1,10 @@ +import '../../core/parser.dart'; +import 'code.dart'; +import 'optimize.dart'; +import 'parser.dart'; + +/// Returns a parser that accepts any of the specified characters. +Parser anyOf(String chars, [String? message]) { + return CharacterParser(optimizedString(chars), + message ?? 'any of "${toReadableString(chars)}" expected'); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/char.dart b/bin/expressions/src/deps/petitparser/src/parser/character/char.dart new file mode 100644 index 0000000..870a92f --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/char.dart @@ -0,0 +1,23 @@ +import '../../core/parser.dart'; +import 'code.dart'; +import 'parser.dart'; +import 'predicate.dart'; + +/// Returns a parser that accepts a specific character only. +Parser char(Object char, [String? message]) { + return CharacterParser(SingleCharPredicate(toCharCode(char)), + message ?? '"${toReadableString(char)}" expected'); +} + +class SingleCharPredicate extends CharacterPredicate { + final int value; + + const SingleCharPredicate(this.value); + + @override + bool test(int value) => identical(this.value, value); + + @override + bool isEqualTo(CharacterPredicate other) => + other is SingleCharPredicate && other.value == value; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/code.dart b/bin/expressions/src/deps/petitparser/src/parser/character/code.dart new file mode 100644 index 0000000..1d79da2 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/code.dart @@ -0,0 +1,46 @@ +/// Converts an object to a character code. +int toCharCode(Object element) { + if (element is num) { + return element.round(); + } + final value = element.toString(); + if (value.length != 1) { + throw ArgumentError('"$value" is not a character'); + } + return value.codeUnitAt(0); +} + +/// Converts a character to a readable string. +String toReadableString(Object element) => element is String + ? _toFormattedString(element) + : _toFormattedChar(toCharCode(element)); + +String _toFormattedString(String input) => + input.codeUnits.map(_toFormattedChar).join(); + +String _toFormattedChar(int code) { + switch (code) { + case 0x08: + return '\\b'; // backspace + case 0x09: + return '\\t'; // horizontal tab + case 0x0A: + return '\\n'; // new line + case 0x0B: + return '\\v'; // vertical tab + case 0x0C: + return '\\f'; // form feed + case 0x0D: + return '\\r'; // carriage return + case 0x22: + return '\\"'; // double quote + case 0x27: + return "\\'"; // single quote + case 0x5C: + return '\\\\'; // backslash + } + if (code < 0x20) { + return '\\x${code.toRadixString(16).padLeft(2, '0')}'; + } + return String.fromCharCode(code); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/constant.dart b/bin/expressions/src/deps/petitparser/src/parser/character/constant.dart new file mode 100644 index 0000000..f6c840f --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/constant.dart @@ -0,0 +1,14 @@ +import 'predicate.dart'; + +class ConstantCharPredicate extends CharacterPredicate { + final bool constant; + + const ConstantCharPredicate(this.constant); + + @override + bool test(int value) => constant; + + @override + bool isEqualTo(CharacterPredicate other) => + other is ConstantCharPredicate && other.constant == constant; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/digit.dart b/bin/expressions/src/deps/petitparser/src/parser/character/digit.dart new file mode 100644 index 0000000..413bed5 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/digit.dart @@ -0,0 +1,18 @@ +import '../../core/parser.dart'; +import 'parser.dart'; +import 'predicate.dart'; + +/// Returns a parser that accepts any digit character. +Parser digit([String message = 'digit expected']) { + return CharacterParser(const DigitCharPredicate(), message); +} + +class DigitCharPredicate extends CharacterPredicate { + const DigitCharPredicate(); + + @override + bool test(int value) => 48 <= value && value <= 57; + + @override + bool isEqualTo(CharacterPredicate other) => other is DigitCharPredicate; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/letter.dart b/bin/expressions/src/deps/petitparser/src/parser/character/letter.dart new file mode 100644 index 0000000..b5ac61a --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/letter.dart @@ -0,0 +1,19 @@ +import '../../core/parser.dart'; +import 'parser.dart'; +import 'predicate.dart'; + +/// Returns a parser that accepts any letter character. +Parser letter([String message = 'letter expected']) { + return CharacterParser(const LetterCharPredicate(), message); +} + +class LetterCharPredicate extends CharacterPredicate { + const LetterCharPredicate(); + + @override + bool test(int value) => + (65 <= value && value <= 90) || (97 <= value && value <= 122); + + @override + bool isEqualTo(CharacterPredicate other) => other is LetterCharPredicate; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/lookup.dart b/bin/expressions/src/deps/petitparser/src/parser/character/lookup.dart new file mode 100644 index 0000000..6c460cf --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/lookup.dart @@ -0,0 +1,75 @@ +import 'dart:typed_data'; + +import 'predicate.dart'; +import 'range.dart'; + +class LookupCharPredicate implements CharacterPredicate { + final int start; + final int stop; + final Uint32List bits; + + LookupCharPredicate(List ranges) + : start = ranges.first.start, + stop = ranges.last.stop, + bits = Uint32List( + (ranges.last.stop - ranges.first.start + 1 + offset) >> shift) { + for (final range in ranges) { + for (var index = range.start - start; + index <= range.stop - start; + index++) { + bits[index >> shift] |= mask[index & offset]; + } + } + } + + @override + bool test(int value) => + start <= value && value <= stop && _testBit(value - start); + + bool _testBit(int value) => + (bits[value >> shift] & mask[value & offset]) != 0; + + @override + bool isEqualTo(CharacterPredicate other) => + other is LookupCharPredicate && + other.start == start && + other.stop == stop && + other.bits == bits; + + static const int shift = 5; + static const int offset = 31; + static const List mask = [ + 1, + 2, + 4, + 8, + 16, + 32, + 64, + 128, + 256, + 512, + 1024, + 2048, + 4096, + 8192, + 16384, + 32768, + 65536, + 131072, + 262144, + 524288, + 1048576, + 2097152, + 4194304, + 8388608, + 16777216, + 33554432, + 67108864, + 134217728, + 268435456, + 536870912, + 1073741824, + 2147483648, + ]; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/lowercase.dart b/bin/expressions/src/deps/petitparser/src/parser/character/lowercase.dart new file mode 100644 index 0000000..c87f7b4 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/lowercase.dart @@ -0,0 +1,18 @@ +import '../../core/parser.dart'; +import 'parser.dart'; +import 'predicate.dart'; + +/// Returns a parser that accepts any lowercase character. +Parser lowercase([String message = 'lowercase letter expected']) { + return CharacterParser(const LowercaseCharPredicate(), message); +} + +class LowercaseCharPredicate extends CharacterPredicate { + const LowercaseCharPredicate(); + + @override + bool test(int value) => 97 <= value && value <= 122; + + @override + bool isEqualTo(CharacterPredicate other) => other is LowercaseCharPredicate; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/none_of.dart b/bin/expressions/src/deps/petitparser/src/parser/character/none_of.dart new file mode 100644 index 0000000..6c68f1c --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/none_of.dart @@ -0,0 +1,11 @@ +import '../../core/parser.dart'; +import 'code.dart'; +import 'not.dart'; +import 'optimize.dart'; +import 'parser.dart'; + +/// Returns a parser that accepts none of the specified characters. +Parser noneOf(String chars, [String? message]) { + return CharacterParser(NotCharacterPredicate(optimizedString(chars)), + message ?? 'none of "${toReadableString(chars)}" expected'); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/not.dart b/bin/expressions/src/deps/petitparser/src/parser/character/not.dart new file mode 100644 index 0000000..5ee22c2 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/not.dart @@ -0,0 +1,16 @@ +import 'predicate.dart'; + +/// Negates the result of a character predicate. +class NotCharacterPredicate extends CharacterPredicate { + final CharacterPredicate predicate; + + const NotCharacterPredicate(this.predicate); + + @override + bool test(int value) => !predicate.test(value); + + @override + bool isEqualTo(CharacterPredicate other) => + other is NotCharacterPredicate && + other.predicate.isEqualTo(other.predicate); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/optimize.dart b/bin/expressions/src/deps/petitparser/src/parser/character/optimize.dart new file mode 100644 index 0000000..459c2e6 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/optimize.dart @@ -0,0 +1,54 @@ +import 'char.dart'; +import 'constant.dart'; +import 'lookup.dart'; +import 'predicate.dart'; +import 'range.dart'; + +/// Creates an optimized character from a string. +CharacterPredicate optimizedString(String string) { + return optimizedRanges( + string.codeUnits.map((value) => RangeCharPredicate(value, value))); +} + +/// Creates an optimized predicate from a list of range predicates. +CharacterPredicate optimizedRanges(Iterable ranges) { + // 1. Sort the ranges: + final sortedRanges = List.of(ranges, growable: false); + sortedRanges.sort((first, second) { + return first.start != second.start + ? first.start - second.start + : first.stop - second.stop; + }); + + // 2. Merge adjacent or overlapping ranges: + final mergedRanges = []; + for (final thisRange in sortedRanges) { + if (mergedRanges.isEmpty) { + mergedRanges.add(thisRange); + } else { + final lastRange = mergedRanges.last; + if (lastRange.stop + 1 >= thisRange.start) { + final characterRange = + RangeCharPredicate(lastRange.start, thisRange.stop); + mergedRanges[mergedRanges.length - 1] = characterRange; + } else { + mergedRanges.add(thisRange); + } + } + } + + // 3. Build the best resulting predicate: + final matchingCount = mergedRanges.fold( + 0, (current, range) => current + (range.stop - range.start + 1)); + if (matchingCount == 0) { + return const ConstantCharPredicate(false); + } else if (matchingCount - 1 == 0xffff) { + return const ConstantCharPredicate(true); + } else if (mergedRanges.length == 1) { + return mergedRanges[0].start == mergedRanges[0].stop + ? SingleCharPredicate(mergedRanges[0].start) + : mergedRanges[0]; + } else { + return LookupCharPredicate(mergedRanges); + } +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/parser.dart b/bin/expressions/src/deps/petitparser/src/parser/character/parser.dart new file mode 100644 index 0000000..9fd6ccd --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/parser.dart @@ -0,0 +1,42 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import 'predicate.dart'; + +/// Parser class for individual character classes. +class CharacterParser extends Parser { + final CharacterPredicate predicate; + + final String message; + + CharacterParser(this.predicate, this.message); + + @override + Result parseOn(Context context) { + final buffer = context.buffer; + final position = context.position; + if (position < buffer.length && + predicate.test(buffer.codeUnitAt(position))) { + return context.success(buffer[position], position + 1); + } + return context.failure(message); + } + + @override + int fastParseOn(String buffer, int position) => + position < buffer.length && predicate.test(buffer.codeUnitAt(position)) + ? position + 1 + : -1; + + @override + String toString() => '${super.toString()}[$message]'; + + @override + CharacterParser copy() => CharacterParser(predicate, message); + + @override + bool hasEqualProperties(CharacterParser other) => + super.hasEqualProperties(other) && + predicate.isEqualTo(other.predicate) && + message == other.message; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/pattern.dart b/bin/expressions/src/deps/petitparser/src/parser/character/pattern.dart new file mode 100644 index 0000000..6c9c691 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/pattern.dart @@ -0,0 +1,75 @@ +import '../../core/parser.dart'; +import '../action/map.dart'; +import '../combinator/choice.dart'; +import '../combinator/optional.dart'; +import '../combinator/sequence.dart'; +import '../predicate/any.dart'; +import '../repeater/possessive.dart'; +import 'char.dart'; +import 'code.dart'; +import 'not.dart'; +import 'optimize.dart'; +import 'parser.dart'; +import 'predicate.dart'; +import 'range.dart'; + +/// Returns a parser that accepts a single character of a given character set +/// provided as a string. +/// +/// Characters match themselves. A dash `-` between two characters matches the +/// range of those characters. A caret `^` at the beginning negates the pattern. +/// +/// For example, the parser `pattern('aou')` accepts the character 'a', 'o', or +/// 'u', and fails for any other input. The parser `pattern('1-3')` accepts +/// either '1', '2', or '3'; and fails for any other character. The parser +/// `pattern('^aou') accepts any character, but fails for the characters 'a', +/// 'o', or 'u'. +Parser pattern(String element, [String? message]) { + return CharacterParser(pattern_.parse(element).value, + message ?? '[${toReadableString(element)}] expected'); +} + +/// Returns a parser that accepts a single character of a given case-insensitive +/// character set provided as a string. +/// +/// Characters match themselves. A dash `-` between two characters matches the +/// range of those characters. A caret `^` at the beginning negates the pattern. +/// +/// For example, the parser `patternIgnoreCase('aoU')` accepts the character +/// 'a', 'o', 'u' and 'A', 'O', 'U', and fails for any other input. The parser +/// `patternIgnoreCase('a-c')` accepts 'a', 'b', 'c' and 'A', 'B', 'C'; and +/// fails for any other character. The parser `patternIgnoreCase('^A') accepts +/// any character, but fails for the characters 'a' or 'A'. +Parser patternIgnoreCase(String element, [String? message]) { + final isNegated = element.startsWith('^'); + final value = isNegated ? element.substring(1) : element; + return pattern( + '${isNegated ? '^' : ''}${value.toLowerCase()}${value.toUpperCase()}', + message); +} + +/// Parser that reads a single character. +final Parser single_ = + any().map((element) => RangeCharPredicate( + toCharCode(element), + toCharCode(element), + )); + +/// Parser that reads a character range. +final Parser range_ = + any().seq(char('-')).seq(any()).map((elements) => RangeCharPredicate( + toCharCode(elements[0]), + toCharCode(elements[2]), + )); + +/// Parser that reads a sequence of single characters or ranges. +final Parser sequence_ = range_.or(single_).star().map( + (predicates) => optimizedRanges(predicates.cast())); + +/// Parser that reads a possibly negated sequence of predicates. +final Parser pattern_ = char('^') + .optional() + .seq(sequence_) + .map((predicates) => predicates[0] == null + ? predicates[1] + : NotCharacterPredicate(predicates[1])); diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/predicate.dart b/bin/expressions/src/deps/petitparser/src/parser/character/predicate.dart new file mode 100644 index 0000000..2e45efd --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/predicate.dart @@ -0,0 +1,13 @@ +import '../../meta/lib/meta.dart'; + +/// Abstract character predicate class. +@immutable +abstract class CharacterPredicate { + const CharacterPredicate(); + + /// Tests if the character predicate is satisfied. + bool test(int value); + + /// Compares the two predicates for equality. + bool isEqualTo(CharacterPredicate other); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/range.dart b/bin/expressions/src/deps/petitparser/src/parser/character/range.dart new file mode 100644 index 0000000..cec2547 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/range.dart @@ -0,0 +1,31 @@ +import '../../core/parser.dart'; +import 'code.dart'; +import 'parser.dart'; +import 'predicate.dart'; + +/// Returns a parser that accepts any character in the range +/// between [start] and [stop]. +Parser range(Object start, Object stop, [String? message]) { + return CharacterParser( + RangeCharPredicate(toCharCode(start), toCharCode(stop)), + message ?? + '${toReadableString(start)}..${toReadableString(stop)} expected'); +} + +class RangeCharPredicate implements CharacterPredicate { + final int start; + final int stop; + + RangeCharPredicate(this.start, this.stop) { + if (start > stop) { + throw ArgumentError('Invalid range: $start-$stop'); + } + } + + @override + bool test(int value) => start <= value && value <= stop; + + @override + bool isEqualTo(CharacterPredicate other) => + other is RangeCharPredicate && other.start == start && other.stop == stop; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/ranges.dart b/bin/expressions/src/deps/petitparser/src/parser/character/ranges.dart new file mode 100644 index 0000000..13d916e --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/ranges.dart @@ -0,0 +1,34 @@ +import 'predicate.dart'; + +class RangesCharPredicate implements CharacterPredicate { + final int length; + final List starts; + final List stops; + + const RangesCharPredicate(this.length, this.starts, this.stops); + + @override + bool test(int value) { + var min = 0; + var max = length; + while (min < max) { + final mid = min + ((max - min) >> 1); + final comp = starts[mid] - value; + if (comp == 0) { + return true; + } else if (comp < 0) { + min = mid + 1; + } else { + max = mid; + } + } + return 0 < min && value <= stops[min - 1]; + } + + @override + bool isEqualTo(CharacterPredicate other) => + other is RangesCharPredicate && + other.length == length && + other.starts == starts && + other.stops == stops; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/uppercase.dart b/bin/expressions/src/deps/petitparser/src/parser/character/uppercase.dart new file mode 100644 index 0000000..da7e4be --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/uppercase.dart @@ -0,0 +1,18 @@ +import '../../core/parser.dart'; +import 'parser.dart'; +import 'predicate.dart'; + +/// Returns a parser that accepts any uppercase character. +Parser uppercase([String message = 'uppercase letter expected']) { + return CharacterParser(const UppercaseCharPredicate(), message); +} + +class UppercaseCharPredicate implements CharacterPredicate { + const UppercaseCharPredicate(); + + @override + bool test(int value) => 65 <= value && value <= 90; + + @override + bool isEqualTo(CharacterPredicate other) => other is UppercaseCharPredicate; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/whitespace.dart b/bin/expressions/src/deps/petitparser/src/parser/character/whitespace.dart new file mode 100644 index 0000000..0855d38 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/whitespace.dart @@ -0,0 +1,58 @@ +import '../../core/parser.dart'; +import 'parser.dart'; +import 'predicate.dart'; + +/// Returns a parser that accepts any whitespace character. +Parser whitespace([String message = 'whitespace expected']) { + return CharacterParser(const WhitespaceCharPredicate(), message); +} + +class WhitespaceCharPredicate implements CharacterPredicate { + const WhitespaceCharPredicate(); + + @override + bool test(int value) { + if (value < 256) { + switch (value) { + case 9: + case 10: + case 11: + case 12: + case 13: + case 32: + case 133: + case 160: + return true; + default: + return false; + } + } else { + switch (value) { + case 5760: + case 8192: + case 8193: + case 8194: + case 8195: + case 8196: + case 8197: + case 8198: + case 8199: + case 8200: + case 8201: + case 8202: + case 8232: + case 8233: + case 8239: + case 8287: + case 12288: + case 65279: + return true; + default: + return false; + } + } + } + + @override + bool isEqualTo(CharacterPredicate other) => other is WhitespaceCharPredicate; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/character/word.dart b/bin/expressions/src/deps/petitparser/src/parser/character/word.dart new file mode 100644 index 0000000..cfabc93 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/character/word.dart @@ -0,0 +1,22 @@ +import '../../core/parser.dart'; +import 'parser.dart'; +import 'predicate.dart'; + +/// Returns a parser that accepts any word character. +Parser word([String message = 'letter or digit expected']) { + return CharacterParser(const WordCharPredicate(), message); +} + +class WordCharPredicate implements CharacterPredicate { + const WordCharPredicate(); + + @override + bool test(int value) => + (65 <= value && value <= 90) || + (97 <= value && value <= 122) || + (48 <= value && value <= 57) || + identical(value, 95); + + @override + bool isEqualTo(CharacterPredicate other) => other is WordCharPredicate; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/combinator/and.dart b/bin/expressions/src/deps/petitparser/src/parser/combinator/and.dart new file mode 100644 index 0000000..c690f67 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/combinator/and.dart @@ -0,0 +1,40 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import 'delegate.dart'; + +extension AndParserExtension on Parser { + /// Returns a parser (logical and-predicate) that succeeds whenever the + /// receiver does, but never consumes input. + /// + /// For example, the parser `char('_').and().seq(identifier)` accepts + /// identifiers that start with an underscore character. Since the predicate + /// does not consume accepted input, the parser `identifier` is given the + /// ability to process the complete identifier. + Parser and() => AndParser(this); +} + +/// The and-predicate, a parser that succeeds whenever its delegate does, but +/// does not consume the input stream [Parr 1994, 1995]. +class AndParser extends DelegateParser { + AndParser(Parser delegate) : super(delegate); + + @override + Result parseOn(Context context) { + final result = delegate.parseOn(context); + if (result.isSuccess) { + return context.success(result.value); + } else { + return result as Result; + } + } + + @override + int fastParseOn(String buffer, int position) { + final result = delegate.fastParseOn(buffer, position); + return result < 0 ? -1 : position; + } + + @override + AndParser copy() => AndParser(delegate); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/combinator/choice.dart b/bin/expressions/src/deps/petitparser/src/parser/combinator/choice.dart new file mode 100644 index 0000000..fa47da0 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/combinator/choice.dart @@ -0,0 +1,65 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import 'list.dart'; + +extension ChoiceParserExtension on Parser { + /// Returns a parser that accepts the receiver or [other]. The resulting + /// parser returns the parse result of the receiver, if the receiver fails + /// it returns the parse result of [other] (exclusive ordered choice). + /// + /// For example, the parser `letter().or(digit())` accepts a letter or a + /// digit. An example where the order matters is the following choice between + /// overlapping parsers: `letter().or(char('a'))`. In the example the parser + /// `char('a')` will never be activated, because the input is always consumed + /// `letter()`. This can be problematic if the author intended to attach a + /// production action to `char('a')`. + Parser or(Parser other) => this is ChoiceParser + ? ChoiceParser([...children, other]) + : ChoiceParser([this, other]); + + /// Convenience operator returning a parser that accepts the receiver or + /// [other]. See [or] for details. + Parser operator |(Parser other) => or(other); +} + +extension ChoiceIterableExtension on Iterable> { + /// Converts the parser in this iterable to a choice of parsers. + Parser toChoiceParser() => ChoiceParser(this); +} + +/// A parser that uses the first parser that succeeds. +class ChoiceParser extends ListParser { + ChoiceParser(Iterable> children) : super(children) { + if (children.isEmpty) { + throw ArgumentError('Choice parser cannot be empty.'); + } + } + + @override + Result parseOn(Context context) { + Result? result; + for (var i = 0; i < children.length; i++) { + result = children[i].parseOn(context); + if (result.isSuccess) { + return result as Result; + } + } + return result as Result; + } + + @override + int fastParseOn(String buffer, int position) { + var result = -1; + for (var i = 0; i < children.length; i++) { + result = children[i].fastParseOn(buffer, position); + if (result >= 0) { + return result; + } + } + return result; + } + + @override + ChoiceParser copy() => ChoiceParser(children as List>); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/combinator/delegate.dart b/bin/expressions/src/deps/petitparser/src/parser/combinator/delegate.dart new file mode 100644 index 0000000..e8aa2ac --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/combinator/delegate.dart @@ -0,0 +1,19 @@ +import '../../core/parser.dart'; + +/// An abstract parser that delegates to another one. +abstract class DelegateParser extends Parser { + Parser delegate; + + DelegateParser(this.delegate); + + @override + List get children => [delegate]; + + @override + void replace(Parser source, Parser target) { + super.replace(source, target); + if (delegate == source) { + delegate = target; + } + } +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/combinator/list.dart b/bin/expressions/src/deps/petitparser/src/parser/combinator/list.dart new file mode 100644 index 0000000..cf8dc00 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/combinator/list.dart @@ -0,0 +1,20 @@ +import '../../core/parser.dart'; + +/// Abstract parser that parses a list of things in some way. +abstract class ListParser extends Parser { + ListParser(Iterable children) + : children = List.of(children, growable: false); + + @override + final List children; + + @override + void replace(Parser source, Parser target) { + super.replace(source, target); + for (var i = 0; i < children.length; i++) { + if (children[i] == source) { + children[i] = target; + } + } + } +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/combinator/not.dart b/bin/expressions/src/deps/petitparser/src/parser/combinator/not.dart new file mode 100644 index 0000000..cd19085 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/combinator/not.dart @@ -0,0 +1,65 @@ +import '../../context/context.dart'; +import '../../context/failure.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../action/cast.dart'; +import '../action/pick.dart'; +import '../combinator/sequence.dart'; +import '../predicate/any.dart'; +import 'delegate.dart'; + +extension NotParserExtension on Parser { + /// Returns a parser (logical not-predicate) that succeeds with the [Failure] + /// whenever the receiver fails, but never consumes input. + /// + /// For example, the parser `char('_').not().seq(identifier)` accepts + /// identifiers that do not start with an underscore character. If the parser + /// `char('_')` accepts the input, the negation and subsequently the + /// complete parser fails. Otherwise the parser `identifier` is given the + /// ability to process the complete identifier. + Parser> not([String message = 'success not expected']) => + NotParser(this, message); + + /// Returns a parser that consumes any input token (character), but the + /// receiver. + /// + /// For example, the parser `letter().neg()` accepts any input but a letter. + /// The parser fails for inputs like `'a'` or `'Z'`, but succeeds for + /// input like `'1'`, `'_'` or `'$'`. + Parser neg([String message = 'input not expected']) => + [not(message), any()].toSequenceParser().pick(1).cast(); +} + +/// The not-predicate, a parser that succeeds whenever its delegate does not, +/// but consumes no input [Parr 1994, 1995]. +class NotParser extends DelegateParser> { + final String message; + + NotParser(Parser delegate, this.message) : super(delegate); + + @override + Result> parseOn(Context context) { + final result = delegate.parseOn(context); + if (result.isFailure) { + return context.success(result as Failure); + } else { + return context.failure(message); + } + } + + @override + int fastParseOn(String buffer, int position) { + final result = delegate.fastParseOn(buffer, position); + return result < 0 ? position : -1; + } + + @override + String toString() => '${super.toString()}[$message]'; + + @override + NotParser copy() => NotParser(delegate as Parser, message); + + @override + bool hasEqualProperties(NotParser other) => + super.hasEqualProperties(other) && message == other.message; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/combinator/optional.dart b/bin/expressions/src/deps/petitparser/src/parser/combinator/optional.dart new file mode 100644 index 0000000..73f55c4 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/combinator/optional.dart @@ -0,0 +1,53 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import 'delegate.dart'; + +extension OptionalParserExtension on Parser { + /// Returns new parser that accepts the receiver, if possible. The resulting + /// parser returns the result of the receiver, or `null` if not applicable. + /// + /// For example, the parser `letter().optional()` accepts a letter as input + /// and returns that letter. When given something else the parser succeeds as + /// well, does not consume anything and returns `null`. + Parser optional() => OptionalParser(this, null); + + /// Returns new parser that accepts the receiver, if possible. The resulting + /// parser returns the result of the receiver, or [value] if not applicable. + /// + /// For example, the parser `letter().optionalWith('!')` accepts a letter as + /// input and returns that letter. When given something else the parser + /// succeeds as well, does not consume anything and returns `'!'`. + Parser optionalWith(T value) => OptionalParser(this, value); +} + +/// A parser that optionally parsers its delegate, or answers null. +class OptionalParser extends DelegateParser { + final T otherwise; + + OptionalParser(Parser delegate, this.otherwise) : super(delegate); + + @override + Result parseOn(Context context) { + final result = delegate.parseOn(context); + if (result.isSuccess) { + return result as Result; + } else { + return context.success(otherwise); + } + } + + @override + int fastParseOn(String buffer, int position) { + final result = delegate.fastParseOn(buffer, position); + return result < 0 ? position : result; + } + + @override + OptionalParser copy() => + OptionalParser(delegate as Parser, otherwise); + + @override + bool hasEqualProperties(OptionalParser other) => + super.hasEqualProperties(other) && otherwise == other.otherwise; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/combinator/sequence.dart b/bin/expressions/src/deps/petitparser/src/parser/combinator/sequence.dart new file mode 100644 index 0000000..b744038 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/combinator/sequence.dart @@ -0,0 +1,62 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import 'list.dart'; + +extension SequenceParserExtension on Parser { + /// Returns a parser that accepts the receiver followed by [other]. The + /// resulting parser returns a list of the parse result of the receiver + /// followed by the parse result of [other]. Calling this method on an + /// existing sequence code does not nest this sequence into a new one, but + /// instead augments the existing sequence with [other]. + /// + /// For example, the parser `letter().seq(digit()).seq(letter())` accepts a + /// letter followed by a digit and another letter. The parse result of the + /// input string `'a1b'` is the list `['a', '1', 'b']`. + Parser seq(Parser other) => this is SequenceParser + ? SequenceParser([...children, other]) + : SequenceParser([this, other]); + + /// Convenience operator returning a parser that accepts the receiver followed + /// by [other]. See [seq] for details. + Parser operator &(Parser other) => seq(other); +} + +extension SequenceIterableExtension on Iterable> { + /// Converts the parser in this iterable to a sequence of parsers. + Parser> toSequenceParser() => SequenceParser(this); +} + +/// A parser that parses a sequence of parsers. +class SequenceParser extends ListParser> { + SequenceParser(Iterable> children) : super(children); + + @override + Result> parseOn(Context context) { + var current = context; + final elements = []; + for (var i = 0; i < children.length; i++) { + final result = children[i].parseOn(current); + if (result.isFailure) { + return result.failure(result.message); + } + elements.add(result.value); + current = result; + } + return current.success(elements); + } + + @override + int fastParseOn(String buffer, int position) { + for (var i = 0; i < children.length; i++) { + position = children[i].fastParseOn(buffer, position); + if (position < 0) { + return position; + } + } + return position; + } + + @override + SequenceParser copy() => SequenceParser(children as List>); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/combinator/settable.dart b/bin/expressions/src/deps/petitparser/src/parser/combinator/settable.dart new file mode 100644 index 0000000..b6442e1 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/combinator/settable.dart @@ -0,0 +1,45 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../combinator/delegate.dart'; +import '../misc/failure.dart'; + +extension SettableParserExtension on Parser { + /// Returns a parser that points to the receiver, but can be changed to point + /// to something else at a later point in time. + /// + /// For example, the parser `letter().settable()` behaves exactly the same + /// as `letter()`, but it can be replaced with another parser using + /// [SettableParser.set]. + SettableParser settable() => SettableParser(this); +} + +/// Returns a parser that is not defined, but that can be set at a later +/// point in time. +/// +/// For example, the following code sets up a parser that points to itself +/// and that accepts a sequence of a's ended with the letter b. +/// +/// final p = undefined(); +/// p.set(char('a').seq(p).or(char('b'))); +SettableParser undefined([String message = 'undefined parser']) => + failure(message).settable(); + +/// A parser that is not defined, but that can be set at a later +/// point in time. +class SettableParser extends DelegateParser { + SettableParser(Parser delegate) : super(delegate); + + /// Sets the receiver to delegate to [parser]. + void set(Parser parser) => replace(children[0], parser); + + @override + Result parseOn(Context context) => delegate.parseOn(context) as Result; + + @override + int fastParseOn(String buffer, int position) => + delegate.fastParseOn(buffer, position); + + @override + SettableParser copy() => SettableParser(delegate as Parser); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/misc/eof.dart b/bin/expressions/src/deps/petitparser/src/parser/misc/eof.dart new file mode 100644 index 0000000..e5a4bc7 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/misc/eof.dart @@ -0,0 +1,47 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import '../action/cast.dart'; +import '../action/pick.dart'; +import '../combinator/sequence.dart'; + +extension EndOfInputParserExtension on Parser { + /// Returns a parser that succeeds only if the receiver consumes the complete + /// input, otherwise return a failure with the optional [message]. + /// + /// For example, the parser `letter().end()` succeeds on the input `'a'` + /// and fails on `'ab'`. In contrast the parser `letter()` alone would + /// succeed on both inputs, but not consume everything for the second input. + Parser end([String message = 'end of input expected']) => + [this, endOfInput(message)].toSequenceParser().pick(0).cast(); +} + +/// Returns a parser that succeeds at the end of input. +Parser endOfInput([String message = 'end of input expected']) => + EndOfInputParser(message); + +/// A parser that succeeds at the end of input. +class EndOfInputParser extends Parser { + final String message; + + EndOfInputParser(this.message); + + @override + Result parseOn(Context context) => context.position < context.buffer.length + ? context.failure(message) + : context.success(null); + + @override + int fastParseOn(String buffer, int position) => + position < buffer.length ? -1 : position; + + @override + String toString() => '${super.toString()}[$message]'; + + @override + EndOfInputParser copy() => EndOfInputParser(message); + + @override + bool hasEqualProperties(EndOfInputParser other) => + super.hasEqualProperties(other) && message == other.message; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/misc/epsilon.dart b/bin/expressions/src/deps/petitparser/src/parser/misc/epsilon.dart new file mode 100644 index 0000000..030318f --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/misc/epsilon.dart @@ -0,0 +1,32 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; + +/// Returns a parser that consumes nothing and succeeds. +/// +/// For example, `char('a').or(epsilon())` is equivalent to +/// `char('a').optional()`. +Parser epsilon() => epsilonWith(null); + +/// Returns a parser that consumes nothing and succeeds with [result]. +Parser epsilonWith(T result) => EpsilonParser(result); + +/// A parser that consumes nothing and succeeds. +class EpsilonParser extends Parser { + final T result; + + EpsilonParser(this.result); + + @override + Result parseOn(Context context) => context.success(result); + + @override + int fastParseOn(String buffer, int position) => position; + + @override + EpsilonParser copy() => EpsilonParser(result); + + @override + bool hasEqualProperties(EpsilonParser other) => + super.hasEqualProperties(other) && result == other.result; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/misc/failure.dart b/bin/expressions/src/deps/petitparser/src/parser/misc/failure.dart new file mode 100644 index 0000000..8518d85 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/misc/failure.dart @@ -0,0 +1,32 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; + +/// Returns a parser that consumes nothing and fails. +/// +/// For example, `failure()` always fails, no matter what input it is given. +Parser failure([String message = 'unable to parse']) => + FailureParser(message); + +/// A parser that consumes nothing and fails. +class FailureParser extends Parser { + final String message; + + FailureParser(this.message); + + @override + Result parseOn(Context context) => context.failure(message); + + @override + int fastParseOn(String buffer, int position) => -1; + + @override + String toString() => '${super.toString()}[$message]'; + + @override + FailureParser copy() => FailureParser(message); + + @override + bool hasEqualProperties(FailureParser other) => + super.hasEqualProperties(other) && message == other.message; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/misc/position.dart b/bin/expressions/src/deps/petitparser/src/parser/misc/position.dart new file mode 100644 index 0000000..571025c --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/misc/position.dart @@ -0,0 +1,20 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; + +/// Returns a parser that reports the current input position. +Parser position() => PositionParser(); + +/// A parser that reports the current input position. +class PositionParser extends Parser { + PositionParser(); + + @override + Result parseOn(Context context) => context.success(context.position); + + @override + int fastParseOn(String buffer, int position) => position; + + @override + PositionParser copy() => PositionParser(); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/predicate/any.dart b/bin/expressions/src/deps/petitparser/src/parser/predicate/any.dart new file mode 100644 index 0000000..08a2782 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/predicate/any.dart @@ -0,0 +1,38 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; + +/// Returns a parser that accepts any input element. +/// +/// For example, `any()` succeeds and consumes any given letter. It only +/// fails for an empty input. +Parser any([String message = 'input expected']) { + return AnyParser(message); +} + +/// A parser that accepts any input element. +class AnyParser extends Parser { + final String message; + + AnyParser(this.message); + + @override + Result parseOn(Context context) { + final position = context.position; + final buffer = context.buffer; + return position < buffer.length + ? context.success(buffer[position], position + 1) + : context.failure(message); + } + + @override + int fastParseOn(String buffer, int position) => + position < buffer.length ? position + 1 : -1; + + @override + AnyParser copy() => AnyParser(message); + + @override + bool hasEqualProperties(AnyParser other) => + super.hasEqualProperties(other) && message == other.message; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/predicate/predicate.dart b/bin/expressions/src/deps/petitparser/src/parser/predicate/predicate.dart new file mode 100644 index 0000000..0821104 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/predicate/predicate.dart @@ -0,0 +1,62 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; + +/// A generic predicate function returning `true` or `false` for a given +/// [input] argument. +typedef Predicate = bool Function(String input); + +/// Returns a parser that reads input of the specified [length], accepts +/// it if the [predicate] matches, or fails with the given [message]. +Parser predicate(int length, Predicate predicate, String message) { + return PredicateParser(length, predicate, message); +} + +/// A parser for a literal satisfying a predicate. +class PredicateParser extends Parser { + /// The length of the input to read. + final int length; + + /// The predicate function testing the input. + final Predicate predicate; + + /// The failure message in case of a miss-match. + final String message; + + PredicateParser(this.length, this.predicate, this.message) + : assert(length > 0, 'length must be positive'); + + @override + Result parseOn(Context context) { + final start = context.position; + final stop = start + length; + if (stop <= context.buffer.length) { + final result = context.buffer.substring(start, stop); + if (predicate(result)) { + return context.success(result, stop); + } + } + return context.failure(message); + } + + @override + int fastParseOn(String buffer, int position) { + final stop = position + length; + return stop <= buffer.length && predicate(buffer.substring(position, stop)) + ? stop + : -1; + } + + @override + String toString() => '${super.toString()}[$message]'; + + @override + PredicateParser copy() => PredicateParser(length, predicate, message); + + @override + bool hasEqualProperties(PredicateParser other) => + super.hasEqualProperties(other) && + length == other.length && + predicate == other.predicate && + message == other.message; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/predicate/string.dart b/bin/expressions/src/deps/petitparser/src/parser/predicate/string.dart new file mode 100644 index 0000000..a2bc0ec --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/predicate/string.dart @@ -0,0 +1,52 @@ +import '../../core/parser.dart'; +import '../character/any_of.dart'; +import '../character/char.dart'; +import '../character/pattern.dart'; +import '../misc/epsilon.dart'; +import 'predicate.dart'; + +extension PredicateStringExtension on String { + /// Converts this string to a corresponding parser. + Parser toParser({ + bool isPattern = false, + bool caseInsensitive = false, + String? message, + }) { + if (isEmpty) { + return epsilonWith(this); + } else if (length == 1) { + return caseInsensitive + ? anyOf('${toLowerCase()}${toUpperCase()}', message) + : char(this, message); + } else { + if (isPattern) { + return caseInsensitive + ? patternIgnoreCase(this, message) + : pattern(this, message); + } else { + return caseInsensitive + ? stringIgnoreCase(this, message) + : string(this, message); + } + } + } +} + +/// Returns a parser that accepts the string [element]. +/// +/// For example, `string('foo')` `succeeds and consumes the input string +/// `'foo'`. Fails for any other input.` +Parser string(String element, [String? message]) { + return predicate(element.length, (each) => element == each, + message ?? '$element expected'); +} + +/// Returns a parser that accepts the string [element] ignoring the case. +/// +/// For example, `stringIgnoreCase('foo')` succeeds and consumes the input +/// string `'Foo'` or `'FOO'`. Fails for any other input. +Parser stringIgnoreCase(String element, [String? message]) { + final lowerElement = element.toLowerCase(); + return predicate(element.length, (each) => lowerElement == each.toLowerCase(), + message ?? '$element expected'); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/repeater/greedy.dart b/bin/expressions/src/deps/petitparser/src/parser/repeater/greedy.dart new file mode 100644 index 0000000..784dc35 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/repeater/greedy.dart @@ -0,0 +1,126 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import 'lazy.dart'; +import 'limited.dart'; +import 'possessive.dart'; +import 'unbounded.dart'; + +extension GreedyRepeatingParserExtension on Parser { + /// Returns a parser that parses the receiver zero or more times until it + /// reaches a [limit]. This is a greedy non-blind implementation of the + /// [star] operator. The [limit] is not consumed. + /// + /// For example, the parser `char('{') & any().starGreedy(char('}')) & + /// char('}')` consumes the complete input `'{abc}def}'` of `'{abc}def}'`. + /// + /// See [starLazy] for the lazy, more efficient, and generally preferred + /// variation of this combinator. + Parser> starGreedy(Parser limit) => repeatGreedy(limit, 0, unbounded); + + /// Returns a parser that parses the receiver one or more times until it + /// reaches [limit]. This is a greedy non-blind implementation of the [plus] + /// operator. The [limit] is not consumed. + /// + /// For example, the parser `char('{') & any().plusGreedy(char('}')) & + /// char('}')` consumes the complete input `'{abc}def}'` of `'{abc}def}'`. + /// + /// See [plusLazy] for the lazy, more efficient, and generally preferred + /// variation of this combinator. + Parser> plusGreedy(Parser limit) => repeatGreedy(limit, 1, unbounded); + + /// Returns a parser that parses the receiver at least [min] and at most [max] + /// times until it reaches a [limit]. This is a greedy non-blind + /// implementation of the [repeat] operator. The [limit] is not consumed. + /// + /// This is the more generic variation of the [starGreedy] and [plusGreedy] + /// combinators. + Parser> repeatGreedy(Parser limit, int min, int max) => + GreedyRepeatingParser(this, limit, min, max); +} + +/// A greedy repeating parser, commonly seen in regular expression +/// implementations. It aggressively consumes as much input as possible and then +/// backtracks to meet the 'limit' condition. +class GreedyRepeatingParser extends LimitedRepeatingParser { + GreedyRepeatingParser(Parser parser, Parser limit, int min, int max) + : super(parser, limit, min, max); + + @override + Result> parseOn(Context context) { + var current = context; + final elements = []; + while (elements.length < min) { + final result = delegate.parseOn(current); + if (result.isFailure) { + return result.failure(result.message); + } + elements.add(result.value); + current = result; + } + final contexts = [current]; + while (max == unbounded || elements.length < max) { + final result = delegate.parseOn(current); + if (result.isFailure) { + break; + } + elements.add(result.value); + contexts.add(current = result); + } + for (;;) { + final limiter = limit.parseOn(contexts.last); + if (limiter.isSuccess) { + return contexts.last.success(elements); + } + if (elements.isEmpty) { + return limiter.failure(limiter.message); + } + contexts.removeLast(); + elements.removeLast(); + if (contexts.isEmpty) { + return limiter.failure(limiter.message); + } + } + } + + @override + int fastParseOn(String buffer, int position) { + var count = 0; + var current = position; + while (count < min) { + final result = delegate.fastParseOn(buffer, current); + if (result < 0) { + return -1; + } + current = result; + count++; + } + final positions = [current]; + while (max == unbounded || count < max) { + final result = delegate.fastParseOn(buffer, current); + if (result < 0) { + break; + } + positions.add(current = result); + count++; + } + for (;;) { + final limiter = limit.fastParseOn(buffer, positions.last); + if (limiter >= 0) { + return positions.last; + } + if (count == 0) { + return -1; + } + positions.removeLast(); + count--; + if (positions.isEmpty) { + return -1; + } + } + } + + @override + GreedyRepeatingParser copy() => + GreedyRepeatingParser(delegate as Parser, limit, min, max); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/repeater/lazy.dart b/bin/expressions/src/deps/petitparser/src/parser/repeater/lazy.dart new file mode 100644 index 0000000..573c368 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/repeater/lazy.dart @@ -0,0 +1,112 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import 'greedy.dart'; +import 'limited.dart'; +import 'possessive.dart'; +import 'unbounded.dart'; + +extension LazyRepeatingParserExtension on Parser { + /// Returns a parser that parses the receiver zero or more times until it + /// reaches a [limit]. This is a lazy non-blind implementation of the [star] + /// operator. The [limit] is not consumed. + /// + /// For example, the parser `char('{') & any().starLazy(char('}')) & + /// char('}')` only consumes the part `'{abc}'` of `'{abc}def}'`. + /// + /// See [starGreedy] for the greedy and less efficient variation of + /// this combinator. + Parser> starLazy(Parser limit) => repeatLazy(limit, 0, unbounded); + + /// Returns a parser that parses the receiver one or more times until it + /// reaches a [limit]. This is a lazy non-blind implementation of the [plus] + /// operator. The [limit] is not consumed. + /// + /// For example, the parser `char('{') & any().plusLazy(char('}')) & + /// char('}')` only consumes the part `'{abc}'` of `'{abc}def}'`. + /// + /// See [plusGreedy] for the greedy and less efficient variation of + /// this combinator. + Parser> plusLazy(Parser limit) => repeatLazy(limit, 1, unbounded); + + /// Returns a parser that parses the receiver at least [min] and at most [max] + /// times until it reaches a [limit]. This is a lazy non-blind implementation + /// of the [repeat] operator. The [limit] is not consumed. + /// + /// This is the more generic variation of the [starLazy] and [plusLazy] + /// combinators. + Parser> repeatLazy(Parser limit, int min, int max) => + LazyRepeatingParser(this, limit, min, max); +} + +/// A lazy repeating parser, commonly seen in regular expression +/// implementations. It limits its consumption to meet the 'limit' condition as +/// early as possible. +class LazyRepeatingParser extends LimitedRepeatingParser { + LazyRepeatingParser(Parser parser, Parser limit, int min, int max) + : super(parser, limit, min, max); + + @override + Result> parseOn(Context context) { + var current = context; + final elements = []; + while (elements.length < min) { + final result = delegate.parseOn(current); + if (result.isFailure) { + return result.failure(result.message); + } + elements.add(result.value); + current = result; + } + for (;;) { + final limiter = limit.parseOn(current); + if (limiter.isSuccess) { + return current.success(elements); + } else { + if (max != unbounded && elements.length >= max) { + return limiter.failure(limiter.message); + } + final result = delegate.parseOn(current); + if (result.isFailure) { + return limiter.failure(limiter.message); + } + elements.add(result.value); + current = result; + } + } + } + + @override + int fastParseOn(String buffer, int position) { + var count = 0; + var current = position; + while (count < min) { + final result = delegate.fastParseOn(buffer, current); + if (result < 0) { + return -1; + } + current = result; + count++; + } + for (;;) { + final limiter = limit.fastParseOn(buffer, current); + if (limiter >= 0) { + return current; + } else { + if (max != unbounded && count >= max) { + return -1; + } + final result = delegate.fastParseOn(buffer, current); + if (result < 0) { + return -1; + } + current = result; + count++; + } + } + } + + @override + LazyRepeatingParser copy() => + LazyRepeatingParser(delegate as Parser, limit, min, max); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/repeater/limited.dart b/bin/expressions/src/deps/petitparser/src/parser/repeater/limited.dart new file mode 100644 index 0000000..3f89488 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/repeater/limited.dart @@ -0,0 +1,24 @@ +import '../../core/parser.dart'; +import 'repeating.dart'; + +/// An abstract parser that repeatedly parses between 'min' and 'max' instances +/// of its delegate and that requires the input to be completed with a specified +/// parser 'limit'. Subclasses provide repeating behavior as typically seen in +/// regular expression implementations (non-blind). +abstract class LimitedRepeatingParser extends RepeatingParser { + Parser limit; + + LimitedRepeatingParser(Parser delegate, this.limit, int min, int max) + : super(delegate, min, max); + + @override + List get children => [delegate, limit]; + + @override + void replace(Parser source, Parser target) { + super.replace(source, target); + if (limit == source) { + limit = target; + } + } +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/repeater/possessive.dart b/bin/expressions/src/deps/petitparser/src/parser/repeater/possessive.dart new file mode 100644 index 0000000..62022a6 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/repeater/possessive.dart @@ -0,0 +1,103 @@ +import '../../context/context.dart'; +import '../../context/result.dart'; +import '../../core/parser.dart'; +import 'repeating.dart'; +import 'unbounded.dart'; + +extension PossessiveRepeatingParserExtension on Parser { + /// Returns a parser that accepts the receiver zero or more times. The + /// resulting parser returns a list of the parse results of the receiver. + /// + /// This is a greedy and blind implementation that tries to consume as much + /// input as possible and that does not consider what comes afterwards. + /// + /// For example, the parser `letter().star()` accepts the empty string or + /// any sequence of letters and returns a possibly empty list of the parsed + /// letters. + Parser> star() => repeat(0, unbounded); + + /// Returns a parser that accepts the receiver one or more times. The + /// resulting parser returns a list of the parse results of the receiver. + /// + /// This is a greedy and blind implementation that tries to consume as much + /// input as possible and that does not consider what comes afterwards. + /// + /// For example, the parser `letter().plus()` accepts any sequence of + /// letters and returns a list of the parsed letters. + Parser> plus() => repeat(1, unbounded); + + /// Returns a parser that accepts the receiver exactly [count] times. The + /// resulting parser returns a list of the parse results of the receiver. + /// + /// For example, the parser `letter().times(2)` accepts two letters and + /// returns a list of the two parsed letters. + Parser> times(int count) => repeat(count, count); + + /// Returns a parser that accepts the receiver between [min] and [max] times. + /// The resulting parser returns a list of the parse results of the receiver. + /// + /// This is a greedy and blind implementation that tries to consume as much + /// input as possible and that does not consider what comes afterwards. + /// + /// For example, the parser `letter().repeat(2, 4)` accepts a sequence of + /// two, three, or four letters and returns the accepted letters as a list. + Parser> repeat(int min, [int? max]) => + PossessiveRepeatingParser(this, min, max ?? min); +} + +/// A greedy parser that repeatedly parses between 'min' and 'max' instances of +/// its delegate. +class PossessiveRepeatingParser extends RepeatingParser { + PossessiveRepeatingParser(Parser parser, int min, int max) + : super(parser, min, max); + + @override + Result> parseOn(Context context) { + final elements = []; + var current = context; + while (elements.length < min) { + final result = delegate.parseOn(current); + if (result.isFailure) { + return result.failure(result.message); + } + elements.add(result.value); + current = result; + } + while (max == unbounded || elements.length < max) { + final result = delegate.parseOn(current); + if (result.isFailure) { + return current.success(elements); + } + elements.add(result.value); + current = result; + } + return current.success(elements); + } + + @override + int fastParseOn(String buffer, int position) { + var count = 0; + var current = position; + while (count < min) { + final result = delegate.fastParseOn(buffer, current); + if (result < 0) { + return -1; + } + current = result; + count++; + } + while (max == unbounded || count < max) { + final result = delegate.fastParseOn(buffer, current); + if (result < 0) { + return current; + } + current = result; + count++; + } + return current; + } + + @override + PossessiveRepeatingParser copy() => + PossessiveRepeatingParser(delegate as Parser, min, max); +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/repeater/repeating.dart b/bin/expressions/src/deps/petitparser/src/parser/repeater/repeating.dart new file mode 100644 index 0000000..b48ff40 --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/repeater/repeating.dart @@ -0,0 +1,29 @@ +import '../../core/parser.dart'; +import '../combinator/delegate.dart'; +import 'unbounded.dart'; + +/// An abstract parser that repeatedly parses between 'min' and 'max' instances +/// of its delegate. +abstract class RepeatingParser extends DelegateParser> { + final int min; + final int max; + + RepeatingParser(Parser parser, this.min, this.max) : super(parser) { + if (min < 0) { + throw ArgumentError( + 'Minimum repetitions must be positive, but got $min.'); + } + if (max != unbounded && max < min) { + throw ArgumentError( + 'Maximum repetitions must be larger than $min, but got $max.'); + } + } + + @override + String toString() => + '${super.toString()}[$min..${max == unbounded ? '*' : max}]'; + + @override + bool hasEqualProperties(RepeatingParser other) => + super.hasEqualProperties(other) && min == other.min && max == other.max; +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/repeater/separated_by.dart b/bin/expressions/src/deps/petitparser/src/parser/repeater/separated_by.dart new file mode 100644 index 0000000..53cb31a --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/repeater/separated_by.dart @@ -0,0 +1,44 @@ +import '../../core/parser.dart'; +import '../action/map.dart'; +import '../combinator/optional.dart'; +import '../combinator/sequence.dart'; +import '../repeater/possessive.dart'; + +extension SeparatedBy on Parser { + /// Returns a parser that consumes the receiver one or more times separated + /// by the [separator] parser. The resulting parser returns a flat list of + /// the parse results of the receiver interleaved with the parse result of the + /// separator parser. The type parameter `R` defines the type of the returned + /// list. + /// + /// If the optional argument [includeSeparators] is set to `false`, then the + /// separators are not included in the parse result. If the optional argument + /// [optionalSeparatorAtEnd] is set to `true` the parser also accepts an + /// optional separator at the end. + /// + /// For example, the parser `digit().separatedBy(char('-'))` returns a parser + /// that consumes input like `'1-2-3'` and returns a list of the elements and + /// separators: `['1', '-', '2', '-', '3']`. + Parser> separatedBy(Parser separator, + {bool includeSeparators = true, bool optionalSeparatorAtEnd = false}) { + final parser = [ + this, + [separator, this].toSequenceParser().star(), + if (optionalSeparatorAtEnd) separator.optional(), + ].toSequenceParser(); + return parser.map((list) { + final result = []; + result.add(list[0]); + for (final tuple in list[1]) { + if (includeSeparators) { + result.add(tuple[0]); + } + result.add(tuple[1]); + } + if (includeSeparators && optionalSeparatorAtEnd && list[2] != null) { + result.add(list[2]); + } + return result; + }); + } +} diff --git a/bin/expressions/src/deps/petitparser/src/parser/repeater/unbounded.dart b/bin/expressions/src/deps/petitparser/src/parser/repeater/unbounded.dart new file mode 100644 index 0000000..b12bc0f --- /dev/null +++ b/bin/expressions/src/deps/petitparser/src/parser/repeater/unbounded.dart @@ -0,0 +1,2 @@ +/// An [int] used to mark an unbounded maximum repetition. +const int unbounded = -1; diff --git a/bin/expressions/src/deps/quiver/LICENSE b/bin/expressions/src/deps/quiver/LICENSE new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/bin/expressions/src/deps/quiver/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/bin/expressions/src/deps/quiver/core.dart b/bin/expressions/src/deps/quiver/core.dart new file mode 100644 index 0000000..a7570a9 --- /dev/null +++ b/bin/expressions/src/deps/quiver/core.dart @@ -0,0 +1,15 @@ +/// Generates a hash code for three objects. +int hash3(a, b, c) => _finish( + _combine(_combine(_combine(0, a.hashCode), b.hashCode), c.hashCode)); + +int _finish(int hash) { + hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3)); + hash = hash ^ (hash >> 11); + return 0x1fffffff & (hash + ((0x00003fff & hash) << 15)); +} + +int _combine(int hash, int value) { + hash = 0x1fffffff & (hash + value); + hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10)); + return hash ^ (hash >> 6); +} \ No newline at end of file diff --git a/bin/expressions/src/evaluator.dart b/bin/expressions/src/evaluator.dart new file mode 100644 index 0000000..99ec34d --- /dev/null +++ b/bin/expressions/src/evaluator.dart @@ -0,0 +1,137 @@ +library expressions.evaluator; + +import 'expressions.dart'; + +class ExpressionEvaluator { + const ExpressionEvaluator(); + + dynamic eval(Expression expression, Map context) { + if (expression is Literal) return evalLiteral(expression, context); + if (expression is Variable) return evalVariable(expression, context); + if (expression is ThisExpression) return evalThis(expression, context); + if (expression is MemberExpression) { + return evalMemberExpression(expression, context); + } + if (expression is IndexExpression) { + return evalIndexExpression(expression, context); + } + if (expression is CallExpression) { + return evalCallExpression(expression, context); + } + if (expression is UnaryExpression) { + return evalUnaryExpression(expression, context); + } + if (expression is BinaryExpression) { + return evalBinaryExpression(expression, context); + } + if (expression is ConditionalExpression) { + return evalConditionalExpression(expression, context); + } + throw ArgumentError("Unknown expression type '${expression.runtimeType}'"); + } + + dynamic evalLiteral(Literal literal, Map context) { + var value = literal.value; + if (value is List) return value.map((e) => eval(e, context)).toList(); + if (value is Map) { + return value.map( + (key, value) => MapEntry(eval(key, context), eval(value, context))); + } + return value; + } + + dynamic evalVariable(Variable variable, Map context) { + return context[variable.identifier.name]; + } + + dynamic evalThis(ThisExpression expression, Map context) { + return context['this']; + } + + dynamic evalMemberExpression( + MemberExpression expression, Map context) { + throw UnsupportedError('Member expressions not supported'); + } + + dynamic evalIndexExpression( + IndexExpression expression, Map context) { + return eval(expression.object, context)[eval(expression.index, context)]; + } + + dynamic evalCallExpression( + CallExpression expression, Map context) { + var callee = eval(expression.callee, context); + var arguments = expression.arguments.map((e) => eval(e, context)).toList(); + return Function.apply(callee, arguments); + } + + dynamic evalUnaryExpression( + UnaryExpression expression, Map context) { + var argument = eval(expression.argument, context); + switch (expression.operator) { + case '-': + return -argument; + case '+': + return argument; + case '!': + return !argument; + case '~': + return ~argument; + } + throw ArgumentError('Unknown unary operator ${expression.operator}'); + } + + dynamic evalBinaryExpression( + BinaryExpression expression, Map context) { + var left = eval(expression.left, context); + var right = () => eval(expression.right, context); + switch (expression.operator) { + case '||': + return left || right(); + case '&&': + return left && right(); + case '|': + return left | right(); + case '^': + return left ^ right(); + case '&': + return left & right(); + case '==': + return left == right(); + case '!=': + return left != right(); + case '<=': + return left <= right(); + case '>=': + return left >= right(); + case '<': + return left < right(); + case '>': + return left > right(); + case '<<': + return left << right(); + case '>>': + return left >> right(); + case '+': + return left + right(); + case '-': + return left - right(); + case '*': + return left * right(); + case '/': + return left / right(); + case '%': + return left % right(); + } + throw ArgumentError( + 'Unknown operator ${expression.operator} in expression'); + } + + dynamic evalConditionalExpression( + ConditionalExpression expression, Map context) { + var test = eval(expression.test, context); + return test + ? eval(expression.consequent, context) + : eval(expression.alternate, context); + } +} diff --git a/bin/expressions/src/expressions.dart b/bin/expressions/src/expressions.dart new file mode 100644 index 0000000..2366801 --- /dev/null +++ b/bin/expressions/src/expressions.dart @@ -0,0 +1,163 @@ +library expressions.core; + +import 'deps/quiver/core.dart'; +import 'parser.dart'; +import 'deps/petitparser/petitparser.dart'; + +class Identifier { + final String name; + + Identifier(this.name) { + assert(name != 'null'); + assert(name != 'false'); + assert(name != 'true'); + assert(name != 'this'); + } + + @override + String toString() => name; +} + +abstract class Expression { + String toTokenString(); + + static final ExpressionParser _parser = ExpressionParser(); + + static Expression? tryParse(String formattedString) { + final result = _parser.expression.end().parse(formattedString); + return result.isSuccess ? result.value : null; + } + + static Expression parse(String formattedString) => + _parser.expression.end().parse(formattedString).value; +} + +abstract class SimpleExpression implements Expression { + @override + String toTokenString() => toString(); +} + +abstract class CompoundExpression implements Expression { + @override + String toTokenString() => '($this)'; +} + +class Literal extends SimpleExpression { + final dynamic value; + final String raw; + + Literal(this.value, [String? raw]) + : raw = raw ?? (value is String ? '"$value"' /*TODO escape*/ : '$value'); + + @override + String toString() => raw; + + @override + int get hashCode => value.hashCode; + + @override + bool operator ==(dynamic other) => other is Literal && other.value == value; +} + +class Variable extends SimpleExpression { + final Identifier identifier; + + Variable(this.identifier); + + @override + String toString() => '$identifier'; +} + +class ThisExpression extends SimpleExpression {} + +class MemberExpression extends SimpleExpression { + final Expression object; + + final Identifier property; + + MemberExpression(this.object, this.property); + + @override + String toString() => '${object.toTokenString()}.$property'; +} + +class IndexExpression extends SimpleExpression { + final Expression object; + + final Expression index; + + IndexExpression(this.object, this.index); + + @override + String toString() => '${object.toTokenString()}[$index]'; +} + +class CallExpression extends SimpleExpression { + final Expression callee; + final List arguments; + + CallExpression(this.callee, this.arguments); + + @override + String toString() => '${callee.toTokenString()}(${arguments.join(', ')})'; +} + +class UnaryExpression extends SimpleExpression { + final String operator; + + final Expression argument; + + final bool prefix; + + UnaryExpression(this.operator, this.argument, {this.prefix = true}); + + @override + String toString() => '$operator$argument'; +} + +class BinaryExpression extends CompoundExpression { + final String operator; + final Expression left; + final Expression right; + + BinaryExpression(this.operator, this.left, this.right); + + static int precedenceForOperator(String operator) => + ExpressionParser.binaryOperations[operator]!; + + int get precedence => precedenceForOperator(operator); + + @override + String toString() { + var l = (left is BinaryExpression && + (left as BinaryExpression).precedence < precedence) + ? '($left)' + : '$left'; + var r = (right is BinaryExpression && + (right as BinaryExpression).precedence < precedence) + ? '($right)' + : '$right'; + return '$l$operator$r'; + } + + @override + int get hashCode => hash3(left, operator, right); + + @override + bool operator ==(dynamic other) => + other is BinaryExpression && + other.left == left && + other.operator == operator && + other.right == right; +} + +class ConditionalExpression extends CompoundExpression { + final BinaryExpression test; + final Expression consequent; + final Expression alternate; + + ConditionalExpression(this.test, this.consequent, this.alternate); + + @override + String toString() => '$test ? $consequent : $alternate'; +} diff --git a/bin/expressions/src/parser.dart b/bin/expressions/src/parser.dart new file mode 100644 index 0000000..decdfb1 --- /dev/null +++ b/bin/expressions/src/parser.dart @@ -0,0 +1,249 @@ +library expressions.parser; + +import 'expressions.dart'; +import 'deps/petitparser/petitparser.dart'; + +class ExpressionParser { + ExpressionParser() { + expression.set(binaryExpression.seq(conditionArguments.optional()).map( + (l) => l[1] == null + ? l[0] + : ConditionalExpression(l[0], l[1][0], l[1][1]))); + token.set((literal | unaryExpression | variable).cast()); + } + + // Gobbles only identifiers + // e.g.: `foo`, `_value`, `$x1` + Parser get identifier => + (digit().not() & (word() | char(r'$')).plus()) + .flatten() + .map((v) => Identifier(v)); + + // Parse simple numeric literals: `12`, `3.4`, `.5`. + Parser get numericLiteral => ((digit() | char('.')).and() & + (digit().star() & + ((char('.') & digit().plus()) | + (char('x') & digit().plus()) | + (anyOf('Ee') & + anyOf('+-').optional() & + digit().plus())) + .optional())) + .flatten() + .map((v) { + return Literal(num.parse(v), v); + }); + + Parser get escapedChar => (char(r'\') & anyOf("nrtbfv\"'")).pick(1); + + String unescape(String v) => v.replaceAllMapped( + RegExp("\\\\[nrtbf\"']"), + (v) => const { + 'n': '\n', + 'r': '\r', + 't': '\t', + 'b': '\b', + 'f': '\f', + 'v': '\v', + "'": "'", + '"': '"' + }[v.group(0)!.substring(1)]!); + + Parser get sqStringLiteral => (char("'") & + (anyOf(r"'\").neg() | escapedChar).star().flatten() & + char("'")) + .pick(1) + .map((v) => Literal(unescape(v), "'$v'")); + + Parser get dqStringLiteral => (char('"') & + (anyOf(r'"\').neg() | escapedChar).star().flatten() & + char('"')) + .pick(1) + .map((v) => Literal(unescape(v), '"$v"')); + + // Parses a string literal, staring with single or double quotes with basic + // support for escape codes e.g. `'hello world'`, `'this is\nJSEP'` + Parser get stringLiteral => + sqStringLiteral.or(dqStringLiteral).cast(); + + // Parses a boolean literal + Parser get boolLiteral => + (string('true') | string('false')).map((v) => Literal(v == 'true', v)); + + // Parses the null literal + Parser get nullLiteral => + string('null').map((v) => Literal(null, v)); + + // Parses the this literal + Parser get thisExpression => + string('this').map((v) => ThisExpression()); + + // Responsible for parsing Array literals `[1, 2, 3]` + // This function assumes that it needs to gobble the opening bracket + // and then tries to gobble the expressions as arguments. + Parser get arrayLiteral => + (char('[').trim() & arguments & char(']').trim()) + .pick(1) + .map((l) => Literal(l, '$l')); + + Parser get mapLiteral => + (char('{').trim() & mapArguments & char('}').trim()) + .pick(1) + .map((l) => Literal(l, '$l')); + + Parser get literal => (numericLiteral | + stringLiteral | + boolLiteral | + nullLiteral | + arrayLiteral | + mapLiteral) + .cast(); + + // An individual part of a binary expression: + // e.g. `foo.bar(baz)`, `1`, `'abc'`, `(a % 2)` (because it's in parenthesis) + final SettableParser token = undefined(); + + // Also use a map for the binary operations but set their values to their + // binary precedence for quick reference: + // see [Order of operations](http://en.wikipedia.org/wiki/Order_of_operations#Programming_language) + static const Map binaryOperations = { + '||': 1, + '&&': 2, + '|': 3, + '^': 4, + '&': 5, + '==': 6, + '!=': 6, + '<=': 7, + '>=': 7, + '<': 7, + '>': 7, + '<<': 8, + '>>': 8, + '+': 9, + '-': 9, + '*': 10, + '/': 10, + '%': 10 + }; + + // This function is responsible for gobbling an individual expression, + // e.g. `1`, `1+2`, `a+(b*2)-Math.sqrt(2)` + Parser get binaryOperation => binaryOperations.keys + .map>((v) => string(v)) + .reduce((a, b) => (a | b).cast()) + .trim(); + + Parser get binaryExpression => + token.separatedBy(binaryOperation).map((l) { + var first = l[0]; + var stack = [first]; + + for (var i = 1; i < l.length; i += 2) { + var op = l[i]; + var prec = BinaryExpression.precedenceForOperator(op); + + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && + (prec <= + BinaryExpression.precedenceForOperator( + stack[stack.length - 2]))) { + var right = stack.removeLast(); + var op = stack.removeLast(); + var left = stack.removeLast(); + var node = BinaryExpression(op, left, right); + stack.add(node); + } + + var node = l[i + 1]; + stack.addAll([op, node]); + } + + var i = stack.length - 1; + var node = stack[i]; + while (i > 1) { + node = BinaryExpression(stack[i - 1], stack[i - 2], node); + i -= 2; + } + return node; + }); + + // Use a quickly-accessible map to store all of the unary operators + // Values are set to `true` (it really doesn't matter) + static const _unaryOperations = ['-', '!', '~', '+']; + + Parser get unaryExpression => _unaryOperations + .map>((v) => string(v)) + .reduce((a, b) => (a | b).cast()) + .trim() + .seq(token) + .map((l) => UnaryExpression(l[0], l[1])); + + // Gobbles a list of arguments within the context of a function call + // or array literal. This function also assumes that the opening character + // `(` or `[` has already been gobbled, and gobbles expressions and commas + // until the terminator character `)` or `]` is encountered. + // e.g. `foo(bar, baz)`, `my_func()`, or `[bar, baz]` + Parser> get arguments => expression + .separatedBy(char(',').trim(), includeSeparators: false) + .castList() + .optionalWith([]); + + Parser> get mapArguments => + (expression & char(':').trim() & expression) + .map((l) => MapEntry(l[0], l[2])) + .separatedBy(char(',').trim(), includeSeparators: false) + .castList>() + .map((l) => Map.fromEntries(l)) + .optionalWith({}); + + // Gobble a non-literal variable name. This variable name may include properties + // e.g. `foo`, `bar.baz`, `foo['bar'].baz` + // It also gobbles function calls: + // e.g. `Math.acos(obj.angle)` + Parser get variable => groupOrIdentifier + .seq((memberArgument.cast() | indexArgument | callArgument).star()) + .map((l) { + var a = l[0] as Expression; + var b = l[1] as List; + return b.fold(a, (Expression object, argument) { + if (argument is Identifier) { + return MemberExpression(object, argument); + } + if (argument is Expression) { + return IndexExpression(object, argument); + } + if (argument is List) { + return CallExpression(object, argument); + } + throw ArgumentError('Invalid type ${argument.runtimeType}'); + }); + }); + + // Responsible for parsing a group of things within parentheses `()` + // This function assumes that it needs to gobble the opening parenthesis + // and then tries to gobble everything within that parenthesis, assuming + // that the next thing it should see is the close parenthesis. If not, + // then the expression probably doesn't have a `)` + Parser get group => + (char('(') & expression.trim() & char(')')).pick(1); + + Parser get groupOrIdentifier => + (group | thisExpression | identifier.map((v) => Variable(v))).cast(); + + Parser get memberArgument => (char('.') & identifier).pick(1); + + Parser get indexArgument => + (char('[') & expression.trim() & char(']')).pick(1); + + Parser> get callArgument => + (char('(') & arguments & char(')')).pick(1); + + // Ternary expression: test ? consequent : alternate + Parser> get conditionArguments => + (char('?').trim() & expression & char(':').trim()) + .pick(1) + .seq(expression) + .castList(); + + final SettableParser expression = undefined(); +} diff --git a/bin/pre_script.dart b/bin/pre_script.dart index 187a7d2..da022f9 100644 --- a/bin/pre_script.dart +++ b/bin/pre_script.dart @@ -1,94 +1,73 @@ import 'dart:io'; import 'parse_arguments.dart'; -import 'path_utils.dart'; +import 'expressions/expressions.dart'; -String mode; -List flavors; -Args args; +String? exp; +late String mode; +late String flavor; enum STATE { none, notMatch, caching, - cached, replace, } void main(List arguments) { print("Running default pre_script."); - args = parse(arguments); + var args = parse(arguments); + mode = args.mode; + flavor = args.flavor; var rootDir = Directory('./'); rootDir.listSync().forEach(walkPath); } -File file; +File? file; StringBuffer sb = StringBuffer(); StringBuffer tmp = StringBuffer(); STATE state = STATE.none; -RegExp re = RegExp(r'// #\[(debug|release)?(?:\[(.*)\])?\]'); -RegExp pathRe = RegExp(r'\[(debug|release)?(?:\[(.*)\])?\]'); -Match ma; +RegExp re = RegExp(r'// #\{\{(.+)\}\}'); + +Match? ma; bool modified = false; +const evaluator = const ExpressionEvaluator(); + void walkPath(FileSystemEntity path) { var stat = path.statSync(); if (stat.type == FileSystemEntityType.directory) { Directory(path.path).listSync().forEach(walkPath); } else if (stat.type == FileSystemEntityType.file) { - ma = pathRe.firstMatch(PathUtils.baseName(path)); - if (ma != null) { - mode = ma.group(1); - flavors = (ma.group(2) ?? '').split(' ').where((ele) => ele.trim() != '').toList(); - if (checkModeAndFlavors()) { - var defaultFilePath = path.path.replaceFirst(ma.group(0), ''); - var defaultFile = File(defaultFilePath); - if (defaultFile.existsSync()) { - defaultFile.renameSync(defaultFilePath + '.default'); - } - File(path.path).copySync(defaultFilePath); - } - return; - } - - // 文件名不带规则,逐行读取后进行处理 file = File(path.path); sb.clear(); modified = false; try { - file.readAsLinesSync().forEach((line) { + file!.readAsLinesSync().forEach((line) { ma = re.firstMatch(line); if (ma != null) { modified = true; - mode = ma.group(1); - flavors = (ma.group(2) ?? '').split(' ').where((ele) => ele.trim() != '').toList(); - - // 默认的代码块 - if (mode == null && flavors.length == 0) { - // 前一状态为replace,此时应该将缓存内容写入替换区域,并将状态复位为none - if (state == STATE.replace) { + exp = ma!.group(1); + if (exp == "default") { + // 默认代码块开始 + if (tmp.isNotEmpty) { sb.write(tmp); - state = STATE.none; - } - // 前一状态为缓存中或缓存结束,此时应该将状态改为替换,用于跳过默认内容 - else if (state == STATE.caching || state == STATE.cached) { state = STATE.replace; - } else if (state == STATE.notMatch) { + } else { state = STATE.none; } + } else if (exp == "end") { + // 默认代码块结束 + state = STATE.none; + tmp.clear(); } else { - // 带有条件的替换代码块 - if (state == STATE.caching) { - // 此时状态为缓存中,将状态改为已缓存 - state = STATE.cached; - } else if (state == STATE.none || state == STATE.notMatch) { - // 此时状态为none或者未匹配,需要进行匹配判断 - if (checkModeAndFlavors()) { - state = STATE.caching; - tmp.clear(); - } else { - state = STATE.notMatch; - } + if (evaluator.eval( + Expression.parse(exp!), {'mode': mode, 'flavor': flavor})) { + // 匹配到 + tmp.clear(); + state = STATE.caching; + } else { + state = STATE.notMatch; } } } else { @@ -97,13 +76,15 @@ void walkPath(FileSystemEntity path) { sb.writeln(line); } // 缓存中状态,将用于替换的内容移除注释后写入缓存 - else if (state == STATE.caching) tmp.writeln(line.replaceFirst('// ', '')); + else if (state == STATE.caching) + tmp.writeln(line.replaceFirst('// ', '')); // 这样就跳过了没有匹配上的替换代码块和默认内容 } }); if (modified) { - file.renameSync(path.path + '.bak'); - File(path.path).writeAsStringSync(sb.toString(), flush: true); + // file!.renameSync(path.path + '.bak'); + // File(path.path).writeAsStringSync(sb.toString(), flush: true); + print(sb.toString()); } } catch (e) { if (!(e is FileSystemException)) { @@ -112,17 +93,3 @@ void walkPath(FileSystemEntity path) { } } } - -bool checkModeAndFlavors() { - if (mode != null && mode != args.mode) { - return false; - } - - if (flavors.isEmpty) return true; - - if (flavors[0].startsWith('!')) { - return !flavors.map((e) => e.replaceFirst('!', '')).toList().contains(args.flavor); - } else { - return flavors.contains(args.flavor); - } -} diff --git a/flutter.sh b/flutter.sh index b67f394..a97a938 100644 --- a/flutter.sh +++ b/flutter.sh @@ -4,7 +4,7 @@ SCRIPT_ABS=$(readlink -f "$0") SCRIPT_DIR=$(dirname "$SCRIPT_ABS") # shellcheck disable=SC2005 -DART_EXE=$(echo "$(command -v flutter)" | awk '{print substr($0,0,length()-7)}')cache/dart-sdk/bin/dart +DART_EXE=$(command -v dart) if [[ ! -x "$DART_EXE" ]]; then echo "Can't find dart executable file !" diff --git a/flutter_app_test/.gitignore b/flutter_app_test/.gitignore deleted file mode 100644 index 1ba9c33..0000000 --- a/flutter_app_test/.gitignore +++ /dev/null @@ -1,43 +0,0 @@ -# Miscellaneous -*.class -*.log -*.pyc -*.swp -.DS_Store -.atom/ -.buildlog/ -.history -.svn/ - -# IntelliJ related -*.iml -*.ipr -*.iws -.idea/ - -# The .vscode folder contains launch configuration and tasks you configure in -# VS Code which you may wish to be included in version control, so this line -# is commented out by default. -#.vscode/ - -# Flutter/Dart/Pub related -**/doc/api/ -.dart_tool/ -.flutter-plugins -.flutter-plugins-dependencies -.packages -.pub-cache/ -.pub/ -/build/ - -# Web related -lib/generated_plugin_registrant.dart - -# Symbolication related -app.*.symbols - -# Obfuscation related -app.*.map.json - -# Exceptions to above rules. -!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/flutter_app_test/.metadata b/flutter_app_test/.metadata deleted file mode 100644 index 6daa7e3..0000000 --- a/flutter_app_test/.metadata +++ /dev/null @@ -1,10 +0,0 @@ -# This file tracks properties of this Flutter project. -# Used by Flutter tool to assess capabilities and perform upgrades etc. -# -# This file should be version controlled and should not be manually edited. - -version: - revision: 5f21edf8b66e31a39133177319414395cc5b5f48 - channel: stable - -project_type: app diff --git a/flutter_app_test/README.md b/flutter_app_test/README.md deleted file mode 100644 index 5c88b80..0000000 --- a/flutter_app_test/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# flutterapp - -A new Flutter application. - -## Getting Started - -This project is a starting point for a Flutter application. - -A few resources to get you started if this is your first Flutter project: - -- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab) -- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook) - -For help getting started with Flutter, view our -[online documentation](https://flutter.dev/docs), which offers tutorials, -samples, guidance on mobile development, and a full API reference. diff --git a/flutter_app_test/android/.gitignore b/flutter_app_test/android/.gitignore deleted file mode 100644 index bc2100d..0000000 --- a/flutter_app_test/android/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -gradle-wrapper.jar -/.gradle -/captures/ -/gradlew -/gradlew.bat -/local.properties -GeneratedPluginRegistrant.java diff --git a/flutter_app_test/android/app/build.gradle b/flutter_app_test/android/app/build.gradle deleted file mode 100644 index 28b2736..0000000 --- a/flutter_app_test/android/app/build.gradle +++ /dev/null @@ -1,63 +0,0 @@ -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' -apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" - -android { - compileSdkVersion 28 - - sourceSets { - main.java.srcDirs += 'src/main/kotlin' - } - - lintOptions { - disable 'InvalidPackage' - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.debuggerx.flutterapp" - minSdkVersion 16 - targetSdkVersion 28 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} - -dependencies { - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" -} diff --git a/flutter_app_test/android/app/src/debug/AndroidManifest.xml b/flutter_app_test/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index f6719da..0000000 --- a/flutter_app_test/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/flutter_app_test/android/app/src/main/AndroidManifest.xml b/flutter_app_test/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 6c58bb2..0000000 --- a/flutter_app_test/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,47 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/flutter_app_test/android/app/src/main/kotlin/com/debuggerx/flutterapp/MainActivity.kt b/flutter_app_test/android/app/src/main/kotlin/com/debuggerx/flutterapp/MainActivity.kt deleted file mode 100644 index 6e5c8ca..0000000 --- a/flutter_app_test/android/app/src/main/kotlin/com/debuggerx/flutterapp/MainActivity.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.debuggerx.flutterapp - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() { -} diff --git a/flutter_app_test/android/app/src/main/res/drawable/launch_background.xml b/flutter_app_test/android/app/src/main/res/drawable/launch_background.xml deleted file mode 100644 index 304732f..0000000 --- a/flutter_app_test/android/app/src/main/res/drawable/launch_background.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/flutter_app_test/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/flutter_app_test/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index db77bb4..0000000 Binary files a/flutter_app_test/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/flutter_app_test/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/flutter_app_test/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 17987b7..0000000 Binary files a/flutter_app_test/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/flutter_app_test/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/flutter_app_test/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 09d4391..0000000 Binary files a/flutter_app_test/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/flutter_app_test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/flutter_app_test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index d5f1c8d..0000000 Binary files a/flutter_app_test/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/flutter_app_test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/flutter_app_test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4d6372e..0000000 Binary files a/flutter_app_test/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/flutter_app_test/android/app/src/main/res/values/styles.xml b/flutter_app_test/android/app/src/main/res/values/styles.xml deleted file mode 100644 index 1f83a33..0000000 --- a/flutter_app_test/android/app/src/main/res/values/styles.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - diff --git a/flutter_app_test/android/app/src/profile/AndroidManifest.xml b/flutter_app_test/android/app/src/profile/AndroidManifest.xml deleted file mode 100644 index f6719da..0000000 --- a/flutter_app_test/android/app/src/profile/AndroidManifest.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - diff --git a/flutter_app_test/android/build.gradle b/flutter_app_test/android/build.gradle deleted file mode 100644 index 3100ad2..0000000 --- a/flutter_app_test/android/build.gradle +++ /dev/null @@ -1,31 +0,0 @@ -buildscript { - ext.kotlin_version = '1.3.50' - repositories { - google() - jcenter() - } - - dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' - classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - } -} - -allprojects { - repositories { - google() - jcenter() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/flutter_app_test/android/gradle.properties b/flutter_app_test/android/gradle.properties deleted file mode 100644 index 38c8d45..0000000 --- a/flutter_app_test/android/gradle.properties +++ /dev/null @@ -1,4 +0,0 @@ -org.gradle.jvmargs=-Xmx1536M -android.enableR8=true -android.useAndroidX=true -android.enableJetifier=true diff --git a/flutter_app_test/android/gradle/wrapper/gradle-wrapper.properties b/flutter_app_test/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 296b146..0000000 --- a/flutter_app_test/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Fri Jun 23 08:50:38 CEST 2017 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip diff --git a/flutter_app_test/android/settings.gradle b/flutter_app_test/android/settings.gradle deleted file mode 100644 index d3b6a40..0000000 --- a/flutter_app_test/android/settings.gradle +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Flutter Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -include ':app' - -def localPropertiesFile = new File(rootProject.projectDir, "local.properties") -def properties = new Properties() - -assert localPropertiesFile.exists() -localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } - -def flutterSdkPath = properties.getProperty("flutter.sdk") -assert flutterSdkPath != null, "flutter.sdk not set in local.properties" -apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/flutter_app_test/images/avatar.png b/flutter_app_test/images/avatar.png deleted file mode 100644 index 6b6d162..0000000 Binary files a/flutter_app_test/images/avatar.png and /dev/null differ diff --git a/flutter_app_test/images/avatar.png.default b/flutter_app_test/images/avatar.png.default deleted file mode 100644 index b8f5e2c..0000000 Binary files a/flutter_app_test/images/avatar.png.default and /dev/null differ diff --git a/flutter_app_test/images/avatar[release].png b/flutter_app_test/images/avatar[release].png deleted file mode 100644 index 6b6d162..0000000 Binary files a/flutter_app_test/images/avatar[release].png and /dev/null differ diff --git a/flutter_app_test/ios/.gitignore b/flutter_app_test/ios/.gitignore deleted file mode 100644 index e96ef60..0000000 --- a/flutter_app_test/ios/.gitignore +++ /dev/null @@ -1,32 +0,0 @@ -*.mode1v3 -*.mode2v3 -*.moved-aside -*.pbxuser -*.perspectivev3 -**/*sync/ -.sconsign.dblite -.tags* -**/.vagrant/ -**/DerivedData/ -Icon? -**/Pods/ -**/.symlinks/ -profile -xcuserdata -**/.generated/ -Flutter/App.framework -Flutter/Flutter.framework -Flutter/Flutter.podspec -Flutter/Generated.xcconfig -Flutter/app.flx -Flutter/app.zip -Flutter/flutter_assets/ -Flutter/flutter_export_environment.sh -ServiceDefinitions.json -Runner/GeneratedPluginRegistrant.* - -# Exceptions to above rules. -!default.mode1v3 -!default.mode2v3 -!default.pbxuser -!default.perspectivev3 diff --git a/flutter_app_test/ios/Flutter/AppFrameworkInfo.plist b/flutter_app_test/ios/Flutter/AppFrameworkInfo.plist deleted file mode 100644 index 6b4c0f7..0000000 --- a/flutter_app_test/ios/Flutter/AppFrameworkInfo.plist +++ /dev/null @@ -1,26 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - App - CFBundleIdentifier - io.flutter.flutter.app - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - App - CFBundlePackageType - FMWK - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1.0 - MinimumOSVersion - 8.0 - - diff --git a/flutter_app_test/ios/Flutter/Debug.xcconfig b/flutter_app_test/ios/Flutter/Debug.xcconfig deleted file mode 100644 index 592ceee..0000000 --- a/flutter_app_test/ios/Flutter/Debug.xcconfig +++ /dev/null @@ -1 +0,0 @@ -#include "Generated.xcconfig" diff --git a/flutter_app_test/ios/Flutter/Release.xcconfig b/flutter_app_test/ios/Flutter/Release.xcconfig deleted file mode 100644 index 592ceee..0000000 --- a/flutter_app_test/ios/Flutter/Release.xcconfig +++ /dev/null @@ -1 +0,0 @@ -#include "Generated.xcconfig" diff --git a/flutter_app_test/ios/Runner.xcodeproj/project.pbxproj b/flutter_app_test/ios/Runner.xcodeproj/project.pbxproj deleted file mode 100644 index 43c9f99..0000000 --- a/flutter_app_test/ios/Runner.xcodeproj/project.pbxproj +++ /dev/null @@ -1,506 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 9705A1C41CF9048500538489 /* Embed Frameworks */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = ""; - dstSubfolderSpec = 10; - files = ( - ); - name = "Embed Frameworks"; - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; - 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; - 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; - 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; - 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; - 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; - 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; - 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 97C146EB1CF9000F007C117D /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 9740EEB11CF90186004384FC /* Flutter */ = { - isa = PBXGroup; - children = ( - 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, - 9740EEB21CF90195004384FC /* Debug.xcconfig */, - 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, - 9740EEB31CF90195004384FC /* Generated.xcconfig */, - ); - name = Flutter; - sourceTree = ""; - }; - 97C146E51CF9000F007C117D = { - isa = PBXGroup; - children = ( - 9740EEB11CF90186004384FC /* Flutter */, - 97C146F01CF9000F007C117D /* Runner */, - 97C146EF1CF9000F007C117D /* Products */, - ); - sourceTree = ""; - }; - 97C146EF1CF9000F007C117D /* Products */ = { - isa = PBXGroup; - children = ( - 97C146EE1CF9000F007C117D /* Runner.app */, - ); - name = Products; - sourceTree = ""; - }; - 97C146F01CF9000F007C117D /* Runner */ = { - isa = PBXGroup; - children = ( - 97C146FA1CF9000F007C117D /* Main.storyboard */, - 97C146FD1CF9000F007C117D /* Assets.xcassets */, - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, - 97C147021CF9000F007C117D /* Info.plist */, - 97C146F11CF9000F007C117D /* Supporting Files */, - 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, - 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, - 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, - 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, - ); - path = Runner; - sourceTree = ""; - }; - 97C146F11CF9000F007C117D /* Supporting Files */ = { - isa = PBXGroup; - children = ( - ); - name = "Supporting Files"; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - 97C146ED1CF9000F007C117D /* Runner */ = { - isa = PBXNativeTarget; - buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; - buildPhases = ( - 9740EEB61CF901F6004384FC /* Run Script */, - 97C146EA1CF9000F007C117D /* Sources */, - 97C146EB1CF9000F007C117D /* Frameworks */, - 97C146EC1CF9000F007C117D /* Resources */, - 9705A1C41CF9048500538489 /* Embed Frameworks */, - 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = Runner; - productName = Runner; - productReference = 97C146EE1CF9000F007C117D /* Runner.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 97C146E61CF9000F007C117D /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1020; - ORGANIZATIONNAME = ""; - TargetAttributes = { - 97C146ED1CF9000F007C117D = { - CreatedOnToolsVersion = 7.3.1; - LastSwiftMigration = 1100; - }; - }; - }; - buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; - compatibilityVersion = "Xcode 9.3"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - Base, - ); - mainGroup = 97C146E51CF9000F007C117D; - productRefGroup = 97C146EF1CF9000F007C117D /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 97C146ED1CF9000F007C117D /* Runner */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 97C146EC1CF9000F007C117D /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, - 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, - 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, - 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Thin Binary"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; - }; - 9740EEB61CF901F6004384FC /* Run Script */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Run Script"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 97C146EA1CF9000F007C117D /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, - 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXVariantGroup section */ - 97C146FA1CF9000F007C117D /* Main.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C146FB1CF9000F007C117D /* Base */, - ); - name = Main.storyboard; - sourceTree = ""; - }; - 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { - isa = PBXVariantGroup; - children = ( - 97C147001CF9000F007C117D /* Base */, - ); - name = LaunchScreen.storyboard; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 249021D3217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Profile; - }; - 249021D4217E4FDB00AE95B9 /* Profile */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.debuggerx.flutterapp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Profile; - }; - 97C147031CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = dwarf; - ENABLE_STRICT_OBJC_MSGSEND = YES; - ENABLE_TESTABILITY = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_NO_COMMON_BLOCKS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = YES; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = iphoneos; - TARGETED_DEVICE_FAMILY = "1,2"; - }; - name = Debug; - }; - 97C147041CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - CLANG_ANALYZER_NONNULL = YES; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_MODULES = YES; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; - CLANG_WARN_BOOL_CONVERSION = YES; - CLANG_WARN_COMMA = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; - CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INFINITE_RECURSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; - CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; - CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; - CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; - CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; - CLANG_WARN_STRICT_PROTOTYPES = YES; - CLANG_WARN_SUSPICIOUS_MOVE = YES; - CLANG_WARN_UNREACHABLE_CODE = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - COPY_PHASE_STRIP = NO; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - ENABLE_NS_ASSERTIONS = NO; - ENABLE_STRICT_OBJC_MSGSEND = YES; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_NO_COMMON_BLOCKS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; - GCC_WARN_UNUSED_FUNCTION = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; - MTL_ENABLE_DEBUG_INFO = NO; - SDKROOT = iphoneos; - SUPPORTED_PLATFORMS = iphoneos; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - TARGETED_DEVICE_FAMILY = "1,2"; - VALIDATE_PRODUCT = YES; - }; - name = Release; - }; - 97C147061CF9000F007C117D /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.debuggerx.flutterapp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_OPTIMIZATION_LEVEL = "-Onone"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Debug; - }; - 97C147071CF9000F007C117D /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; - buildSettings = { - ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; - CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - ENABLE_BITCODE = NO; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - INFOPLIST_FILE = Runner/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "$(PROJECT_DIR)/Flutter", - ); - PRODUCT_BUNDLE_IDENTIFIER = com.debuggerx.flutterapp; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; - SWIFT_VERSION = 5.0; - VERSIONING_SYSTEM = "apple-generic"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147031CF9000F007C117D /* Debug */, - 97C147041CF9000F007C117D /* Release */, - 249021D3217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 97C147061CF9000F007C117D /* Debug */, - 97C147071CF9000F007C117D /* Release */, - 249021D4217E4FDB00AE95B9 /* Profile */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 97C146E61CF9000F007C117D /* Project object */; -} diff --git a/flutter_app_test/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/flutter_app_test/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1d526a1..0000000 --- a/flutter_app_test/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/flutter_app_test/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_app_test/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/flutter_app_test/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/flutter_app_test/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/flutter_app_test/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/flutter_app_test/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/flutter_app_test/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/flutter_app_test/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme deleted file mode 100644 index a28140c..0000000 --- a/flutter_app_test/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/flutter_app_test/ios/Runner.xcworkspace/contents.xcworkspacedata b/flutter_app_test/ios/Runner.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index 1d526a1..0000000 --- a/flutter_app_test/ios/Runner.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/flutter_app_test/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/flutter_app_test/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist deleted file mode 100644 index 18d9810..0000000 --- a/flutter_app_test/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +++ /dev/null @@ -1,8 +0,0 @@ - - - - - IDEDidComputeMac32BitWarning - - - diff --git a/flutter_app_test/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/flutter_app_test/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings deleted file mode 100644 index f9b0d7c..0000000 --- a/flutter_app_test/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +++ /dev/null @@ -1,8 +0,0 @@ - - - - - PreviewsEnabled - - - diff --git a/flutter_app_test/ios/Runner/AppDelegate.swift b/flutter_app_test/ios/Runner/AppDelegate.swift deleted file mode 100644 index 70693e4..0000000 --- a/flutter_app_test/ios/Runner/AppDelegate.swift +++ /dev/null @@ -1,13 +0,0 @@ -import UIKit -import Flutter - -@UIApplicationMain -@objc class AppDelegate: FlutterAppDelegate { - override func application( - _ application: UIApplication, - didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? - ) -> Bool { - GeneratedPluginRegistrant.register(with: self) - return super.application(application, didFinishLaunchingWithOptions: launchOptions) - } -} diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index d36b1fa..0000000 --- a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,122 +0,0 @@ -{ - "images" : [ - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "20x20", - "idiom" : "iphone", - "filename" : "Icon-App-20x20@3x.png", - "scale" : "3x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "iphone", - "filename" : "Icon-App-29x29@3x.png", - "scale" : "3x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "iphone", - "filename" : "Icon-App-40x40@3x.png", - "scale" : "3x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@2x.png", - "scale" : "2x" - }, - { - "size" : "60x60", - "idiom" : "iphone", - "filename" : "Icon-App-60x60@3x.png", - "scale" : "3x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@1x.png", - "scale" : "1x" - }, - { - "size" : "20x20", - "idiom" : "ipad", - "filename" : "Icon-App-20x20@2x.png", - "scale" : "2x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@1x.png", - "scale" : "1x" - }, - { - "size" : "29x29", - "idiom" : "ipad", - "filename" : "Icon-App-29x29@2x.png", - "scale" : "2x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@1x.png", - "scale" : "1x" - }, - { - "size" : "40x40", - "idiom" : "ipad", - "filename" : "Icon-App-40x40@2x.png", - "scale" : "2x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@1x.png", - "scale" : "1x" - }, - { - "size" : "76x76", - "idiom" : "ipad", - "filename" : "Icon-App-76x76@2x.png", - "scale" : "2x" - }, - { - "size" : "83.5x83.5", - "idiom" : "ipad", - "filename" : "Icon-App-83.5x83.5@2x.png", - "scale" : "2x" - }, - { - "size" : "1024x1024", - "idiom" : "ios-marketing", - "filename" : "Icon-App-1024x1024@1x.png", - "scale" : "1x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png deleted file mode 100644 index dc9ada4..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png deleted file mode 100644 index 28c6bf0..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png deleted file mode 100644 index 2ccbfd9..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png deleted file mode 100644 index f091b6b..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png deleted file mode 100644 index 4cde121..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png deleted file mode 100644 index d0ef06e..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png deleted file mode 100644 index dcdc230..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png deleted file mode 100644 index 2ccbfd9..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png deleted file mode 100644 index c8f9ed8..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png deleted file mode 100644 index a6d6b86..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png deleted file mode 100644 index a6d6b86..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png deleted file mode 100644 index 75b2d16..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png deleted file mode 100644 index c4df70d..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png deleted file mode 100644 index 6a84f41..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png deleted file mode 100644 index d0e1f58..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json deleted file mode 100644 index 0bedcf2..0000000 --- a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "LaunchImage.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "LaunchImage@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png deleted file mode 100644 index 9da19ea..0000000 Binary files a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png and /dev/null differ diff --git a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md deleted file mode 100644 index 89c2725..0000000 --- a/flutter_app_test/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Launch Screen Assets - -You can customize the launch screen with your own desired assets by replacing the image files in this directory. - -You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/flutter_app_test/ios/Runner/Base.lproj/LaunchScreen.storyboard b/flutter_app_test/ios/Runner/Base.lproj/LaunchScreen.storyboard deleted file mode 100644 index f2e259c..0000000 --- a/flutter_app_test/ios/Runner/Base.lproj/LaunchScreen.storyboard +++ /dev/null @@ -1,37 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/flutter_app_test/ios/Runner/Base.lproj/Main.storyboard b/flutter_app_test/ios/Runner/Base.lproj/Main.storyboard deleted file mode 100644 index f3c2851..0000000 --- a/flutter_app_test/ios/Runner/Base.lproj/Main.storyboard +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/flutter_app_test/ios/Runner/Info.plist b/flutter_app_test/ios/Runner/Info.plist deleted file mode 100644 index 99eea96..0000000 --- a/flutter_app_test/ios/Runner/Info.plist +++ /dev/null @@ -1,45 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - flutterapp - CFBundlePackageType - APPL - CFBundleShortVersionString - $(FLUTTER_BUILD_NAME) - CFBundleSignature - ???? - CFBundleVersion - $(FLUTTER_BUILD_NUMBER) - LSRequiresIPhoneOS - - UILaunchStoryboardName - LaunchScreen - UIMainStoryboardFile - Main - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UIViewControllerBasedStatusBarAppearance - - - diff --git a/flutter_app_test/ios/Runner/Runner-Bridging-Header.h b/flutter_app_test/ios/Runner/Runner-Bridging-Header.h deleted file mode 100644 index 308a2a5..0000000 --- a/flutter_app_test/ios/Runner/Runner-Bridging-Header.h +++ /dev/null @@ -1 +0,0 @@ -#import "GeneratedPluginRegistrant.h" diff --git a/flutter_app_test/lib/main.dart b/flutter_app_test/lib/main.dart deleted file mode 100644 index a15a595..0000000 --- a/flutter_app_test/lib/main.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'package:flutter/material.dart'; - -void main() { - runApp(MyApp()); -} - -class MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - primarySwatch: Colors.blue, - visualDensity: VisualDensity.adaptivePlatformDensity, - ), - home: MyHomePage(title: 'Flutter Demo Home Page'), - ); - } -} - -class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); - - final String title; - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - Text('RELEASE'), - Image.asset('images/avatar.png'), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: Icon(Icons.add), - ), - ); - } -} diff --git a/flutter_app_test/lib/main.dart.bak b/flutter_app_test/lib/main.dart.bak deleted file mode 100644 index 7ecfb59..0000000 --- a/flutter_app_test/lib/main.dart.bak +++ /dev/null @@ -1,72 +0,0 @@ -import 'package:flutter/material.dart'; - -void main() { - runApp(MyApp()); -} - -class MyApp extends StatelessWidget { - @override - Widget build(BuildContext context) { - return MaterialApp( - title: 'Flutter Demo', - theme: ThemeData( - primarySwatch: Colors.blue, - visualDensity: VisualDensity.adaptivePlatformDensity, - ), - home: MyHomePage(title: 'Flutter Demo Home Page'), - ); - } -} - -class MyHomePage extends StatefulWidget { - MyHomePage({Key key, this.title}) : super(key: key); - - final String title; - - @override - _MyHomePageState createState() => _MyHomePageState(); -} - -class _MyHomePageState extends State { - int _counter = 0; - - void _incrementCounter() { - setState(() { - _counter++; - }); - } - - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - title: Text(widget.title), - ), - body: Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'You have pushed the button this many times:', - ), - Text( - '$_counter', - style: Theme.of(context).textTheme.headline4, - ), - // #[release] - // Text('RELEASE'), - // #[[]] - Text('DEBUG'), - // #[[]] - Image.asset('images/avatar.png'), - ], - ), - ), - floatingActionButton: FloatingActionButton( - onPressed: _incrementCounter, - tooltip: 'Increment', - child: Icon(Icons.add), - ), - ); - } -} diff --git a/flutter_app_test/pubspec.lock b/flutter_app_test/pubspec.lock deleted file mode 100644 index b6489c5..0000000 --- a/flutter_app_test/pubspec.lock +++ /dev/null @@ -1,188 +0,0 @@ -# Generated by pub -# See https://dart.dev/tools/pub/glossary#lockfile -packages: - archive: - dependency: transitive - description: - name: archive - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.13" - args: - dependency: transitive - description: - name: args - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.0" - async: - dependency: transitive - description: - name: async - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.1" - boolean_selector: - dependency: transitive - description: - name: boolean_selector - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - charcode: - dependency: transitive - description: - name: charcode - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.3" - collection: - dependency: transitive - description: - name: collection - url: "https://pub.dartlang.org" - source: hosted - version: "1.14.12" - convert: - dependency: transitive - description: - name: convert - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.1" - crypto: - dependency: transitive - description: - name: crypto - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.4" - cupertino_icons: - dependency: "direct main" - description: - name: cupertino_icons - url: "https://pub.dartlang.org" - source: hosted - version: "0.1.3" - flutter: - dependency: "direct main" - description: flutter - source: sdk - version: "0.0.0" - flutter_test: - dependency: "direct dev" - description: flutter - source: sdk - version: "0.0.0" - image: - dependency: transitive - description: - name: image - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.12" - matcher: - dependency: transitive - description: - name: matcher - url: "https://pub.dartlang.org" - source: hosted - version: "0.12.6" - meta: - dependency: transitive - description: - name: meta - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.8" - path: - dependency: transitive - description: - name: path - url: "https://pub.dartlang.org" - source: hosted - version: "1.6.4" - petitparser: - dependency: transitive - description: - name: petitparser - url: "https://pub.dartlang.org" - source: hosted - version: "2.4.0" - quiver: - dependency: transitive - description: - name: quiver - url: "https://pub.dartlang.org" - source: hosted - version: "2.1.3" - sky_engine: - dependency: transitive - description: flutter - source: sdk - version: "0.0.99" - source_span: - dependency: transitive - description: - name: source_span - url: "https://pub.dartlang.org" - source: hosted - version: "1.7.0" - stack_trace: - dependency: transitive - description: - name: stack_trace - url: "https://pub.dartlang.org" - source: hosted - version: "1.9.3" - stream_channel: - dependency: transitive - description: - name: stream_channel - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.0" - string_scanner: - dependency: transitive - description: - name: string_scanner - url: "https://pub.dartlang.org" - source: hosted - version: "1.0.5" - term_glyph: - dependency: transitive - description: - name: term_glyph - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.0" - test_api: - dependency: transitive - description: - name: test_api - url: "https://pub.dartlang.org" - source: hosted - version: "0.2.15" - typed_data: - dependency: transitive - description: - name: typed_data - url: "https://pub.dartlang.org" - source: hosted - version: "1.1.6" - vector_math: - dependency: transitive - description: - name: vector_math - url: "https://pub.dartlang.org" - source: hosted - version: "2.0.8" - xml: - dependency: transitive - description: - name: xml - url: "https://pub.dartlang.org" - source: hosted - version: "3.6.1" -sdks: - dart: ">=2.7.0 <3.0.0" diff --git a/flutter_app_test/pubspec.yaml b/flutter_app_test/pubspec.yaml deleted file mode 100644 index 71e3f74..0000000 --- a/flutter_app_test/pubspec.yaml +++ /dev/null @@ -1,76 +0,0 @@ -name: flutterapp -description: A new Flutter application. - -# The following line prevents the package from being accidentally published to -# pub.dev using `pub publish`. This is preferred for private packages. -publish_to: 'none' # Remove this line if you wish to publish to pub.dev - -# The following defines the version and build number for your application. -# A version number is three numbers separated by dots, like 1.2.43 -# followed by an optional build number separated by a +. -# Both the version and the builder number may be overridden in flutter -# build by specifying --build-name and --build-number, respectively. -# In Android, build-name is used as versionName while build-number used as versionCode. -# Read more about Android versioning at https://developer.android.com/studio/publish/versioning -# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. -# Read more about iOS versioning at -# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html -version: 1.0.0+1 - -environment: - sdk: ">=2.7.0 <3.0.0" - -dependencies: - flutter: - sdk: flutter - - - # The following adds the Cupertino Icons font to your application. - # Use with the CupertinoIcons class for iOS style icons. - cupertino_icons: ^0.1.3 - -dev_dependencies: - flutter_test: - sdk: flutter - -# For information on the generic Dart part of this file, see the -# following page: https://dart.dev/tools/pub/pubspec - -# The following section is specific to Flutter. -flutter: - - # The following line ensures that the Material Icons font is - # included with your application, so that you can use the icons in - # the material Icons class. - uses-material-design: true - - # To add assets to your application, add an assets section, like this: - assets: - - images/avatar.png - # - images/a_dot_ham.jpeg - - # An image asset can refer to one or more resolution-specific "variants", see - # https://flutter.dev/assets-and-images/#resolution-aware. - - # For details regarding adding assets from package dependencies, see - # https://flutter.dev/assets-and-images/#from-packages - - # To add custom fonts to your application, add a fonts section here, - # in this "flutter" section. Each entry in this list should have a - # "family" key with the font family name, and a "fonts" key with a - # list giving the asset and other descriptors for the font. For - # example: - # fonts: - # - family: Schyler - # fonts: - # - asset: fonts/Schyler-Regular.ttf - # - asset: fonts/Schyler-Italic.ttf - # style: italic - # - family: Trajan Pro - # fonts: - # - asset: fonts/TrajanPro.ttf - # - asset: fonts/TrajanPro_Bold.ttf - # weight: 700 - # - # For details regarding fonts from package dependencies, - # see https://flutter.dev/custom-fonts/#from-packages diff --git a/flutter_app_test/test/widget_test.dart b/flutter_app_test/test/widget_test.dart deleted file mode 100644 index 826743f..0000000 --- a/flutter_app_test/test/widget_test.dart +++ /dev/null @@ -1,30 +0,0 @@ -// This is a basic Flutter widget test. -// -// To perform an interaction with a widget in your test, use the WidgetTester -// utility that Flutter provides. For example, you can send tap and scroll -// gestures. You can also use WidgetTester to find child widgets in the widget -// tree, read text, and verify that the values of widget properties are correct. - -import 'package:flutter/material.dart'; -import 'package:flutter_test/flutter_test.dart'; - -import 'package:flutterapp/main.dart'; - -void main() { - testWidgets('Counter increments smoke test', (WidgetTester tester) async { - // Build our app and trigger a frame. - await tester.pumpWidget(MyApp()); - - // Verify that our counter starts at 0. - expect(find.text('0'), findsOneWidget); - expect(find.text('1'), findsNothing); - - // Tap the '+' icon and trigger a frame. - await tester.tap(find.byIcon(Icons.add)); - await tester.pump(); - - // Verify that our counter has incremented. - expect(find.text('0'), findsNothing); - expect(find.text('1'), findsOneWidget); - }); -} diff --git a/test/avatar.png b/test/avatar.png deleted file mode 100644 index b8f5e2c..0000000 Binary files a/test/avatar.png and /dev/null differ diff --git a/test/avatar[release].png b/test/avatar[release].png deleted file mode 100644 index 6b6d162..0000000 Binary files a/test/avatar[release].png and /dev/null differ diff --git a/test/test.dart b/test/test.dart deleted file mode 100644 index 3581f28..0000000 --- a/test/test.dart +++ /dev/null @@ -1,16 +0,0 @@ -void main(List arguments) { - print(1); - // #[release[google]] - // print(2); - // #[release[!asd]] - // print(3); - // #[debug] - // print(4); - // #[release[test]] - // print(5); - // #[[test asd]] - // print(6); - // #[[]] - // print(7) - // #[[]] -}