Skip to content

Support changes for induced modifiers in analyzer #3371

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
670 changes: 336 additions & 334 deletions lib/resources/docs.dart.js

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions lib/resources/docs.dart.js.map

Large diffs are not rendered by default.

44 changes: 22 additions & 22 deletions lib/src/generator/templates.runtime_renderers.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6807,6 +6807,20 @@ class _Renderer_InheritingContainer extends RendererBase<InheritingContainer> {
_render_Field(e, ast, r.template, sink, parent: r));
},
),
'containerModifiers': Property(
getValue: (CT_ c) => c.containerModifiers,
renderVariable: (CT_ c, Property<CT_> self,
List<String> remainingNames) =>
self.renderSimpleVariable(
c, remainingNames, 'List<ContainerModifier>'),
renderIterable: (CT_ c, RendererBase<CT_> r,
List<MustachioNode> ast, StringSink sink) {
return c.containerModifiers.map((e) => renderSimple(
e, ast, r.template, sink,
parent: r,
getters: _invisibleGetters['ContainerModifier']!));
},
),
'declaredFields': Property(
getValue: (CT_ c) => c.declaredFields,
renderVariable: (CT_ c, Property<CT_> self,
Expand Down Expand Up @@ -7092,28 +7106,6 @@ class _Renderer_InheritingContainer extends RendererBase<InheritingContainer> {
parent: r);
},
),
'modifiers': Property(
getValue: (CT_ c) => c.modifiers,
renderVariable:
(CT_ c, Property<CT_> self, List<String> remainingNames) {
if (remainingNames.isEmpty) {
return self.getValue(c).toString();
}
var name = remainingNames.first;
var nextProperty =
_Renderer_String.propertyMap().getValue(name);
return nextProperty.renderVariable(
self.getValue(c) as String,
nextProperty,
[...remainingNames.skip(1)]);
},
isNullValue: (CT_ c) => false,
renderValue: (CT_ c, RendererBase<CT_> r,
List<MustachioNode> ast, StringSink sink) {
_render_String(c.modifiers, ast, r.template, sink,
parent: r);
},
),
'publicInheritedFields': Property(
getValue: (CT_ c) => c.publicInheritedFields,
renderVariable: (CT_ c, Property<CT_> self,
Expand Down Expand Up @@ -15847,6 +15839,14 @@ const _invisibleGetters = {
'returnType',
'runtimeType'
},
'ContainerModifier': {
'displayName',
'hashCode',
'hideIfPresent',
'name',
'order',
'runtimeType'
},
'Context': {'current', 'hashCode', 'runtimeType', 'separator', 'style'},
'DartType': {
'alias',
Expand Down
6 changes: 3 additions & 3 deletions lib/src/model/class.dart
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class Class extends InheritingContainer
bool get isAbstract => element.isAbstract;

@override
bool get isBase => element.isBase;
bool get isBase => element.isBase && !element.isSealed;

bool get isErrorOrException {
bool isError(InterfaceElement element) =>
Expand All @@ -64,10 +64,10 @@ class Class extends InheritingContainer
}

@override
bool get isFinal => element.isFinal;
bool get isFinal => element.isFinal && !element.isSealed;

@override
bool get isInterface => element.isInterface;
bool get isInterface => element.isInterface && !element.isSealed;

@override
bool get isMixinClass => element.isMixinClass;
Expand Down
50 changes: 50 additions & 0 deletions lib/src/model/container_modifiers.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Copyright (c) 2023, 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:collection/collection.dart' show IterableExtension;

/// Represents a single modifier applicable to containers.
class ContainerModifier implements Comparable<ContainerModifier> {
final String name;
final String displayName;

/// If this modifier is present with any of these modifiers, it should
/// not be displayed as part of a fullKind prefix.
final Set<ContainerModifier> hideIfPresent;

/// The display order of this modifier.
final int order;
const ContainerModifier._(
this.name, {
required this.order,
String? displayName,
Set<ContainerModifier>? hideIfPresent,
}) : displayName = displayName ?? name,
hideIfPresent = hideIfPresent ?? const <ContainerModifier>{};

@override
String toString() => displayName;

@override
int compareTo(ContainerModifier a) => order.compareTo(a.order);

static const ContainerModifier sealed =
ContainerModifier._('sealed', order: 0);
static const ContainerModifier abstract =
ContainerModifier._('abstract', order: 0, hideIfPresent: {sealed});
static const ContainerModifier base = ContainerModifier._('base', order: 1);
static const ContainerModifier interface =
ContainerModifier._('interface', order: 2);
static const ContainerModifier finalModifier =
ContainerModifier._('final', order: 3);
static const ContainerModifier mixin = ContainerModifier._('mixin', order: 4);
}

extension ContainerModifiers on Iterable<ContainerModifier> {
/// Returns a string suitable for prefixing the class name in Dartdoc
/// title bars based on given modifiers.
String modifiersAsFullKindPrefix() => sorted((a, b) => a.compareTo(b))
.where((m) => !m.hideIfPresent.any(contains))
.join(' ');
}
23 changes: 11 additions & 12 deletions lib/src/model/inheriting_container.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:analyzer/dart/element/type.dart';
import 'package:collection/collection.dart' show IterableExtension;
import 'package:dartdoc/src/element_type.dart';
import 'package:dartdoc/src/model/comment_referable.dart';
import 'package:dartdoc/src/model/container_modifiers.dart';
import 'package:dartdoc/src/model/extension_target.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/model_utils.dart' as model_utils;
Expand Down Expand Up @@ -86,16 +87,14 @@ abstract class InheritingContainer extends Container
/// Class modifiers from the Dart feature specification.
///
/// These apply to or have some meaning for [Class]es and [Mixin]s.
late String modifiers = [
if (isSealed) 'sealed' else if (isAbstract) 'abstract',
if (isBase)
'base'
else if (isInterface)
'interface'
else if (isFinal)
'final',
if (isMixinClass) 'mixin',
].join(' ');
late List<ContainerModifier> containerModifiers = [
if (isAbstract) ContainerModifier.abstract,
if (isSealed) ContainerModifier.sealed,
if (isBase) ContainerModifier.base,
if (isInterface) ContainerModifier.interface,
if (isFinal) ContainerModifier.finalModifier,
if (isMixinClass) ContainerModifier.mixin,
];

late final List<ModelElement> _allModelElements = [
...super.allModelElements,
Expand Down Expand Up @@ -269,8 +268,8 @@ abstract class InheritingContainer extends Container
Library get enclosingElement => library;

String get fullkind {
if (modifiers.isNotEmpty) {
return '$modifiers $kind';
if (containerModifiers.isNotEmpty) {
return '${containerModifiers.modifiersAsFullKindPrefix()} $kind';
}
return kind;
}
Expand Down
46 changes: 46 additions & 0 deletions test/class_modifiers_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,50 @@ base mixin O {}
expect(Nmixin.fullkind, equals('mixin'));
expect(Omixin.fullkind, equals('base mixin'));
}

void test_abstractSealed() async {
var library = await bootPackageWithLibrary('''
abstract class A {}
sealed class B extends A {}
''');
var Bclass = library.classes.named('B');
expect(Bclass.fullkind, equals('sealed class')); // *not* sealed abstract
}

void test_inferredModifiers() async {
var library = await bootPackageWithLibrary('''
base class A {}
sealed class B extends A {}
base class C extends B {}

interface class D {}
sealed class E extends D {}
interface class F extends E {}

final class G {}
sealed class H extends G {}
final class I extends H {}

class J {}
base mixin K on J {}
sealed class L extends J with K {}
base class M extends L {}
''');
var Bclass = library.classes.named('B');
var Cclass = library.classes.named('C');
var Eclass = library.classes.named('E');
var Fclass = library.classes.named('F');
var Hclass = library.classes.named('H');
var Iclass = library.classes.named('I');
var Lclass = library.classes.named('L');
var Mclass = library.classes.named('M');
expect(Bclass.fullkind, equals('sealed class')); // *not* sealed base
expect(Cclass.fullkind, equals('base class'));
expect(Eclass.fullkind, equals('sealed class'));
expect(Fclass.fullkind, equals('interface class'));
expect(Hclass.fullkind, equals('sealed class'));
expect(Iclass.fullkind, equals('final class'));
expect(Lclass.fullkind, equals('sealed class'));
expect(Mclass.fullkind, equals('base class'));
}
}
29 changes: 29 additions & 0 deletions test/container_modifiers_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) 2023, 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:dartdoc/src/model/container_modifiers.dart';
import 'package:test/test.dart';

void main() {
group('fullKind string tests', () {
test('basic', () {
var l = {
ContainerModifier.base,
ContainerModifier.interface,
ContainerModifier.abstract
};
expect(l.modifiersAsFullKindPrefix(), equals('abstract base interface'));
});

test('hide abstract on sealed', () {
var l = {ContainerModifier.abstract, ContainerModifier.sealed};
expect(l.modifiersAsFullKindPrefix(), equals('sealed'));
});

test('empty', () {
var l = <ContainerModifier>{};
expect(l.modifiersAsFullKindPrefix(), equals(''));
});
});
}