| // Copyright (c) 2024, 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:_fe_analyzer_shared/src/scanner/token.dart' |
| show |
| Keyword, |
| // ignore: unused_shown_name |
| SimpleToken, // Used for DartDocTest. |
| // ignore: unused_shown_name |
| StringToken, // Used for DartDocTest. |
| Token, |
| // ignore: unused_shown_name |
| TokenType; // Used for DartDocTest. |
| |
| const int _abstractMask = 1; |
| |
| const int _augmentMask = _abstractMask << 1; |
| |
| const int _constMask = _augmentMask << 1; |
| |
| const int _covariantMask = _constMask << 1; |
| |
| const int _externalMask = _covariantMask << 1; |
| |
| const int _finalMask = _externalMask << 1; |
| |
| const int _staticMask = _finalMask << 1; |
| |
| const int _lateMask = _staticMask << 1; |
| |
| const int _requiredMask = _lateMask << 1; |
| |
| const int _macroMask = _requiredMask << 1; |
| |
| const int _sealedMask = _macroMask << 1; |
| |
| const int _baseMask = _sealedMask << 1; |
| |
| const int _interfaceMask = _baseMask << 1; |
| |
| const int _mixinMask = _interfaceMask << 1; |
| |
| const int _namedMixinApplicationMask = _mixinMask << 1; |
| |
| /// Not a modifier, used by fields to track if they have an initializer. |
| const int _hasInitializerMask = _namedMixinApplicationMask << 1; |
| |
| /// Not a modifier, used by formal parameters to track if they are initializing. |
| const int _initializingFormalMask = _hasInitializerMask << 1; |
| |
| /// Not a modifier, used by classes to track if the class declares a const |
| /// constructor. |
| const int _declaresConstConstructorMask = _initializingFormalMask << 1; |
| |
| /// Not a modifier, used by formal parameters to track if they are |
| /// super-parameter initializers. |
| const int _superInitializingFormalMask = _declaresConstConstructorMask << 1; |
| |
| /// Extension type that encodes a set of modifiers as a bit mask. |
| extension type const Modifiers(int _mask) implements Object { |
| /// The empty set of modifiers. |
| static const Modifiers empty = const Modifiers(0); |
| |
| // Coverage-ignore(suite): Not run. |
| /// Returns `true` if the set of modifiers is empty. |
| bool get isEmpty => _mask == 0; |
| |
| /// Returns the [Modifiers] that is the union between the modifiers in this |
| /// and [other]. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.empty | Modifiers.empty, Modifiers.empty) |
| /// DartDocTest((Modifiers.Final | Modifiers.Covariant).isFinal, true) |
| /// DartDocTest((Modifiers.Final | Modifiers.Covariant).isCovariant, true) |
| /// ``` |
| Modifiers operator |(Modifiers other) { |
| return new Modifiers(_mask | other._mask); |
| } |
| |
| /// Returns the [Modifiers] that removes the modifiers in [other] from this |
| /// set of modifiers. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Final - Modifiers.Final, Modifiers.empty) |
| /// DartDocTest(Modifiers.Final - Modifiers.empty, Modifiers.Final) |
| /// DartDocTest(Modifiers.Final - Modifiers.Const, Modifiers.Final) |
| /// ``ยด |
| Modifiers operator -(Modifiers other) { |
| return new Modifiers(_mask & ~other._mask); |
| } |
| |
| /// Creates a [Modifiers] using the provided [Token]s. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.from().isEmpty, true) |
| /// DartDocTest(Modifiers.from().isAbstract, false) |
| /// DartDocTest(Modifiers.from().isAugment, false) |
| /// |
| /// DartDocTest(Modifiers.from( |
| /// abstractToken: new SimpleToken(Keyword.ABSTRACT, -1)), |
| /// Modifiers.Abstract) |
| /// DartDocTest(Modifiers.from( |
| /// augmentToken: new SimpleToken(Keyword.AUGMENT, -1)), |
| /// Modifiers.Augment) |
| /// DartDocTest(Modifiers.from( |
| /// baseToken: new SimpleToken(Keyword.BASE, -1)), |
| /// Modifiers.Base) |
| /// DartDocTest(Modifiers.from( |
| /// covariantToken: new SimpleToken(Keyword.COVARIANT, -1)), |
| /// Modifiers.Covariant) |
| /// DartDocTest(Modifiers.from( |
| /// constToken: new SimpleToken(Keyword.CONST, -1)), |
| /// Modifiers.Const) |
| /// DartDocTest(Modifiers.from( |
| /// externalToken: new SimpleToken(Keyword.EXTERNAL, -1)), |
| /// Modifiers.External) |
| /// DartDocTest(Modifiers.from( |
| /// finalToken: new SimpleToken(Keyword.FINAL, -1)), |
| /// Modifiers.Final) |
| /// DartDocTest(Modifiers.from( |
| /// interfaceToken: new SimpleToken(Keyword.INTERFACE, -1)), |
| /// Modifiers.Interface) |
| /// DartDocTest(Modifiers.from( |
| /// lateToken: new SimpleToken(Keyword.LATE, -1)), |
| /// Modifiers.Late) |
| /// DartDocTest(Modifiers.from( |
| /// macroToken: new StringToken(TokenType.IDENTIFIER, 'macro', -1)), |
| /// Modifiers.Macro) |
| /// DartDocTest(Modifiers.from( |
| /// mixinToken: new SimpleToken(Keyword.MIXIN, -1)), |
| /// Modifiers.Mixin) |
| /// DartDocTest(Modifiers.from( |
| /// requiredToken: new SimpleToken(Keyword.REQUIRED, -1)), |
| /// Modifiers.Required) |
| /// DartDocTest(Modifiers.from( |
| /// sealedToken: new SimpleToken(Keyword.SEALED, -1)), |
| /// Modifiers.Sealed) |
| /// DartDocTest(Modifiers.from( |
| /// staticToken: new SimpleToken(Keyword.STATIC, -1)), |
| /// Modifiers.Static) |
| /// |
| /// DartDocTest(Modifiers.from( |
| /// varFinalOrConst: new SimpleToken(Keyword.VAR, -1)), |
| /// Modifiers.empty) |
| /// DartDocTest(Modifiers.from( |
| /// varFinalOrConst: new SimpleToken(Keyword.FINAL, -1)), |
| /// Modifiers.Final) |
| /// DartDocTest(Modifiers.from( |
| /// varFinalOrConst: new SimpleToken(Keyword.CONST, -1)), |
| /// Modifiers.Const) |
| /// DartDocTestThrow(Modifiers.from( |
| /// varFinalOrConst: new SimpleToken(Keyword.STATIC, -1))) |
| /// |
| /// DartDocTest(Modifiers.from( |
| /// finalToken: new SimpleToken(Keyword.FINAL, -1), |
| /// staticToken: new SimpleToken(Keyword.STATIC, -1)), |
| /// Modifiers.Final | Modifiers.Static) |
| /// ``` |
| static Modifiers from( |
| {Token? abstractToken, |
| Token? augmentToken, |
| Token? baseToken, |
| Token? covariantToken, |
| Token? constToken, |
| Token? externalToken, |
| Token? finalToken, |
| Token? interfaceToken, |
| Token? lateToken, |
| Token? macroToken, |
| Token? mixinToken, |
| Token? requiredToken, |
| Token? sealedToken, |
| Token? staticToken, |
| Token? varFinalOrConst}) { |
| assert(abstractToken == null || abstractToken.type == Keyword.ABSTRACT); |
| assert(augmentToken == null || |
| // Coverage-ignore(suite): Not run. |
| augmentToken.type == Keyword.AUGMENT); |
| assert(baseToken == null || baseToken.type == Keyword.BASE); |
| assert(covariantToken == null || covariantToken.type == Keyword.COVARIANT); |
| assert(constToken == null || constToken.type == Keyword.CONST); |
| assert(finalToken == null || finalToken.type == Keyword.FINAL); |
| assert(interfaceToken == null || interfaceToken.type == Keyword.INTERFACE); |
| assert(lateToken == null || lateToken.type == Keyword.LATE); |
| assert(macroToken == null || |
| // Coverage-ignore(suite): Not run. |
| macroToken.lexeme == 'macro'); |
| assert(mixinToken == null || mixinToken.type == Keyword.MIXIN); |
| assert(requiredToken == null || requiredToken.type == Keyword.REQUIRED); |
| assert(sealedToken == null || sealedToken.type == Keyword.SEALED); |
| assert(staticToken == null || staticToken.type == Keyword.STATIC); |
| |
| int mask = (abstractToken != null ? _abstractMask : 0) | |
| (augmentToken != null ? _augmentMask : 0) | |
| (baseToken != null ? _baseMask : 0) | |
| (covariantToken != null ? _covariantMask : 0) | |
| (constToken != null ? _constMask : 0) | |
| (externalToken != null ? _externalMask : 0) | |
| (finalToken != null ? _finalMask : 0) | |
| (interfaceToken != null ? _interfaceMask : 0) | |
| (lateToken != null ? _lateMask : 0) | |
| (macroToken != null ? _macroMask : 0) | |
| (mixinToken != null ? _mixinMask : 0) | |
| (requiredToken != null ? _requiredMask : 0) | |
| (sealedToken != null ? _sealedMask : 0) | |
| (staticToken != null ? _staticMask : 0); |
| if (varFinalOrConst != null) { |
| mask |= switch (varFinalOrConst.type) { |
| Keyword.CONST => _constMask, |
| Keyword.FINAL => _finalMask, |
| Keyword.VAR => 0, |
| _ => // Coverage-ignore(suite): Not run. |
| throw new UnsupportedError( |
| "Unexpected varFinalOrConst token $varFinalOrConst."), |
| }; |
| } |
| return new Modifiers(mask); |
| } |
| |
| /// The set of modifiers containing only `abstract`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Abstract.isAbstract, true) |
| /// DartDocTest(Modifiers.Abstract.isEmpty, false) |
| /// DartDocTest(Modifiers.Abstract.isAugment, false) |
| /// ``` |
| static const Modifiers Abstract = const Modifiers(_abstractMask); |
| |
| /// Returns `true` if the set of modifiers contains `abstract'. |
| bool get isAbstract => (_mask & _abstractMask) != 0; |
| |
| /// The set of modifiers containing only `augment`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Augment.isAugment, true) |
| /// DartDocTest(Modifiers.Augment.isEmpty, false) |
| /// DartDocTest(Modifiers.Augment.isConst, false) |
| /// ``` |
| static const Modifiers Augment = const Modifiers(_augmentMask); |
| |
| /// Returns `true` if the set of modifiers contains `augment'. |
| bool get isAugment => (_mask & _augmentMask) != 0; |
| |
| /// The set of modifiers containing only `const`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Const.isConst, true) |
| /// DartDocTest(Modifiers.Const.isEmpty, false) |
| /// DartDocTest(Modifiers.Const.isCovariant, false) |
| /// ``` |
| static const Modifiers Const = const Modifiers(_constMask); |
| |
| /// Returns `true` if the set of modifiers contains `const'. |
| bool get isConst => (_mask & _constMask) != 0; |
| |
| /// The set of modifiers containing only `covariant`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Covariant.isCovariant, true) |
| /// DartDocTest(Modifiers.Covariant.isEmpty, false) |
| /// DartDocTest(Modifiers.Covariant.isExternal, false) |
| /// ``` |
| static const Modifiers Covariant = const Modifiers(_covariantMask); |
| |
| /// Returns `true` if the set of modifiers contains `covariant'. |
| bool get isCovariant => (_mask & _covariantMask) != 0; |
| |
| /// The set of modifiers containing only `external`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.External.isExternal, true) |
| /// DartDocTest(Modifiers.External.isEmpty, false) |
| /// DartDocTest(Modifiers.External.isFinal, false) |
| /// ``` |
| static const Modifiers External = const Modifiers(_externalMask); |
| |
| /// Returns `true` if the set of modifiers contains `external'. |
| bool get isExternal => (_mask & _externalMask) != 0; |
| |
| /// The set of modifiers containing only `final`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Final.isFinal, true) |
| /// DartDocTest(Modifiers.Final.isEmpty, false) |
| /// DartDocTest(Modifiers.Final.isStatic, false) |
| /// ``` |
| static const Modifiers Final = const Modifiers(_finalMask); |
| |
| /// Returns `true` if the set of modifiers contains `final'. |
| bool get isFinal => (_mask & _finalMask) != 0; |
| |
| /// The set of modifiers containing only `static`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Static.isStatic, true) |
| /// DartDocTest(Modifiers.Static.isEmpty, false) |
| /// DartDocTest(Modifiers.Static.isLate, false) |
| /// ``` |
| static const Modifiers Static = const Modifiers(_staticMask); |
| |
| /// Returns `true` if the set of modifiers contains `static'. |
| bool get isStatic => (_mask & _staticMask) != 0; |
| |
| /// The set of modifiers containing only `late`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Late.isLate, true) |
| /// DartDocTest(Modifiers.Late.isEmpty, false) |
| /// DartDocTest(Modifiers.Late.isRequired, false) |
| /// ``` |
| static const Modifiers Late = const Modifiers(_lateMask); |
| |
| /// Returns `true` if the set of modifiers contains `late'. |
| bool get isLate => (_mask & _lateMask) != 0; |
| |
| /// The set of modifiers containing only `required`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Required.isRequired, true) |
| /// DartDocTest(Modifiers.Required.isEmpty, false) |
| /// DartDocTest(Modifiers.Required.isMacro, false) |
| /// ``` |
| static const Modifiers Required = const Modifiers(_requiredMask); |
| |
| /// Returns `true` if the set of modifiers contains `required'. |
| bool get isRequired => (_mask & _requiredMask) != 0; |
| |
| /// The set of modifiers containing only `macro`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Macro.isMacro, true) |
| /// DartDocTest(Modifiers.Macro.isEmpty, false) |
| /// DartDocTest(Modifiers.Macro.isSealed, false) |
| /// ``` |
| static const Modifiers Macro = const Modifiers(_macroMask); |
| |
| // Coverage-ignore(suite): Not run. |
| /// Returns `true` if the set of modifiers contains `macro'. |
| bool get isMacro => (_mask & _macroMask) != 0; |
| |
| /// The set of modifiers containing only `sealed`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Sealed.isSealed, true) |
| /// DartDocTest(Modifiers.Sealed.isEmpty, false) |
| /// DartDocTest(Modifiers.Sealed.isBase, false) |
| /// ``` |
| static const Modifiers Sealed = const Modifiers(_sealedMask); |
| |
| /// Returns `true` if the set of modifiers contains `sealed'. |
| bool get isSealed => (_mask & _sealedMask) != 0; |
| |
| /// The set of modifiers containing only `base`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Base.isBase, true) |
| /// DartDocTest(Modifiers.Base.isEmpty, false) |
| /// DartDocTest(Modifiers.Base.isInterface, false) |
| /// ``` |
| static const Modifiers Base = const Modifiers(_baseMask); |
| |
| /// Returns `true` if the set of modifiers contains `base'. |
| bool get isBase => (_mask & _baseMask) != 0; |
| |
| /// The set of modifiers containing only `interface`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Interface.isInterface, true) |
| /// DartDocTest(Modifiers.Interface.isEmpty, false) |
| /// DartDocTest(Modifiers.Interface.isMixin, false) |
| /// ``` |
| static const Modifiers Interface = const Modifiers(_interfaceMask); |
| |
| /// Returns `true` if the set of modifiers contains `interface'. |
| bool get isInterface => (_mask & _interfaceMask) != 0; |
| |
| /// The set of modifiers containing only `mixin`. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.Mixin.isMixin, true) |
| /// DartDocTest(Modifiers.Mixin.isEmpty, false) |
| /// DartDocTest(Modifiers.Mixin.isNamedMixinApplication, false) |
| /// ``` |
| static const Modifiers Mixin = const Modifiers(_mixinMask); |
| |
| /// Returns `true` if the set of modifiers contains `mixin'. |
| bool get isMixin => (_mask & _mixinMask) != 0; |
| |
| /// The set of modifiers containing only the synthetic modifier used to denote |
| /// that a class is a named mixin application. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.NamedMixinApplication.isNamedMixinApplication, true) |
| /// DartDocTest(Modifiers.NamedMixinApplication.isEmpty, false) |
| /// DartDocTest(Modifiers.NamedMixinApplication.hasInitializer, false) |
| /// ``` |
| static const Modifiers NamedMixinApplication = |
| const Modifiers(_namedMixinApplicationMask); |
| |
| /// Returns `true` if the set of modifiers contains the synthetic modifier |
| /// used to denote that a class is a named mixin application. |
| bool get isNamedMixinApplication => (_mask & _namedMixinApplicationMask) != 0; |
| |
| /// The set of modifiers containing only the synthetic modifier used to denote |
| /// that a field or variable has an explicit initializer. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.HasInitializer.hasInitializer, true) |
| /// DartDocTest(Modifiers.HasInitializer.isEmpty, false) |
| /// DartDocTest(Modifiers.HasInitializer.isInitializingFormal, false) |
| /// ``` |
| static const Modifiers HasInitializer = const Modifiers(_hasInitializerMask); |
| |
| /// Returns `true` if the set of modifiers contains the synthetic modifier |
| /// used to denote that a field or variable has an explicit initializer. |
| bool get hasInitializer => (_mask & _hasInitializerMask) != 0; |
| |
| /// The set of modifiers containing only the synthetic modifier used to denote |
| /// that a parameter is an initializing formal. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.InitializingFormal.isInitializingFormal, true) |
| /// DartDocTest(Modifiers.InitializingFormal.isEmpty, false) |
| /// DartDocTest(Modifiers.InitializingFormal.declaresConstConstructor, false) |
| /// ``` |
| static const Modifiers InitializingFormal = |
| const Modifiers(_initializingFormalMask); |
| |
| /// Returns `true` if the set of modifiers contains the synthetic modifier |
| /// used to denote that a parameter is an initializing formal. |
| bool get isInitializingFormal => (_mask & _initializingFormalMask) != 0; |
| |
| /// The set of modifiers containing only the synthetic modifier used to denote |
| /// that a declaration declares a const constructor. |
| /// |
| /// ``` |
| /// DartDocTest( |
| /// Modifiers.DeclaresConstConstructor.declaresConstConstructor, true) |
| /// DartDocTest(Modifiers.DeclaresConstConstructor.isEmpty, false) |
| /// DartDocTest( |
| /// Modifiers.DeclaresConstConstructor.isSuperInitializingFormal, false) |
| /// ``` |
| static const Modifiers DeclaresConstConstructor = |
| const Modifiers(_declaresConstConstructorMask); |
| |
| /// Returns `true` if the set of modifiers contains the synthetic modifier |
| /// used to denote that a declaration declares a const constructor. |
| bool get declaresConstConstructor => |
| (_mask & _declaresConstConstructorMask) != 0; |
| |
| /// The set of modifiers containing only the synthetic modifier used to denote |
| /// that a parameter is a super initializing formal. |
| /// |
| /// ``` |
| /// DartDocTest( |
| /// Modifiers.SuperInitializingFormal.isSuperInitializingFormal, true) |
| /// DartDocTest(Modifiers.SuperInitializingFormal.isEmpty, false) |
| /// DartDocTest(Modifiers.SuperInitializingFormal.isAbstract, false) |
| /// ``` |
| static const Modifiers SuperInitializingFormal = |
| const Modifiers(_superInitializingFormalMask); |
| |
| /// Returns `true` if the set of modifiers contains the synthetic modifier |
| /// used to denote that a parameter is a super initializing formal. |
| bool get isSuperInitializingFormal => |
| (_mask & _superInitializingFormalMask) != 0; |
| |
| /// Returns `true` if this set of modifiers contains any syntactic modifiers. |
| /// |
| /// If [ignoreRequired] is `true`, `required` is ignored. If |
| /// [ignoreCovariant] is `true`, `covariant` is ignored. |
| /// |
| /// This ignores synthetic modifiers like [HasInitializer] and |
| /// [InitializingFormal]. |
| /// |
| /// ``` |
| /// DartDocTest(Modifiers.empty.containsSyntacticModifiers(), false) |
| /// |
| /// DartDocTest(Modifiers.Required.containsSyntacticModifiers(), true) |
| /// DartDocTest( |
| /// Modifiers.Required.containsSyntacticModifiers(ignoreRequired: true), |
| /// false) |
| /// |
| /// DartDocTest(Modifiers.Covariant.containsSyntacticModifiers(), true) |
| /// DartDocTest( |
| /// Modifiers.Covariant.containsSyntacticModifiers(ignoreCovariant: true), |
| /// false) |
| /// |
| /// DartDocTest(Modifiers.Abstract.containsSyntacticModifiers(), true) |
| /// DartDocTest(Modifiers.Augment.containsSyntacticModifiers(), true) |
| /// DartDocTest(Modifiers.Base.containsSyntacticModifiers(), true) |
| /// DartDocTest(Modifiers.Const.containsSyntacticModifiers(), true) |
| /// DartDocTest( |
| /// Modifiers.DeclaresConstConstructor.containsSyntacticModifiers(), |
| /// false) |
| /// DartDocTest(Modifiers.External.containsSyntacticModifiers(), true) |
| /// DartDocTest(Modifiers.Final.containsSyntacticModifiers(), true) |
| /// DartDocTest(Modifiers.HasInitializer.containsSyntacticModifiers(), false) |
| /// DartDocTest( |
| /// Modifiers.InitializingFormal.containsSyntacticModifiers(), false) |
| /// DartDocTest(Modifiers.Interface.containsSyntacticModifiers(), true) |
| /// DartDocTest(Modifiers.Late.containsSyntacticModifiers(), true) |
| /// DartDocTest(Modifiers.Macro.containsSyntacticModifiers(), true) |
| /// DartDocTest(Modifiers.Mixin.containsSyntacticModifiers(), true) |
| /// DartDocTest( |
| /// Modifiers.NamedMixinApplication.containsSyntacticModifiers(), false) |
| /// DartDocTest(Modifiers.Sealed.containsSyntacticModifiers(), true) |
| /// DartDocTest(Modifiers.Static.containsSyntacticModifiers(), true) |
| /// DartDocTest( |
| /// Modifiers.SuperInitializingFormal.containsSyntacticModifiers(), false) |
| /// ``` |
| bool containsSyntacticModifiers( |
| {bool ignoreRequired = false, bool ignoreCovariant = false}) { |
| int mask = _mask & |
| ~(_hasInitializerMask | |
| _initializingFormalMask | |
| _declaresConstConstructorMask | |
| _namedMixinApplicationMask | |
| _superInitializingFormalMask); |
| if (ignoreRequired) { |
| mask &= ~_requiredMask; |
| } |
| if (ignoreCovariant) { |
| mask &= ~_covariantMask; |
| } |
| return mask != 0; |
| } |
| } |