├── .gitignore ├── test ├── test_files │ ├── augmented.dart │ ├── parameters.dart │ ├── augmentation.dart │ ├── numbers.dart │ ├── directives.dart │ ├── records.dart │ ├── literals.dart │ ├── extension_types.dart │ ├── control.dart │ ├── misc.dart │ ├── operators.dart │ ├── functions.dart │ ├── support.dart │ ├── classes.dart │ ├── string_interpolation.dart │ ├── comments.dart │ ├── patterns.dart │ └── variable_names.dart ├── goldens │ ├── augmented.dart.golden │ ├── numbers.dart.golden │ ├── augmentation.dart.golden │ ├── parameters.dart.golden │ ├── extension_types.dart.golden │ ├── control.dart.golden │ ├── records.dart.golden │ ├── directives.dart.golden │ ├── misc.dart.golden │ ├── literals.dart.golden │ ├── functions.dart.golden │ ├── operators.dart.golden │ ├── comments.dart.golden │ ├── classes.dart.golden │ ├── string_interpolation.dart.golden │ ├── patterns.dart.golden │ └── variable_names.dart.golden ├── golden_test.dart └── support │ └── span_parser.dart ├── pubspec.yaml ├── analysis_options.yaml ├── .github ├── dependabot.yml └── workflows │ └── dart.yml ├── .vscode └── settings.json ├── tool └── verify.dart ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── CHANGELOG.md └── grammars └── dart.json /.gitignore: -------------------------------------------------------------------------------- 1 | .dart_tool/ 2 | pubspec.lock 3 | -------------------------------------------------------------------------------- /test/test_files/augmented.dart: -------------------------------------------------------------------------------- 1 | import augment 'augmentation.dart'; 2 | 3 | class MyClass { 4 | void myMethod() {} 5 | String get myGetter => ''; 6 | set mySetter(String value) {} 7 | } 8 | 9 | void myFunction() {} 10 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: dart_syntax_highlight 2 | publish_to: none 3 | environment: 4 | sdk: ^3.2.0 5 | 6 | dev_dependencies: 7 | collection: ^1.19.0 8 | dart_flutter_team_lints: ^3.2.1 9 | path: ^1.9.0 10 | string_scanner: ^1.4.0 11 | test: ^1.25.8 12 | -------------------------------------------------------------------------------- /test/test_files/parameters.dart: -------------------------------------------------------------------------------- 1 | void f1() {} 2 | void f2(String a) {} 3 | void f3(String a, [int? b]) {} 4 | void f4(String a, {int? b}) {} 5 | void f5(String a, {required int b}) {} 6 | void f6( 7 | String a, 8 | List> Function(String a) b, 9 | ) {} 10 | -------------------------------------------------------------------------------- /analysis_options.yaml: -------------------------------------------------------------------------------- 1 | include: package:dart_flutter_team_lints/analysis_options.yaml 2 | 3 | analyzer: 4 | language: 5 | strict-raw-types: true 6 | exclude: 7 | - test/test_files/** 8 | 9 | linter: 10 | rules: 11 | - prefer_final_in_for_each 12 | - prefer_final_locals 13 | -------------------------------------------------------------------------------- /test/test_files/augmentation.dart: -------------------------------------------------------------------------------- 1 | augment library 'augmented.dart'; 2 | 3 | augment class MyClass { 4 | augment void myMethod() { 5 | augmented(); 6 | } 7 | 8 | String get myGetter => augmented; 9 | set mySetter(String value) { augmented = value; } 10 | } 11 | 12 | augment void myFunction() { 13 | augmented(); 14 | } 15 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # Dependabot configuration file. 2 | # See https://docs.github.com/en/code-security/dependabot/dependabot-version-updates 3 | version: 2 4 | 5 | updates: 6 | - package-ecosystem: github-actions 7 | directory: / 8 | schedule: 9 | interval: monthly 10 | labels: 11 | - autosubmit 12 | groups: 13 | github-actions: 14 | patterns: 15 | - "*" 16 | -------------------------------------------------------------------------------- /test/test_files/numbers.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | var a = [ 6 | 1, 7 | .0, 8 | 1.2, 9 | 0x123, 10 | 100__000_000__000_000__000_000, 11 | 0x4000_0000_0000_0000, 12 | 0.000_000_000_01, 13 | 0x00_14_22_01_23_45, 14 | 555_123_4567, 15 | ]; 16 | -------------------------------------------------------------------------------- /test/test_files/directives.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'dart:io'; 6 | import 'dart:io' as io; 7 | import 'dart:io' show File; 8 | import 'dart:io' hide Directory; 9 | import 'dart:io' show File hide Directory; 10 | import 'dart:io' as io show Directory; 11 | import 'dart:async' deferred as deferredAsync show Future; 12 | 13 | export 'comments.dart'; 14 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | // To help testing with this project in VS Code, disable 3 | // semantic tokens (since they override the grammar) and 4 | // enable rainbow brackets (to make it clear if our scopes 5 | // are preventing VS Code from matching brackets correctly). 6 | "editor.semanticHighlighting.enabled": false, 7 | "editor.bracketPairColorization.enabled": true, 8 | // Disable formatting because some test files are 9 | // formatted specifically to test certain conditions 10 | // or to make the results easier to see. 11 | "dart.enableSdkFormatter": false 12 | } 13 | -------------------------------------------------------------------------------- /test/test_files/records.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | (int, int)? aaa; 6 | (int aaa, int bbb)? bbb; 7 | (int aaa, int, {String? ccc})? ccc; 8 | (int, (int, (int, String)))? ddd; 9 | 10 | (int aaa, int bbb) func((String aaaa, String? bbbb) ccc) { 11 | final ddd = (1, 2, eee: ''); 12 | return (1, 2); 13 | } 14 | 15 | class R { 16 | (int aaa, int, {String? ccc})? get getter => null; 17 | final variable = (1, 2, eee: ''); 18 | } 19 | -------------------------------------------------------------------------------- /test/test_files/literals.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | const a = 'aaaaa'; 6 | 7 | const list1 = []; 8 | const list2 = []; 9 | const list3 = ['', '$a']; 10 | const list4 = ['', '$a']; 11 | 12 | const set1 = {}; 13 | const set2 = {}; 14 | const set3 = {'', '$a'}; 15 | const set4 = {'', '$a'}; 16 | 17 | const map1 = {}; 18 | const map2 = {'': '$a'}; 19 | const map3 = {'': '$a'}; 20 | -------------------------------------------------------------------------------- /test/test_files/extension_types.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | extension type MyInt(int it) { 6 | void foo() { print(it.isEven); } 7 | } 8 | 9 | final extension = 1; 10 | int get extension => 1; 11 | set extension(int value) {} 12 | void extension() { 13 | var extension = 1; 14 | } 15 | 16 | final type = 1; 17 | int get type => 1; 18 | set type(int value) {} 19 | void type() { 20 | var type = 1; 21 | } 22 | -------------------------------------------------------------------------------- /tool/verify.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:convert'; 6 | import 'dart:io'; 7 | 8 | void main() { 9 | // Validate the grammars/dart.json file. 10 | final grammarFile = File('grammars/dart.json'); 11 | 12 | try { 13 | jsonDecode(grammarFile.readAsStringSync()); 14 | print('${grammarFile.path} ok.'); 15 | exit(0); 16 | } catch (e) { 17 | print('Error parsing ${grammarFile.path}: $e'); 18 | exit(1); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /test/test_files/control.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | void err() { 6 | try { 7 | throw ''; 8 | } on ArgumentError { 9 | rethrow; 10 | } catch (e) { 11 | print('e'); 12 | } 13 | } 14 | 15 | void loops() { 16 | while (1 > 2) { 17 | if (3 > 4) { 18 | continue; 19 | } else { 20 | break; 21 | } 22 | return; 23 | } 24 | 25 | do { 26 | print(''); 27 | } while (1 > 2); 28 | } 29 | 30 | void switches() { 31 | Object? i = 1; 32 | switch (i as int) { 33 | case 1: 34 | break; 35 | default: 36 | return; 37 | } 38 | } 39 | 40 | void conditions() { 41 | if (1 > 2) { 42 | } else if (3 > 4) { 43 | } else {} 44 | } 45 | -------------------------------------------------------------------------------- /test/test_files/misc.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | library foo; 6 | 7 | external int get externalInt; 8 | 9 | typedef StringAlias = String; 10 | typedef void FunctionAlias1(String a, String b); 11 | typedef FunctionAlias2 = void Function(String a, String b); 12 | 13 | Map, List>>? nestedTypeArguments; 14 | 15 | void misc(int a, {required int b}) { 16 | assert(true); 17 | assert(1 == 1, 'fail'); 18 | 19 | var a = new String.fromCharCode(1); 20 | const b = int.fromEnvironment(''); 21 | final c = ''; 22 | late final d = ''; 23 | print(d is String); 24 | print(d is! String); 25 | } 26 | 27 | class Covariance { 28 | void covariance(covariant List items) {} 29 | } 30 | -------------------------------------------------------------------------------- /.github/workflows/dart.yml: -------------------------------------------------------------------------------- 1 | name: Dart 2 | 3 | on: 4 | schedule: 5 | # “At 00:00 (UTC) on Sunday.” 6 | - cron: '0 0 * * 0' 7 | push: 8 | branches: [ master, main ] 9 | pull_request: 10 | branches: [ master, main ] 11 | 12 | env: 13 | PUB_ENVIRONMENT: bot.github 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@1af3b93b6815bc44a9784bd300feb67ff0d1eeb3 20 | - uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c 21 | with: 22 | sdk: stable 23 | - name: Print Dart version 24 | run: dart --version 25 | - name: Install dependencies 26 | run: dart pub get 27 | - name: Analyze 28 | run: dart analyze --fatal-infos 29 | - name: Verify grammar file 30 | run: dart run tool/verify.dart 31 | - name: Test 32 | run: dart test 33 | -------------------------------------------------------------------------------- /test/test_files/operators.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | void foo() { 6 | Object? a; 7 | if (1 == 2) {} 8 | if (1 != 2) {} 9 | if (1 < 2) {} 10 | if (1 <= 2) {} 11 | if (1 > 2) {} 12 | if (1 >= 2) {} 13 | var b = 1 < 2 ? 1 / 1 : 2 * 2; 14 | a ??= b; 15 | b += 1; 16 | b -= 1; 17 | b = b / 2; 18 | b = b ~/ 2; 19 | b = b % 2; 20 | b++; 21 | b--; 22 | ++b; 23 | --b; 24 | var c = 1 >> 2; 25 | c >>= 1; 26 | var d = 1 << 2; 27 | d <<= 2; 28 | var e = 1 >>> 2; 29 | e >>>= 3; 30 | var f = -b; 31 | var g = 1 & 2; 32 | var h = 1 ^ 2; 33 | var i = ~2; 34 | var j = 1 & 2; 35 | j &= 2; 36 | j ^= 2; 37 | j |= 2; 38 | var k = 1 ^ 2; 39 | var l = 1 | 2; 40 | var m = !(a == a && false || true); 41 | } 42 | -------------------------------------------------------------------------------- /test/test_files/functions.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | void simplePrint() { 6 | print('hello world'); 7 | } 8 | 9 | noReturnValue() { 10 | print('hello world'); 11 | } 12 | 13 | void returns() { 14 | return; 15 | } 16 | 17 | Future asyncPrint() async { 18 | await Future.delayed(const Duration(seconds: 1)); 19 | print('hello world'); 20 | } 21 | 22 | Map> nestedGenerics() { 23 | return {}; 24 | } 25 | 26 | Iterable syncYield() sync* { 27 | yield ''; 28 | } 29 | 30 | Iterable syncYieldStar() sync* { 31 | yield* syncYield(); 32 | } 33 | 34 | Stream asyncYield() async* { 35 | await Future.delayed(const Duration(seconds: 1)); 36 | yield ''; 37 | } 38 | 39 | Stream asyncYieldStar() async* { 40 | await Future.delayed(const Duration(seconds: 1)); 41 | yield* asyncYield(); 42 | } 43 | 44 | T foo(String a) => throw UnimplementedError(); 45 | -------------------------------------------------------------------------------- /test/goldens/augmented.dart.golden: -------------------------------------------------------------------------------- 1 | >import augment 'augmentation.dart'; 2 | #^^^^^^^^^^^^^^ meta.declaration.dart keyword.other.import.dart 3 | # ^ meta.declaration.dart 4 | # ^^^^^^^^^^^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 5 | # ^ meta.declaration.dart punctuation.terminator.dart 6 | > 7 | >class MyClass { 8 | #^^^^^ keyword.declaration.dart 9 | # ^^^^^^^ support.class.dart 10 | > void myMethod() {} 11 | # ^^^^ storage.type.primitive.dart 12 | # ^^^^^^^^ entity.name.function.dart 13 | > String get myGetter => ''; 14 | # ^^^^^^ support.class.dart 15 | # ^^^ keyword.declaration.dart 16 | # ^^ keyword.operator.closure.dart 17 | # ^^ string.interpolated.single.dart 18 | # ^ punctuation.terminator.dart 19 | > set mySetter(String value) {} 20 | # ^^^ keyword.declaration.dart 21 | # ^^^^^^^^ entity.name.function.dart 22 | # ^^^^^^ support.class.dart 23 | >} 24 | > 25 | >void myFunction() {} 26 | #^^^^ storage.type.primitive.dart 27 | # ^^^^^^^^^^ entity.name.function.dart 28 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | For license agreement and CLA information, contribution workflow information, 4 | code reviews, code style, and community guidelines, please see 5 | . 6 | 7 | 8 | # Adding Tests for Changes 9 | 10 | In the `test/test_files` folder are a set of `.dart` files 11 | that are parsed using the grammar. Text representations of the results 12 | are stored in `test/goldens` and verified by tests. 13 | If your changes to the grammar affect the output you will need to 14 | regenerate the golden files and commit them to pass the bots. 15 | 16 | If the existing test files do not already include sample code that 17 | covers the changes you are making, you should add new examples first. 18 | Regenerating and committing the new examples and updated golden files 19 | _before_ making grammar changes will make your changes easier to review, 20 | since the PR will then contain a snapshot of both before and after: 21 | 22 | 1. Add new sample code to `test/test_files` if required 23 | 1. Regenerate golden files 24 | 1. Commit changes to your branch 25 | 1. Make grammar changes 26 | 1. Regenerate golden files 27 | 1. Commit changes to your branch 28 | 29 | ## Regenerating goldens 30 | 31 | To regenerate the golden files, run: 32 | 33 | ``` 34 | UPDATE_GOLDENS=true dart test 35 | ``` 36 | -------------------------------------------------------------------------------- /test/test_files/support.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | // Classes and variables here are not part of the golden tests, they are here 6 | // to avoid polluting test files with definitions that can be used by test files 7 | // to avoid polluting them with code unrelated to the syntax being tested. 8 | 9 | import 'dart:math' as math; 10 | 11 | abstract class Shape { 12 | double calculateArea(); 13 | double get size => calculateArea(); 14 | } 15 | 16 | class Square extends Shape { 17 | final double length; 18 | Square(this.length); 19 | 20 | double calculateArea() => length * length; 21 | } 22 | 23 | class Circle extends Shape { 24 | final double radius; 25 | Circle(this.radius); 26 | 27 | double calculateArea() => math.pi * radius * radius; 28 | } 29 | 30 | var testShape = Circle(123); 31 | 32 | enum Color { red, yellow, blue, green } 33 | 34 | Color testColor = Color.red; 35 | 36 | var testRecord = (1, 2); 37 | var testList = [1, 2, 3]; 38 | var testMap = {'first': 1, 'second': 2}; 39 | 40 | const space = 32; 41 | const zero = 48; 42 | const nine = 57; 43 | 44 | String? maybeString = ''; 45 | Object testObject = Object(); 46 | 47 | class Rect { 48 | final double width, height; 49 | 50 | Rect(this.width, this.height); 51 | } 52 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2020, the Dart project authors. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above 10 | copyright notice, this list of conditions and the following 11 | disclaimer in the documentation and/or other materials provided 12 | with the distribution. 13 | * Neither the name of Google LLC nor the names of its 14 | contributors may be used to endorse or promote products derived 15 | from this software without specific prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /test/test_files/classes.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | class Class1 {} 6 | 7 | abstract class Class2 implements Class1 { 8 | String get a; 9 | set a(String value); 10 | } 11 | 12 | class Class3 extends Class2 with MyMixin { 13 | @override 14 | String get a => ''; 15 | 16 | @override 17 | set a(String value) {} 18 | 19 | void method() {} 20 | } 21 | 22 | class Class4 implements Class1 {} 23 | 24 | class MyClass { 25 | void method1() {} 26 | void Method2() {} 27 | void get() {} 28 | void get() {} 29 | void set() {} 30 | void set() {} 31 | 32 | String? _foo; 33 | String? get foo => _foo; 34 | set foo(String? value) => _foo = value; 35 | } 36 | 37 | void get() {} 38 | void get() {} 39 | void set() {} 40 | void set() {} 41 | 42 | mixin MyMixin {} 43 | 44 | mixin MyMixin2 on Class1 {} 45 | 46 | extension on String {} 47 | 48 | extension StringExtension on String {} 49 | 50 | extension StringListExtension on List {} 51 | 52 | extension on T {} 53 | 54 | class my_lowercase_class { 55 | my_lowercase_class? foo() => null; 56 | List? bar() => null; 57 | } 58 | 59 | class A1 {} 60 | 61 | class A2 extends A1 {} 62 | 63 | class A3 implements A1 {} 64 | 65 | class A4 extends Class1 with MyMixin2 {} 66 | 67 | base class MyBaseClass {} 68 | interface class MyInterfaceClass {} 69 | sealed class MySealedClass {} 70 | final class MyFinalClass {} 71 | mixin class MyMixinClass {} 72 | macro class MyMacroClass {} 73 | -------------------------------------------------------------------------------- /test/goldens/numbers.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// for details. All rights reserved. Use of this source code is governed by a 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// BSD-style license that can be found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >var a = [ 9 | #^^^ storage.type.primitive.dart 10 | # ^ keyword.operator.assignment.dart 11 | > 1, 12 | # ^ constant.numeric.dart 13 | # ^ punctuation.comma.dart 14 | > .0, 15 | # ^ punctuation.dot.dart 16 | # ^ constant.numeric.dart 17 | # ^ punctuation.comma.dart 18 | > 1.2, 19 | # ^^^ constant.numeric.dart 20 | # ^ punctuation.comma.dart 21 | > 0x123, 22 | # ^^^^^ constant.numeric.dart 23 | # ^ punctuation.comma.dart 24 | > 100__000_000__000_000__000_000, 25 | # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant.numeric.dart 26 | # ^ punctuation.comma.dart 27 | > 0x4000_0000_0000_0000, 28 | # ^^^^^^^^^^^^^^^^^^^^^ constant.numeric.dart 29 | # ^ punctuation.comma.dart 30 | > 0.000_000_000_01, 31 | # ^^^^^^^^^^^^^^^^ constant.numeric.dart 32 | # ^ punctuation.comma.dart 33 | > 0x00_14_22_01_23_45, 34 | # ^^^^^^^^^^^^^^^^^^^ constant.numeric.dart 35 | # ^ punctuation.comma.dart 36 | > 555_123_4567, 37 | # ^^^^^^^^^^^^ constant.numeric.dart 38 | # ^ punctuation.comma.dart 39 | >]; 40 | # ^ punctuation.terminator.dart 41 | -------------------------------------------------------------------------------- /test/goldens/augmentation.dart.golden: -------------------------------------------------------------------------------- 1 | >augment library 'augmented.dart'; 2 | #^^^^^^^^^^^^^^^ meta.declaration.dart keyword.other.import.dart 3 | # ^ meta.declaration.dart 4 | # ^^^^^^^^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 5 | # ^ meta.declaration.dart punctuation.terminator.dart 6 | > 7 | >augment class MyClass { 8 | #^^^^^^^ storage.modifier.dart 9 | # ^^^^^ keyword.declaration.dart 10 | # ^^^^^^^ support.class.dart 11 | > augment void myMethod() { 12 | # ^^^^^^^ storage.modifier.dart 13 | # ^^^^ storage.type.primitive.dart 14 | # ^^^^^^^^ entity.name.function.dart 15 | > augmented(); 16 | # ^^^^^^^^^ variable.language.dart 17 | # ^ punctuation.terminator.dart 18 | > } 19 | > 20 | > String get myGetter => augmented; 21 | # ^^^^^^ support.class.dart 22 | # ^^^ keyword.declaration.dart 23 | # ^^ keyword.operator.closure.dart 24 | # ^^^^^^^^^ variable.language.dart 25 | # ^ punctuation.terminator.dart 26 | > set mySetter(String value) { augmented = value; } 27 | # ^^^ keyword.declaration.dart 28 | # ^^^^^^^^ entity.name.function.dart 29 | # ^^^^^^ support.class.dart 30 | # ^^^^^^^^^ variable.language.dart 31 | # ^ keyword.operator.assignment.dart 32 | # ^ punctuation.terminator.dart 33 | >} 34 | > 35 | >augment void myFunction() { 36 | #^^^^^^^ storage.modifier.dart 37 | # ^^^^ storage.type.primitive.dart 38 | # ^^^^^^^^^^ entity.name.function.dart 39 | > augmented(); 40 | # ^^^^^^^^^ variable.language.dart 41 | # ^ punctuation.terminator.dart 42 | >} 43 | -------------------------------------------------------------------------------- /test/goldens/parameters.dart.golden: -------------------------------------------------------------------------------- 1 | >void f1() {} 2 | #^^^^ storage.type.primitive.dart 3 | # ^^ entity.name.function.dart 4 | >void f2(String a) {} 5 | #^^^^ storage.type.primitive.dart 6 | # ^^ entity.name.function.dart 7 | # ^^^^^^ support.class.dart 8 | >void f3(String a, [int? b]) {} 9 | #^^^^ storage.type.primitive.dart 10 | # ^^ entity.name.function.dart 11 | # ^^^^^^ support.class.dart 12 | # ^ punctuation.comma.dart 13 | # ^^^ support.class.dart 14 | # ^ keyword.operator.ternary.dart 15 | >void f4(String a, {int? b}) {} 16 | #^^^^ storage.type.primitive.dart 17 | # ^^ entity.name.function.dart 18 | # ^^^^^^ support.class.dart 19 | # ^ punctuation.comma.dart 20 | # ^^^ support.class.dart 21 | # ^ keyword.operator.ternary.dart 22 | >void f5(String a, {required int b}) {} 23 | #^^^^ storage.type.primitive.dart 24 | # ^^ entity.name.function.dart 25 | # ^^^^^^ support.class.dart 26 | # ^ punctuation.comma.dart 27 | # ^^^^^^^^ storage.modifier.dart 28 | # ^^^ support.class.dart 29 | >void f6( 30 | #^^^^ storage.type.primitive.dart 31 | # ^^ entity.name.function.dart 32 | > String a, 33 | # ^^^^^^ support.class.dart 34 | # ^ punctuation.comma.dart 35 | > List> Function(String a) b, 36 | # ^^^^ support.class.dart 37 | # ^ other.source.dart 38 | # ^^^ support.class.dart 39 | # ^ other.source.dart 40 | # ^^^^^^ support.class.dart 41 | # ^^^^^^ support.class.dart 42 | # ^^ other.source.dart 43 | # ^^^^^^^^ support.class.dart 44 | # ^^^^^^ support.class.dart 45 | # ^ punctuation.comma.dart 46 | >) {} 47 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Solutions in this repo 2 | 3 | ![](https://github.com/dart-lang/dart-syntax-highlight/workflows/Dart/badge.svg) 4 | 5 | ## grammars/dart.json 6 | 7 | A [TextMate](https://macromates.com/manual/en/language_grammars) language grammar for Dart. 8 | 9 | Used by: 10 | 11 | * The [Dart-Code](https://github.com/Dart-Code/Dart-Code) Dart extension for VS Code. 12 | * VS Code's [built-in Dart](https://github.com/microsoft/vscode/tree/main/extensions/dart) basic language support. 13 | * [Dart & Flutter DevTools](https://github.com/flutter/devtools). 14 | * [GitHub](https://github.com) via [Linguist](https://github.com/github/linguist). 15 | * [dart.dev](https://dart.dev) via [Shiki](https://shiki.style). 16 | 17 | When updating the grammar, consider raising issues (or PRs) to update the 18 | following files which do not have automated updates from this grammar: 19 | 20 | * [Dart-Code/Dart-Code/syntaxes/dart.json](https://github.com/Dart-Code/Dart-Code/blob/master/syntaxes/dart.json) 21 | * [flutter/devtools/packages/devtools_app/assets/dart_syntax.json](https://github.com/flutter/devtools/blob/master/packages/devtools_app/assets/dart_syntax.json) 22 | 23 | # Other solutions 24 | 25 | ## highlight.js 26 | 27 | [highlight.js](https://highlightjs.org/) is web based syntax highlighter that 28 | can syntax highlight `` references on a web page. 29 | 30 | * [Dart-specific code](https://github.com/highlightjs/highlight.js/blob/main/src/languages/dart.js) 31 | * Used by: 32 | * [DartDoc](https://github.com/dart-lang/dartdoc) 33 | * See https://github.com/dart-lang/dartdoc/tree/main/lib/resources 34 | * [pub.dev](https://github.com/dart-lang/pub-dev/) 35 | * See https://github.com/dart-lang/pub-dev/tree/master/third_party/highlight 36 | 37 | ## CodeMirror 38 | 39 | [CodeMirror](https://codemirror.net/) is a web-based editing component 40 | with Dart highlighting support. 41 | 42 | * CodeMirror 5 [Dart mode implementation](https://github.com/codemirror/codemirror5/tree/master/mode/dart) 43 | * Used by: 44 | * DartPad 45 | -------------------------------------------------------------------------------- /test/test_files/string_interpolation.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | void values() { 6 | final i = 1; 7 | final j = 2; 8 | 9 | print('the value of \$i is $i'); 10 | print('the value after \$i is ${i + 1}'); 11 | print('the value of \$i + \$j is ${i + j}'); 12 | } 13 | 14 | void functions() { 15 | print('${() { 16 | return 'Hello'; 17 | }}'); 18 | print('print(${() { 19 | return 'Hello'; 20 | }()})'); 21 | print('${() => 'Hello'}'); 22 | print('print(${(() => 'Hello')()})'); 23 | } 24 | 25 | void nestedBraces() { 26 | print( '${ { " {} ${ "}" } {}" } }' ); 27 | print( '${ {} }' ); 28 | print( '${ "{}" }' ); 29 | print( '${ "{" }' ); 30 | print( '${ "}" }' ); 31 | print( '${ {} }' ); 32 | print( "${ {} }" ); 33 | print( "${ "{}" }" ); 34 | print( "${ "{" }" ); 35 | print( "${ "}" }" ); 36 | print( "${ {} }" ); 37 | print( '''${ {} }'''); 38 | print( '''${ "{}" }'''); 39 | print( '''${ "{" }'''); 40 | print( '''${ "}" }'''); 41 | print( '''${ {} }'''); 42 | print( """${ {} }"""); 43 | print( """${ "{}" }"""); 44 | print( """${ "{" }"""); 45 | print( """${ "}" }"""); 46 | print( """${ {} }"""); 47 | print( r'${ {} }' ); 48 | print( r'${ "{}" }' ); 49 | print( r'${ "{" }' ); 50 | print( r'${ "}" }' ); 51 | print( r'${ {} }' ); 52 | print( r"${ {} }" ); 53 | print( r"${ '{}' }" ); 54 | print( r"${ '{' }" ); 55 | print( r"${ '}' }" ); 56 | print( r"${ {} }" ); 57 | print(r'''${ {} }'''); 58 | print(r'''${ "{}" }'''); 59 | print(r'''${ "{" }'''); 60 | print(r'''${ "}" }'''); 61 | print(r'''${ {} }'''); 62 | print(r"""${ {} }"""); 63 | print(r"""${ "{}" }"""); 64 | print(r"""${ "{" }"""); 65 | print(r"""${ "}" }"""); 66 | print(r"""${ {} }"""); 67 | } 68 | -------------------------------------------------------------------------------- /test/test_files/comments.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2022 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | /// Multiline dartdoc comment with triple backticks. 6 | /// 7 | /// ``` 8 | /// code 9 | /// ``` 10 | /// 11 | /// ... 12 | var doc1; 13 | 14 | /// Multiline dartdoc comment with unclosed triple backticks. 15 | /// 16 | /// ``` 17 | /// code 18 | var doc2; 19 | 20 | /// Multiline dartdoc comment with unclosed backticks. 21 | /// 22 | /// `code 23 | var doc3; 24 | 25 | /// Multiline dartdoc comment with indented code. 26 | /// 27 | /// code1 28 | /// code2 29 | /// 30 | /// code3 31 | /// 32 | /// ... 33 | var doc4; 34 | 35 | /** Block dartdoc comment with triple backticks. 36 | * 37 | * ``` 38 | * code 39 | * ``` 40 | * 41 | * ... 42 | */ 43 | var blockDoc1; 44 | 45 | /** Block dartdoc comment with unclosed triple backticks. 46 | * 47 | * ``` 48 | * code 49 | */ 50 | var blockDoc2; 51 | 52 | /** Block dartdoc comment with unclosed backticks. 53 | * 54 | * `code 55 | */ 56 | var blockDoc3; 57 | 58 | /** Block dartdoc comment with indented code. 59 | * 60 | * code1 61 | * code2 62 | * 63 | * code3 64 | * 65 | * ... 66 | */ 67 | var blockDoc4; 68 | 69 | /// `` 70 | var noInlineCode; 71 | 72 | /// `Stream` 73 | var inlineCode; 74 | 75 | /// ` ` 76 | var inlineCodeJustWhitespace; 77 | 78 | /* 79 | * Old-style dartdoc 80 | * 81 | * ... 82 | */ 83 | var b; 84 | 85 | /* Inline block comment */ 86 | var c; 87 | 88 | /** 89 | * Nested block 90 | * 91 | * /** 92 | * * Nested block 93 | * */ 94 | */ 95 | var d; 96 | 97 | /** 98 | * /** 99 | * * bbb 100 | * */ 101 | */ 102 | var d2; 103 | 104 | /** 105 | * Nested 106 | * 107 | * /* Inline */ 108 | */ 109 | var e; 110 | 111 | /* Nested /* Inline */ */ 112 | var f; 113 | 114 | // Simple comment 115 | var g; 116 | 117 | /// Dartdoc with reference to [a]. 118 | /// And a link to [example.org](http://example.org/). 119 | var h; 120 | 121 | class A { 122 | void b() {} 123 | Future c() {} 124 | } 125 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 1.4.1 (2024-11-18) 2 | 3 | - Fixed a bug where a closing block comment marker indented by more than 4 spaces would not end the comment. 4 | 5 | ## 1.4.0 (2024-11-18) 6 | 7 | - Removed use of 'while' in the grammar to avoid some differences in implementations between GitHub and VS Code 8 | - Improved handling of unclosed code blocks in dartdoc comments 9 | 10 | ## 1.3.0 (2024-07-31) 11 | 12 | - Added support for digit separators (`_`). 13 | 14 | ## 1.2.9 (2024-04-24) 15 | 16 | - Added support for `macro`, `augment library`, `import augment`, `augment`, `augmented`. 17 | 18 | ## 1.2.8 (2024-04-08) 19 | 20 | - Improve handling of braces inside string interpolation so `}` in expressions are not considered the end of the interpolation. 21 | - Change nested expression scopes from `string.interpolated.expression.dart` to `meta.embedded.expression.dart`. 22 | 23 | ## 1.2.7 (2024-02-08) 24 | 25 | - Updated the scope for `return` keywords from `keyword.control.dart` to `keyword.control.return.dart`. 26 | 27 | ## 1.2.6 (2024-01-25) 28 | 29 | - Don't highlight methods named `get`/`set` with type parameters as keywords. 30 | 31 | ## 1.2.5 (2023-11-27) 32 | 33 | - Don't mark empty double backticks as inline code. 34 | 35 | ## 1.2.4 (2023-11-26) 36 | 37 | - Include the opening `$` of a simple identifier string interpolation 38 | inside the `string.interpolated.expression.dart` scope. 39 | 40 | ## 1.2.3 (2023-09-11) 41 | 42 | - Removed support for `inline class` keyword and 43 | added support for `extension type`. 44 | 45 | ## 1.2.2 (2023-06-28) 46 | 47 | - Added support for `inline class`. 48 | 49 | ## 1.2.1 (2023-05-04) 50 | 51 | - Fixed highlighting of comments inside type arguments. 52 | 53 | ## 1.2.0 (2023-01-30) 54 | 55 | - Added support for class modifiers. 56 | - Added support for some patterns. 57 | - Identifiers preceding `=>` are no longer coloured as 58 | functions/methods if they do not have parens. 59 | 60 | ## 1.1.1 (2022-12-13) 61 | 62 | - Fixed highlighting of names that match some 63 | reserved words/classes with a `$` prefix/suffix. 64 | 65 | ## 1.1.0 (2022-12-07) 66 | 67 | - Improved handling of nested type parameters/arguments. 68 | - Improved handling of class declarations with 69 | both type arguments and `extends`. 70 | - Fixed handling of `get` and `set` as function names. 71 | 72 | ## 1.0.0 (2022-07-26) 73 | 74 | - Added an initial version number to the `grammars/dart.json` to help 75 | compare versions for projects using a copy of this file. 76 | -------------------------------------------------------------------------------- /test/goldens/extension_types.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright (c) 2023, the Dart project authors. Please see the AUTHORS file 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// for details. All rights reserved. Use of this source code is governed by a 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// BSD-style license that can be found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >extension type MyInt(int it) { 9 | #^^^^^^^^^^^^^^ keyword.declaration.dart 10 | # ^^^^^ support.class.dart 11 | # ^^^ support.class.dart 12 | > void foo() { print(it.isEven); } 13 | # ^^^^ storage.type.primitive.dart 14 | # ^^^ entity.name.function.dart 15 | # ^^^^^ entity.name.function.dart 16 | # ^ punctuation.dot.dart 17 | # ^ punctuation.terminator.dart 18 | >} 19 | > 20 | >final extension = 1; 21 | #^^^^^ storage.modifier.dart 22 | # ^^^^^^^^^ keyword.declaration.dart 23 | # ^ keyword.operator.assignment.dart 24 | # ^ constant.numeric.dart 25 | # ^ punctuation.terminator.dart 26 | >int get extension => 1; 27 | #^^^ support.class.dart 28 | # ^^^ keyword.declaration.dart 29 | # ^^^^^^^^^ keyword.declaration.dart 30 | # ^^ keyword.operator.closure.dart 31 | # ^ constant.numeric.dart 32 | # ^ punctuation.terminator.dart 33 | >set extension(int value) {} 34 | #^^^ keyword.declaration.dart 35 | # ^^^^^^^^^ keyword.declaration.dart 36 | # ^^^ support.class.dart 37 | >void extension() { 38 | #^^^^ storage.type.primitive.dart 39 | # ^^^^^^^^^ keyword.declaration.dart 40 | > var extension = 1; 41 | # ^^^ storage.type.primitive.dart 42 | # ^^^^^^^^^ keyword.declaration.dart 43 | # ^ keyword.operator.assignment.dart 44 | # ^ constant.numeric.dart 45 | # ^ punctuation.terminator.dart 46 | >} 47 | > 48 | >final type = 1; 49 | #^^^^^ storage.modifier.dart 50 | # ^ keyword.operator.assignment.dart 51 | # ^ constant.numeric.dart 52 | # ^ punctuation.terminator.dart 53 | >int get type => 1; 54 | #^^^ support.class.dart 55 | # ^^^ keyword.declaration.dart 56 | # ^^ keyword.operator.closure.dart 57 | # ^ constant.numeric.dart 58 | # ^ punctuation.terminator.dart 59 | >set type(int value) {} 60 | #^^^ keyword.declaration.dart 61 | # ^^^^ entity.name.function.dart 62 | # ^^^ support.class.dart 63 | >void type() { 64 | #^^^^ storage.type.primitive.dart 65 | # ^^^^ entity.name.function.dart 66 | > var type = 1; 67 | # ^^^ storage.type.primitive.dart 68 | # ^ keyword.operator.assignment.dart 69 | # ^ constant.numeric.dart 70 | # ^ punctuation.terminator.dart 71 | >} 72 | -------------------------------------------------------------------------------- /test/test_files/patterns.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2023, the Dart project authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'dart:math' as math; 6 | 7 | import 'support.dart'; 8 | 9 | // Samples taken from 10 | // https://github.com/dart-lang/language/blob/master/accepted/future-releases/0546-patterns/feature-specification.md 11 | 12 | void destructuring() { 13 | var (lat, long) = testRecord; 14 | var [a, b, c] = testList; 15 | var {'first': first, 'second': second} = testMap; 16 | } 17 | 18 | double algebraicDataTypes(Shape shape) => 19 | switch (shape) { 20 | Square(length: var l) => l * l, 21 | Circle(radius: var r) => math.pi * r * r 22 | }; 23 | 24 | void logicalOr() { 25 | var isPrimary = switch (testColor) { 26 | Color.red || Color.yellow || Color.blue => true, 27 | _ => false 28 | }; 29 | 30 | switch (testShape) { 31 | case Square(size: var s) || Circle(size: var s) when s > 0: 32 | print('Non-empty symmetric shape'); 33 | case Square() || Circle(): 34 | print('Empty symmetric shape'); 35 | default: 36 | print('Asymmetric shape'); 37 | } 38 | 39 | switch (testList) { 40 | case ['a' || 'b', var c]: 41 | } 42 | } 43 | 44 | String logicalAnd_relational(int char) { 45 | return switch (char) { 46 | < space => 'control', 47 | == space => 'space', 48 | > space && < zero => 'punctuation', 49 | >= zero && <= nine => 'digit' 50 | }; 51 | } 52 | 53 | void castPattern() { 54 | var (i as int, j as int) = testRecord; 55 | } 56 | 57 | void nullCheckPattern_nullAssertPattern() { 58 | switch (maybeString) { 59 | case var s?: 60 | } 61 | 62 | var (x!, y!) = testRecord; 63 | 64 | switch (testList) { 65 | case ['user', var name!]: 66 | } 67 | } 68 | 69 | void variablePattern() { 70 | switch ((1, 2, 3)) { 71 | case (var a, final b, _): 72 | } 73 | switch ((1, 2, 3)) { 74 | case (int a, String b, String _): 75 | } 76 | } 77 | 78 | void listPatterns() { 79 | var [_, two, _] = testList; 80 | var [a, b, ...rest, c, d] = [1, 2, 3, 4, 5, 6, 7]; 81 | } 82 | 83 | void mapPatterns() { 84 | var {'field1': String field1, ... } = { 'field1': 'value1', 'field2': 'value2' }; 85 | } 86 | 87 | void recordPatterns() { 88 | // Variable: 89 | var (untyped: untyped, typed: int typed) = testRecord; 90 | var (:untyped, :int typed) = testRecord; 91 | 92 | switch (testObject) { 93 | case (untyped: var untyped, typed: int typed): 94 | case (:var untyped, :int typed): 95 | } 96 | 97 | // Null-check and null-assert: 98 | switch (testObject) { 99 | case (checked: var checked?, asserted: var asserted!): 100 | case (:var checked?, :var asserted!): 101 | } 102 | 103 | // Cast: 104 | var (field: field as int) = testRecord; 105 | var (:field as int) = testRecord; 106 | } 107 | 108 | void objectPatterns(Object obj) { 109 | switch (obj) { 110 | case Rect(width: var w, height: var h): 111 | default: 112 | } 113 | switch (obj) { 114 | case Rect(:var width, :var height): 115 | default: 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /test/test_files/variable_names.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | const $bool = null; 6 | const bool$ = null; 7 | const $num = null; 8 | const num$ = null; 9 | const $int = null; 10 | const int$ = null; 11 | const $double = null; 12 | const double$ = null; 13 | const $dynamic = null; 14 | const dynamic$ = null; 15 | const $true = null; 16 | const true$ = null; 17 | const $false = null; 18 | const false$ = null; 19 | const $null = null; 20 | const null$ = null; 21 | const $this = null; 22 | const this$ = null; 23 | const $super = null; 24 | const super$ = null; 25 | const $as = null; 26 | const as$ = null; 27 | const $try = null; 28 | const try$ = null; 29 | const $on = null; 30 | const on$ = null; 31 | const $catch = null; 32 | const catch$ = null; 33 | const $finally = null; 34 | const finally$ = null; 35 | const $throw = null; 36 | const throw$ = null; 37 | const $rethrow = null; 38 | const rethrow$ = null; 39 | const $break = null; 40 | const break$ = null; 41 | const $case = null; 42 | const case$ = null; 43 | const $continue = null; 44 | const continue$ = null; 45 | const $default = null; 46 | const default$ = null; 47 | const $do = null; 48 | const do$ = null; 49 | const $else = null; 50 | const else$ = null; 51 | const $for = null; 52 | const for$ = null; 53 | const $if = null; 54 | const if$ = null; 55 | const $in = null; 56 | const in$ = null; 57 | const $return = null; 58 | const return$ = null; 59 | const $switch = null; 60 | const switch$ = null; 61 | const $while = null; 62 | const while$ = null; 63 | const $sync = null; 64 | const sync$ = null; 65 | const $async = null; 66 | const async$ = null; 67 | const $await = null; 68 | const await$ = null; 69 | const $yield = null; 70 | const yield$ = null; 71 | const $assert = null; 72 | const assert$ = null; 73 | const $new = null; 74 | const new$ = null; 75 | const $abstract = null; 76 | const abstract$ = null; 77 | const $class = null; 78 | const class$ = null; 79 | const $enum = null; 80 | const enum$ = null; 81 | const $extends = null; 82 | const extends$ = null; 83 | const $extension = null; 84 | const extension$ = null; 85 | const $external = null; 86 | const external$ = null; 87 | const $factory = null; 88 | const factory$ = null; 89 | const $implements = null; 90 | const implements$ = null; 91 | const $get = null; 92 | const get$ = null; 93 | const $mixin = null; 94 | const mixin$ = null; 95 | const $native = null; 96 | const native$ = null; 97 | const $operator = null; 98 | const operator$ = null; 99 | const $set = null; 100 | const set$ = null; 101 | const $typedef = null; 102 | const typedef$ = null; 103 | const $with = null; 104 | const with$ = null; 105 | const $covariant = null; 106 | const covariant$ = null; 107 | const $static = null; 108 | const static$ = null; 109 | const $final = null; 110 | const final$ = null; 111 | const $const = null; 112 | const const$ = null; 113 | const $required = null; 114 | const required$ = null; 115 | const $late = null; 116 | const late$ = null; 117 | const $void = null; 118 | const void$ = null; 119 | const $var = null; 120 | const var$ = null; 121 | const $is = null; 122 | const is$ = null; 123 | const $sealed = null; 124 | const sealed$ = null; 125 | const $interface = null; 126 | const interface$ = null; 127 | const $base = null; 128 | const base$ = null; 129 | -------------------------------------------------------------------------------- /test/goldens/control.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >void err() { 9 | #^^^^ storage.type.primitive.dart 10 | # ^^^ entity.name.function.dart 11 | > try { 12 | # ^^^ keyword.control.catch-exception.dart 13 | > throw ''; 14 | # ^^^^^ keyword.control.catch-exception.dart 15 | # ^^ string.interpolated.single.dart 16 | # ^ punctuation.terminator.dart 17 | > } on ArgumentError { 18 | # ^^ keyword.control.catch-exception.dart 19 | # ^^^^^^^^^^^^^ support.class.dart 20 | > rethrow; 21 | # ^^^^^^^ keyword.control.catch-exception.dart 22 | # ^ punctuation.terminator.dart 23 | > } catch (e) { 24 | # ^^^^^ keyword.control.catch-exception.dart 25 | > print('e'); 26 | # ^^^^^ entity.name.function.dart 27 | # ^^^ string.interpolated.single.dart 28 | # ^ punctuation.terminator.dart 29 | > } 30 | >} 31 | > 32 | >void loops() { 33 | #^^^^ storage.type.primitive.dart 34 | # ^^^^^ entity.name.function.dart 35 | > while (1 > 2) { 36 | # ^^^^^ keyword.control.dart 37 | # ^ constant.numeric.dart 38 | # ^ keyword.operator.comparison.dart 39 | # ^ constant.numeric.dart 40 | > if (3 > 4) { 41 | # ^^ keyword.control.dart 42 | # ^ constant.numeric.dart 43 | # ^ keyword.operator.comparison.dart 44 | # ^ constant.numeric.dart 45 | > continue; 46 | # ^^^^^^^^ keyword.control.dart 47 | # ^ punctuation.terminator.dart 48 | > } else { 49 | # ^^^^ keyword.control.dart 50 | > break; 51 | # ^^^^^ keyword.control.dart 52 | # ^ punctuation.terminator.dart 53 | > } 54 | > return; 55 | # ^^^^^^ keyword.control.return.dart 56 | # ^ punctuation.terminator.dart 57 | > } 58 | > 59 | > do { 60 | # ^^ keyword.control.dart 61 | > print(''); 62 | # ^^^^^ entity.name.function.dart 63 | # ^^ string.interpolated.single.dart 64 | # ^ punctuation.terminator.dart 65 | > } while (1 > 2); 66 | # ^^^^^ keyword.control.dart 67 | # ^ constant.numeric.dart 68 | # ^ keyword.operator.comparison.dart 69 | # ^ constant.numeric.dart 70 | # ^ punctuation.terminator.dart 71 | >} 72 | > 73 | >void switches() { 74 | #^^^^ storage.type.primitive.dart 75 | # ^^^^^^^^ entity.name.function.dart 76 | > Object? i = 1; 77 | # ^^^^^^ support.class.dart 78 | # ^ keyword.operator.ternary.dart 79 | # ^ keyword.operator.assignment.dart 80 | # ^ constant.numeric.dart 81 | # ^ punctuation.terminator.dart 82 | > switch (i as int) { 83 | # ^^^^^^ keyword.control.dart 84 | # ^^ keyword.cast.dart 85 | # ^^^ support.class.dart 86 | > case 1: 87 | # ^^^^ keyword.control.dart 88 | # ^ constant.numeric.dart 89 | # ^ keyword.operator.ternary.dart 90 | > break; 91 | # ^^^^^ keyword.control.dart 92 | # ^ punctuation.terminator.dart 93 | > default: 94 | # ^^^^^^^ keyword.control.dart 95 | # ^ keyword.operator.ternary.dart 96 | > return; 97 | # ^^^^^^ keyword.control.return.dart 98 | # ^ punctuation.terminator.dart 99 | > } 100 | >} 101 | > 102 | >void conditions() { 103 | #^^^^ storage.type.primitive.dart 104 | # ^^^^^^^^^^ entity.name.function.dart 105 | > if (1 > 2) { 106 | # ^^ keyword.control.dart 107 | # ^ constant.numeric.dart 108 | # ^ keyword.operator.comparison.dart 109 | # ^ constant.numeric.dart 110 | > } else if (3 > 4) { 111 | # ^^^^ keyword.control.dart 112 | # ^^ keyword.control.dart 113 | # ^ constant.numeric.dart 114 | # ^ keyword.operator.comparison.dart 115 | # ^ constant.numeric.dart 116 | > } else {} 117 | # ^^^^ keyword.control.dart 118 | >} 119 | -------------------------------------------------------------------------------- /test/goldens/records.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >(int, int)? aaa; 9 | # ^^^ support.class.dart 10 | # ^ punctuation.comma.dart 11 | # ^^^ support.class.dart 12 | # ^ keyword.operator.ternary.dart 13 | # ^ punctuation.terminator.dart 14 | >(int aaa, int bbb)? bbb; 15 | # ^^^ support.class.dart 16 | # ^ punctuation.comma.dart 17 | # ^^^ support.class.dart 18 | # ^ keyword.operator.ternary.dart 19 | # ^ punctuation.terminator.dart 20 | >(int aaa, int, {String? ccc})? ccc; 21 | # ^^^ support.class.dart 22 | # ^ punctuation.comma.dart 23 | # ^^^ support.class.dart 24 | # ^ punctuation.comma.dart 25 | # ^^^^^^ support.class.dart 26 | # ^ keyword.operator.ternary.dart 27 | # ^ keyword.operator.ternary.dart 28 | # ^ punctuation.terminator.dart 29 | >(int, (int, (int, String)))? ddd; 30 | # ^^^ support.class.dart 31 | # ^ punctuation.comma.dart 32 | # ^^^ support.class.dart 33 | # ^ punctuation.comma.dart 34 | # ^^^ support.class.dart 35 | # ^ punctuation.comma.dart 36 | # ^^^^^^ support.class.dart 37 | # ^ keyword.operator.ternary.dart 38 | # ^ punctuation.terminator.dart 39 | > 40 | >(int aaa, int bbb) func((String aaaa, String? bbbb) ccc) { 41 | # ^^^ support.class.dart 42 | # ^ punctuation.comma.dart 43 | # ^^^ support.class.dart 44 | # ^^^^ entity.name.function.dart 45 | # ^^^^^^ support.class.dart 46 | # ^ punctuation.comma.dart 47 | # ^^^^^^ support.class.dart 48 | # ^ keyword.operator.ternary.dart 49 | > final ddd = (1, 2, eee: ''); 50 | # ^^^^^ storage.modifier.dart 51 | # ^ keyword.operator.assignment.dart 52 | # ^ constant.numeric.dart 53 | # ^ punctuation.comma.dart 54 | # ^ constant.numeric.dart 55 | # ^ punctuation.comma.dart 56 | # ^ keyword.operator.ternary.dart 57 | # ^^ string.interpolated.single.dart 58 | # ^ punctuation.terminator.dart 59 | > return (1, 2); 60 | # ^^^^^^ keyword.control.return.dart 61 | # ^ constant.numeric.dart 62 | # ^ punctuation.comma.dart 63 | # ^ constant.numeric.dart 64 | # ^ punctuation.terminator.dart 65 | >} 66 | > 67 | >class R { 68 | #^^^^^ keyword.declaration.dart 69 | # ^ support.class.dart 70 | > (int aaa, int, {String? ccc})? get getter => null; 71 | # ^^^ support.class.dart 72 | # ^ punctuation.comma.dart 73 | # ^^^ support.class.dart 74 | # ^ punctuation.comma.dart 75 | # ^^^^^^ support.class.dart 76 | # ^ keyword.operator.ternary.dart 77 | # ^ keyword.operator.ternary.dart 78 | # ^^^ keyword.declaration.dart 79 | # ^^ keyword.operator.closure.dart 80 | # ^^^^ constant.language.dart 81 | # ^ punctuation.terminator.dart 82 | > final variable = (1, 2, eee: ''); 83 | # ^^^^^ storage.modifier.dart 84 | # ^ keyword.operator.assignment.dart 85 | # ^ constant.numeric.dart 86 | # ^ punctuation.comma.dart 87 | # ^ constant.numeric.dart 88 | # ^ punctuation.comma.dart 89 | # ^ keyword.operator.ternary.dart 90 | # ^^ string.interpolated.single.dart 91 | # ^ punctuation.terminator.dart 92 | >} 93 | -------------------------------------------------------------------------------- /test/goldens/directives.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >import 'dart:io'; 9 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 10 | # ^ meta.declaration.dart 11 | # ^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 12 | # ^ meta.declaration.dart punctuation.terminator.dart 13 | >import 'dart:io' as io; 14 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 15 | # ^ meta.declaration.dart 16 | # ^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 17 | # ^ meta.declaration.dart 18 | # ^^ meta.declaration.dart keyword.other.import.dart 19 | # ^^^ meta.declaration.dart 20 | # ^ meta.declaration.dart punctuation.terminator.dart 21 | >import 'dart:io' show File; 22 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 23 | # ^ meta.declaration.dart 24 | # ^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 25 | # ^ meta.declaration.dart 26 | # ^^^^ meta.declaration.dart keyword.other.import.dart 27 | # ^^^^^ meta.declaration.dart 28 | # ^ meta.declaration.dart punctuation.terminator.dart 29 | >import 'dart:io' hide Directory; 30 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 31 | # ^ meta.declaration.dart 32 | # ^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 33 | # ^ meta.declaration.dart 34 | # ^^^^ meta.declaration.dart keyword.other.import.dart 35 | # ^^^^^^^^^^ meta.declaration.dart 36 | # ^ meta.declaration.dart punctuation.terminator.dart 37 | >import 'dart:io' show File hide Directory; 38 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 39 | # ^ meta.declaration.dart 40 | # ^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 41 | # ^ meta.declaration.dart 42 | # ^^^^ meta.declaration.dart keyword.other.import.dart 43 | # ^^^^^^ meta.declaration.dart 44 | # ^^^^ meta.declaration.dart keyword.other.import.dart 45 | # ^^^^^^^^^^ meta.declaration.dart 46 | # ^ meta.declaration.dart punctuation.terminator.dart 47 | >import 'dart:io' as io show Directory; 48 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 49 | # ^ meta.declaration.dart 50 | # ^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 51 | # ^ meta.declaration.dart 52 | # ^^ meta.declaration.dart keyword.other.import.dart 53 | # ^^^^ meta.declaration.dart 54 | # ^^^^ meta.declaration.dart keyword.other.import.dart 55 | # ^^^^^^^^^^ meta.declaration.dart 56 | # ^ meta.declaration.dart punctuation.terminator.dart 57 | >import 'dart:async' deferred as deferredAsync show Future; 58 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 59 | # ^ meta.declaration.dart 60 | # ^^^^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 61 | # ^^^^^^^^^^ meta.declaration.dart 62 | # ^^ meta.declaration.dart keyword.other.import.dart 63 | # ^^^^^^^^^^^^^^^ meta.declaration.dart 64 | # ^^^^ meta.declaration.dart keyword.other.import.dart 65 | # ^^^^^^^ meta.declaration.dart 66 | # ^ meta.declaration.dart punctuation.terminator.dart 67 | > 68 | >export 'comments.dart'; 69 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 70 | # ^ meta.declaration.dart 71 | # ^^^^^^^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 72 | # ^ meta.declaration.dart punctuation.terminator.dart 73 | -------------------------------------------------------------------------------- /test/golden_test.dart: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | // for details. All rights reserved. Use of this source code is governed by a 3 | // BSD-style license that can be found in the LICENSE file. 4 | 5 | import 'dart:convert'; 6 | import 'dart:io'; 7 | 8 | import 'package:collection/collection.dart'; 9 | import 'package:path/path.dart' as path; 10 | import 'package:test/test.dart'; 11 | 12 | import 'support/span_parser.dart'; 13 | 14 | void main() { 15 | final projectRoot = path.normalize( 16 | path.join(path.basename(Platform.script.toFilePath()), '..'), 17 | ); 18 | final testFileDirectory = 19 | Directory(path.join(projectRoot, 'test', 'test_files')); 20 | final goldenDirectory = Directory(path.join(projectRoot, 'test', 'goldens')); 21 | final grammarFile = File(path.join(projectRoot, 'grammars/dart.json')); 22 | final grammar = Grammar.fromJson( 23 | jsonDecode(grammarFile.readAsStringSync()) as Map); 24 | final updateGoldens = Platform.environment.containsKey('UPDATE_GOLDENS'); 25 | 26 | group('golden', () { 27 | final testFiles = testFileDirectory 28 | .listSync() 29 | .whereType() 30 | .where((file) => path.extension(file.path) == '.dart') 31 | .where((file) => 32 | path.withoutExtension(path.basename(file.path)) != 'support'); 33 | 34 | for (final testFile in testFiles) { 35 | final goldenFile = File(path.join( 36 | goldenDirectory.path, 37 | '${path.basename(testFile.path)}.golden', 38 | )); 39 | if (updateGoldens) { 40 | test('${path.basename(testFile.path)} (update goldens)', () { 41 | final content = testFile.readAsStringSync(); 42 | final spans = SpanParser.parse(grammar, content); 43 | final actual = _buildGoldenText(content, spans); 44 | 45 | goldenFile.writeAsStringSync(actual); 46 | }); 47 | } 48 | 49 | for (final eol in ['\n', '\r\n']) { 50 | test('${path.basename(testFile.path)} (eol=${jsonEncode(eol)})', () { 51 | if (!goldenFile.existsSync()) { 52 | fail('Missing golden file: ${goldenFile.path}'); 53 | } 54 | 55 | /// Normalises newlines to the set we're comparing. 56 | String normalize(String code) => 57 | code.replaceAll('\r', '').replaceAll('\n', eol); 58 | 59 | final content = normalize(testFile.readAsStringSync()); 60 | final spans = SpanParser.parse(grammar, content); 61 | final actual = _buildGoldenText(content, spans); 62 | 63 | final expected = normalize(goldenFile.readAsStringSync()); 64 | expect(actual, expected); 65 | }); 66 | } 67 | } 68 | }); 69 | } 70 | 71 | String _buildGoldenText(String content, List spans) { 72 | final buffer = StringBuffer(); 73 | final spansByLine = groupBy(spans, (ScopeSpan s) => s.line - 1); 74 | 75 | final lines = content.split('\n'); 76 | for (var i = 0; i < lines.length; i++) { 77 | // We only output characters for the line, excluding any newlines on the 78 | // end. 79 | final line = lines[i].trimRight(); 80 | // Track what the eol was (restore the newline, subtract any untrimmed 81 | // part). This may end up as `\r\n` or `\n` depending on whether Windows 82 | // and the git autocrlf setting. 83 | final eol = '${lines[i]}\n'.substring(line.length); 84 | final lineLengthWithNewline = line.length + eol.length; 85 | 86 | // If this is the last line and it's blank, skip it. 87 | if (i == lines.length - 1 && line.isEmpty) { 88 | break; 89 | } 90 | 91 | buffer.write('>$line$eol'); 92 | final lineSpans = spansByLine[i]; 93 | if (lineSpans != null) { 94 | for (final span in lineSpans) { 95 | final col = span.column - 1; 96 | var length = span.length; 97 | 98 | // Spans may roll over onto the next line, so truncate them and insert 99 | // the remainder into the next. 100 | if (col + length > lineLengthWithNewline) { 101 | final thisLineLength = line.length - col; 102 | final offsetToStartOfNextLine = lineLengthWithNewline - col; 103 | length = thisLineLength; 104 | spansByLine[i + 1] ??= []; 105 | // Insert the wrapped span before other spans on the next line so the 106 | // order is preserved. 107 | spansByLine[i + 1]!.insert( 108 | 0, 109 | ScopeSpan( 110 | scopes: span.scopes, 111 | startLocation: ScopeStackLocation( 112 | position: span.start + offsetToStartOfNextLine, 113 | line: span.line + 1, 114 | column: 0, 115 | ), 116 | endLocation: span.endLocation, 117 | ), 118 | ); 119 | } else if (col + length > line.length) { 120 | // Truncate any spans that include the trailing newline. 121 | length = line.length - col; 122 | } 123 | 124 | // If this span just covers the trailing newline, skip it 125 | // as it doesn't produce any useful output. 126 | if (col >= line.length) { 127 | continue; 128 | } 129 | 130 | buffer.write('#'); 131 | buffer.write(' ' * col); 132 | buffer.write('^' * length); 133 | buffer.write(' '); 134 | buffer.write(span.scopes.join(' ')); 135 | buffer.write(eol); 136 | } 137 | } 138 | } 139 | 140 | return buffer.toString(); 141 | } 142 | -------------------------------------------------------------------------------- /test/goldens/misc.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >library foo; 9 | #^^^^^^^ meta.declaration.dart keyword.other.import.dart 10 | # ^^^^ meta.declaration.dart 11 | # ^ meta.declaration.dart punctuation.terminator.dart 12 | > 13 | >external int get externalInt; 14 | #^^^^^^^^ keyword.declaration.dart 15 | # ^^^ support.class.dart 16 | # ^^^ keyword.declaration.dart 17 | # ^ punctuation.terminator.dart 18 | > 19 | >typedef StringAlias = String; 20 | #^^^^^^^ keyword.declaration.dart 21 | # ^^^^^^^^^^^ support.class.dart 22 | # ^ keyword.operator.assignment.dart 23 | # ^^^^^^ support.class.dart 24 | # ^ punctuation.terminator.dart 25 | >typedef void FunctionAlias1(String a, String b); 26 | #^^^^^^^ keyword.declaration.dart 27 | # ^^^^ storage.type.primitive.dart 28 | # ^^^^^^^^^^^^^^ support.class.dart 29 | # ^^^^^^ support.class.dart 30 | # ^ punctuation.comma.dart 31 | # ^^^^^^ support.class.dart 32 | # ^ punctuation.terminator.dart 33 | >typedef FunctionAlias2 = void Function(String a, String b); 34 | #^^^^^^^ keyword.declaration.dart 35 | # ^^^^^^^^^^^^^^ support.class.dart 36 | # ^ keyword.operator.assignment.dart 37 | # ^^^^ storage.type.primitive.dart 38 | # ^^^^^^^^ support.class.dart 39 | # ^^^^^^ support.class.dart 40 | # ^ punctuation.comma.dart 41 | # ^^^^^^ support.class.dart 42 | # ^ punctuation.terminator.dart 43 | > 44 | >Map, List>>? nestedTypeArguments; 45 | #^^^ support.class.dart 46 | # ^ other.source.dart 47 | # ^^^^ support.class.dart 48 | # ^ other.source.dart 49 | # ^^^^^^ support.class.dart 50 | # ^ other.source.dart 51 | # ^^^^ support.class.dart 52 | # ^ other.source.dart 53 | # ^^^^ support.class.dart 54 | # ^ other.source.dart 55 | # ^^^^^^ support.class.dart 56 | # ^^^ other.source.dart 57 | # ^ keyword.operator.ternary.dart 58 | # ^ punctuation.terminator.dart 59 | > 60 | >void misc(int a, {required int b}) { 61 | #^^^^ storage.type.primitive.dart 62 | # ^^^^ entity.name.function.dart 63 | # ^^^ support.class.dart 64 | # ^ punctuation.comma.dart 65 | # ^^^^^^^^ storage.modifier.dart 66 | # ^^^ support.class.dart 67 | > assert(true); 68 | # ^^^^^^ keyword.control.dart 69 | # ^^^^ constant.language.dart 70 | # ^ punctuation.terminator.dart 71 | > assert(1 == 1, 'fail'); 72 | # ^^^^^^ keyword.control.dart 73 | # ^ constant.numeric.dart 74 | # ^^ keyword.operator.comparison.dart 75 | # ^ constant.numeric.dart 76 | # ^ punctuation.comma.dart 77 | # ^^^^^^ string.interpolated.single.dart 78 | # ^ punctuation.terminator.dart 79 | > 80 | > var a = new String.fromCharCode(1); 81 | # ^^^ storage.type.primitive.dart 82 | # ^ keyword.operator.assignment.dart 83 | # ^^^ keyword.control.new.dart 84 | # ^^^^^^ support.class.dart 85 | # ^ punctuation.dot.dart 86 | # ^^^^^^^^^^^^ entity.name.function.dart 87 | # ^ constant.numeric.dart 88 | # ^ punctuation.terminator.dart 89 | > const b = int.fromEnvironment(''); 90 | # ^^^^^ storage.modifier.dart 91 | # ^ keyword.operator.assignment.dart 92 | # ^^^ support.class.dart 93 | # ^ punctuation.dot.dart 94 | # ^^^^^^^^^^^^^^^ entity.name.function.dart 95 | # ^^ string.interpolated.single.dart 96 | # ^ punctuation.terminator.dart 97 | > final c = ''; 98 | # ^^^^^ storage.modifier.dart 99 | # ^ keyword.operator.assignment.dart 100 | # ^^ string.interpolated.single.dart 101 | # ^ punctuation.terminator.dart 102 | > late final d = ''; 103 | # ^^^^ storage.modifier.dart 104 | # ^^^^^ storage.modifier.dart 105 | # ^ keyword.operator.assignment.dart 106 | # ^^ string.interpolated.single.dart 107 | # ^ punctuation.terminator.dart 108 | > print(d is String); 109 | # ^^^^^ entity.name.function.dart 110 | # ^^ keyword.operator.dart 111 | # ^^^^^^ support.class.dart 112 | # ^ punctuation.terminator.dart 113 | > print(d is! String); 114 | # ^^^^^ entity.name.function.dart 115 | # ^^ keyword.operator.dart 116 | # ^ keyword.operator.logical.dart 117 | # ^^^^^^ support.class.dart 118 | # ^ punctuation.terminator.dart 119 | >} 120 | > 121 | >class Covariance { 122 | #^^^^^ keyword.declaration.dart 123 | # ^^^^^^^^^^ support.class.dart 124 | # ^ other.source.dart 125 | # ^ support.class.dart 126 | # ^ other.source.dart 127 | > void covariance(covariant List items) {} 128 | # ^^^^ storage.type.primitive.dart 129 | # ^^^^^^^^^^ entity.name.function.dart 130 | # ^^^^^^^^^ keyword.declaration.dart 131 | # ^^^^ support.class.dart 132 | # ^ other.source.dart 133 | # ^ support.class.dart 134 | # ^ other.source.dart 135 | >} 136 | -------------------------------------------------------------------------------- /test/goldens/literals.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >const a = 'aaaaa'; 9 | #^^^^^ storage.modifier.dart 10 | # ^ keyword.operator.assignment.dart 11 | # ^^^^^^^ string.interpolated.single.dart 12 | # ^ punctuation.terminator.dart 13 | > 14 | >const list1 = []; 15 | #^^^^^ storage.modifier.dart 16 | # ^ keyword.operator.assignment.dart 17 | # ^ punctuation.terminator.dart 18 | >const list2 = []; 19 | #^^^^^ storage.modifier.dart 20 | # ^ keyword.operator.assignment.dart 21 | # ^ keyword.operator.comparison.dart 22 | # ^^^^^^ support.class.dart 23 | # ^ keyword.operator.comparison.dart 24 | # ^ punctuation.terminator.dart 25 | >const list3 = ['', '$a']; 26 | #^^^^^ storage.modifier.dart 27 | # ^ keyword.operator.assignment.dart 28 | # ^^ string.interpolated.single.dart 29 | # ^ punctuation.comma.dart 30 | # ^ string.interpolated.single.dart 31 | # ^ string.interpolated.single.dart meta.embedded.expression.dart 32 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 33 | # ^ string.interpolated.single.dart 34 | # ^ punctuation.terminator.dart 35 | >const list4 = ['', '$a']; 36 | #^^^^^ storage.modifier.dart 37 | # ^ keyword.operator.assignment.dart 38 | # ^ keyword.operator.comparison.dart 39 | # ^^^^^^ support.class.dart 40 | # ^ keyword.operator.comparison.dart 41 | # ^^ string.interpolated.single.dart 42 | # ^ punctuation.comma.dart 43 | # ^ string.interpolated.single.dart 44 | # ^ string.interpolated.single.dart meta.embedded.expression.dart 45 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 46 | # ^ string.interpolated.single.dart 47 | # ^ punctuation.terminator.dart 48 | > 49 | >const set1 = {}; 50 | #^^^^^ storage.modifier.dart 51 | # ^ keyword.operator.assignment.dart 52 | # ^ punctuation.terminator.dart 53 | >const set2 = {}; 54 | #^^^^^ storage.modifier.dart 55 | # ^ keyword.operator.assignment.dart 56 | # ^ keyword.operator.comparison.dart 57 | # ^^^^^^ support.class.dart 58 | # ^ keyword.operator.comparison.dart 59 | # ^ punctuation.terminator.dart 60 | >const set3 = {'', '$a'}; 61 | #^^^^^ storage.modifier.dart 62 | # ^ keyword.operator.assignment.dart 63 | # ^^ string.interpolated.single.dart 64 | # ^ punctuation.comma.dart 65 | # ^ string.interpolated.single.dart 66 | # ^ string.interpolated.single.dart meta.embedded.expression.dart 67 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 68 | # ^ string.interpolated.single.dart 69 | # ^ punctuation.terminator.dart 70 | >const set4 = {'', '$a'}; 71 | #^^^^^ storage.modifier.dart 72 | # ^ keyword.operator.assignment.dart 73 | # ^ keyword.operator.comparison.dart 74 | # ^^^^^^ support.class.dart 75 | # ^ keyword.operator.comparison.dart 76 | # ^^ string.interpolated.single.dart 77 | # ^ punctuation.comma.dart 78 | # ^ string.interpolated.single.dart 79 | # ^ string.interpolated.single.dart meta.embedded.expression.dart 80 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 81 | # ^ string.interpolated.single.dart 82 | # ^ punctuation.terminator.dart 83 | > 84 | >const map1 = {}; 85 | #^^^^^ storage.modifier.dart 86 | # ^ keyword.operator.assignment.dart 87 | # ^ keyword.operator.comparison.dart 88 | # ^^^^^^ support.class.dart 89 | # ^ punctuation.comma.dart 90 | # ^^^^^^ support.class.dart 91 | # ^ keyword.operator.comparison.dart 92 | # ^ punctuation.terminator.dart 93 | >const map2 = {'': '$a'}; 94 | #^^^^^ storage.modifier.dart 95 | # ^ keyword.operator.assignment.dart 96 | # ^^ string.interpolated.single.dart 97 | # ^ keyword.operator.ternary.dart 98 | # ^ string.interpolated.single.dart 99 | # ^ string.interpolated.single.dart meta.embedded.expression.dart 100 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 101 | # ^ string.interpolated.single.dart 102 | # ^ punctuation.terminator.dart 103 | >const map3 = {'': '$a'}; 104 | #^^^^^ storage.modifier.dart 105 | # ^ keyword.operator.assignment.dart 106 | # ^ keyword.operator.comparison.dart 107 | # ^^^^^^ support.class.dart 108 | # ^ punctuation.comma.dart 109 | # ^^^^^^ support.class.dart 110 | # ^ keyword.operator.comparison.dart 111 | # ^^ string.interpolated.single.dart 112 | # ^ keyword.operator.ternary.dart 113 | # ^ string.interpolated.single.dart 114 | # ^ string.interpolated.single.dart meta.embedded.expression.dart 115 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 116 | # ^ string.interpolated.single.dart 117 | # ^ punctuation.terminator.dart 118 | -------------------------------------------------------------------------------- /test/goldens/functions.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >void simplePrint() { 9 | #^^^^ storage.type.primitive.dart 10 | # ^^^^^^^^^^^ entity.name.function.dart 11 | > print('hello world'); 12 | # ^^^^^ entity.name.function.dart 13 | # ^^^^^^^^^^^^^ string.interpolated.single.dart 14 | # ^ punctuation.terminator.dart 15 | >} 16 | > 17 | >noReturnValue() { 18 | #^^^^^^^^^^^^^ entity.name.function.dart 19 | > print('hello world'); 20 | # ^^^^^ entity.name.function.dart 21 | # ^^^^^^^^^^^^^ string.interpolated.single.dart 22 | # ^ punctuation.terminator.dart 23 | >} 24 | > 25 | >void returns() { 26 | #^^^^ storage.type.primitive.dart 27 | # ^^^^^^^ entity.name.function.dart 28 | > return; 29 | # ^^^^^^ keyword.control.return.dart 30 | # ^ punctuation.terminator.dart 31 | >} 32 | > 33 | >Future asyncPrint() async { 34 | #^^^^^^ support.class.dart 35 | # ^ other.source.dart 36 | # ^^^^ storage.type.primitive.dart 37 | # ^ other.source.dart 38 | # ^^^^^^^^^^ entity.name.function.dart 39 | # ^^^^^ keyword.control.dart 40 | > await Future.delayed(const Duration(seconds: 1)); 41 | # ^^^^^ keyword.control.dart 42 | # ^^^^^^ support.class.dart 43 | # ^ punctuation.dot.dart 44 | # ^^^^^^^ entity.name.function.dart 45 | # ^^^^^ storage.modifier.dart 46 | # ^^^^^^^^ support.class.dart 47 | # ^ keyword.operator.ternary.dart 48 | # ^ constant.numeric.dart 49 | # ^ punctuation.terminator.dart 50 | > print('hello world'); 51 | # ^^^^^ entity.name.function.dart 52 | # ^^^^^^^^^^^^^ string.interpolated.single.dart 53 | # ^ punctuation.terminator.dart 54 | >} 55 | > 56 | >Map> nestedGenerics() { 57 | #^^^ support.class.dart 58 | # ^ other.source.dart 59 | # ^^ support.class.dart 60 | # ^^^^ support.class.dart 61 | # ^ other.source.dart 62 | # ^^ support.class.dart 63 | # ^^ other.source.dart 64 | # ^^^^^^^^^^^^^^ entity.name.function.dart 65 | # ^ other.source.dart 66 | # ^^ support.class.dart 67 | # ^^ support.class.dart 68 | # ^^^^^^^ keyword.declaration.dart 69 | # ^^^^^^ support.class.dart 70 | # ^ other.source.dart 71 | > return {}; 72 | # ^^^^^^ keyword.control.return.dart 73 | # ^ punctuation.terminator.dart 74 | >} 75 | > 76 | >Iterable syncYield() sync* { 77 | #^^^^^^^^ support.class.dart 78 | # ^ other.source.dart 79 | # ^^^^^^ support.class.dart 80 | # ^ other.source.dart 81 | # ^^^^^^^^^ entity.name.function.dart 82 | # ^^^^ keyword.control.dart 83 | # ^ keyword.operator.arithmetic.dart 84 | > yield ''; 85 | # ^^^^^ keyword.control.dart 86 | # ^^ string.interpolated.single.dart 87 | # ^ punctuation.terminator.dart 88 | >} 89 | > 90 | >Iterable syncYieldStar() sync* { 91 | #^^^^^^^^ support.class.dart 92 | # ^ other.source.dart 93 | # ^^^^^^ support.class.dart 94 | # ^ other.source.dart 95 | # ^^^^^^^^^^^^^ entity.name.function.dart 96 | # ^^^^ keyword.control.dart 97 | # ^ keyword.operator.arithmetic.dart 98 | > yield* syncYield(); 99 | # ^^^^^ keyword.control.dart 100 | # ^ keyword.operator.arithmetic.dart 101 | # ^^^^^^^^^ entity.name.function.dart 102 | # ^ punctuation.terminator.dart 103 | >} 104 | > 105 | >Stream asyncYield() async* { 106 | #^^^^^^ support.class.dart 107 | # ^ other.source.dart 108 | # ^^^^^^ support.class.dart 109 | # ^ other.source.dart 110 | # ^^^^^^^^^^ entity.name.function.dart 111 | # ^^^^^ keyword.control.dart 112 | # ^ keyword.operator.arithmetic.dart 113 | > await Future.delayed(const Duration(seconds: 1)); 114 | # ^^^^^ keyword.control.dart 115 | # ^^^^^^ support.class.dart 116 | # ^ punctuation.dot.dart 117 | # ^^^^^^^ entity.name.function.dart 118 | # ^^^^^ storage.modifier.dart 119 | # ^^^^^^^^ support.class.dart 120 | # ^ keyword.operator.ternary.dart 121 | # ^ constant.numeric.dart 122 | # ^ punctuation.terminator.dart 123 | > yield ''; 124 | # ^^^^^ keyword.control.dart 125 | # ^^ string.interpolated.single.dart 126 | # ^ punctuation.terminator.dart 127 | >} 128 | > 129 | >Stream asyncYieldStar() async* { 130 | #^^^^^^ support.class.dart 131 | # ^ other.source.dart 132 | # ^^^^^^ support.class.dart 133 | # ^ other.source.dart 134 | # ^^^^^^^^^^^^^^ entity.name.function.dart 135 | # ^^^^^ keyword.control.dart 136 | # ^ keyword.operator.arithmetic.dart 137 | > await Future.delayed(const Duration(seconds: 1)); 138 | # ^^^^^ keyword.control.dart 139 | # ^^^^^^ support.class.dart 140 | # ^ punctuation.dot.dart 141 | # ^^^^^^^ entity.name.function.dart 142 | # ^^^^^ storage.modifier.dart 143 | # ^^^^^^^^ support.class.dart 144 | # ^ keyword.operator.ternary.dart 145 | # ^ constant.numeric.dart 146 | # ^ punctuation.terminator.dart 147 | > yield* asyncYield(); 148 | # ^^^^^ keyword.control.dart 149 | # ^ keyword.operator.arithmetic.dart 150 | # ^^^^^^^^^^ entity.name.function.dart 151 | # ^ punctuation.terminator.dart 152 | >} 153 | > 154 | >T foo(String a) => throw UnimplementedError(); 155 | #^ support.class.dart 156 | # ^^^ entity.name.function.dart 157 | # ^ other.source.dart 158 | # ^ support.class.dart 159 | # ^^^^^^^ keyword.declaration.dart 160 | # ^^^^^^ support.class.dart 161 | # ^ other.source.dart 162 | # ^^^^^^ support.class.dart 163 | # ^^ keyword.operator.closure.dart 164 | # ^^^^^ keyword.control.catch-exception.dart 165 | # ^^^^^^^^^^^^^^^^^^ support.class.dart 166 | # ^ punctuation.terminator.dart 167 | -------------------------------------------------------------------------------- /test/goldens/operators.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >void foo() { 9 | #^^^^ storage.type.primitive.dart 10 | # ^^^ entity.name.function.dart 11 | > Object? a; 12 | # ^^^^^^ support.class.dart 13 | # ^ keyword.operator.ternary.dart 14 | # ^ punctuation.terminator.dart 15 | > if (1 == 2) {} 16 | # ^^ keyword.control.dart 17 | # ^ constant.numeric.dart 18 | # ^^ keyword.operator.comparison.dart 19 | # ^ constant.numeric.dart 20 | > if (1 != 2) {} 21 | # ^^ keyword.control.dart 22 | # ^ constant.numeric.dart 23 | # ^^ keyword.operator.comparison.dart 24 | # ^ constant.numeric.dart 25 | > if (1 < 2) {} 26 | # ^^ keyword.control.dart 27 | # ^ constant.numeric.dart 28 | # ^ keyword.operator.comparison.dart 29 | # ^ constant.numeric.dart 30 | > if (1 <= 2) {} 31 | # ^^ keyword.control.dart 32 | # ^ constant.numeric.dart 33 | # ^^ keyword.operator.comparison.dart 34 | # ^ constant.numeric.dart 35 | > if (1 > 2) {} 36 | # ^^ keyword.control.dart 37 | # ^ constant.numeric.dart 38 | # ^ keyword.operator.comparison.dart 39 | # ^ constant.numeric.dart 40 | > if (1 >= 2) {} 41 | # ^^ keyword.control.dart 42 | # ^ constant.numeric.dart 43 | # ^^ keyword.operator.comparison.dart 44 | # ^ constant.numeric.dart 45 | > var b = 1 < 2 ? 1 / 1 : 2 * 2; 46 | # ^^^ storage.type.primitive.dart 47 | # ^ keyword.operator.assignment.dart 48 | # ^ constant.numeric.dart 49 | # ^ keyword.operator.comparison.dart 50 | # ^ constant.numeric.dart 51 | # ^ keyword.operator.ternary.dart 52 | # ^ constant.numeric.dart 53 | # ^ keyword.operator.arithmetic.dart 54 | # ^ constant.numeric.dart 55 | # ^ keyword.operator.ternary.dart 56 | # ^ constant.numeric.dart 57 | # ^ keyword.operator.arithmetic.dart 58 | # ^ constant.numeric.dart 59 | # ^ punctuation.terminator.dart 60 | > a ??= b; 61 | # ^^ keyword.operator.ternary.dart 62 | # ^ keyword.operator.assignment.dart 63 | # ^ punctuation.terminator.dart 64 | > b += 1; 65 | # ^^ keyword.operator.assignment.arithmetic.dart 66 | # ^ constant.numeric.dart 67 | # ^ punctuation.terminator.dart 68 | > b -= 1; 69 | # ^^ keyword.operator.assignment.arithmetic.dart 70 | # ^ constant.numeric.dart 71 | # ^ punctuation.terminator.dart 72 | > b = b / 2; 73 | # ^ keyword.operator.assignment.dart 74 | # ^ keyword.operator.arithmetic.dart 75 | # ^ constant.numeric.dart 76 | # ^ punctuation.terminator.dart 77 | > b = b ~/ 2; 78 | # ^ keyword.operator.assignment.dart 79 | # ^ keyword.operator.bitwise.dart 80 | # ^ keyword.operator.arithmetic.dart 81 | # ^ constant.numeric.dart 82 | # ^ punctuation.terminator.dart 83 | > b = b % 2; 84 | # ^ keyword.operator.assignment.dart 85 | # ^ keyword.operator.arithmetic.dart 86 | # ^ constant.numeric.dart 87 | # ^ punctuation.terminator.dart 88 | > b++; 89 | # ^^ keyword.operator.increment-decrement.dart 90 | # ^ punctuation.terminator.dart 91 | > b--; 92 | # ^^ keyword.operator.increment-decrement.dart 93 | # ^ punctuation.terminator.dart 94 | > ++b; 95 | # ^^ keyword.operator.increment-decrement.dart 96 | # ^ punctuation.terminator.dart 97 | > --b; 98 | # ^^ keyword.operator.increment-decrement.dart 99 | # ^ punctuation.terminator.dart 100 | > var c = 1 >> 2; 101 | # ^^^ storage.type.primitive.dart 102 | # ^ keyword.operator.assignment.dart 103 | # ^ constant.numeric.dart 104 | # ^^ keyword.operator.bitwise.dart 105 | # ^ constant.numeric.dart 106 | # ^ punctuation.terminator.dart 107 | > c >>= 1; 108 | # ^^ keyword.operator.bitwise.dart 109 | # ^ keyword.operator.assignment.dart 110 | # ^ constant.numeric.dart 111 | # ^ punctuation.terminator.dart 112 | > var d = 1 << 2; 113 | # ^^^ storage.type.primitive.dart 114 | # ^ keyword.operator.assignment.dart 115 | # ^ constant.numeric.dart 116 | # ^^ keyword.operator.bitwise.dart 117 | # ^ constant.numeric.dart 118 | # ^ punctuation.terminator.dart 119 | > d <<= 2; 120 | # ^^ keyword.operator.bitwise.dart 121 | # ^ keyword.operator.assignment.dart 122 | # ^ constant.numeric.dart 123 | # ^ punctuation.terminator.dart 124 | > var e = 1 >>> 2; 125 | # ^^^ storage.type.primitive.dart 126 | # ^ keyword.operator.assignment.dart 127 | # ^ constant.numeric.dart 128 | # ^^^ keyword.operator.bitwise.dart 129 | # ^ constant.numeric.dart 130 | # ^ punctuation.terminator.dart 131 | > e >>>= 3; 132 | # ^^^ keyword.operator.bitwise.dart 133 | # ^ keyword.operator.assignment.dart 134 | # ^ constant.numeric.dart 135 | # ^ punctuation.terminator.dart 136 | > var f = -b; 137 | # ^^^ storage.type.primitive.dart 138 | # ^ keyword.operator.assignment.dart 139 | # ^ keyword.operator.arithmetic.dart 140 | # ^ punctuation.terminator.dart 141 | > var g = 1 & 2; 142 | # ^^^ storage.type.primitive.dart 143 | # ^ keyword.operator.assignment.dart 144 | # ^ constant.numeric.dart 145 | # ^ keyword.operator.bitwise.dart 146 | # ^ constant.numeric.dart 147 | # ^ punctuation.terminator.dart 148 | > var h = 1 ^ 2; 149 | # ^^^ storage.type.primitive.dart 150 | # ^ keyword.operator.assignment.dart 151 | # ^ constant.numeric.dart 152 | # ^ keyword.operator.bitwise.dart 153 | # ^ constant.numeric.dart 154 | # ^ punctuation.terminator.dart 155 | > var i = ~2; 156 | # ^^^ storage.type.primitive.dart 157 | # ^ keyword.operator.assignment.dart 158 | # ^ keyword.operator.bitwise.dart 159 | # ^ constant.numeric.dart 160 | # ^ punctuation.terminator.dart 161 | > var j = 1 & 2; 162 | # ^^^ storage.type.primitive.dart 163 | # ^ keyword.operator.assignment.dart 164 | # ^ constant.numeric.dart 165 | # ^ keyword.operator.bitwise.dart 166 | # ^ constant.numeric.dart 167 | # ^ punctuation.terminator.dart 168 | > j &= 2; 169 | # ^ keyword.operator.bitwise.dart 170 | # ^ keyword.operator.assignment.dart 171 | # ^ constant.numeric.dart 172 | # ^ punctuation.terminator.dart 173 | > j ^= 2; 174 | # ^ keyword.operator.bitwise.dart 175 | # ^ keyword.operator.assignment.dart 176 | # ^ constant.numeric.dart 177 | # ^ punctuation.terminator.dart 178 | > j |= 2; 179 | # ^ keyword.operator.bitwise.dart 180 | # ^ keyword.operator.assignment.dart 181 | # ^ constant.numeric.dart 182 | # ^ punctuation.terminator.dart 183 | > var k = 1 ^ 2; 184 | # ^^^ storage.type.primitive.dart 185 | # ^ keyword.operator.assignment.dart 186 | # ^ constant.numeric.dart 187 | # ^ keyword.operator.bitwise.dart 188 | # ^ constant.numeric.dart 189 | # ^ punctuation.terminator.dart 190 | > var l = 1 | 2; 191 | # ^^^ storage.type.primitive.dart 192 | # ^ keyword.operator.assignment.dart 193 | # ^ constant.numeric.dart 194 | # ^ keyword.operator.bitwise.dart 195 | # ^ constant.numeric.dart 196 | # ^ punctuation.terminator.dart 197 | > var m = !(a == a && false || true); 198 | # ^^^ storage.type.primitive.dart 199 | # ^ keyword.operator.assignment.dart 200 | # ^ keyword.operator.logical.dart 201 | # ^^ keyword.operator.comparison.dart 202 | # ^^ keyword.operator.bitwise.dart 203 | # ^^^^^ constant.language.dart 204 | # ^^ keyword.operator.bitwise.dart 205 | # ^^^^ constant.language.dart 206 | # ^ punctuation.terminator.dart 207 | >} 208 | -------------------------------------------------------------------------------- /test/goldens/comments.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >/// Multiline dartdoc comment with triple backticks. 9 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 10 | >/// 11 | #^^^ comment.block.documentation.dart 12 | >/// ``` 13 | #^^^^^^^ comment.block.documentation.dart 14 | >/// code 15 | #^^^^ comment.block.documentation.dart 16 | # ^^^^ comment.block.documentation.dart variable.other.source.dart 17 | >/// ``` 18 | #^^^^^^^ comment.block.documentation.dart 19 | >/// 20 | #^^^ comment.block.documentation.dart 21 | >/// ... 22 | #^^^^^^^ comment.block.documentation.dart 23 | >var doc1; 24 | #^^^ storage.type.primitive.dart 25 | # ^ punctuation.terminator.dart 26 | > 27 | >/// Multiline dartdoc comment with unclosed triple backticks. 28 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 29 | >/// 30 | #^^^ comment.block.documentation.dart 31 | >/// ``` 32 | #^^^^^^^ comment.block.documentation.dart 33 | >/// code 34 | #^^^^ comment.block.documentation.dart 35 | # ^^^^ comment.block.documentation.dart variable.other.source.dart 36 | >var doc2; 37 | #^^^ storage.type.primitive.dart 38 | # ^ punctuation.terminator.dart 39 | > 40 | >/// Multiline dartdoc comment with unclosed backticks. 41 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 42 | >/// 43 | #^^^ comment.block.documentation.dart 44 | >/// `code 45 | #^^^^^^^^^ comment.block.documentation.dart 46 | >var doc3; 47 | #^^^ storage.type.primitive.dart 48 | # ^ punctuation.terminator.dart 49 | > 50 | >/// Multiline dartdoc comment with indented code. 51 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 52 | >/// 53 | #^^^ comment.block.documentation.dart 54 | >/// code1 55 | #^^^^^^^^ comment.block.documentation.dart 56 | # ^^^^^ comment.block.documentation.dart variable.other.source.dart 57 | >/// code2 58 | #^^^^^^^^ comment.block.documentation.dart 59 | # ^^^^^ comment.block.documentation.dart variable.other.source.dart 60 | >/// 61 | #^^^ comment.block.documentation.dart 62 | >/// code3 63 | #^^^^^^^^ comment.block.documentation.dart 64 | # ^^^^^ comment.block.documentation.dart variable.other.source.dart 65 | >/// 66 | #^^^ comment.block.documentation.dart 67 | >/// ... 68 | #^^^^^^^ comment.block.documentation.dart 69 | >var doc4; 70 | #^^^ storage.type.primitive.dart 71 | # ^ punctuation.terminator.dart 72 | > 73 | >/** Block dartdoc comment with triple backticks. 74 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 75 | > * 76 | #^^ comment.block.documentation.dart 77 | > * ``` 78 | #^^^^^^ comment.block.documentation.dart 79 | > * code 80 | #^^^ comment.block.documentation.dart 81 | # ^^^^ comment.block.documentation.dart variable.other.source.dart 82 | > * ``` 83 | #^^^^^^ comment.block.documentation.dart 84 | > * 85 | #^^ comment.block.documentation.dart 86 | > * ... 87 | #^^^^^^ comment.block.documentation.dart 88 | > */ 89 | #^^^ comment.block.documentation.dart 90 | >var blockDoc1; 91 | #^^^ storage.type.primitive.dart 92 | # ^ punctuation.terminator.dart 93 | > 94 | >/** Block dartdoc comment with unclosed triple backticks. 95 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 96 | > * 97 | #^^ comment.block.documentation.dart 98 | > * ``` 99 | #^^^^^^ comment.block.documentation.dart 100 | > * code 101 | #^^^ comment.block.documentation.dart 102 | # ^^^^ comment.block.documentation.dart variable.other.source.dart 103 | > */ 104 | #^^^ comment.block.documentation.dart 105 | >var blockDoc2; 106 | #^^^ storage.type.primitive.dart 107 | # ^ punctuation.terminator.dart 108 | > 109 | >/** Block dartdoc comment with unclosed backticks. 110 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 111 | > * 112 | #^^ comment.block.documentation.dart 113 | > * `code 114 | #^^^^^^^^ comment.block.documentation.dart 115 | > */ 116 | #^^^ comment.block.documentation.dart 117 | >var blockDoc3; 118 | #^^^ storage.type.primitive.dart 119 | # ^ punctuation.terminator.dart 120 | > 121 | >/** Block dartdoc comment with indented code. 122 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 123 | > * 124 | #^^ comment.block.documentation.dart 125 | > * code1 126 | #^^^^^^^ comment.block.documentation.dart 127 | # ^^^^^ comment.block.documentation.dart variable.other.source.dart 128 | > * code2 129 | #^^^^^^^ comment.block.documentation.dart 130 | # ^^^^^ comment.block.documentation.dart variable.other.source.dart 131 | > * 132 | #^^ comment.block.documentation.dart 133 | > * code3 134 | #^^^^^^^ comment.block.documentation.dart 135 | # ^^^^^ comment.block.documentation.dart variable.other.source.dart 136 | > * 137 | #^^ comment.block.documentation.dart 138 | > * ... 139 | #^^^^^^ comment.block.documentation.dart 140 | > */ 141 | #^^^ comment.block.documentation.dart 142 | >var blockDoc4; 143 | #^^^ storage.type.primitive.dart 144 | # ^ punctuation.terminator.dart 145 | > 146 | >/// `` 147 | #^^^^^^ comment.block.documentation.dart 148 | >var noInlineCode; 149 | #^^^ storage.type.primitive.dart 150 | # ^ punctuation.terminator.dart 151 | > 152 | >/// `Stream` 153 | #^^^^ comment.block.documentation.dart 154 | # ^^^^^^^^^^^^^ comment.block.documentation.dart variable.other.source.dart 155 | >var inlineCode; 156 | #^^^ storage.type.primitive.dart 157 | # ^ punctuation.terminator.dart 158 | > 159 | >/// ` ` 160 | #^^^^ comment.block.documentation.dart 161 | # ^^^ comment.block.documentation.dart variable.other.source.dart 162 | >var inlineCodeJustWhitespace; 163 | #^^^ storage.type.primitive.dart 164 | # ^ punctuation.terminator.dart 165 | > 166 | >/* 167 | #^^ comment.block.dart 168 | > * Old-style dartdoc 169 | #^^^^^^^^^^^^^^^^^^^^ comment.block.dart 170 | > * 171 | #^^ comment.block.dart 172 | > * ... 173 | #^^^^^^ comment.block.dart 174 | > */ 175 | #^^^ comment.block.dart 176 | >var b; 177 | #^^^ storage.type.primitive.dart 178 | # ^ punctuation.terminator.dart 179 | > 180 | >/* Inline block comment */ 181 | #^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.dart 182 | >var c; 183 | #^^^ storage.type.primitive.dart 184 | # ^ punctuation.terminator.dart 185 | > 186 | >/** 187 | #^^^ comment.block.documentation.dart 188 | > * Nested block 189 | #^^^^^^^^^^^^^^^ comment.block.documentation.dart 190 | > * 191 | #^^ comment.block.documentation.dart 192 | > * /** 193 | #^^^^^^ comment.block.documentation.dart 194 | > * * Nested block 195 | #^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 196 | > * */ 197 | #^^^^^^ comment.block.documentation.dart 198 | > */ 199 | #^^^ comment.block.documentation.dart 200 | >var d; 201 | #^^^ storage.type.primitive.dart 202 | # ^ punctuation.terminator.dart 203 | > 204 | >/** 205 | #^^^ comment.block.documentation.dart 206 | > * /** 207 | #^^^^^^^^ comment.block.documentation.dart 208 | > * * bbb 209 | #^^^^^^ comment.block.documentation.dart 210 | # ^^^^^ comment.block.documentation.dart variable.other.source.dart 211 | > * */ 212 | #^^^^^^^^ comment.block.documentation.dart 213 | > */ 214 | #^^^ comment.block.documentation.dart 215 | >var d2; 216 | #^^^ storage.type.primitive.dart 217 | # ^ punctuation.terminator.dart 218 | > 219 | >/** 220 | #^^^ comment.block.documentation.dart 221 | > * Nested 222 | #^^^^^^^^^ comment.block.documentation.dart 223 | > * 224 | #^^ comment.block.documentation.dart 225 | > * /* Inline */ 226 | #^^^ comment.block.documentation.dart 227 | # ^^^^^^^^^^^^ comment.block.documentation.dart comment.block.dart 228 | > */ 229 | #^^^ comment.block.documentation.dart 230 | >var e; 231 | #^^^ storage.type.primitive.dart 232 | # ^ punctuation.terminator.dart 233 | > 234 | >/* Nested /* Inline */ */ 235 | #^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.dart 236 | >var f; 237 | #^^^ storage.type.primitive.dart 238 | # ^ punctuation.terminator.dart 239 | > 240 | >// Simple comment 241 | #^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 242 | >var g; 243 | #^^^ storage.type.primitive.dart 244 | # ^ punctuation.terminator.dart 245 | > 246 | >/// Dartdoc with reference to [a]. 247 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 248 | # ^^^ comment.block.documentation.dart variable.name.source.dart 249 | # ^ comment.block.documentation.dart 250 | >/// And a link to [example.org](http://example.org/). 251 | #^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 252 | # ^^^^^^^^^^^^^ comment.block.documentation.dart variable.name.source.dart 253 | # ^^^^^^^^^^^^^^^^^^^^^^ comment.block.documentation.dart 254 | >var h; 255 | #^^^ storage.type.primitive.dart 256 | # ^ punctuation.terminator.dart 257 | > 258 | >class A { 259 | #^^^^^ keyword.declaration.dart 260 | # ^ support.class.dart 261 | # ^ other.source.dart 262 | # ^ support.class.dart 263 | # ^^^^^^^^^^^^^ comment.block.dart 264 | # ^ other.source.dart 265 | > void b() {} 266 | # ^^^^ storage.type.primitive.dart 267 | # ^ keyword.operator.comparison.dart 268 | # ^ support.class.dart 269 | # ^^^^^^^^^^^^^ comment.block.dart 270 | # ^ keyword.operator.comparison.dart 271 | > Future c() {} 272 | # ^^^^^^ support.class.dart 273 | # ^ other.source.dart 274 | # ^ support.class.dart 275 | # ^^^^^^^^^^^^^ comment.block.dart 276 | # ^ other.source.dart 277 | # ^ entity.name.function.dart 278 | >} 279 | -------------------------------------------------------------------------------- /test/goldens/classes.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >class Class1 {} 9 | #^^^^^ keyword.declaration.dart 10 | # ^^^^^^ support.class.dart 11 | > 12 | >abstract class Class2 implements Class1 { 13 | #^^^^^^^^ keyword.declaration.dart 14 | # ^^^^^ keyword.declaration.dart 15 | # ^^^^^^ support.class.dart 16 | # ^^^^^^^^^^ keyword.declaration.dart 17 | # ^^^^^^ support.class.dart 18 | > String get a; 19 | # ^^^^^^ support.class.dart 20 | # ^^^ keyword.declaration.dart 21 | # ^ punctuation.terminator.dart 22 | > set a(String value); 23 | # ^^^ keyword.declaration.dart 24 | # ^ entity.name.function.dart 25 | # ^^^^^^ support.class.dart 26 | # ^ punctuation.terminator.dart 27 | >} 28 | > 29 | >class Class3 extends Class2 with MyMixin { 30 | #^^^^^ keyword.declaration.dart 31 | # ^^^^^^ support.class.dart 32 | # ^^^^^^^ keyword.declaration.dart 33 | # ^^^^^^ support.class.dart 34 | # ^^^^ keyword.declaration.dart 35 | # ^^^^^^^ support.class.dart 36 | > @override 37 | # ^^^^^^^^^ storage.type.annotation.dart 38 | > String get a => ''; 39 | # ^^^^^^ support.class.dart 40 | # ^^^ keyword.declaration.dart 41 | # ^^ keyword.operator.closure.dart 42 | # ^^ string.interpolated.single.dart 43 | # ^ punctuation.terminator.dart 44 | > 45 | > @override 46 | # ^^^^^^^^^ storage.type.annotation.dart 47 | > set a(String value) {} 48 | # ^^^ keyword.declaration.dart 49 | # ^ entity.name.function.dart 50 | # ^^^^^^ support.class.dart 51 | > 52 | > void method() {} 53 | # ^^^^ storage.type.primitive.dart 54 | # ^^^^^^ entity.name.function.dart 55 | >} 56 | > 57 | >class Class4 implements Class1 {} 58 | #^^^^^ keyword.declaration.dart 59 | # ^^^^^^ support.class.dart 60 | # ^ other.source.dart 61 | # ^ support.class.dart 62 | # ^^^^^^^ keyword.declaration.dart 63 | # ^^^^^^ support.class.dart 64 | # ^ other.source.dart 65 | # ^^^^^^^^^^ keyword.declaration.dart 66 | # ^^^^^^ support.class.dart 67 | > 68 | >class MyClass { 69 | #^^^^^ keyword.declaration.dart 70 | # ^^^^^^^ support.class.dart 71 | > void method1() {} 72 | # ^^^^ storage.type.primitive.dart 73 | # ^^^^^^^ entity.name.function.dart 74 | > void Method2() {} 75 | # ^^^^ storage.type.primitive.dart 76 | # ^^^^^^^ support.class.dart 77 | > void get() {} 78 | # ^^^^ storage.type.primitive.dart 79 | # ^^^ entity.name.function.dart 80 | > void get() {} 81 | # ^^^^ storage.type.primitive.dart 82 | # ^^^ entity.name.function.dart 83 | # ^ other.source.dart 84 | # ^ support.class.dart 85 | # ^ other.source.dart 86 | > void set() {} 87 | # ^^^^ storage.type.primitive.dart 88 | # ^^^ entity.name.function.dart 89 | > void set() {} 90 | # ^^^^ storage.type.primitive.dart 91 | # ^^^ entity.name.function.dart 92 | # ^ other.source.dart 93 | # ^ support.class.dart 94 | # ^ other.source.dart 95 | > 96 | > String? _foo; 97 | # ^^^^^^ support.class.dart 98 | # ^ keyword.operator.ternary.dart 99 | # ^ punctuation.terminator.dart 100 | > String? get foo => _foo; 101 | # ^^^^^^ support.class.dart 102 | # ^ keyword.operator.ternary.dart 103 | # ^^^ keyword.declaration.dart 104 | # ^^ keyword.operator.closure.dart 105 | # ^ punctuation.terminator.dart 106 | > set foo(String? value) => _foo = value; 107 | # ^^^ keyword.declaration.dart 108 | # ^^^ entity.name.function.dart 109 | # ^^^^^^ support.class.dart 110 | # ^ keyword.operator.ternary.dart 111 | # ^^ keyword.operator.closure.dart 112 | # ^ keyword.operator.assignment.dart 113 | # ^ punctuation.terminator.dart 114 | >} 115 | > 116 | >void get() {} 117 | #^^^^ storage.type.primitive.dart 118 | # ^^^ entity.name.function.dart 119 | >void get() {} 120 | #^^^^ storage.type.primitive.dart 121 | # ^^^ entity.name.function.dart 122 | # ^ other.source.dart 123 | # ^ support.class.dart 124 | # ^ other.source.dart 125 | >void set() {} 126 | #^^^^ storage.type.primitive.dart 127 | # ^^^ entity.name.function.dart 128 | >void set() {} 129 | #^^^^ storage.type.primitive.dart 130 | # ^^^ entity.name.function.dart 131 | # ^ other.source.dart 132 | # ^ support.class.dart 133 | # ^ other.source.dart 134 | > 135 | >mixin MyMixin {} 136 | #^^^^^ keyword.declaration.dart 137 | # ^^^^^^^ support.class.dart 138 | > 139 | >mixin MyMixin2 on Class1 {} 140 | #^^^^^ keyword.declaration.dart 141 | # ^^^^^^^^ support.class.dart 142 | # ^ other.source.dart 143 | # ^ support.class.dart 144 | # ^ other.source.dart 145 | # ^^ keyword.control.catch-exception.dart 146 | # ^^^^^^ support.class.dart 147 | > 148 | >extension on String {} 149 | #^^^^^^^^^ keyword.declaration.dart 150 | # ^^ keyword.control.catch-exception.dart 151 | # ^^^^^^ support.class.dart 152 | > 153 | >extension StringExtension on String {} 154 | #^^^^^^^^^ keyword.declaration.dart 155 | # ^^^^^^^^^^^^^^^ support.class.dart 156 | # ^^ keyword.control.catch-exception.dart 157 | # ^^^^^^ support.class.dart 158 | > 159 | >extension StringListExtension on List {} 160 | #^^^^^^^^^ keyword.declaration.dart 161 | # ^^^^^^^^^^^^^^^^^^^ support.class.dart 162 | # ^^ keyword.control.catch-exception.dart 163 | # ^^^^ support.class.dart 164 | # ^ other.source.dart 165 | # ^^^^^^ support.class.dart 166 | # ^ other.source.dart 167 | > 168 | >extension on T {} 169 | #^^^^^^^^^ keyword.declaration.dart 170 | # ^ keyword.operator.comparison.dart 171 | # ^ support.class.dart 172 | # ^^^^^^^ keyword.declaration.dart 173 | # ^^^^^^ support.class.dart 174 | # ^ keyword.operator.comparison.dart 175 | # ^^ keyword.control.catch-exception.dart 176 | # ^ support.class.dart 177 | > 178 | >class my_lowercase_class { 179 | #^^^^^ keyword.declaration.dart 180 | > my_lowercase_class? foo() => null; 181 | # ^ keyword.operator.ternary.dart 182 | # ^^^ entity.name.function.dart 183 | # ^^ keyword.operator.closure.dart 184 | # ^^^^ constant.language.dart 185 | # ^ punctuation.terminator.dart 186 | > List? bar() => null; 187 | # ^^^^ support.class.dart 188 | # ^ other.source.dart 189 | # ^ other.source.dart 190 | # ^ keyword.operator.ternary.dart 191 | # ^^^ entity.name.function.dart 192 | # ^^ keyword.operator.closure.dart 193 | # ^^^^ constant.language.dart 194 | # ^ punctuation.terminator.dart 195 | >} 196 | > 197 | >class A1 {} 198 | #^^^^^ keyword.declaration.dart 199 | # ^^ support.class.dart 200 | # ^ other.source.dart 201 | # ^ support.class.dart 202 | # ^ other.source.dart 203 | > 204 | >class A2 extends A1 {} 205 | #^^^^^ keyword.declaration.dart 206 | # ^^ support.class.dart 207 | # ^ other.source.dart 208 | # ^ support.class.dart 209 | # ^ other.source.dart 210 | # ^^^^^^^ keyword.declaration.dart 211 | # ^^ support.class.dart 212 | # ^ other.source.dart 213 | # ^ support.class.dart 214 | # ^ other.source.dart 215 | > 216 | >class A3 implements A1 {} 217 | #^^^^^ keyword.declaration.dart 218 | # ^^ support.class.dart 219 | # ^ other.source.dart 220 | # ^ support.class.dart 221 | # ^ other.source.dart 222 | # ^^^^^^^^^^ keyword.declaration.dart 223 | # ^^ support.class.dart 224 | # ^ other.source.dart 225 | # ^ support.class.dart 226 | # ^ other.source.dart 227 | > 228 | >class A4 extends Class1 with MyMixin2 {} 229 | #^^^^^ keyword.declaration.dart 230 | # ^^ support.class.dart 231 | # ^ other.source.dart 232 | # ^ support.class.dart 233 | # ^ other.source.dart 234 | # ^^^^^^^ keyword.declaration.dart 235 | # ^^^^^^ support.class.dart 236 | # ^^^^ keyword.declaration.dart 237 | # ^^^^^^^^ support.class.dart 238 | # ^ other.source.dart 239 | # ^ support.class.dart 240 | # ^ other.source.dart 241 | > 242 | >base class MyBaseClass {} 243 | #^^^^ keyword.declaration.dart 244 | # ^^^^^ keyword.declaration.dart 245 | # ^^^^^^^^^^^ support.class.dart 246 | >interface class MyInterfaceClass {} 247 | #^^^^^^^^^ keyword.declaration.dart 248 | # ^^^^^ keyword.declaration.dart 249 | # ^^^^^^^^^^^^^^^^ support.class.dart 250 | >sealed class MySealedClass {} 251 | #^^^^^^ keyword.declaration.dart 252 | # ^^^^^ keyword.declaration.dart 253 | # ^^^^^^^^^^^^^ support.class.dart 254 | >final class MyFinalClass {} 255 | #^^^^^ storage.modifier.dart 256 | # ^^^^^ keyword.declaration.dart 257 | # ^^^^^^^^^^^^ support.class.dart 258 | >mixin class MyMixinClass {} 259 | #^^^^^ keyword.declaration.dart 260 | # ^^^^^ keyword.declaration.dart 261 | # ^^^^^^^^^^^^ support.class.dart 262 | >macro class MyMacroClass {} 263 | #^^^^^ storage.modifier.dart 264 | # ^^^^^ keyword.declaration.dart 265 | # ^^^^^^^^^^^^ support.class.dart 266 | -------------------------------------------------------------------------------- /grammars/dart.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Dart", 3 | "version": "1.4.1", 4 | "fileTypes": [ 5 | "dart" 6 | ], 7 | "scopeName": "source.dart", 8 | 9 | "foldingStartMarker": "\\{\\s*$", 10 | "foldingStopMarker": "^\\s*\\}", 11 | 12 | "patterns": [ 13 | { 14 | "name": "meta.preprocessor.script.dart", 15 | "match": "^(#!.*)$" 16 | }, 17 | { 18 | "name": "meta.declaration.dart", 19 | "begin": "^\\w*\\b(augment\\s+library|library|import\\s+augment|import|part\\s+of|part|export)\\b", 20 | "beginCaptures": { 21 | "0": { 22 | "name": "keyword.other.import.dart" 23 | } 24 | }, 25 | "end": ";", 26 | "endCaptures": { 27 | "0": { 28 | "name": "punctuation.terminator.dart" 29 | } 30 | }, 31 | "patterns": [ 32 | { 33 | "include": "#strings" 34 | }, 35 | { 36 | "include": "#comments" 37 | }, 38 | { 39 | "name": "keyword.other.import.dart", 40 | "match": "\\b(as|show|hide)\\b" 41 | }, 42 | { 43 | "name": "keyword.control.dart", 44 | "match": "\\b(if)\\b" 45 | } 46 | ] 47 | }, 48 | { 49 | "include": "#comments" 50 | }, 51 | { 52 | "include": "#punctuation" 53 | }, 54 | { 55 | "include": "#annotations" 56 | }, 57 | { 58 | "include": "#keywords" 59 | }, 60 | { 61 | "include": "#constants-and-special-vars" 62 | }, 63 | { 64 | "include": "#operators" 65 | }, 66 | { 67 | "include": "#strings" 68 | } 69 | ], 70 | 71 | "repository": { 72 | "dartdoc-codeblock-triple": { 73 | "begin": "^\\s*///\\s*(?!\\s*```)", 74 | "end": "\n", 75 | "contentName": "variable.other.source.dart" 76 | }, 77 | "dartdoc-codeblock-block": { 78 | "begin": "^\\s*\\*\\s*(?!(\\s*```|\/))", 79 | "end": "\n", 80 | "contentName": "variable.other.source.dart" 81 | }, 82 | "dartdoc": { 83 | "patterns": [ 84 | { 85 | "match": "(\\[.*?\\])", 86 | "captures": { 87 | "0": { 88 | "name": "variable.name.source.dart" 89 | } 90 | } 91 | }, 92 | { 93 | "begin": "^\\s*///\\s*(```)", 94 | "end": "^\\s*///\\s*(```)|^(?!\\s*///)", 95 | "patterns": [ 96 | { 97 | "include": "#dartdoc-codeblock-triple" 98 | } 99 | ] 100 | }, 101 | { 102 | "begin": "^\\s*\\*\\s*(```)", 103 | "end": "^\\s*\\*\\s*(```)|^(?=\\s*\\*\/)", 104 | "patterns": [ 105 | { 106 | "include": "#dartdoc-codeblock-block" 107 | } 108 | ] 109 | }, 110 | { 111 | "match": "`[^`\n]+`", 112 | "name": "variable.other.source.dart" 113 | }, 114 | { 115 | "match": "(?:\\*|\\/\\/)\\s{4,}(.*?)(?=($|\\*\\/))", 116 | "captures": { 117 | "1": { 118 | "name": "variable.other.source.dart" 119 | } 120 | } 121 | } 122 | ] 123 | }, 124 | "comments": { 125 | "patterns": [ 126 | { 127 | "name": "comment.block.empty.dart", 128 | "match": "/\\*\\*/", 129 | "captures": { 130 | "0": { 131 | "name": "punctuation.definition.comment.dart" 132 | } 133 | } 134 | }, 135 | { 136 | "include": "#comments-doc-oldschool" 137 | }, 138 | { 139 | "include": "#comments-doc" 140 | }, 141 | { 142 | "include": "#comments-inline" 143 | } 144 | ] 145 | }, 146 | "comments-doc-oldschool": { 147 | "patterns": [ 148 | { 149 | "name": "comment.block.documentation.dart", 150 | "begin": "/\\*\\*", 151 | "end": "\\*/", 152 | "patterns": [ 153 | { 154 | "include": "#comments-doc-oldschool" 155 | }, 156 | { 157 | "include": "#comments-block" 158 | }, 159 | { 160 | "include": "#dartdoc" 161 | } 162 | ] 163 | } 164 | ] 165 | }, 166 | "comments-doc": { 167 | "patterns": [ 168 | { 169 | "name": "comment.block.documentation.dart", 170 | "begin": "///", 171 | "end": "^(?!\\s*///)", 172 | "patterns": [ 173 | { 174 | "include": "#dartdoc" 175 | } 176 | ] 177 | } 178 | ] 179 | }, 180 | "comments-inline": { 181 | "patterns": [ 182 | { 183 | "include": "#comments-block" 184 | }, 185 | { 186 | "match": "((//).*)$", 187 | "captures": { 188 | "1": { 189 | "name": "comment.line.double-slash.dart" 190 | } 191 | } 192 | } 193 | ] 194 | }, 195 | "comments-block": { 196 | "patterns": [ 197 | { 198 | "name": "comment.block.dart", 199 | "begin": "/\\*", 200 | "end": "\\*/", 201 | "patterns": [ 202 | { 203 | "include": "#comments-block" 204 | } 205 | ] 206 | } 207 | ] 208 | }, 209 | "annotations": { 210 | "patterns": [ 211 | { 212 | "name": "storage.type.annotation.dart", 213 | "match": "@[a-zA-Z]+" 214 | } 215 | ] 216 | }, 217 | "constants-and-special-vars": { 218 | "patterns": [ 219 | { 220 | "name": "constant.language.dart", 221 | "match": "(??]|,\\s*|\\s+extends\\s+)+>)?[!?]?\\(", 270 | "captures": { 271 | "1": { 272 | "name": "entity.name.function.dart" 273 | }, 274 | "2": { 275 | "patterns": [ 276 | { 277 | "include": "#type-args" 278 | } 279 | ] 280 | } 281 | } 282 | } 283 | ] 284 | }, 285 | "type-args": { 286 | "begin": "(<)", 287 | "end": "(>)", 288 | "beginCaptures": { 289 | "1": { 290 | "name": "other.source.dart" 291 | } 292 | }, 293 | "endCaptures": { 294 | "1": { 295 | "name": "other.source.dart" 296 | } 297 | }, 298 | "patterns": [ 299 | { 300 | "include": "#class-identifier" 301 | }, 302 | { 303 | "match": "," 304 | }, 305 | { 306 | "name": "keyword.declaration.dart", 307 | "match": "extends" 308 | }, 309 | { 310 | "include": "#comments" 311 | } 312 | ] 313 | }, 314 | "keywords": { 315 | "patterns": [ 316 | { 317 | "name": "keyword.cast.dart", 318 | "match": "(?>>?|~|\\^|\\||&)" 371 | }, 372 | { 373 | "name": "keyword.operator.assignment.bitwise.dart", 374 | "match": "((&|\\^|\\||<<|>>>?)=)" 375 | }, 376 | { 377 | "name": "keyword.operator.closure.dart", 378 | "match": "(=>)" 379 | }, 380 | { 381 | "name": "keyword.operator.comparison.dart", 382 | "match": "(==|!=|<=?|>=?)" 383 | }, 384 | { 385 | "name": "keyword.operator.assignment.arithmetic.dart", 386 | "match": "(([+*/%-]|\\~)=)" 387 | }, 388 | { 389 | "name": "keyword.operator.assignment.dart", 390 | "match": "(=)" 391 | }, 392 | { 393 | "name": "keyword.operator.increment-decrement.dart", 394 | "match": "(\\-\\-|\\+\\+)" 395 | }, 396 | { 397 | "name": "keyword.operator.arithmetic.dart", 398 | "match": "(\\-|\\+|\\*|\\/|\\~\\/|%)" 399 | }, 400 | { 401 | "name": "keyword.operator.logical.dart", 402 | "match": "(!|&&|\\|\\|)" 403 | } 404 | ] 405 | }, 406 | "expression": { 407 | "patterns": [ 408 | { 409 | "include": "#constants-and-special-vars" 410 | }, 411 | { 412 | "include": "#strings" 413 | }, 414 | { 415 | "name": "variable.parameter.dart", 416 | "match": "[a-zA-Z0-9_]+" 417 | }, 418 | { 419 | "begin": "\\{", 420 | "end": "\\}", 421 | "patterns": [ 422 | { 423 | "include": "#expression" 424 | } 425 | ] 426 | } 427 | ] 428 | }, 429 | "string-interp": { 430 | "patterns": [ 431 | { 432 | "name": "meta.embedded.expression.dart", 433 | "match": "\\$([a-zA-Z0-9_]+)", 434 | "captures": { 435 | "1": { 436 | "name": "variable.parameter.dart" 437 | } 438 | } 439 | }, 440 | { 441 | "name": "meta.embedded.expression.dart", 442 | "begin": "\\$\\{", 443 | "end": "\\}", 444 | "patterns": [ 445 | { 446 | "include": "#expression" 447 | } 448 | ] 449 | }, 450 | { 451 | "name": "constant.character.escape.dart", 452 | "match": "\\\\." 453 | } 454 | ] 455 | }, 456 | "strings": { 457 | "patterns": [ 458 | { 459 | "name": "string.interpolated.triple.double.dart", 460 | "begin": "(?// Copyright 2022 The Chromium Authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >void values() { 9 | #^^^^ storage.type.primitive.dart 10 | # ^^^^^^ entity.name.function.dart 11 | > final i = 1; 12 | # ^^^^^ storage.modifier.dart 13 | # ^ keyword.operator.assignment.dart 14 | # ^ constant.numeric.dart 15 | # ^ punctuation.terminator.dart 16 | > final j = 2; 17 | # ^^^^^ storage.modifier.dart 18 | # ^ keyword.operator.assignment.dart 19 | # ^ constant.numeric.dart 20 | # ^ punctuation.terminator.dart 21 | > 22 | > print('the value of \$i is $i'); 23 | # ^^^^^ entity.name.function.dart 24 | # ^^^^^^^^^^^^^^ string.interpolated.single.dart 25 | # ^^ string.interpolated.single.dart constant.character.escape.dart 26 | # ^^^^^ string.interpolated.single.dart 27 | # ^ string.interpolated.single.dart meta.embedded.expression.dart 28 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 29 | # ^ string.interpolated.single.dart 30 | # ^ punctuation.terminator.dart 31 | > print('the value after \$i is ${i + 1}'); 32 | # ^^^^^ entity.name.function.dart 33 | # ^^^^^^^^^^^^^^^^^ string.interpolated.single.dart 34 | # ^^ string.interpolated.single.dart constant.character.escape.dart 35 | # ^^^^^ string.interpolated.single.dart 36 | # ^^ string.interpolated.single.dart meta.embedded.expression.dart 37 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 38 | # ^^^ string.interpolated.single.dart meta.embedded.expression.dart 39 | # ^ string.interpolated.single.dart meta.embedded.expression.dart constant.numeric.dart 40 | # ^ string.interpolated.single.dart meta.embedded.expression.dart 41 | # ^ string.interpolated.single.dart 42 | # ^ punctuation.terminator.dart 43 | > print('the value of \$i + \$j is ${i + j}'); 44 | # ^^^^^ entity.name.function.dart 45 | # ^^^^^^^^^^^^^^ string.interpolated.single.dart 46 | # ^^ string.interpolated.single.dart constant.character.escape.dart 47 | # ^^^^ string.interpolated.single.dart 48 | # ^^ string.interpolated.single.dart constant.character.escape.dart 49 | # ^^^^^ string.interpolated.single.dart 50 | # ^^ string.interpolated.single.dart meta.embedded.expression.dart 51 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 52 | # ^^^ string.interpolated.single.dart meta.embedded.expression.dart 53 | # ^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 54 | # ^ string.interpolated.single.dart meta.embedded.expression.dart 55 | # ^ string.interpolated.single.dart 56 | # ^ punctuation.terminator.dart 57 | >} 58 | > 59 | >void functions() { 60 | #^^^^ storage.type.primitive.dart 61 | # ^^^^^^^^^ entity.name.function.dart 62 | > print('${() { 63 | # ^^^^^ entity.name.function.dart 64 | # ^ string.interpolated.single.dart 65 | # ^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 66 | > return 'Hello'; 67 | #^^^^ string.interpolated.single.dart meta.embedded.expression.dart 68 | # ^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 69 | # ^^^^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 70 | > }}'); 71 | #^^^^ string.interpolated.single.dart meta.embedded.expression.dart 72 | # ^ string.interpolated.single.dart 73 | # ^ punctuation.terminator.dart 74 | > print('print(${() { 75 | # ^^^^^ entity.name.function.dart 76 | # ^^^^^^^ string.interpolated.single.dart 77 | # ^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 78 | > return 'Hello'; 79 | #^^^^ string.interpolated.single.dart meta.embedded.expression.dart 80 | # ^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart variable.parameter.dart 81 | # ^^^^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 82 | > }()})'); 83 | #^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 84 | # ^^ string.interpolated.single.dart 85 | # ^ punctuation.terminator.dart 86 | > print('${() => 'Hello'}'); 87 | # ^^^^^ entity.name.function.dart 88 | # ^ string.interpolated.single.dart 89 | # ^^^^^^^^^^^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 90 | # ^ string.interpolated.single.dart 91 | # ^ punctuation.terminator.dart 92 | > print('print(${(() => 'Hello')()})'); 93 | # ^^^^^ entity.name.function.dart 94 | # ^^^^^^^ string.interpolated.single.dart 95 | # ^^^^^^^^^^^^^^^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 96 | # ^^ string.interpolated.single.dart 97 | # ^ punctuation.terminator.dart 98 | >} 99 | > 100 | >void nestedBraces() { 101 | #^^^^ storage.type.primitive.dart 102 | # ^^^^^^^^^^^^ entity.name.function.dart 103 | > print( '${ { " {} ${ "}" } {}" } }' ); 104 | # ^^^^^ entity.name.function.dart 105 | # ^ string.interpolated.single.dart 106 | # ^^^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 107 | # ^^^^^^^^^^^^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart string.interpolated.double.dart 108 | # ^^^^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 109 | # ^ string.interpolated.single.dart 110 | # ^ punctuation.terminator.dart 111 | > print( '${ {} }' ); 112 | # ^^^^^ entity.name.function.dart 113 | # ^ string.interpolated.single.dart 114 | # ^^^^^^^^^^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 115 | # ^ string.interpolated.single.dart 116 | # ^ punctuation.terminator.dart 117 | > print( '${ "{}" }' ); 118 | # ^^^^^ entity.name.function.dart 119 | # ^ string.interpolated.single.dart 120 | # ^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 121 | # ^^^^ string.interpolated.single.dart meta.embedded.expression.dart string.interpolated.double.dart 122 | # ^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 123 | # ^ string.interpolated.single.dart 124 | # ^ punctuation.terminator.dart 125 | > print( '${ "{" }' ); 126 | # ^^^^^ entity.name.function.dart 127 | # ^ string.interpolated.single.dart 128 | # ^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 129 | # ^^^ string.interpolated.single.dart meta.embedded.expression.dart string.interpolated.double.dart 130 | # ^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 131 | # ^ string.interpolated.single.dart 132 | # ^ punctuation.terminator.dart 133 | > print( '${ "}" }' ); 134 | # ^^^^^ entity.name.function.dart 135 | # ^ string.interpolated.single.dart 136 | # ^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 137 | # ^^^ string.interpolated.single.dart meta.embedded.expression.dart string.interpolated.double.dart 138 | # ^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 139 | # ^ string.interpolated.single.dart 140 | # ^ punctuation.terminator.dart 141 | > print( '${ {} }' ); 142 | # ^^^^^ entity.name.function.dart 143 | # ^ string.interpolated.single.dart 144 | # ^^^^^^^^^^^^^^^ string.interpolated.single.dart meta.embedded.expression.dart 145 | # ^ string.interpolated.single.dart 146 | # ^ punctuation.terminator.dart 147 | > print( "${ {} }" ); 148 | # ^^^^^ entity.name.function.dart 149 | # ^ string.interpolated.double.dart 150 | # ^^^^^^^^^^^^^^^ string.interpolated.double.dart meta.embedded.expression.dart 151 | # ^ string.interpolated.double.dart 152 | # ^ punctuation.terminator.dart 153 | > print( "${ "{}" }" ); 154 | # ^^^^^ entity.name.function.dart 155 | # ^ string.interpolated.double.dart 156 | # ^^^^^^^^^^^^^^^ string.interpolated.double.dart meta.embedded.expression.dart 157 | # ^ string.interpolated.double.dart 158 | # ^ punctuation.terminator.dart 159 | > print( "${ "{" }" ); 160 | # ^^^^^ entity.name.function.dart 161 | # ^ string.interpolated.double.dart 162 | # ^^^^^^^^^^^^^^^ string.interpolated.double.dart meta.embedded.expression.dart 163 | # ^ string.interpolated.double.dart 164 | # ^ punctuation.terminator.dart 165 | > print( "${ "}" }" ); 166 | # ^^^^^ entity.name.function.dart 167 | # ^ string.interpolated.double.dart 168 | # ^^^^^^^^^^^^^^^ string.interpolated.double.dart meta.embedded.expression.dart 169 | # ^ string.interpolated.double.dart 170 | # ^ punctuation.terminator.dart 171 | > print( "${ {} }" ); 172 | # ^^^^^ entity.name.function.dart 173 | # ^ string.interpolated.double.dart 174 | # ^^^^^^^^^^^^^^^ string.interpolated.double.dart meta.embedded.expression.dart 175 | # ^ string.interpolated.double.dart 176 | # ^ punctuation.terminator.dart 177 | > print( '''${ {} }'''); 178 | # ^^^^^ entity.name.function.dart 179 | # ^^^ string.interpolated.triple.single.dart 180 | # ^^^^^^^^^^^^^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart 181 | # ^^^ string.interpolated.triple.single.dart 182 | # ^ punctuation.terminator.dart 183 | > print( '''${ "{}" }'''); 184 | # ^^^^^ entity.name.function.dart 185 | # ^^^ string.interpolated.triple.single.dart 186 | # ^^^^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart 187 | # ^^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart string.interpolated.double.dart 188 | # ^^^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart 189 | # ^^^ string.interpolated.triple.single.dart 190 | # ^ punctuation.terminator.dart 191 | > print( '''${ "{" }'''); 192 | # ^^^^^ entity.name.function.dart 193 | # ^^^ string.interpolated.triple.single.dart 194 | # ^^^^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart 195 | # ^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart string.interpolated.double.dart 196 | # ^^^^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart 197 | # ^^^ string.interpolated.triple.single.dart 198 | # ^ punctuation.terminator.dart 199 | > print( '''${ "}" }'''); 200 | # ^^^^^ entity.name.function.dart 201 | # ^^^ string.interpolated.triple.single.dart 202 | # ^^^^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart 203 | # ^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart string.interpolated.double.dart 204 | # ^^^^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart 205 | # ^^^ string.interpolated.triple.single.dart 206 | # ^ punctuation.terminator.dart 207 | > print( '''${ {} }'''); 208 | # ^^^^^ entity.name.function.dart 209 | # ^^^ string.interpolated.triple.single.dart 210 | # ^^^^^^^^^^^^^^^ string.interpolated.triple.single.dart meta.embedded.expression.dart 211 | # ^^^ string.interpolated.triple.single.dart 212 | # ^ punctuation.terminator.dart 213 | > print( """${ {} }"""); 214 | # ^^^^^ entity.name.function.dart 215 | # ^^^ string.interpolated.triple.double.dart 216 | # ^^^^^^^^^^^^^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart 217 | # ^^^ string.interpolated.triple.double.dart 218 | # ^ punctuation.terminator.dart 219 | > print( """${ "{}" }"""); 220 | # ^^^^^ entity.name.function.dart 221 | # ^^^ string.interpolated.triple.double.dart 222 | # ^^^^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart 223 | # ^^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart string.interpolated.double.dart 224 | # ^^^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart 225 | # ^^^ string.interpolated.triple.double.dart 226 | # ^ punctuation.terminator.dart 227 | > print( """${ "{" }"""); 228 | # ^^^^^ entity.name.function.dart 229 | # ^^^ string.interpolated.triple.double.dart 230 | # ^^^^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart 231 | # ^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart string.interpolated.double.dart 232 | # ^^^^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart 233 | # ^^^ string.interpolated.triple.double.dart 234 | # ^ punctuation.terminator.dart 235 | > print( """${ "}" }"""); 236 | # ^^^^^ entity.name.function.dart 237 | # ^^^ string.interpolated.triple.double.dart 238 | # ^^^^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart 239 | # ^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart string.interpolated.double.dart 240 | # ^^^^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart 241 | # ^^^ string.interpolated.triple.double.dart 242 | # ^ punctuation.terminator.dart 243 | > print( """${ {} }"""); 244 | # ^^^^^ entity.name.function.dart 245 | # ^^^ string.interpolated.triple.double.dart 246 | # ^^^^^^^^^^^^^^^ string.interpolated.triple.double.dart meta.embedded.expression.dart 247 | # ^^^ string.interpolated.triple.double.dart 248 | # ^ punctuation.terminator.dart 249 | > print( r'${ {} }' ); 250 | # ^^^^^ entity.name.function.dart 251 | # ^^^^^^^^^^^^^^^^^^ string.quoted.single.dart 252 | # ^ punctuation.terminator.dart 253 | > print( r'${ "{}" }' ); 254 | # ^^^^^ entity.name.function.dart 255 | # ^^^^^^^^^^^^^^^^^^ string.quoted.single.dart 256 | # ^ punctuation.terminator.dart 257 | > print( r'${ "{" }' ); 258 | # ^^^^^ entity.name.function.dart 259 | # ^^^^^^^^^^^^^^^^^^ string.quoted.single.dart 260 | # ^ punctuation.terminator.dart 261 | > print( r'${ "}" }' ); 262 | # ^^^^^ entity.name.function.dart 263 | # ^^^^^^^^^^^^^^^^^^ string.quoted.single.dart 264 | # ^ punctuation.terminator.dart 265 | > print( r'${ {} }' ); 266 | # ^^^^^ entity.name.function.dart 267 | # ^^^^^^^^^^^^^^^^^^ string.quoted.single.dart 268 | # ^ punctuation.terminator.dart 269 | > print( r"${ {} }" ); 270 | # ^^^^^ entity.name.function.dart 271 | # ^^^^^^^^^^^^^^^^^^ string.quoted.double.dart 272 | # ^ punctuation.terminator.dart 273 | > print( r"${ '{}' }" ); 274 | # ^^^^^ entity.name.function.dart 275 | # ^^^^^^^^^^^^^^^^^^ string.quoted.double.dart 276 | # ^ punctuation.terminator.dart 277 | > print( r"${ '{' }" ); 278 | # ^^^^^ entity.name.function.dart 279 | # ^^^^^^^^^^^^^^^^^^ string.quoted.double.dart 280 | # ^ punctuation.terminator.dart 281 | > print( r"${ '}' }" ); 282 | # ^^^^^ entity.name.function.dart 283 | # ^^^^^^^^^^^^^^^^^^ string.quoted.double.dart 284 | # ^ punctuation.terminator.dart 285 | > print( r"${ {} }" ); 286 | # ^^^^^ entity.name.function.dart 287 | # ^^^^^^^^^^^^^^^^^^ string.quoted.double.dart 288 | # ^ punctuation.terminator.dart 289 | > print(r'''${ {} }'''); 290 | # ^^^^^ entity.name.function.dart 291 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.single.dart 292 | # ^ punctuation.terminator.dart 293 | > print(r'''${ "{}" }'''); 294 | # ^^^^^ entity.name.function.dart 295 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.single.dart 296 | # ^ punctuation.terminator.dart 297 | > print(r'''${ "{" }'''); 298 | # ^^^^^ entity.name.function.dart 299 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.single.dart 300 | # ^ punctuation.terminator.dart 301 | > print(r'''${ "}" }'''); 302 | # ^^^^^ entity.name.function.dart 303 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.single.dart 304 | # ^ punctuation.terminator.dart 305 | > print(r'''${ {} }'''); 306 | # ^^^^^ entity.name.function.dart 307 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.single.dart 308 | # ^ punctuation.terminator.dart 309 | > print(r"""${ {} }"""); 310 | # ^^^^^ entity.name.function.dart 311 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.double.dart 312 | # ^ punctuation.terminator.dart 313 | > print(r"""${ "{}" }"""); 314 | # ^^^^^ entity.name.function.dart 315 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.double.dart 316 | # ^ punctuation.terminator.dart 317 | > print(r"""${ "{" }"""); 318 | # ^^^^^ entity.name.function.dart 319 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.double.dart 320 | # ^ punctuation.terminator.dart 321 | > print(r"""${ "}" }"""); 322 | # ^^^^^ entity.name.function.dart 323 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.double.dart 324 | # ^ punctuation.terminator.dart 325 | > print(r"""${ {} }"""); 326 | # ^^^^^ entity.name.function.dart 327 | # ^^^^^^^^^^^^^^^^^^^^^^ string.quoted.triple.double.dart 328 | # ^ punctuation.terminator.dart 329 | >} 330 | -------------------------------------------------------------------------------- /test/goldens/patterns.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright (c) 2023, the Dart project authors. All rights reserved. 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// Use of this source code is governed by a BSD-style license that can be 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >import 'dart:math' as math; 9 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 10 | # ^ meta.declaration.dart 11 | # ^^^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 12 | # ^ meta.declaration.dart 13 | # ^^ meta.declaration.dart keyword.other.import.dart 14 | # ^^^^^ meta.declaration.dart 15 | # ^ meta.declaration.dart punctuation.terminator.dart 16 | > 17 | >import 'support.dart'; 18 | #^^^^^^ meta.declaration.dart keyword.other.import.dart 19 | # ^ meta.declaration.dart 20 | # ^^^^^^^^^^^^^^ meta.declaration.dart string.interpolated.single.dart 21 | # ^ meta.declaration.dart punctuation.terminator.dart 22 | > 23 | >// Samples taken from 24 | #^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 25 | >// https://github.com/dart-lang/language/blob/master/accepted/future-releases/0546-patterns/feature-specification.md 26 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 27 | > 28 | >void destructuring() { 29 | #^^^^ storage.type.primitive.dart 30 | # ^^^^^^^^^^^^^ entity.name.function.dart 31 | > var (lat, long) = testRecord; 32 | # ^^^ storage.type.primitive.dart 33 | # ^ punctuation.comma.dart 34 | # ^ keyword.operator.assignment.dart 35 | # ^ punctuation.terminator.dart 36 | > var [a, b, c] = testList; 37 | # ^^^ storage.type.primitive.dart 38 | # ^ punctuation.comma.dart 39 | # ^ punctuation.comma.dart 40 | # ^ keyword.operator.assignment.dart 41 | # ^ punctuation.terminator.dart 42 | > var {'first': first, 'second': second} = testMap; 43 | # ^^^ storage.type.primitive.dart 44 | # ^^^^^^^ string.interpolated.single.dart 45 | # ^ keyword.operator.ternary.dart 46 | # ^ punctuation.comma.dart 47 | # ^^^^^^^^ string.interpolated.single.dart 48 | # ^ keyword.operator.ternary.dart 49 | # ^ keyword.operator.assignment.dart 50 | # ^ punctuation.terminator.dart 51 | >} 52 | > 53 | >double algebraicDataTypes(Shape shape) => 54 | #^^^^^^ support.class.dart 55 | # ^^^^^^^^^^^^^^^^^^ entity.name.function.dart 56 | # ^^^^^ support.class.dart 57 | # ^^ keyword.operator.closure.dart 58 | > switch (shape) { 59 | # ^^^^^^ keyword.control.dart 60 | > Square(length: var l) => l * l, 61 | # ^^^^^^ support.class.dart 62 | # ^ keyword.operator.ternary.dart 63 | # ^^^ storage.type.primitive.dart 64 | # ^^ keyword.operator.closure.dart 65 | # ^ keyword.operator.arithmetic.dart 66 | # ^ punctuation.comma.dart 67 | > Circle(radius: var r) => math.pi * r * r 68 | # ^^^^^^ support.class.dart 69 | # ^ keyword.operator.ternary.dart 70 | # ^^^ storage.type.primitive.dart 71 | # ^^ keyword.operator.closure.dart 72 | # ^ punctuation.dot.dart 73 | # ^ keyword.operator.arithmetic.dart 74 | # ^ keyword.operator.arithmetic.dart 75 | > }; 76 | # ^ punctuation.terminator.dart 77 | > 78 | >void logicalOr() { 79 | #^^^^ storage.type.primitive.dart 80 | # ^^^^^^^^^ entity.name.function.dart 81 | > var isPrimary = switch (testColor) { 82 | # ^^^ storage.type.primitive.dart 83 | # ^ keyword.operator.assignment.dart 84 | # ^^^^^^ keyword.control.dart 85 | > Color.red || Color.yellow || Color.blue => true, 86 | # ^^^^^ support.class.dart 87 | # ^ punctuation.dot.dart 88 | # ^^ keyword.operator.bitwise.dart 89 | # ^^^^^ support.class.dart 90 | # ^ punctuation.dot.dart 91 | # ^^ keyword.operator.bitwise.dart 92 | # ^^^^^ support.class.dart 93 | # ^ punctuation.dot.dart 94 | # ^^ keyword.operator.closure.dart 95 | # ^^^^ constant.language.dart 96 | # ^ punctuation.comma.dart 97 | > _ => false 98 | # ^^ keyword.operator.closure.dart 99 | # ^^^^^ constant.language.dart 100 | > }; 101 | # ^ punctuation.terminator.dart 102 | > 103 | > switch (testShape) { 104 | # ^^^^^^ keyword.control.dart 105 | > case Square(size: var s) || Circle(size: var s) when s > 0: 106 | # ^^^^ keyword.control.dart 107 | # ^^^^^^ support.class.dart 108 | # ^ keyword.operator.ternary.dart 109 | # ^^^ storage.type.primitive.dart 110 | # ^^ keyword.operator.bitwise.dart 111 | # ^^^^^^ support.class.dart 112 | # ^ keyword.operator.ternary.dart 113 | # ^^^ storage.type.primitive.dart 114 | # ^^^^ keyword.control.dart 115 | # ^ keyword.operator.comparison.dart 116 | # ^ constant.numeric.dart 117 | # ^ keyword.operator.ternary.dart 118 | > print('Non-empty symmetric shape'); 119 | # ^^^^^ entity.name.function.dart 120 | # ^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.interpolated.single.dart 121 | # ^ punctuation.terminator.dart 122 | > case Square() || Circle(): 123 | # ^^^^ keyword.control.dart 124 | # ^^^^^^ support.class.dart 125 | # ^^ keyword.operator.bitwise.dart 126 | # ^^^^^^ support.class.dart 127 | # ^ keyword.operator.ternary.dart 128 | > print('Empty symmetric shape'); 129 | # ^^^^^ entity.name.function.dart 130 | # ^^^^^^^^^^^^^^^^^^^^^^^ string.interpolated.single.dart 131 | # ^ punctuation.terminator.dart 132 | > default: 133 | # ^^^^^^^ keyword.control.dart 134 | # ^ keyword.operator.ternary.dart 135 | > print('Asymmetric shape'); 136 | # ^^^^^ entity.name.function.dart 137 | # ^^^^^^^^^^^^^^^^^^ string.interpolated.single.dart 138 | # ^ punctuation.terminator.dart 139 | > } 140 | > 141 | > switch (testList) { 142 | # ^^^^^^ keyword.control.dart 143 | > case ['a' || 'b', var c]: 144 | # ^^^^ keyword.control.dart 145 | # ^^^ string.interpolated.single.dart 146 | # ^^ keyword.operator.bitwise.dart 147 | # ^^^ string.interpolated.single.dart 148 | # ^ punctuation.comma.dart 149 | # ^^^ storage.type.primitive.dart 150 | # ^ keyword.operator.ternary.dart 151 | > } 152 | >} 153 | > 154 | >String logicalAnd_relational(int char) { 155 | #^^^^^^ support.class.dart 156 | # ^^^^^^^^^^^^^^^^^^^^^ entity.name.function.dart 157 | # ^^^ support.class.dart 158 | > return switch (char) { 159 | # ^^^^^^ keyword.control.return.dart 160 | # ^^^^^^ keyword.control.dart 161 | > < space => 'control', 162 | # ^ keyword.operator.comparison.dart 163 | # ^^ keyword.operator.closure.dart 164 | # ^^^^^^^^^ string.interpolated.single.dart 165 | # ^ punctuation.comma.dart 166 | > == space => 'space', 167 | # ^^ keyword.operator.comparison.dart 168 | # ^^ keyword.operator.closure.dart 169 | # ^^^^^^^ string.interpolated.single.dart 170 | # ^ punctuation.comma.dart 171 | > > space && < zero => 'punctuation', 172 | # ^ keyword.operator.comparison.dart 173 | # ^^ keyword.operator.bitwise.dart 174 | # ^ keyword.operator.comparison.dart 175 | # ^^ keyword.operator.closure.dart 176 | # ^^^^^^^^^^^^^ string.interpolated.single.dart 177 | # ^ punctuation.comma.dart 178 | > >= zero && <= nine => 'digit' 179 | # ^^ keyword.operator.comparison.dart 180 | # ^^ keyword.operator.bitwise.dart 181 | # ^^ keyword.operator.comparison.dart 182 | # ^^ keyword.operator.closure.dart 183 | # ^^^^^^^ string.interpolated.single.dart 184 | > }; 185 | # ^ punctuation.terminator.dart 186 | >} 187 | > 188 | >void castPattern() { 189 | #^^^^ storage.type.primitive.dart 190 | # ^^^^^^^^^^^ entity.name.function.dart 191 | > var (i as int, j as int) = testRecord; 192 | # ^^^ storage.type.primitive.dart 193 | # ^^ keyword.cast.dart 194 | # ^^^ support.class.dart 195 | # ^ punctuation.comma.dart 196 | # ^^ keyword.cast.dart 197 | # ^^^ support.class.dart 198 | # ^ keyword.operator.assignment.dart 199 | # ^ punctuation.terminator.dart 200 | >} 201 | > 202 | >void nullCheckPattern_nullAssertPattern() { 203 | #^^^^ storage.type.primitive.dart 204 | # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ entity.name.function.dart 205 | > switch (maybeString) { 206 | # ^^^^^^ keyword.control.dart 207 | > case var s?: 208 | # ^^^^ keyword.control.dart 209 | # ^^^ storage.type.primitive.dart 210 | # ^^ keyword.operator.ternary.dart 211 | > } 212 | > 213 | > var (x!, y!) = testRecord; 214 | # ^^^ storage.type.primitive.dart 215 | # ^ keyword.operator.logical.dart 216 | # ^ punctuation.comma.dart 217 | # ^ keyword.operator.logical.dart 218 | # ^ keyword.operator.assignment.dart 219 | # ^ punctuation.terminator.dart 220 | > 221 | > switch (testList) { 222 | # ^^^^^^ keyword.control.dart 223 | > case ['user', var name!]: 224 | # ^^^^ keyword.control.dart 225 | # ^^^^^^ string.interpolated.single.dart 226 | # ^ punctuation.comma.dart 227 | # ^^^ storage.type.primitive.dart 228 | # ^ keyword.operator.logical.dart 229 | # ^ keyword.operator.ternary.dart 230 | > } 231 | >} 232 | > 233 | >void variablePattern() { 234 | #^^^^ storage.type.primitive.dart 235 | # ^^^^^^^^^^^^^^^ entity.name.function.dart 236 | > switch ((1, 2, 3)) { 237 | # ^^^^^^ keyword.control.dart 238 | # ^ constant.numeric.dart 239 | # ^ punctuation.comma.dart 240 | # ^ constant.numeric.dart 241 | # ^ punctuation.comma.dart 242 | # ^ constant.numeric.dart 243 | > case (var a, final b, _): 244 | # ^^^^ keyword.control.dart 245 | # ^^^ storage.type.primitive.dart 246 | # ^ punctuation.comma.dart 247 | # ^^^^^ storage.modifier.dart 248 | # ^ punctuation.comma.dart 249 | # ^ keyword.operator.ternary.dart 250 | > } 251 | > switch ((1, 2, 3)) { 252 | # ^^^^^^ keyword.control.dart 253 | # ^ constant.numeric.dart 254 | # ^ punctuation.comma.dart 255 | # ^ constant.numeric.dart 256 | # ^ punctuation.comma.dart 257 | # ^ constant.numeric.dart 258 | > case (int a, String b, String _): 259 | # ^^^^ keyword.control.dart 260 | # ^^^ support.class.dart 261 | # ^ punctuation.comma.dart 262 | # ^^^^^^ support.class.dart 263 | # ^ punctuation.comma.dart 264 | # ^^^^^^ support.class.dart 265 | # ^ keyword.operator.ternary.dart 266 | > } 267 | >} 268 | > 269 | >void listPatterns() { 270 | #^^^^ storage.type.primitive.dart 271 | # ^^^^^^^^^^^^ entity.name.function.dart 272 | > var [_, two, _] = testList; 273 | # ^^^ storage.type.primitive.dart 274 | # ^ punctuation.comma.dart 275 | # ^ punctuation.comma.dart 276 | # ^ keyword.operator.assignment.dart 277 | # ^ punctuation.terminator.dart 278 | > var [a, b, ...rest, c, d] = [1, 2, 3, 4, 5, 6, 7]; 279 | # ^^^ storage.type.primitive.dart 280 | # ^ punctuation.comma.dart 281 | # ^ punctuation.comma.dart 282 | # ^^^ punctuation.dot.dart 283 | # ^ punctuation.comma.dart 284 | # ^ punctuation.comma.dart 285 | # ^ keyword.operator.assignment.dart 286 | # ^ constant.numeric.dart 287 | # ^ punctuation.comma.dart 288 | # ^ constant.numeric.dart 289 | # ^ punctuation.comma.dart 290 | # ^ constant.numeric.dart 291 | # ^ punctuation.comma.dart 292 | # ^ constant.numeric.dart 293 | # ^ punctuation.comma.dart 294 | # ^ constant.numeric.dart 295 | # ^ punctuation.comma.dart 296 | # ^ constant.numeric.dart 297 | # ^ punctuation.comma.dart 298 | # ^ constant.numeric.dart 299 | # ^ punctuation.terminator.dart 300 | >} 301 | > 302 | >void mapPatterns() { 303 | #^^^^ storage.type.primitive.dart 304 | # ^^^^^^^^^^^ entity.name.function.dart 305 | > var {'field1': String field1, ... } = { 'field1': 'value1', 'field2': 'value2' }; 306 | # ^^^ storage.type.primitive.dart 307 | # ^^^^^^^^ string.interpolated.single.dart 308 | # ^ keyword.operator.ternary.dart 309 | # ^^^^^^ support.class.dart 310 | # ^ punctuation.comma.dart 311 | # ^^^ punctuation.dot.dart 312 | # ^ keyword.operator.assignment.dart 313 | # ^^^^^^^^ string.interpolated.single.dart 314 | # ^ keyword.operator.ternary.dart 315 | # ^^^^^^^^ string.interpolated.single.dart 316 | # ^ punctuation.comma.dart 317 | # ^^^^^^^^ string.interpolated.single.dart 318 | # ^ keyword.operator.ternary.dart 319 | # ^^^^^^^^ string.interpolated.single.dart 320 | # ^ punctuation.terminator.dart 321 | >} 322 | > 323 | >void recordPatterns() { 324 | #^^^^ storage.type.primitive.dart 325 | # ^^^^^^^^^^^^^^ entity.name.function.dart 326 | > // Variable: 327 | # ^^^^^^^^^^^^ comment.line.double-slash.dart 328 | > var (untyped: untyped, typed: int typed) = testRecord; 329 | # ^^^ storage.type.primitive.dart 330 | # ^ keyword.operator.ternary.dart 331 | # ^ punctuation.comma.dart 332 | # ^ keyword.operator.ternary.dart 333 | # ^^^ support.class.dart 334 | # ^ keyword.operator.assignment.dart 335 | # ^ punctuation.terminator.dart 336 | > var (:untyped, :int typed) = testRecord; 337 | # ^^^ storage.type.primitive.dart 338 | # ^ keyword.operator.ternary.dart 339 | # ^ punctuation.comma.dart 340 | # ^ keyword.operator.ternary.dart 341 | # ^^^ support.class.dart 342 | # ^ keyword.operator.assignment.dart 343 | # ^ punctuation.terminator.dart 344 | > 345 | > switch (testObject) { 346 | # ^^^^^^ keyword.control.dart 347 | > case (untyped: var untyped, typed: int typed): 348 | # ^^^^ keyword.control.dart 349 | # ^ keyword.operator.ternary.dart 350 | # ^^^ storage.type.primitive.dart 351 | # ^ punctuation.comma.dart 352 | # ^ keyword.operator.ternary.dart 353 | # ^^^ support.class.dart 354 | # ^ keyword.operator.ternary.dart 355 | > case (:var untyped, :int typed): 356 | # ^^^^ keyword.control.dart 357 | # ^ keyword.operator.ternary.dart 358 | # ^^^ storage.type.primitive.dart 359 | # ^ punctuation.comma.dart 360 | # ^ keyword.operator.ternary.dart 361 | # ^^^ support.class.dart 362 | # ^ keyword.operator.ternary.dart 363 | > } 364 | > 365 | > // Null-check and null-assert: 366 | # ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 367 | > switch (testObject) { 368 | # ^^^^^^ keyword.control.dart 369 | > case (checked: var checked?, asserted: var asserted!): 370 | # ^^^^ keyword.control.dart 371 | # ^ keyword.operator.ternary.dart 372 | # ^^^ storage.type.primitive.dart 373 | # ^ keyword.operator.ternary.dart 374 | # ^ punctuation.comma.dart 375 | # ^ keyword.operator.ternary.dart 376 | # ^^^ storage.type.primitive.dart 377 | # ^ keyword.operator.logical.dart 378 | # ^ keyword.operator.ternary.dart 379 | > case (:var checked?, :var asserted!): 380 | # ^^^^ keyword.control.dart 381 | # ^ keyword.operator.ternary.dart 382 | # ^^^ storage.type.primitive.dart 383 | # ^ keyword.operator.ternary.dart 384 | # ^ punctuation.comma.dart 385 | # ^ keyword.operator.ternary.dart 386 | # ^^^ storage.type.primitive.dart 387 | # ^ keyword.operator.logical.dart 388 | # ^ keyword.operator.ternary.dart 389 | > } 390 | > 391 | > // Cast: 392 | # ^^^^^^^^ comment.line.double-slash.dart 393 | > var (field: field as int) = testRecord; 394 | # ^^^ storage.type.primitive.dart 395 | # ^ keyword.operator.ternary.dart 396 | # ^^ keyword.cast.dart 397 | # ^^^ support.class.dart 398 | # ^ keyword.operator.assignment.dart 399 | # ^ punctuation.terminator.dart 400 | > var (:field as int) = testRecord; 401 | # ^^^ storage.type.primitive.dart 402 | # ^ keyword.operator.ternary.dart 403 | # ^^ keyword.cast.dart 404 | # ^^^ support.class.dart 405 | # ^ keyword.operator.assignment.dart 406 | # ^ punctuation.terminator.dart 407 | >} 408 | > 409 | >void objectPatterns(Object obj) { 410 | #^^^^ storage.type.primitive.dart 411 | # ^^^^^^^^^^^^^^ entity.name.function.dart 412 | # ^^^^^^ support.class.dart 413 | > switch (obj) { 414 | # ^^^^^^ keyword.control.dart 415 | > case Rect(width: var w, height: var h): 416 | # ^^^^ keyword.control.dart 417 | # ^^^^ support.class.dart 418 | # ^ keyword.operator.ternary.dart 419 | # ^^^ storage.type.primitive.dart 420 | # ^ punctuation.comma.dart 421 | # ^ keyword.operator.ternary.dart 422 | # ^^^ storage.type.primitive.dart 423 | # ^ keyword.operator.ternary.dart 424 | > default: 425 | # ^^^^^^^ keyword.control.dart 426 | # ^ keyword.operator.ternary.dart 427 | > } 428 | > switch (obj) { 429 | # ^^^^^^ keyword.control.dart 430 | > case Rect(:var width, :var height): 431 | # ^^^^ keyword.control.dart 432 | # ^^^^ support.class.dart 433 | # ^ keyword.operator.ternary.dart 434 | # ^^^ storage.type.primitive.dart 435 | # ^ punctuation.comma.dart 436 | # ^ keyword.operator.ternary.dart 437 | # ^^^ storage.type.primitive.dart 438 | # ^ keyword.operator.ternary.dart 439 | > default: 440 | # ^^^^^^^ keyword.control.dart 441 | # ^ keyword.operator.ternary.dart 442 | > } 443 | >} 444 | -------------------------------------------------------------------------------- /test/goldens/variable_names.dart.golden: -------------------------------------------------------------------------------- 1 | >// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file 2 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 3 | >// for details. All rights reserved. Use of this source code is governed by a 4 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 5 | >// BSD-style license that can be found in the LICENSE file. 6 | #^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ comment.line.double-slash.dart 7 | > 8 | >const $bool = null; 9 | #^^^^^ storage.modifier.dart 10 | # ^ keyword.operator.assignment.dart 11 | # ^^^^ constant.language.dart 12 | # ^ punctuation.terminator.dart 13 | >const bool$ = null; 14 | #^^^^^ storage.modifier.dart 15 | # ^ keyword.operator.assignment.dart 16 | # ^^^^ constant.language.dart 17 | # ^ punctuation.terminator.dart 18 | >const $num = null; 19 | #^^^^^ storage.modifier.dart 20 | # ^ keyword.operator.assignment.dart 21 | # ^^^^ constant.language.dart 22 | # ^ punctuation.terminator.dart 23 | >const num$ = null; 24 | #^^^^^ storage.modifier.dart 25 | # ^ keyword.operator.assignment.dart 26 | # ^^^^ constant.language.dart 27 | # ^ punctuation.terminator.dart 28 | >const $int = null; 29 | #^^^^^ storage.modifier.dart 30 | # ^ keyword.operator.assignment.dart 31 | # ^^^^ constant.language.dart 32 | # ^ punctuation.terminator.dart 33 | >const int$ = null; 34 | #^^^^^ storage.modifier.dart 35 | # ^ keyword.operator.assignment.dart 36 | # ^^^^ constant.language.dart 37 | # ^ punctuation.terminator.dart 38 | >const $double = null; 39 | #^^^^^ storage.modifier.dart 40 | # ^ keyword.operator.assignment.dart 41 | # ^^^^ constant.language.dart 42 | # ^ punctuation.terminator.dart 43 | >const double$ = null; 44 | #^^^^^ storage.modifier.dart 45 | # ^ keyword.operator.assignment.dart 46 | # ^^^^ constant.language.dart 47 | # ^ punctuation.terminator.dart 48 | >const $dynamic = null; 49 | #^^^^^ storage.modifier.dart 50 | # ^ keyword.operator.assignment.dart 51 | # ^^^^ constant.language.dart 52 | # ^ punctuation.terminator.dart 53 | >const dynamic$ = null; 54 | #^^^^^ storage.modifier.dart 55 | # ^ keyword.operator.assignment.dart 56 | # ^^^^ constant.language.dart 57 | # ^ punctuation.terminator.dart 58 | >const $true = null; 59 | #^^^^^ storage.modifier.dart 60 | # ^ keyword.operator.assignment.dart 61 | # ^^^^ constant.language.dart 62 | # ^ punctuation.terminator.dart 63 | >const true$ = null; 64 | #^^^^^ storage.modifier.dart 65 | # ^ keyword.operator.assignment.dart 66 | # ^^^^ constant.language.dart 67 | # ^ punctuation.terminator.dart 68 | >const $false = null; 69 | #^^^^^ storage.modifier.dart 70 | # ^ keyword.operator.assignment.dart 71 | # ^^^^ constant.language.dart 72 | # ^ punctuation.terminator.dart 73 | >const false$ = null; 74 | #^^^^^ storage.modifier.dart 75 | # ^ keyword.operator.assignment.dart 76 | # ^^^^ constant.language.dart 77 | # ^ punctuation.terminator.dart 78 | >const $null = null; 79 | #^^^^^ storage.modifier.dart 80 | # ^ keyword.operator.assignment.dart 81 | # ^^^^ constant.language.dart 82 | # ^ punctuation.terminator.dart 83 | >const null$ = null; 84 | #^^^^^ storage.modifier.dart 85 | # ^ keyword.operator.assignment.dart 86 | # ^^^^ constant.language.dart 87 | # ^ punctuation.terminator.dart 88 | >const $this = null; 89 | #^^^^^ storage.modifier.dart 90 | # ^ keyword.operator.assignment.dart 91 | # ^^^^ constant.language.dart 92 | # ^ punctuation.terminator.dart 93 | >const this$ = null; 94 | #^^^^^ storage.modifier.dart 95 | # ^ keyword.operator.assignment.dart 96 | # ^^^^ constant.language.dart 97 | # ^ punctuation.terminator.dart 98 | >const $super = null; 99 | #^^^^^ storage.modifier.dart 100 | # ^ keyword.operator.assignment.dart 101 | # ^^^^ constant.language.dart 102 | # ^ punctuation.terminator.dart 103 | >const super$ = null; 104 | #^^^^^ storage.modifier.dart 105 | # ^ keyword.operator.assignment.dart 106 | # ^^^^ constant.language.dart 107 | # ^ punctuation.terminator.dart 108 | >const $as = null; 109 | #^^^^^ storage.modifier.dart 110 | # ^ keyword.operator.assignment.dart 111 | # ^^^^ constant.language.dart 112 | # ^ punctuation.terminator.dart 113 | >const as$ = null; 114 | #^^^^^ storage.modifier.dart 115 | # ^ keyword.operator.assignment.dart 116 | # ^^^^ constant.language.dart 117 | # ^ punctuation.terminator.dart 118 | >const $try = null; 119 | #^^^^^ storage.modifier.dart 120 | # ^ keyword.operator.assignment.dart 121 | # ^^^^ constant.language.dart 122 | # ^ punctuation.terminator.dart 123 | >const try$ = null; 124 | #^^^^^ storage.modifier.dart 125 | # ^ keyword.operator.assignment.dart 126 | # ^^^^ constant.language.dart 127 | # ^ punctuation.terminator.dart 128 | >const $on = null; 129 | #^^^^^ storage.modifier.dart 130 | # ^ keyword.operator.assignment.dart 131 | # ^^^^ constant.language.dart 132 | # ^ punctuation.terminator.dart 133 | >const on$ = null; 134 | #^^^^^ storage.modifier.dart 135 | # ^ keyword.operator.assignment.dart 136 | # ^^^^ constant.language.dart 137 | # ^ punctuation.terminator.dart 138 | >const $catch = null; 139 | #^^^^^ storage.modifier.dart 140 | # ^ keyword.operator.assignment.dart 141 | # ^^^^ constant.language.dart 142 | # ^ punctuation.terminator.dart 143 | >const catch$ = null; 144 | #^^^^^ storage.modifier.dart 145 | # ^ keyword.operator.assignment.dart 146 | # ^^^^ constant.language.dart 147 | # ^ punctuation.terminator.dart 148 | >const $finally = null; 149 | #^^^^^ storage.modifier.dart 150 | # ^ keyword.operator.assignment.dart 151 | # ^^^^ constant.language.dart 152 | # ^ punctuation.terminator.dart 153 | >const finally$ = null; 154 | #^^^^^ storage.modifier.dart 155 | # ^ keyword.operator.assignment.dart 156 | # ^^^^ constant.language.dart 157 | # ^ punctuation.terminator.dart 158 | >const $throw = null; 159 | #^^^^^ storage.modifier.dart 160 | # ^ keyword.operator.assignment.dart 161 | # ^^^^ constant.language.dart 162 | # ^ punctuation.terminator.dart 163 | >const throw$ = null; 164 | #^^^^^ storage.modifier.dart 165 | # ^ keyword.operator.assignment.dart 166 | # ^^^^ constant.language.dart 167 | # ^ punctuation.terminator.dart 168 | >const $rethrow = null; 169 | #^^^^^ storage.modifier.dart 170 | # ^ keyword.operator.assignment.dart 171 | # ^^^^ constant.language.dart 172 | # ^ punctuation.terminator.dart 173 | >const rethrow$ = null; 174 | #^^^^^ storage.modifier.dart 175 | # ^ keyword.operator.assignment.dart 176 | # ^^^^ constant.language.dart 177 | # ^ punctuation.terminator.dart 178 | >const $break = null; 179 | #^^^^^ storage.modifier.dart 180 | # ^ keyword.operator.assignment.dart 181 | # ^^^^ constant.language.dart 182 | # ^ punctuation.terminator.dart 183 | >const break$ = null; 184 | #^^^^^ storage.modifier.dart 185 | # ^ keyword.operator.assignment.dart 186 | # ^^^^ constant.language.dart 187 | # ^ punctuation.terminator.dart 188 | >const $case = null; 189 | #^^^^^ storage.modifier.dart 190 | # ^ keyword.operator.assignment.dart 191 | # ^^^^ constant.language.dart 192 | # ^ punctuation.terminator.dart 193 | >const case$ = null; 194 | #^^^^^ storage.modifier.dart 195 | # ^ keyword.operator.assignment.dart 196 | # ^^^^ constant.language.dart 197 | # ^ punctuation.terminator.dart 198 | >const $continue = null; 199 | #^^^^^ storage.modifier.dart 200 | # ^ keyword.operator.assignment.dart 201 | # ^^^^ constant.language.dart 202 | # ^ punctuation.terminator.dart 203 | >const continue$ = null; 204 | #^^^^^ storage.modifier.dart 205 | # ^ keyword.operator.assignment.dart 206 | # ^^^^ constant.language.dart 207 | # ^ punctuation.terminator.dart 208 | >const $default = null; 209 | #^^^^^ storage.modifier.dart 210 | # ^ keyword.operator.assignment.dart 211 | # ^^^^ constant.language.dart 212 | # ^ punctuation.terminator.dart 213 | >const default$ = null; 214 | #^^^^^ storage.modifier.dart 215 | # ^ keyword.operator.assignment.dart 216 | # ^^^^ constant.language.dart 217 | # ^ punctuation.terminator.dart 218 | >const $do = null; 219 | #^^^^^ storage.modifier.dart 220 | # ^ keyword.operator.assignment.dart 221 | # ^^^^ constant.language.dart 222 | # ^ punctuation.terminator.dart 223 | >const do$ = null; 224 | #^^^^^ storage.modifier.dart 225 | # ^ keyword.operator.assignment.dart 226 | # ^^^^ constant.language.dart 227 | # ^ punctuation.terminator.dart 228 | >const $else = null; 229 | #^^^^^ storage.modifier.dart 230 | # ^ keyword.operator.assignment.dart 231 | # ^^^^ constant.language.dart 232 | # ^ punctuation.terminator.dart 233 | >const else$ = null; 234 | #^^^^^ storage.modifier.dart 235 | # ^ keyword.operator.assignment.dart 236 | # ^^^^ constant.language.dart 237 | # ^ punctuation.terminator.dart 238 | >const $for = null; 239 | #^^^^^ storage.modifier.dart 240 | # ^ keyword.operator.assignment.dart 241 | # ^^^^ constant.language.dart 242 | # ^ punctuation.terminator.dart 243 | >const for$ = null; 244 | #^^^^^ storage.modifier.dart 245 | # ^ keyword.operator.assignment.dart 246 | # ^^^^ constant.language.dart 247 | # ^ punctuation.terminator.dart 248 | >const $if = null; 249 | #^^^^^ storage.modifier.dart 250 | # ^ keyword.operator.assignment.dart 251 | # ^^^^ constant.language.dart 252 | # ^ punctuation.terminator.dart 253 | >const if$ = null; 254 | #^^^^^ storage.modifier.dart 255 | # ^ keyword.operator.assignment.dart 256 | # ^^^^ constant.language.dart 257 | # ^ punctuation.terminator.dart 258 | >const $in = null; 259 | #^^^^^ storage.modifier.dart 260 | # ^ keyword.operator.assignment.dart 261 | # ^^^^ constant.language.dart 262 | # ^ punctuation.terminator.dart 263 | >const in$ = null; 264 | #^^^^^ storage.modifier.dart 265 | # ^ keyword.operator.assignment.dart 266 | # ^^^^ constant.language.dart 267 | # ^ punctuation.terminator.dart 268 | >const $return = null; 269 | #^^^^^ storage.modifier.dart 270 | # ^ keyword.operator.assignment.dart 271 | # ^^^^ constant.language.dart 272 | # ^ punctuation.terminator.dart 273 | >const return$ = null; 274 | #^^^^^ storage.modifier.dart 275 | # ^ keyword.operator.assignment.dart 276 | # ^^^^ constant.language.dart 277 | # ^ punctuation.terminator.dart 278 | >const $switch = null; 279 | #^^^^^ storage.modifier.dart 280 | # ^ keyword.operator.assignment.dart 281 | # ^^^^ constant.language.dart 282 | # ^ punctuation.terminator.dart 283 | >const switch$ = null; 284 | #^^^^^ storage.modifier.dart 285 | # ^ keyword.operator.assignment.dart 286 | # ^^^^ constant.language.dart 287 | # ^ punctuation.terminator.dart 288 | >const $while = null; 289 | #^^^^^ storage.modifier.dart 290 | # ^ keyword.operator.assignment.dart 291 | # ^^^^ constant.language.dart 292 | # ^ punctuation.terminator.dart 293 | >const while$ = null; 294 | #^^^^^ storage.modifier.dart 295 | # ^ keyword.operator.assignment.dart 296 | # ^^^^ constant.language.dart 297 | # ^ punctuation.terminator.dart 298 | >const $sync = null; 299 | #^^^^^ storage.modifier.dart 300 | # ^ keyword.operator.assignment.dart 301 | # ^^^^ constant.language.dart 302 | # ^ punctuation.terminator.dart 303 | >const sync$ = null; 304 | #^^^^^ storage.modifier.dart 305 | # ^ keyword.operator.assignment.dart 306 | # ^^^^ constant.language.dart 307 | # ^ punctuation.terminator.dart 308 | >const $async = null; 309 | #^^^^^ storage.modifier.dart 310 | # ^ keyword.operator.assignment.dart 311 | # ^^^^ constant.language.dart 312 | # ^ punctuation.terminator.dart 313 | >const async$ = null; 314 | #^^^^^ storage.modifier.dart 315 | # ^ keyword.operator.assignment.dart 316 | # ^^^^ constant.language.dart 317 | # ^ punctuation.terminator.dart 318 | >const $await = null; 319 | #^^^^^ storage.modifier.dart 320 | # ^ keyword.operator.assignment.dart 321 | # ^^^^ constant.language.dart 322 | # ^ punctuation.terminator.dart 323 | >const await$ = null; 324 | #^^^^^ storage.modifier.dart 325 | # ^ keyword.operator.assignment.dart 326 | # ^^^^ constant.language.dart 327 | # ^ punctuation.terminator.dart 328 | >const $yield = null; 329 | #^^^^^ storage.modifier.dart 330 | # ^ keyword.operator.assignment.dart 331 | # ^^^^ constant.language.dart 332 | # ^ punctuation.terminator.dart 333 | >const yield$ = null; 334 | #^^^^^ storage.modifier.dart 335 | # ^ keyword.operator.assignment.dart 336 | # ^^^^ constant.language.dart 337 | # ^ punctuation.terminator.dart 338 | >const $assert = null; 339 | #^^^^^ storage.modifier.dart 340 | # ^ keyword.operator.assignment.dart 341 | # ^^^^ constant.language.dart 342 | # ^ punctuation.terminator.dart 343 | >const assert$ = null; 344 | #^^^^^ storage.modifier.dart 345 | # ^ keyword.operator.assignment.dart 346 | # ^^^^ constant.language.dart 347 | # ^ punctuation.terminator.dart 348 | >const $new = null; 349 | #^^^^^ storage.modifier.dart 350 | # ^ keyword.operator.assignment.dart 351 | # ^^^^ constant.language.dart 352 | # ^ punctuation.terminator.dart 353 | >const new$ = null; 354 | #^^^^^ storage.modifier.dart 355 | # ^ keyword.operator.assignment.dart 356 | # ^^^^ constant.language.dart 357 | # ^ punctuation.terminator.dart 358 | >const $abstract = null; 359 | #^^^^^ storage.modifier.dart 360 | # ^ keyword.operator.assignment.dart 361 | # ^^^^ constant.language.dart 362 | # ^ punctuation.terminator.dart 363 | >const abstract$ = null; 364 | #^^^^^ storage.modifier.dart 365 | # ^ keyword.operator.assignment.dart 366 | # ^^^^ constant.language.dart 367 | # ^ punctuation.terminator.dart 368 | >const $class = null; 369 | #^^^^^ storage.modifier.dart 370 | # ^ keyword.operator.assignment.dart 371 | # ^^^^ constant.language.dart 372 | # ^ punctuation.terminator.dart 373 | >const class$ = null; 374 | #^^^^^ storage.modifier.dart 375 | # ^ keyword.operator.assignment.dart 376 | # ^^^^ constant.language.dart 377 | # ^ punctuation.terminator.dart 378 | >const $enum = null; 379 | #^^^^^ storage.modifier.dart 380 | # ^ keyword.operator.assignment.dart 381 | # ^^^^ constant.language.dart 382 | # ^ punctuation.terminator.dart 383 | >const enum$ = null; 384 | #^^^^^ storage.modifier.dart 385 | # ^ keyword.operator.assignment.dart 386 | # ^^^^ constant.language.dart 387 | # ^ punctuation.terminator.dart 388 | >const $extends = null; 389 | #^^^^^ storage.modifier.dart 390 | # ^ keyword.operator.assignment.dart 391 | # ^^^^ constant.language.dart 392 | # ^ punctuation.terminator.dart 393 | >const extends$ = null; 394 | #^^^^^ storage.modifier.dart 395 | # ^ keyword.operator.assignment.dart 396 | # ^^^^ constant.language.dart 397 | # ^ punctuation.terminator.dart 398 | >const $extension = null; 399 | #^^^^^ storage.modifier.dart 400 | # ^ keyword.operator.assignment.dart 401 | # ^^^^ constant.language.dart 402 | # ^ punctuation.terminator.dart 403 | >const extension$ = null; 404 | #^^^^^ storage.modifier.dart 405 | # ^ keyword.operator.assignment.dart 406 | # ^^^^ constant.language.dart 407 | # ^ punctuation.terminator.dart 408 | >const $external = null; 409 | #^^^^^ storage.modifier.dart 410 | # ^ keyword.operator.assignment.dart 411 | # ^^^^ constant.language.dart 412 | # ^ punctuation.terminator.dart 413 | >const external$ = null; 414 | #^^^^^ storage.modifier.dart 415 | # ^ keyword.operator.assignment.dart 416 | # ^^^^ constant.language.dart 417 | # ^ punctuation.terminator.dart 418 | >const $factory = null; 419 | #^^^^^ storage.modifier.dart 420 | # ^ keyword.operator.assignment.dart 421 | # ^^^^ constant.language.dart 422 | # ^ punctuation.terminator.dart 423 | >const factory$ = null; 424 | #^^^^^ storage.modifier.dart 425 | # ^ keyword.operator.assignment.dart 426 | # ^^^^ constant.language.dart 427 | # ^ punctuation.terminator.dart 428 | >const $implements = null; 429 | #^^^^^ storage.modifier.dart 430 | # ^ keyword.operator.assignment.dart 431 | # ^^^^ constant.language.dart 432 | # ^ punctuation.terminator.dart 433 | >const implements$ = null; 434 | #^^^^^ storage.modifier.dart 435 | # ^ keyword.operator.assignment.dart 436 | # ^^^^ constant.language.dart 437 | # ^ punctuation.terminator.dart 438 | >const $get = null; 439 | #^^^^^ storage.modifier.dart 440 | # ^ keyword.operator.assignment.dart 441 | # ^^^^ constant.language.dart 442 | # ^ punctuation.terminator.dart 443 | >const get$ = null; 444 | #^^^^^ storage.modifier.dart 445 | # ^ keyword.operator.assignment.dart 446 | # ^^^^ constant.language.dart 447 | # ^ punctuation.terminator.dart 448 | >const $mixin = null; 449 | #^^^^^ storage.modifier.dart 450 | # ^ keyword.operator.assignment.dart 451 | # ^^^^ constant.language.dart 452 | # ^ punctuation.terminator.dart 453 | >const mixin$ = null; 454 | #^^^^^ storage.modifier.dart 455 | # ^ keyword.operator.assignment.dart 456 | # ^^^^ constant.language.dart 457 | # ^ punctuation.terminator.dart 458 | >const $native = null; 459 | #^^^^^ storage.modifier.dart 460 | # ^ keyword.operator.assignment.dart 461 | # ^^^^ constant.language.dart 462 | # ^ punctuation.terminator.dart 463 | >const native$ = null; 464 | #^^^^^ storage.modifier.dart 465 | # ^ keyword.operator.assignment.dart 466 | # ^^^^ constant.language.dart 467 | # ^ punctuation.terminator.dart 468 | >const $operator = null; 469 | #^^^^^ storage.modifier.dart 470 | # ^ keyword.operator.assignment.dart 471 | # ^^^^ constant.language.dart 472 | # ^ punctuation.terminator.dart 473 | >const operator$ = null; 474 | #^^^^^ storage.modifier.dart 475 | # ^ keyword.operator.assignment.dart 476 | # ^^^^ constant.language.dart 477 | # ^ punctuation.terminator.dart 478 | >const $set = null; 479 | #^^^^^ storage.modifier.dart 480 | # ^ keyword.operator.assignment.dart 481 | # ^^^^ constant.language.dart 482 | # ^ punctuation.terminator.dart 483 | >const set$ = null; 484 | #^^^^^ storage.modifier.dart 485 | # ^ keyword.operator.assignment.dart 486 | # ^^^^ constant.language.dart 487 | # ^ punctuation.terminator.dart 488 | >const $typedef = null; 489 | #^^^^^ storage.modifier.dart 490 | # ^ keyword.operator.assignment.dart 491 | # ^^^^ constant.language.dart 492 | # ^ punctuation.terminator.dart 493 | >const typedef$ = null; 494 | #^^^^^ storage.modifier.dart 495 | # ^ keyword.operator.assignment.dart 496 | # ^^^^ constant.language.dart 497 | # ^ punctuation.terminator.dart 498 | >const $with = null; 499 | #^^^^^ storage.modifier.dart 500 | # ^ keyword.operator.assignment.dart 501 | # ^^^^ constant.language.dart 502 | # ^ punctuation.terminator.dart 503 | >const with$ = null; 504 | #^^^^^ storage.modifier.dart 505 | # ^ keyword.operator.assignment.dart 506 | # ^^^^ constant.language.dart 507 | # ^ punctuation.terminator.dart 508 | >const $covariant = null; 509 | #^^^^^ storage.modifier.dart 510 | # ^ keyword.operator.assignment.dart 511 | # ^^^^ constant.language.dart 512 | # ^ punctuation.terminator.dart 513 | >const covariant$ = null; 514 | #^^^^^ storage.modifier.dart 515 | # ^ keyword.operator.assignment.dart 516 | # ^^^^ constant.language.dart 517 | # ^ punctuation.terminator.dart 518 | >const $static = null; 519 | #^^^^^ storage.modifier.dart 520 | # ^ keyword.operator.assignment.dart 521 | # ^^^^ constant.language.dart 522 | # ^ punctuation.terminator.dart 523 | >const static$ = null; 524 | #^^^^^ storage.modifier.dart 525 | # ^ keyword.operator.assignment.dart 526 | # ^^^^ constant.language.dart 527 | # ^ punctuation.terminator.dart 528 | >const $final = null; 529 | #^^^^^ storage.modifier.dart 530 | # ^ keyword.operator.assignment.dart 531 | # ^^^^ constant.language.dart 532 | # ^ punctuation.terminator.dart 533 | >const final$ = null; 534 | #^^^^^ storage.modifier.dart 535 | # ^ keyword.operator.assignment.dart 536 | # ^^^^ constant.language.dart 537 | # ^ punctuation.terminator.dart 538 | >const $const = null; 539 | #^^^^^ storage.modifier.dart 540 | # ^ keyword.operator.assignment.dart 541 | # ^^^^ constant.language.dart 542 | # ^ punctuation.terminator.dart 543 | >const const$ = null; 544 | #^^^^^ storage.modifier.dart 545 | # ^ keyword.operator.assignment.dart 546 | # ^^^^ constant.language.dart 547 | # ^ punctuation.terminator.dart 548 | >const $required = null; 549 | #^^^^^ storage.modifier.dart 550 | # ^ keyword.operator.assignment.dart 551 | # ^^^^ constant.language.dart 552 | # ^ punctuation.terminator.dart 553 | >const required$ = null; 554 | #^^^^^ storage.modifier.dart 555 | # ^ keyword.operator.assignment.dart 556 | # ^^^^ constant.language.dart 557 | # ^ punctuation.terminator.dart 558 | >const $late = null; 559 | #^^^^^ storage.modifier.dart 560 | # ^ keyword.operator.assignment.dart 561 | # ^^^^ constant.language.dart 562 | # ^ punctuation.terminator.dart 563 | >const late$ = null; 564 | #^^^^^ storage.modifier.dart 565 | # ^ keyword.operator.assignment.dart 566 | # ^^^^ constant.language.dart 567 | # ^ punctuation.terminator.dart 568 | >const $void = null; 569 | #^^^^^ storage.modifier.dart 570 | # ^ keyword.operator.assignment.dart 571 | # ^^^^ constant.language.dart 572 | # ^ punctuation.terminator.dart 573 | >const void$ = null; 574 | #^^^^^ storage.modifier.dart 575 | # ^ keyword.operator.assignment.dart 576 | # ^^^^ constant.language.dart 577 | # ^ punctuation.terminator.dart 578 | >const $var = null; 579 | #^^^^^ storage.modifier.dart 580 | # ^ keyword.operator.assignment.dart 581 | # ^^^^ constant.language.dart 582 | # ^ punctuation.terminator.dart 583 | >const var$ = null; 584 | #^^^^^ storage.modifier.dart 585 | # ^ keyword.operator.assignment.dart 586 | # ^^^^ constant.language.dart 587 | # ^ punctuation.terminator.dart 588 | >const $is = null; 589 | #^^^^^ storage.modifier.dart 590 | # ^ keyword.operator.assignment.dart 591 | # ^^^^ constant.language.dart 592 | # ^ punctuation.terminator.dart 593 | >const is$ = null; 594 | #^^^^^ storage.modifier.dart 595 | # ^ keyword.operator.assignment.dart 596 | # ^^^^ constant.language.dart 597 | # ^ punctuation.terminator.dart 598 | >const $sealed = null; 599 | #^^^^^ storage.modifier.dart 600 | # ^ keyword.operator.assignment.dart 601 | # ^^^^ constant.language.dart 602 | # ^ punctuation.terminator.dart 603 | >const sealed$ = null; 604 | #^^^^^ storage.modifier.dart 605 | # ^ keyword.operator.assignment.dart 606 | # ^^^^ constant.language.dart 607 | # ^ punctuation.terminator.dart 608 | >const $interface = null; 609 | #^^^^^ storage.modifier.dart 610 | # ^ keyword.operator.assignment.dart 611 | # ^^^^ constant.language.dart 612 | # ^ punctuation.terminator.dart 613 | >const interface$ = null; 614 | #^^^^^ storage.modifier.dart 615 | # ^ keyword.operator.assignment.dart 616 | # ^^^^ constant.language.dart 617 | # ^ punctuation.terminator.dart 618 | >const $base = null; 619 | #^^^^^ storage.modifier.dart 620 | # ^ keyword.operator.assignment.dart 621 | # ^^^^ constant.language.dart 622 | # ^ punctuation.terminator.dart 623 | >const base$ = null; 624 | #^^^^^ storage.modifier.dart 625 | # ^ keyword.operator.assignment.dart 626 | # ^^^^ constant.language.dart 627 | # ^ punctuation.terminator.dart 628 | -------------------------------------------------------------------------------- /test/support/span_parser.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | // 5 | // This file is taken from DevTools and should be kept in-sync with any changes 6 | // that affect the resulting tokens. 7 | // 8 | // https://github.com/flutter/devtools/blob/master/packages/devtools_app/lib/src/screens/debugger/span_parser.dart 9 | 10 | // ignore_for_file: type=lint 11 | 12 | import 'dart:collection'; 13 | import 'dart:convert'; 14 | 15 | import 'package:collection/collection.dart'; 16 | import 'package:string_scanner/string_scanner.dart'; 17 | 18 | // ignore: avoid_classes_with_only_static_members 19 | abstract class SpanParser { 20 | /// Takes a TextMate [Grammar] and a [String] and outputs a list of 21 | /// [ScopeSpan]s corresponding to the parsed input. 22 | static List parse(Grammar grammar, String src) { 23 | final scopeStack = ScopeStack(); 24 | final scanner = LineScanner(src); 25 | while (!scanner.isDone) { 26 | final foundMatch = 27 | grammar.topLevelMatcher.scan(grammar, scanner, scopeStack); 28 | if (!foundMatch && !scanner.isDone) { 29 | // Found no match, move forward by a character and try again. 30 | scanner.readChar(); 31 | } 32 | } 33 | scopeStack.popAll(scanner.location); 34 | return scopeStack.spans; 35 | } 36 | } 37 | 38 | /// A representation of a TextMate grammar used to create [ScopeSpan]s 39 | /// representing scopes within a body of text. 40 | /// 41 | /// References used: 42 | /// - Grammar specification: 43 | /// https://macromates.com/manual/en/language_grammars#language_grammars 44 | /// - Helpful blog post which clears up ambiguities in the spec: 45 | /// https://www.apeth.com/nonblog/stories/textmatebundle.html 46 | /// 47 | class Grammar { 48 | factory Grammar.fromJson(Map json) { 49 | return Grammar._( 50 | name: json['name'] as String, 51 | scopeName: json['scopeName'] as String, 52 | topLevelMatcher: GrammarMatcher.parse(json), 53 | repository: Repository.build(json), 54 | ); 55 | } 56 | 57 | Grammar._({ 58 | this.name, 59 | this.scopeName, 60 | required this.topLevelMatcher, 61 | required this.repository, 62 | }); 63 | 64 | final String? name; 65 | 66 | final String? scopeName; 67 | 68 | final GrammarMatcher topLevelMatcher; 69 | 70 | final Repository repository; 71 | 72 | @override 73 | String toString() { 74 | return const JsonEncoder.withIndent(' ').convert({ 75 | 'name': name, 76 | 'scopeName': scopeName, 77 | 'topLevelMatcher': topLevelMatcher.toJson(), 78 | 'repository': repository.toJson(), 79 | }); 80 | } 81 | } 82 | 83 | /// A representation of a span of text which has `scope` applied to it. 84 | class ScopeSpan { 85 | ScopeSpan({ 86 | required this.scopes, 87 | required ScopeStackLocation startLocation, 88 | required ScopeStackLocation endLocation, 89 | }) : _startLocation = startLocation, 90 | _endLocation = endLocation; 91 | 92 | ScopeStackLocation get startLocation => _startLocation; 93 | ScopeStackLocation get endLocation => _endLocation; 94 | int get start => _startLocation.position; 95 | int get end => _endLocation.position; 96 | int get length => end - start; 97 | 98 | final ScopeStackLocation _startLocation; 99 | ScopeStackLocation _endLocation; 100 | 101 | /// The one-based line number. 102 | int get line => startLocation.line + 1; 103 | 104 | /// The one-based column number. 105 | int get column => startLocation.column + 1; 106 | 107 | final List scopes; 108 | 109 | bool contains(int token) => (start <= token) && (token < end); 110 | 111 | /// Splits the current [ScopeSpan] into multiple spans separated by [cond]. 112 | /// This is useful for post-processing the results from a rule with a while 113 | /// condition as formatting should not be applied to the characters that 114 | /// match the while condition. 115 | List split(LineScanner scanner, RegExp cond) { 116 | final splitSpans = []; 117 | 118 | // Create a temporary scanner, copying [0, end] to ensure that line/column 119 | // information is consistent with the original scanner. 120 | final splitScanner = LineScanner( 121 | scanner.substring(0, end), 122 | position: start, 123 | ); 124 | 125 | // Start with a copy of the original span 126 | ScopeSpan current = ScopeSpan( 127 | scopes: scopes.toList(), 128 | startLocation: startLocation, 129 | endLocation: endLocation, 130 | ); 131 | 132 | while (!splitScanner.isDone) { 133 | if (splitScanner.matches(cond)) { 134 | // Update the end position for this span as it's been fully processed. 135 | current._endLocation = splitScanner.location; 136 | splitSpans.add(current); 137 | 138 | // Move the scanner position past the matched condition. 139 | splitScanner.scan(cond); 140 | 141 | // Create a new span based on the current position. 142 | current = ScopeSpan( 143 | scopes: scopes.toList(), 144 | startLocation: splitScanner.location, 145 | // Will be updated later. 146 | endLocation: ScopeStackLocation.zero, 147 | ); 148 | } else { 149 | // Move scanner position forward. 150 | splitScanner.readChar(); 151 | } 152 | } 153 | // Finish processing the last span, which will always have the same end 154 | // position as the span we're splitting. 155 | current._endLocation = endLocation; 156 | splitSpans.add(current); 157 | 158 | return splitSpans; 159 | } 160 | 161 | @override 162 | String toString() { 163 | return '[$start, $end, $line:$column (len: $length)] = $scopes'; 164 | } 165 | } 166 | 167 | /// A top-level repository of rules that can be referenced within other rules 168 | /// using the 'includes' keyword. 169 | class Repository { 170 | Repository.build(Map grammarJson) { 171 | final repositoryJson = (grammarJson['repository'] as Map?) 172 | ?.cast>(); 173 | if (repositoryJson == null) { 174 | return; 175 | } 176 | for (final subRepo in repositoryJson.keys) { 177 | matchers[subRepo] = GrammarMatcher.parse(repositoryJson[subRepo]!); 178 | } 179 | } 180 | 181 | final matchers = {}; 182 | 183 | Map toJson() { 184 | return { 185 | for (final entry in matchers.entries) 186 | if (entry.key != null) entry.key!: entry.value.toJson(), 187 | }; 188 | } 189 | } 190 | 191 | abstract class GrammarMatcher { 192 | factory GrammarMatcher.parse(Map json) { 193 | if (_IncludeMatcher.isType(json)) { 194 | return _IncludeMatcher(json['include'] as String); 195 | } else if (_SimpleMatcher.isType(json)) { 196 | return _SimpleMatcher(json); 197 | } else if (_MultilineMatcher.isType(json)) { 198 | return _MultilineMatcher(json); 199 | } else if (_PatternMatcher.isType(json)) { 200 | return _PatternMatcher(json); 201 | } 202 | throw StateError('Unknown matcher type: $json'); 203 | } 204 | 205 | GrammarMatcher._(Map json) : name = json['name'] as String?; 206 | 207 | final String? name; 208 | 209 | bool scan(Grammar grammar, LineScanner scanner, ScopeStack scopeStack); 210 | 211 | void _applyCapture( 212 | Grammar grammar, 213 | LineScanner scanner, 214 | ScopeStack scopeStack, 215 | Map? captures, 216 | ScopeStackLocation location, 217 | ) { 218 | final lastMatch = scanner.lastMatch!; 219 | final start = lastMatch.start; 220 | final end = lastMatch.end; 221 | final matchStartLocation = location; 222 | if (captures != null) { 223 | final match = scanner.substring(start, end); 224 | for (int i = 0; i <= lastMatch.groupCount; ++i) { 225 | // Skip if we don't have a scope or nested patterns for this capture. 226 | if (!captures.containsKey(i.toString())) continue; 227 | 228 | final captureText = lastMatch.group(i); 229 | if (captureText == null || captureText.isEmpty) continue; 230 | 231 | final startOffset = match.indexOf(captureText); 232 | final capture = captures[i.toString()] as Map; 233 | final captureStartLocation = matchStartLocation.offset(startOffset); 234 | final captureEndLocation = 235 | captureStartLocation.offset(captureText.length); 236 | final captureName = capture['name'] as String?; 237 | 238 | scopeStack.push(captureName, captureStartLocation); 239 | 240 | // Handle nested pattern matchers. 241 | if (capture.containsKey('patterns')) { 242 | final captureScanner = LineScanner( 243 | scanner.substring(0, captureEndLocation.position), 244 | position: captureStartLocation.position, 245 | ); 246 | GrammarMatcher.parse(capture) 247 | .scan(grammar, captureScanner, scopeStack); 248 | } 249 | 250 | scopeStack.pop(captureName, captureEndLocation); 251 | } 252 | } 253 | } 254 | 255 | Map toJson(); 256 | } 257 | 258 | /// A simple matcher which matches a single line. 259 | class _SimpleMatcher extends GrammarMatcher { 260 | _SimpleMatcher(Map json) 261 | : match = RegExp(json['match'] as String, multiLine: true), 262 | captures = (json['captures'] as Map?) 263 | ?.cast>(), 264 | super._(json); 265 | 266 | static bool isType(Map json) { 267 | return json.containsKey('match'); 268 | } 269 | 270 | final RegExp match; 271 | 272 | final Map? captures; 273 | 274 | @override 275 | bool scan(Grammar grammar, LineScanner scanner, ScopeStack scopeStack) { 276 | final location = scanner.location; 277 | if (scanner.scan(match)) { 278 | scopeStack.push(name, location); 279 | _applyCapture(grammar, scanner, scopeStack, captures, location); 280 | scopeStack.pop(name, scanner.location); 281 | return true; 282 | } 283 | return false; 284 | } 285 | 286 | @override 287 | Map toJson() { 288 | return { 289 | if (name != null) 'name': name, 290 | 'match': match.pattern, 291 | if (captures != null) 'captures': captures, 292 | }; 293 | } 294 | } 295 | 296 | class _MultilineMatcher extends GrammarMatcher { 297 | _MultilineMatcher(Map json) 298 | : begin = RegExp(json['begin'] as String, multiLine: true), 299 | beginCaptures = json['beginCaptures'] as Map?, 300 | contentName = json['contentName'] as String?, 301 | end = json['end'] == null 302 | ? null 303 | : RegExp(json['end'] as String, multiLine: true), 304 | endCaptures = json['endCaptures'] as Map?, 305 | captures = json['captures'] as Map?, 306 | whileCond = json['while'] == null 307 | ? null 308 | : RegExp(json['while'] as String, multiLine: true), 309 | patterns = (json['patterns'] as List?) 310 | ?.cast>() 311 | .map((e) => GrammarMatcher.parse(e)) 312 | .toList() 313 | .cast(), 314 | super._(json); 315 | 316 | static bool isType(Map json) { 317 | return json.containsKey('begin') && 318 | (json.containsKey('end') || json.containsKey('while')); 319 | } 320 | 321 | /// A regular expression which defines the beginning match of this rule. This 322 | /// property is required and must be defined along with either `end` or 323 | /// `while`. 324 | final RegExp begin; 325 | 326 | /// A set of scopes to apply to groups captured by `begin`. `captures` should 327 | /// be null if this property is provided. 328 | final Map? beginCaptures; 329 | 330 | /// The scope that applies to the content between the matches found by 331 | /// `begin` and `end`. 332 | final String? contentName; 333 | 334 | /// A regular expression which defines the match signaling the end of the 335 | /// rule application. This property is mutually exclusive with the `while` 336 | /// property. 337 | final RegExp? end; 338 | 339 | /// A set of scopes to apply to groups captured by `begin`. `captures` should 340 | /// be null if this property is provided. 341 | final Map? endCaptures; 342 | 343 | /// A regular expression corresponding with the `while` property used to 344 | /// determine if the next line should have the current rule applied. If 345 | /// `patterns` is provided, the contents of a line that satisfy this regular 346 | /// expression will be processed against the provided patterns. 347 | /// 348 | /// This expression is applied to every line **after** the first line matched 349 | /// by `begin`. If this expression fails after the line matched by `begin`, 350 | /// the overall rule does not fail and the resulting [ScopeSpan]s will consist 351 | /// of matches found in the first line. 352 | /// 353 | /// This property is mutually exclusive with the `end` property. 354 | final RegExp? whileCond; 355 | 356 | /// A set of scopes to apply to groups captured by `begin` and `end`. 357 | /// Providing this property is the equivalent of setting `beginCaptures` and 358 | /// `endCaptures` to the same value. `beginCaptures` and `endCaptures` should 359 | /// be null if this property is provided. 360 | final Map? captures; 361 | 362 | final List? patterns; 363 | 364 | void _scanBegin(Grammar grammar, LineScanner scanner, ScopeStack scopeStack) { 365 | final location = scanner.location; 366 | if (!scanner.scan(begin)) { 367 | // This shouldn't happen since we've already checked that `begin` matches 368 | // the beginning of the string. 369 | throw StateError('Expected ${begin.pattern} to match.'); 370 | } 371 | _processCaptureHelper( 372 | grammar, 373 | scanner, 374 | scopeStack, 375 | beginCaptures, 376 | location, 377 | ); 378 | } 379 | 380 | void _scanToEndOfLine( 381 | Grammar grammar, 382 | LineScanner scanner, 383 | ScopeStack scopeStack, 384 | ) { 385 | while (!scanner.isDone) { 386 | if (String.fromCharCode(scanner.peekChar()!) == '\n') { 387 | scanner.readChar(); 388 | break; 389 | } 390 | bool foundMatch = false; 391 | for (final pattern in patterns ?? []) { 392 | if (pattern.scan(grammar, scanner, scopeStack)) { 393 | foundMatch = true; 394 | break; 395 | } 396 | } 397 | if (!foundMatch) { 398 | scanner.readChar(); 399 | } 400 | } 401 | } 402 | 403 | void _scanUpToEndMatch( 404 | Grammar grammar, 405 | LineScanner scanner, 406 | ScopeStack scopeStack, 407 | ) { 408 | while (!scanner.isDone && end != null && !scanner.matches(end!)) { 409 | bool foundMatch = false; 410 | for (final pattern in patterns ?? []) { 411 | if (pattern.scan(grammar, scanner, scopeStack)) { 412 | foundMatch = true; 413 | break; 414 | } 415 | } 416 | if (!foundMatch) { 417 | // Move forward by a character, try again. 418 | scanner.readChar(); 419 | } 420 | } 421 | } 422 | 423 | void _scanEnd(Grammar grammar, LineScanner scanner, ScopeStack scopeStack) { 424 | final location = scanner.location; 425 | if (end != null && !scanner.scan(end!)) { 426 | return; 427 | } 428 | _processCaptureHelper(grammar, scanner, scopeStack, endCaptures, location); 429 | } 430 | 431 | void _processCaptureHelper( 432 | Grammar grammar, 433 | LineScanner scanner, 434 | ScopeStack scopeStack, 435 | Map? customCaptures, 436 | ScopeStackLocation location, 437 | ) { 438 | if (contentName == null || (customCaptures ?? captures) != null) { 439 | _applyCapture( 440 | grammar, 441 | scanner, 442 | scopeStack, 443 | customCaptures ?? captures, 444 | location, 445 | ); 446 | } 447 | } 448 | 449 | @override 450 | bool scan(Grammar grammar, LineScanner scanner, ScopeStack scopeStack) { 451 | if (!scanner.matches(begin)) { 452 | return false; 453 | } 454 | 455 | scopeStack.push(name, scanner.location); 456 | _scanBegin(grammar, scanner, scopeStack); 457 | if (end != null) { 458 | scopeStack.push(contentName, scanner.location); 459 | _scanUpToEndMatch(grammar, scanner, scopeStack); 460 | scopeStack.pop(contentName, scanner.location); 461 | _scanEnd(grammar, scanner, scopeStack); 462 | } else if (whileCond != null) { 463 | // Find the range of the string that is matched by the while condition. 464 | final start = scanner.position; 465 | _skipLine(scanner); 466 | while (!scanner.isDone && whileCond != null && scanner.scan(whileCond!)) { 467 | _skipLine(scanner); 468 | } 469 | final end = scanner.position; 470 | 471 | // Create a temporary scanner to ensure that rules that don't find an 472 | // end match don't try and match all the way to the end of the file. 473 | final contentScanner = LineScanner( 474 | scanner.substring(0, end), 475 | position: start, 476 | ); 477 | 478 | // Capture a marker for where the contents start, used later to split 479 | // spans. 480 | final whileContentBeginMarker = scopeStack.marker(); 481 | 482 | _scanToEndOfLine(grammar, contentScanner, scopeStack); 483 | 484 | // Process each line until the `while` condition fails. 485 | while (!contentScanner.isDone && 486 | whileCond != null && 487 | contentScanner.scan(whileCond!)) { 488 | _scanToEndOfLine(grammar, contentScanner, scopeStack); 489 | } 490 | 491 | // Now, split any spans produced whileContentBeginMarker by `whileCond`. 492 | scopeStack.splitFromMarker( 493 | scanner, 494 | whileContentBeginMarker, 495 | whileCond!, 496 | ); 497 | } else { 498 | throw StateError( 499 | "One of 'end' or 'while' must be provided for rule: $name", 500 | ); 501 | } 502 | scopeStack.pop(name, scanner.location); 503 | return true; 504 | } 505 | 506 | void _skipLine(LineScanner scanner) { 507 | scanner.scan(RegExp('.*\r?\n')); 508 | } 509 | 510 | @override 511 | Map toJson() { 512 | return { 513 | if (name != null) 'name': name, 514 | 'begin': begin.pattern, 515 | if (beginCaptures != null) 'beginCaptures': beginCaptures, 516 | if (end != null) 'end': end!.pattern, 517 | if (endCaptures != null) 'endCaptures': endCaptures, 518 | if (whileCond != null) 'while': whileCond!.pattern, 519 | if (patterns != null) 520 | 'patterns': patterns!.map((e) => e.toJson()).toList(), 521 | }; 522 | } 523 | } 524 | 525 | class _PatternMatcher extends GrammarMatcher { 526 | _PatternMatcher(Map json) 527 | : patterns = (json['patterns'] as List?) 528 | ?.cast>() 529 | .map((e) => GrammarMatcher.parse(e)) 530 | .toList() 531 | .cast(), 532 | super._(json); 533 | 534 | static bool isType(Map json) { 535 | return json.containsKey('patterns'); 536 | } 537 | 538 | final List? patterns; 539 | 540 | @override 541 | bool scan(Grammar grammar, LineScanner scanner, ScopeStack scopeStack) { 542 | // Try each rule in the include and return after the first successful match. 543 | for (final pattern in patterns!) { 544 | if (pattern.scan(grammar, scanner, scopeStack)) { 545 | return true; 546 | } 547 | } 548 | return false; 549 | } 550 | 551 | @override 552 | Map toJson() { 553 | return { 554 | if (name != null) 'name': name, 555 | if (patterns != null) 556 | 'patterns': patterns!.map((e) => e.toJson()).toList(), 557 | }; 558 | } 559 | } 560 | 561 | /// A [GrammarMatcher] that corresponds to an `include` rule referenced in a 562 | /// `patterns` array. Allows for executing rules defined within a 563 | /// [Repository]. 564 | class _IncludeMatcher extends GrammarMatcher { 565 | _IncludeMatcher(String include) 566 | : include = include.substring(1), 567 | super._({}); 568 | 569 | final String include; 570 | 571 | static bool isType(Map json) { 572 | return json.containsKey('include'); 573 | } 574 | 575 | @override 576 | bool scan(Grammar grammar, LineScanner scanner, ScopeStack scopeStack) { 577 | final matcher = grammar.repository.matchers[include]; 578 | if (matcher == null) { 579 | throw StateError('Could not find $include in the repository.'); 580 | } 581 | return matcher.scan(grammar, scanner, scopeStack); 582 | } 583 | 584 | @override 585 | Map toJson() { 586 | return { 587 | 'include': include, 588 | }; 589 | } 590 | } 591 | 592 | /// Tracks the current scope stack, producing [ScopeSpan]s as the contents 593 | /// change. 594 | class ScopeStack { 595 | ScopeStack(); 596 | 597 | final stack = Queue(); 598 | final spans = []; 599 | 600 | /// Location where the next produced span should begin. 601 | ScopeStackLocation _nextLocation = ScopeStackLocation.zero; 602 | 603 | /// Adds a scope for a given region. 604 | /// 605 | /// This method is the same as calling [push] and then [pop] with the same 606 | /// args. 607 | void add( 608 | String? scope, { 609 | required ScopeStackLocation start, 610 | required ScopeStackLocation end, 611 | }) { 612 | push(scope, start); 613 | pop(scope, end); 614 | } 615 | 616 | /// Pushes a new scope onto the stack starting at [start]. 617 | void push(String? scope, ScopeStackLocation location) { 618 | if (scope == null) return; 619 | 620 | // If the stack is empty, seed the position which is used for the start 621 | // of the next produced token. 622 | if (stack.isEmpty) { 623 | _nextLocation = location; 624 | } 625 | 626 | // Whenever we push a new item, produce a span for the region between the 627 | // last started scope and the new current position. 628 | if (location.position > _nextLocation.position) { 629 | final scopes = stack.map((item) => item.scope).toSet(); 630 | _produceSpan(scopes, end: location); 631 | } 632 | 633 | // Add this new scope to the stack, but don't produce its token yet. We will 634 | // do that when the next item is pushed (in which case we'll fill the gap), 635 | // or when this item is popped (in which case we'll produce a span for that 636 | // full region). 637 | stack.add(ScopeStackItem(scope, location)); 638 | } 639 | 640 | /// Pops the last scope off the stack, producing a token if necessary up until 641 | /// [end]. 642 | void pop(String? scope, ScopeStackLocation end) { 643 | if (scope == null) return; 644 | assert(stack.isNotEmpty); 645 | 646 | final scopes = stack.map((item) => item.scope).toSet(); 647 | final last = stack.removeLast(); 648 | assert(last.scope == scope); 649 | assert(last.location.position <= end.position); 650 | 651 | _produceSpan(scopes, end: end); 652 | } 653 | 654 | void popAll(ScopeStackLocation location) { 655 | while (stack.isNotEmpty) { 656 | pop(stack.last.scope, location); 657 | } 658 | } 659 | 660 | /// Captures a marker to identify spans produced before/after this call. 661 | ScopeStackMarker marker() { 662 | return ScopeStackMarker(spanIndex: spans.length, location: _nextLocation); 663 | } 664 | 665 | /// Splits all spans created since [begin] by [condition]. 666 | /// 667 | /// This is used to handle multiline spans that use begin/end such as 668 | /// capturing triple-backtick code blocks that would have captured the leading 669 | /// '/// ', which should not be included. 670 | void splitFromMarker( 671 | LineScanner scanner, 672 | ScopeStackMarker begin, 673 | RegExp condition, 674 | ) { 675 | // Remove the spans to be split. We will push new spans after splitting. 676 | final spansToSplit = spans.sublist(begin.spanIndex); 677 | if (spansToSplit.isEmpty) return; 678 | spans.removeRange(begin.spanIndex, spans.length); 679 | 680 | // Also rewind the last positions to the start place. 681 | _nextLocation = begin.location; 682 | 683 | // Add the split spans individually. 684 | for (final span in spansToSplit 685 | .expand((spanToSplit) => spanToSplit.split(scanner, condition))) { 686 | // To handler spans with multiple scopes, we need to push each scope, and 687 | // then pop each scope. We cannot use `add`. 688 | for (final scope in span.scopes) { 689 | push(scope, span.startLocation); 690 | } 691 | for (final scope in span.scopes.reversed) { 692 | pop(scope, span.endLocation); 693 | } 694 | } 695 | } 696 | 697 | void _produceSpan( 698 | Set scopes, { 699 | required ScopeStackLocation end, 700 | }) { 701 | // Don't produce zero-width spans. 702 | if (end.position == _nextLocation.position) return; 703 | 704 | // If the new span starts at the same place that the previous one ends and 705 | // has the same scopes, we can replace the previous one with a single new 706 | // larger span. 707 | final newScopes = scopes.toList(); 708 | final lastSpan = spans.lastOrNull; 709 | if (lastSpan != null && 710 | lastSpan.endLocation.position == _nextLocation.position && 711 | lastSpan.scopes.equals(newScopes)) { 712 | final span = ScopeSpan( 713 | scopes: newScopes, 714 | startLocation: lastSpan.startLocation, 715 | endLocation: end, 716 | ); 717 | // Replace the last span with this one. 718 | spans.last = span; 719 | } else { 720 | final span = ScopeSpan( 721 | scopes: newScopes, 722 | startLocation: _nextLocation, 723 | endLocation: end, 724 | ); 725 | spans.add(span); 726 | } 727 | _nextLocation = end; 728 | } 729 | } 730 | 731 | /// An item pushed onto the scope stack, consisting of a [String] scope and a 732 | /// location. 733 | class ScopeStackItem { 734 | ScopeStackItem(this.scope, this.location); 735 | 736 | final String scope; 737 | final ScopeStackLocation location; 738 | } 739 | 740 | /// A marker tracking a position in the list of produced tokens. 741 | /// 742 | /// Used for back-tracking when handling nested multiline tokens. 743 | class ScopeStackMarker { 744 | ScopeStackMarker({ 745 | required this.spanIndex, 746 | required this.location, 747 | }); 748 | 749 | final int spanIndex; 750 | final ScopeStackLocation location; 751 | } 752 | 753 | /// A location (including offset, line, column) in the code parsed for scopes. 754 | class ScopeStackLocation { 755 | const ScopeStackLocation({ 756 | required this.position, 757 | required this.line, 758 | required this.column, 759 | }); 760 | 761 | static const zero = ScopeStackLocation(position: 0, line: 0, column: 0); 762 | 763 | /// 0-based offset in content. 764 | final int position; 765 | 766 | /// 0-based line number of [position]. 767 | final int line; 768 | 769 | /// 0-based column number of [position]. 770 | final int column; 771 | 772 | /// Returns a location offset by [offset] characters. 773 | /// 774 | /// This method does not handle line wrapping so should only be used where it 775 | /// is known that the offset does not wrap across a line boundary. 776 | ScopeStackLocation offset(int offset) { 777 | return ScopeStackLocation( 778 | position: position + offset, 779 | line: line, 780 | column: column + offset, 781 | ); 782 | } 783 | } 784 | 785 | extension LineScannerExtension on LineScanner { 786 | ScopeStackLocation get location => 787 | ScopeStackLocation(position: position, line: line, column: column); 788 | } 789 | --------------------------------------------------------------------------------