diff --git a/lib/src/generator/templates.runtime_renderers.dart b/lib/src/generator/templates.runtime_renderers.dart index 8ab179ce3a..da647ef2f5 100644 --- a/lib/src/generator/templates.runtime_renderers.dart +++ b/lib/src/generator/templates.runtime_renderers.dart @@ -3794,6 +3794,19 @@ class _Renderer_ContainerAccessor extends RendererBase { ..._Renderer_Accessor.propertyMap(), ..._Renderer_ContainerMember.propertyMap(), ..._Renderer_Inheritable.propertyMap(), + 'characterLocation': Property( + getValue: (CT_ c) => c.characterLocation, + renderVariable: (CT_ c, Property self, + List remainingNames) => + self.renderSimpleVariable( + c, remainingNames, 'CharacterLocation'), + isNullValue: (CT_ c) => c.characterLocation == null, + renderValue: + (CT_ c, RendererBase r, List ast) { + return renderSimple(c.characterLocation, ast, r.template, + parent: r); + }, + ), 'enclosingElement': Property( getValue: (CT_ c) => c.enclosingElement, renderVariable: diff --git a/lib/src/model/accessor.dart b/lib/src/model/accessor.dart index cdfb01abb8..c8a6976a68 100644 --- a/lib/src/model/accessor.dart +++ b/lib/src/model/accessor.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:analyzer/dart/element/element.dart'; +import 'package:analyzer/source/line_info.dart'; import 'package:analyzer/src/dart/element/member.dart' show ExecutableMember; import 'package:dartdoc/src/element_type.dart'; import 'package:dartdoc/src/model/comment_referable.dart'; @@ -161,6 +162,19 @@ class ContainerAccessor extends Accessor with ContainerMember, Inheritable { return accessor; } + /// The index and values fields are never declared, and must be special cased. + bool get _isEnumSynthetic => + enclosingCombo is EnumField && (name == 'index' || name == 'values'); + + @override + CharacterLocation get characterLocation { + if (_isEnumSynthetic) return enclosingElement.characterLocation; + // TODO(jcollins-g): Remove the enclosingCombo case below once + // https://github.com/dart-lang/sdk/issues/46154 is fixed. + if (enclosingCombo is EnumField) return enclosingCombo.characterLocation; + return super.characterLocation; + } + ModelElement _enclosingElement; bool _isInherited = false; diff --git a/pubspec.yaml b/pubspec.yaml index 2b8a6019dc..515da0f490 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -7,7 +7,7 @@ environment: sdk: '>=2.11.99 <3.0.0' dependencies: - analyzer: ^1.5.0 + analyzer: ^1.7.1 args: ^2.0.0 charcode: ^1.2.0 collection: ^1.2.0 @@ -17,7 +17,7 @@ dependencies: html: ^0.15.0 logging: ^1.0.0 markdown: ^4.0.0 - meta: ^1.2.4 + meta: ^1.3.0 package_config: ^2.0.0 path: ^1.3.0 pub_semver: ^2.0.0 diff --git a/test/end2end/model_test.dart b/test/end2end/model_test.dart index 60b529389e..3199447d1a 100644 --- a/test/end2end/model_test.dart +++ b/test/end2end/model_test.dart @@ -6,6 +6,7 @@ library dartdoc.model_test; import 'dart:io'; +import 'package:analyzer/source/line_info.dart'; import 'package:async/async.dart'; import 'package:dartdoc/src/element_type.dart'; import 'package:dartdoc/src/model/feature.dart'; @@ -3347,6 +3348,39 @@ String topLevelFunction(int param1, bool param2, Cool coolBeans, classB = exLibrary.classes.singleWhere((c) => c.name == 'B'); }); + test('always has a valid location', () { + void expectValidLocation(CharacterLocation location) { + expect(location.lineNumber, greaterThanOrEqualTo(0)); + expect(location.columnNumber, greaterThanOrEqualTo(0)); + } + + ; + var simpleProperty = + fakeLibrary.properties.firstWhere((p) => p.name == 'simpleProperty'); + expectValidLocation(simpleProperty.getter.characterLocation); + expectValidLocation(simpleProperty.setter.characterLocation); + expectValidLocation(onlyGetterGetter.characterLocation); + expectValidLocation(onlySetterSetter.characterLocation); + + Iterable _expandAccessors(Field f) sync* { + if (f.hasGetter) yield f.getter; + if (f.hasSetter) yield f.setter; + } + + // classB has a variety of inherited and partially overridden fields. + // All should have valid locations on their accessors. + for (var a in classB.allFields.expand(_expandAccessors)) { + expectValidLocation(a.characterLocation); + } + + // Enums also have fields and have historically had problems. + var macrosFromAccessors = + fakeLibrary.enums.firstWhere((e) => e.name == 'MacrosFromAccessors'); + for (var a in macrosFromAccessors.allFields.expand(_expandAccessors)) { + expectValidLocation(a.characterLocation); + } + }); + test('are available on top-level variables', () { expect(onlyGetterGetter.name, equals('justGetter')); expect(onlyGetterSetter, isNull); diff --git a/test/mustachio/aot_compiler_builder_test.dart b/test/mustachio/aot_compiler_builder_test.dart index bc55942dc1..1ee4415058 100644 --- a/test/mustachio/aot_compiler_builder_test.dart +++ b/test/mustachio/aot_compiler_builder_test.dart @@ -2,7 +2,7 @@ // 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. -@Timeout.factor(2) +@Timeout.factor(4) import 'dart:convert'; import 'package:analyzer/dart/element/element.dart'; import 'package:build/build.dart'; @@ -77,7 +77,7 @@ import 'package:mustachio/annotations.dart'; expect( renderersLibrary.getTopLevelFunction('_renderFoo_partial_foo_header_0'), isNotNull); - }); + }, timeout: Timeout.factor(2)); test('builds a public API render function', () async { writer = InMemoryAssetWriter();