Skip to content

Commit 8730e57

Browse files
scheglovCommit Queue
authored andcommitted
DeCo. Build fields from primary constructor formal parameters.
Introduce element building for `PrimaryConstructorDeclaration` that synthesizes a backing field and a matching field-formal parameter when a primary constructor parameter is declared with `final` or `var`. The constructor fragment is created, `const` is honored, and child fragments for such parameters are added as synthetic fields. Track the relationship between the declaring formal and the created fragments in `Linker.declaringFormalParameters` via a new `DeclaringFormalParameterInfo`. Subsequent visits to the same parameter reuse these fragments (including for default-parameter wrappers), which avoids duplicates and keeps the element model consistent. Propagate explicit types from declaring formals to the synthesized fields so that explicitly typed or function-typed parameters produce correctly typed fields (`_copyDeclaringFormalParametersExplicitTypes`). Traverse `NameWithTypeParameters` in the declaring-constructors path to pick up type parameters, and add convenience accessors `finalKeyword`/`varKeyword` plus a `hasFinalOrVarKeyword` helper on formal parameters. Some changes to extension type offsets, to align better with new AST presentation. Bug: #61701 Change-Id: Icbd507b4304131df6bce47e1a5eb5fe6f144dbd3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/459160 Commit-Queue: Konstantin Shcheglov <scheglov@google.com> Reviewed-by: Johnni Winther <johnniwinther@google.com>
1 parent c0bd240 commit 8730e57

File tree

14 files changed

+1480
-392
lines changed

14 files changed

+1480
-392
lines changed

pkg/analyzer/lib/src/dart/analysis/driver.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ testFineAfterLibraryAnalyzerHook;
109109
// TODO(scheglov): Clean up the list of implicitly analyzed files.
110110
class AnalysisDriver {
111111
/// The version of data format, should be incremented on every format change.
112-
static const int DATA_VERSION = 581;
112+
static const int DATA_VERSION = 582;
113113

114114
/// The number of exception contexts allowed to write. Once this field is
115115
/// zero, we stop writing any new exception contexts in this process.

pkg/analyzer/lib/src/dart/ast/ast.dart

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12259,6 +12259,14 @@ final class FunctionTypedFormalParameterImpl extends NormalFormalParameterImpl
1225912259
return parameters.endToken;
1226012260
}
1226112261

12262+
/// If [keyword] is `final`, returns it.
12263+
Token? get finalKeyword {
12264+
if (keyword?.keyword == Keyword.FINAL) {
12265+
return keyword;
12266+
}
12267+
return null;
12268+
}
12269+
1226212270
@generated
1226312271
@override
1226412272
Token get firstTokenAfterCommentAndMetadata {
@@ -12284,7 +12292,7 @@ final class FunctionTypedFormalParameterImpl extends NormalFormalParameterImpl
1228412292
bool get isExplicitlyTyped => true;
1228512293

1228612294
@override
12287-
bool get isFinal => false;
12295+
bool get isFinal => keyword?.keyword == Keyword.FINAL;
1228812296

1228912297
@generated
1229012298
@override
@@ -12317,6 +12325,14 @@ final class FunctionTypedFormalParameterImpl extends NormalFormalParameterImpl
1231712325
_typeParameters = _becomeParentOf(typeParameters);
1231812326
}
1231912327

12328+
/// If [keyword] is `var`, returns it.
12329+
Token? get varKeyword {
12330+
if (keyword?.keyword == Keyword.VAR) {
12331+
return keyword;
12332+
}
12333+
return null;
12334+
}
12335+
1232012336
@generated
1232112337
@override
1232212338
ChildEntities get _childEntities => super._childEntities
@@ -22211,6 +22227,14 @@ final class SimpleFormalParameterImpl extends NormalFormalParameterImpl
2221122227
throw StateError('Expected at least one non-null');
2221222228
}
2221322229

22230+
/// If [keyword] is `final`, returns it.
22231+
Token? get finalKeyword {
22232+
if (keyword?.keyword == Keyword.FINAL) {
22233+
return keyword;
22234+
}
22235+
return null;
22236+
}
22237+
2221422238
@generated
2221522239
@override
2221622240
Token get firstTokenAfterCommentAndMetadata {
@@ -22250,6 +22274,14 @@ final class SimpleFormalParameterImpl extends NormalFormalParameterImpl
2225022274
_type = _becomeParentOf(type);
2225122275
}
2225222276

22277+
/// If [keyword] is `var`, returns it.
22278+
Token? get varKeyword {
22279+
if (keyword?.keyword == Keyword.VAR) {
22280+
return keyword;
22281+
}
22282+
return null;
22283+
}
22284+
2225322285
@generated
2225422286
@override
2225522287
ChildEntities get _childEntities => super._childEntities

pkg/analyzer/lib/src/summary2/element_builder.dart

Lines changed: 102 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,7 +1067,7 @@ class FragmentBuilder extends ThrowingAstVisitor<void> {
10671067
var holder = _EnclosingContext(fragment: fragment);
10681068
_withEnclosing(holder, () {
10691069
if (useDeclaringConstructorsAst) {
1070-
node.namePart.typeParameters?.accept(this);
1070+
node.namePart.accept(this);
10711071
node.body.accept(this);
10721072
} else {
10731073
node.typeParameters?.accept(this);
@@ -1603,11 +1603,16 @@ class FragmentBuilder extends ThrowingAstVisitor<void> {
16031603
var nameToken = node.name;
16041604
var name2 = _getFragmentName(nameToken);
16051605

1606-
var fragment = FormalParameterFragmentImpl(
1607-
name: name2,
1608-
nameOffset: null,
1609-
parameterKind: node.kind,
1610-
);
1606+
FormalParameterFragmentImpl fragment;
1607+
if (_linker.getDeclaringFormalInfo(node) case var declaring?) {
1608+
fragment = declaring.formalFragment;
1609+
} else {
1610+
fragment = FormalParameterFragmentImpl(
1611+
name: name2,
1612+
nameOffset: null,
1613+
parameterKind: node.kind,
1614+
);
1615+
}
16111616
_linker.elementNodes[fragment] = node;
16121617
_enclosingContext.addParameter(fragment);
16131618

@@ -1795,6 +1800,11 @@ class FragmentBuilder extends ThrowingAstVisitor<void> {
17951800
node.typeArguments?.accept(this);
17961801
}
17971802

1803+
@override
1804+
void visitNameWithTypeParameters(NameWithTypeParameters node) {
1805+
node.typeParameters?.accept(this);
1806+
}
1807+
17981808
@override
17991809
void visitPartDirective(covariant PartDirectiveImpl node) {
18001810
var index = _partDirectiveIndex++;
@@ -1806,6 +1816,55 @@ class FragmentBuilder extends ThrowingAstVisitor<void> {
18061816
@override
18071817
void visitPartOfDirective(PartOfDirective node) {}
18081818

1819+
@override
1820+
void visitPrimaryConstructorDeclaration(
1821+
covariant PrimaryConstructorDeclarationImpl node,
1822+
) {
1823+
node.typeParameters?.accept(this);
1824+
1825+
var fragmentName = 'new';
1826+
if (node.constructorName?.name case var nameToken?) {
1827+
fragmentName = _getFragmentName(nameToken) ?? 'new';
1828+
}
1829+
1830+
var fragment = ConstructorFragmentImpl(name: fragmentName);
1831+
fragment.isConst = node.constKeyword != null;
1832+
fragment.typeName = node.typeName.lexeme;
1833+
_linker.elementNodes[fragment] = node;
1834+
1835+
_addChildFragment(fragment);
1836+
1837+
// Handle declaring formal parameters.
1838+
for (var formalParameter in node.formalParameters.parameters) {
1839+
if (formalParameter.hasFinalOrVarKeyword) {
1840+
var name = _getFragmentName(formalParameter.name);
1841+
var fieldFragment = FieldFragmentImpl(name: name);
1842+
fieldFragment.isFinal = formalParameter.isFinal;
1843+
fieldFragment.isSynthetic = true;
1844+
_linker.elementNodes[fieldFragment] = formalParameter;
1845+
_addChildFragment(fieldFragment);
1846+
1847+
var formalFragment = FieldFormalParameterFragmentImpl(
1848+
name: name,
1849+
nameOffset: null,
1850+
parameterKind: formalParameter.kind,
1851+
);
1852+
1853+
_linker.declaringFormalParameters[formalParameter] =
1854+
DeclaringFormalParameterInfo(
1855+
node: formalParameter,
1856+
fieldFragment: fieldFragment,
1857+
formalFragment: formalFragment,
1858+
);
1859+
}
1860+
}
1861+
1862+
_buildExecutableElementChildren(
1863+
fragment: fragment,
1864+
formalParameters: node.formalParameters,
1865+
);
1866+
}
1867+
18091868
@override
18101869
void visitRecordTypeAnnotation(RecordTypeAnnotation node) {
18111870
node.positionalFields.accept(this);
@@ -1838,11 +1897,16 @@ class FragmentBuilder extends ThrowingAstVisitor<void> {
18381897
var nameToken = node.name;
18391898
var name2 = _getFragmentName(nameToken);
18401899

1841-
var fragment = FormalParameterFragmentImpl(
1842-
name: name2,
1843-
nameOffset: null,
1844-
parameterKind: node.kind,
1845-
);
1900+
FormalParameterFragmentImpl fragment;
1901+
if (_linker.getDeclaringFormalInfo(node) case var declaring?) {
1902+
fragment = declaring.formalFragment;
1903+
} else {
1904+
fragment = FormalParameterFragmentImpl(
1905+
name: name2,
1906+
nameOffset: null,
1907+
parameterKind: node.kind,
1908+
);
1909+
}
18461910
_linker.elementNodes[fragment] = node;
18471911
_enclosingContext.addParameter(fragment);
18481912

@@ -2131,3 +2195,30 @@ class _EnclosingContext {
21312195
typeParameters.add(fragment);
21322196
}
21332197
}
2198+
2199+
extension _FormalParameterImplExtension on FormalParameterImpl {
2200+
bool get hasFinalOrVarKeyword {
2201+
switch (this) {
2202+
case DefaultFormalParameterImpl self:
2203+
return self.parameter.hasFinalOrVarKeyword;
2204+
case FunctionTypedFormalParameterImpl self:
2205+
return self.finalKeyword != null || self.varKeyword != null;
2206+
case SimpleFormalParameterImpl self:
2207+
return self.finalKeyword != null || self.varKeyword != null;
2208+
default:
2209+
return false;
2210+
}
2211+
}
2212+
2213+
FormalParameterImpl get selfOrParentDefault {
2214+
return parent.ifTypeOrNull<DefaultFormalParameterImpl>() ?? this;
2215+
}
2216+
}
2217+
2218+
extension _LinkerExtension on Linker {
2219+
DeclaringFormalParameterInfo? getDeclaringFormalInfo(
2220+
FormalParameterImpl node,
2221+
) {
2222+
return declaringFormalParameters[node.selfOrParentDefault];
2223+
}
2224+
}

0 commit comments

Comments
 (0)