| // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'package:built_value/built_value.dart'; | |
| import 'package:collection/collection.dart'; | |
| import 'package:meta/meta.dart'; | |
| import '../base.dart'; | |
| import '../visitors.dart'; | |
| part 'directive.g.dart'; | |
| @immutable | |
| abstract class Directive | |
| implements Built<Directive, DirectiveBuilder>, Spec, Comparable<Directive> { | |
| factory Directive([void Function(DirectiveBuilder) updates]) = _$Directive; | |
| factory Directive.import( | |
| String url, { | |
| String? as, | |
| List<String> show = const [], | |
| List<String> hide = const [], | |
| }) => Directive( | |
| (builder) => builder | |
| ..as = as | |
| ..type = DirectiveType.import | |
| ..url = url | |
| ..show.addAll(show) | |
| ..hide.addAll(hide), | |
| ); | |
| factory Directive.importDeferredAs( | |
| String url, | |
| String as, { | |
| List<String> show = const [], | |
| List<String> hide = const [], | |
| }) => Directive( | |
| (builder) => builder | |
| ..as = as | |
| ..type = DirectiveType.import | |
| ..url = url | |
| ..deferred = true | |
| ..show.addAll(show) | |
| ..hide.addAll(hide), | |
| ); | |
| factory Directive.export( | |
| String url, { | |
| List<String> show = const [], | |
| List<String> hide = const [], | |
| }) => Directive( | |
| (builder) => builder | |
| ..type = DirectiveType.export | |
| ..url = url | |
| ..show.addAll(show) | |
| ..hide.addAll(hide), | |
| ); | |
| factory Directive.part(String url) => Directive( | |
| (builder) => builder | |
| ..type = DirectiveType.part | |
| ..url = url, | |
| ); | |
| factory Directive.partOf(String url) => Directive( | |
| (builder) => builder | |
| ..type = DirectiveType.partOf | |
| ..url = url, | |
| ); | |
| Directive._(); | |
| String? get as; | |
| String get url; | |
| DirectiveType get type; | |
| List<String> get show; | |
| List<String> get hide; | |
| bool get deferred; | |
| @override | |
| R accept<R>(SpecVisitor<R> visitor, [R? context]) => | |
| visitor.visitDirective(this, context); | |
| @override | |
| int compareTo(Directive other) => _compareDirectives(this, other); | |
| } | |
| abstract class DirectiveBuilder | |
| implements Builder<Directive, DirectiveBuilder> { | |
| factory DirectiveBuilder() = _$DirectiveBuilder; | |
| DirectiveBuilder._(); | |
| bool deferred = false; | |
| String? as; | |
| String? url; | |
| List<String> show = <String>[]; | |
| List<String> hide = <String>[]; | |
| DirectiveType? type; | |
| } | |
| enum DirectiveType { import, export, part, partOf } | |
| /// Sort import URIs represented by [a] and [b] to honor the | |
| /// "Effective Dart" ordering rules which are enforced by the | |
| /// `directives_ordering` lint. | |
| /// | |
| /// 1. `import`s before `export`s | |
| /// 2. `dart:` | |
| /// 3. `package:` | |
| /// 4. relative | |
| /// 5. `part`s | |
| int _compareDirectives(Directive a, Directive b) { | |
| // NOTE: using the fact that `import` is before `export` in the | |
| // `DirectiveType` enum – which allows us to compare using `indexOf`. | |
| var value = DirectiveType.values | |
| .indexOf(a.type) | |
| .compareTo(DirectiveType.values.indexOf(b.type)); | |
| if (value == 0) { | |
| final uriA = Uri.parse(a.url); | |
| final uriB = Uri.parse(b.url); | |
| if (uriA.hasScheme) { | |
| if (uriB.hasScheme) { | |
| // If both import URIs have schemes, compare them based on scheme | |
| // `dart` will sort before `package` which is what we want | |
| // schemes are case-insensitive, so compare accordingly | |
| value = compareAsciiLowerCase(uriA.scheme, uriB.scheme); | |
| } else { | |
| value = -1; | |
| } | |
| } else if (uriB.hasScheme) { | |
| value = 1; | |
| } | |
| // If both schemes are the same, compare based on path | |
| if (value == 0) { | |
| value = compareAsciiLowerCase(uriA.path, uriB.path); | |
| } | |
| assert((value == 0) == (a.url == b.url)); | |
| } | |
| return value; | |
| } |