From cae4924f84f5cad1ca19c4a6beff1a48e2101382 Mon Sep 17 00:00:00 2001 From: Matthew Nitschke Date: Wed, 25 Sep 2024 20:12:29 -0600 Subject: [PATCH 1/4] fixed getters, setters, and field relationships --- lib/src/relationship_generator.dart | 15 ++++++++-- lib/src/symbol_generator.dart | 3 +- .../basic-project/lib/relationships.dart | 11 ++++++-- .../basic-project/lib/relationships.dart | 28 +++++++++++++++---- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/lib/src/relationship_generator.dart b/lib/src/relationship_generator.dart index d6c612c..9053eb6 100644 --- a/lib/src/relationship_generator.dart +++ b/lib/src/relationship_generator.dart @@ -27,21 +27,30 @@ List? relationshipsFor( // Since mixins do not support inheritance, we only care about // methods that exist on classes - if (node is MethodDeclaration && node.parent is ClassDeclaration) { - final parentNode = node.parent as ClassDeclaration?; + if (element is MethodElement || element is FieldElement || element is PropertyAccessorElement) { + final parentNode = node.thisOrAncestorOfType(); final parentElement = parentNode?.declaredElement; // this shouldn't happen, but if the parent element happens to be // null, just fail fast if (parentElement == null) return null; + late final String name; + if (node is MethodDeclaration) { + name = node.name.toString(); + } else if (element is FieldElement) { + name = element.name; + } else if (element is PropertyAccessorElement) { + name = element.name; + } + // retrieve all of the methods and accessors of every parent type that // has the same name of [node]. These are the elements that this [node] // are overriding final referencingElements = parentElement.allSupertypes .map((type) => [...type.methods, ...type.accessors]) .expand((type) => type) - .where((type) => type.name == node.name.toString()); + .where((type) => type.name == name); if (referencingElements.isNotEmpty) { return referencingElements diff --git a/lib/src/symbol_generator.dart b/lib/src/symbol_generator.dart index 648ef18..d383e8d 100644 --- a/lib/src/symbol_generator.dart +++ b/lib/src/symbol_generator.dart @@ -260,7 +260,8 @@ class SymbolGenerator { return [ '$namespace/', if (parentName != null) '$parentName#', - '${element.name}.' + if (element.isGetter) '`${element.name}`.', + if (element.isSetter) '`${element.name.replaceFirst('=', '')}`.', ].join(); } diff --git a/snapshots/input/basic-project/lib/relationships.dart b/snapshots/input/basic-project/lib/relationships.dart index bd028ee..e66dde6 100644 --- a/snapshots/input/basic-project/lib/relationships.dart +++ b/snapshots/input/basic-project/lib/relationships.dart @@ -1,9 +1,13 @@ abstract class Mammal { - String get hierarchy; + String get getter; + String field = ''; } abstract class Animal extends Mammal { String sound() => 'NOISE!'; + + @override + String field = 'asdf'; } mixin SwimAction { @@ -11,9 +15,12 @@ mixin SwimAction { } class Dog extends Animal with SwimAction { + @override + String field = 'otherVal'; + @override String sound() => 'woof'; @override - String get hierarchy => 'dog.animal.mammal'; + String get getter => 'value'; } \ No newline at end of file diff --git a/snapshots/output/basic-project/lib/relationships.dart b/snapshots/output/basic-project/lib/relationships.dart index 25ee4e0..579d5eb 100755 --- a/snapshots/output/basic-project/lib/relationships.dart +++ b/snapshots/output/basic-project/lib/relationships.dart @@ -1,9 +1,12 @@ abstract class Mammal { // definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/ // ^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal# - String get hierarchy; + String get getter; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# -// ^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#hierarchy. +// ^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`getter`. + String field = ''; +// ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# +// ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. } abstract class Animal extends Mammal { @@ -13,6 +16,13 @@ String sound() => 'NOISE!'; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# // ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#sound(). + + @override +// ^^^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`annotations.dart`/override. + String field = 'asdf'; +// ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# +// ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#field. +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`field`. implementation reference } mixin SwimAction { @@ -29,6 +39,14 @@ // relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/SwimAction# implementation // ^^^^^^ reference scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal# // ^^^^^^^^^^ reference scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/SwimAction# + @override +// ^^^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`annotations.dart`/override. + String field = 'otherVal'; +// ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# +// ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#field. +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#`field`. implementation reference +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`field`. implementation reference + @override // ^^^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`annotations.dart`/override. String sound() => 'woof'; @@ -38,8 +56,8 @@ @override // ^^^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`annotations.dart`/override. - String get hierarchy => 'dog.animal.mammal'; + String get getter => 'value'; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# -// ^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#hierarchy. -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#hierarchy. implementation reference +// ^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#`getter`. +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`getter`. implementation reference } From ee367f4d19e14860b44b4c19f504ff65d543f756 Mon Sep 17 00:00:00 2001 From: Matthew Nitschke Date: Thu, 26 Sep 2024 09:45:28 -0600 Subject: [PATCH 2/4] iter --- lib/src/relationship_generator.dart | 12 +++---- lib/src/symbol_generator.dart | 11 +++++-- .../basic-project/lib/relationships.dart | 8 +++-- .../basic-project/lib/relationships.dart | 31 ++++++++++++++----- 4 files changed, 43 insertions(+), 19 deletions(-) diff --git a/lib/src/relationship_generator.dart b/lib/src/relationship_generator.dart index 9053eb6..922f803 100644 --- a/lib/src/relationship_generator.dart +++ b/lib/src/relationship_generator.dart @@ -36,19 +36,17 @@ List? relationshipsFor( if (parentElement == null) return null; late final String name; - if (node is MethodDeclaration) { - name = node.name.toString(); - } else if (element is FieldElement) { - name = element.name; - } else if (element is PropertyAccessorElement) { - name = element.name; + if (element is PropertyAccessorElement) { + name = element.variable.name; + } else { + name = element.name.toString(); } // retrieve all of the methods and accessors of every parent type that // has the same name of [node]. These are the elements that this [node] // are overriding final referencingElements = parentElement.allSupertypes - .map((type) => [...type.methods, ...type.accessors]) + .map((type) => [...type.methods, ...type.accessors.map((a) => a.variable)]) .expand((type) => type) .where((type) => type.name == name); diff --git a/lib/src/symbol_generator.dart b/lib/src/symbol_generator.dart index d383e8d..76b80c8 100644 --- a/lib/src/symbol_generator.dart +++ b/lib/src/symbol_generator.dart @@ -257,11 +257,18 @@ class SymbolGenerator { if (element is PropertyAccessorElement) { final parentName = element.enclosingElement.name; + + var prefix = ''; + if (element.isGetter) { + prefix = ''; + } else if (element.isSetter) { + prefix = ''; + } + return [ '$namespace/', if (parentName != null) '$parentName#', - if (element.isGetter) '`${element.name}`.', - if (element.isSetter) '`${element.name.replaceFirst('=', '')}`.', + '`$prefix${element.variable.name}`.', ].join(); } diff --git a/snapshots/input/basic-project/lib/relationships.dart b/snapshots/input/basic-project/lib/relationships.dart index e66dde6..1ad9923 100644 --- a/snapshots/input/basic-project/lib/relationships.dart +++ b/snapshots/input/basic-project/lib/relationships.dart @@ -1,5 +1,6 @@ abstract class Mammal { - String get getter; + String get someGetter; + set someSetter(String v); String field = ''; } @@ -22,5 +23,8 @@ class Dog extends Animal with SwimAction { String sound() => 'woof'; @override - String get getter => 'value'; + String get someGetter => 'value'; + + @override + set someSetter(String v) {}; } \ No newline at end of file diff --git a/snapshots/output/basic-project/lib/relationships.dart b/snapshots/output/basic-project/lib/relationships.dart index 579d5eb..ddc72fc 100755 --- a/snapshots/output/basic-project/lib/relationships.dart +++ b/snapshots/output/basic-project/lib/relationships.dart @@ -1,9 +1,13 @@ abstract class Mammal { // definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/ // ^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal# - String get getter; + String get someGetter; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# -// ^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`getter`. +// ^^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`someGetter`. + set someSetter(String v); +// ^^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`someSetter`. +// ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# +// ^ definition local 0 String field = ''; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# // ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. @@ -22,7 +26,8 @@ String field = 'asdf'; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# // ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#field. -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`field`. implementation reference +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. implementation reference +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. implementation reference } mixin SwimAction { @@ -44,8 +49,10 @@ String field = 'otherVal'; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# // ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#field. -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#`field`. implementation reference -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`field`. implementation reference +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#field. implementation reference +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#field. implementation reference +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. implementation reference +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. implementation reference @override // ^^^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`annotations.dart`/override. @@ -56,8 +63,16 @@ @override // ^^^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`annotations.dart`/override. - String get getter => 'value'; + String get someGetter => 'value'; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# -// ^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#`getter`. -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`getter`. implementation reference +// ^^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#`someGetter`. +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#someGetter. implementation reference + + @override +// ^^^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`annotations.dart`/override. + set someSetter(String v) {}; +// ^^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#`someSetter`. +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#someSetter. implementation reference +// ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# +// ^ definition local 1 } From 55a838dcba91a75542c5753f68cd5847cf787356 Mon Sep 17 00:00:00 2001 From: Matthew Nitschke Date: Thu, 26 Sep 2024 22:49:35 -0600 Subject: [PATCH 3/4] fixed relationships for setters --- .github/workflows/ci.yaml | 13 +----- lib/src/relationship_generator.dart | 44 ++++++++++--------- .../basic-project/lib/relationships.dart | 7 +-- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index f88a94d..f0e1c72 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -15,17 +15,8 @@ jobs: checks: uses: Workiva/gha-dart-oss/.github/workflows/checks.yaml@v0.1.6 - sbom: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v4 - - uses: dart-lang/setup-dart@v1 - with: - sdk: 2.19.6 - - uses: anchore/sbom-action@v0 - with: - path: ./ - format: cyclonedx-json + build: + uses: Workiva/gha-dart-oss/.github/workflows/build.yaml@v0.1.6 snapshots: runs-on: ubuntu-latest diff --git a/lib/src/relationship_generator.dart b/lib/src/relationship_generator.dart index 922f803..ec3364e 100644 --- a/lib/src/relationship_generator.dart +++ b/lib/src/relationship_generator.dart @@ -35,29 +35,31 @@ List? relationshipsFor( // null, just fail fast if (parentElement == null) return null; - late final String name; - if (element is PropertyAccessorElement) { - name = element.variable.name; - } else { - name = element.name.toString(); + late final Iterable referencingElements; + if (element is MethodElement) { + referencingElements = parentElement.allSupertypes + .expand((type) => type.methods) + .where((type) => type.name == element.name); + } else if (element is FieldElement) { + referencingElements = parentElement.allSupertypes + .expand((type) => type.accessors) + .map((acc) => acc.variable) + .where((variable) => variable.name == element.name) + .toSet(); // remove any duplicates caused from synthetic getters/setters + } if (element is PropertyAccessorElement) { + referencingElements = parentElement.allSupertypes + .expand((type) => type.accessors) + .where((acc) => acc.isSetter == element.isSetter) + .where((acc) => acc.isGetter == element.isGetter) + .where((acc) => acc.variable.name == element.variable.name); } - // retrieve all of the methods and accessors of every parent type that - // has the same name of [node]. These are the elements that this [node] - // are overriding - final referencingElements = parentElement.allSupertypes - .map((type) => [...type.methods, ...type.accessors.map((a) => a.variable)]) - .expand((type) => type) - .where((type) => type.name == name); - - if (referencingElements.isNotEmpty) { - return referencingElements - .map((type) => Relationship( - symbol: symbolGenerator.symbolFor(type), - isImplementation: true, - isReference: true)) - .toList(); - } + return referencingElements + .map((type) => Relationship( + symbol: symbolGenerator.symbolFor(type), + isImplementation: true, + isReference: true)) + .toList(); } return null; diff --git a/snapshots/output/basic-project/lib/relationships.dart b/snapshots/output/basic-project/lib/relationships.dart index ddc72fc..dc6a8d9 100755 --- a/snapshots/output/basic-project/lib/relationships.dart +++ b/snapshots/output/basic-project/lib/relationships.dart @@ -26,7 +26,6 @@ String field = 'asdf'; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# // ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#field. -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. implementation reference // relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. implementation reference } @@ -50,8 +49,6 @@ // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# // ^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#field. // relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#field. implementation reference -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Animal#field. implementation reference -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. implementation reference // relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#field. implementation reference @override @@ -66,13 +63,13 @@ String get someGetter => 'value'; // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# // ^^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#`someGetter`. -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#someGetter. implementation reference +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`someGetter`. implementation reference @override // ^^^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`annotations.dart`/override. set someSetter(String v) {}; // ^^^^^^^^^^ definition scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Dog#`someSetter`. -// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#someSetter. implementation reference +// relationship scip-dart pub dart_test 1.0.0 lib/`relationships.dart`/Mammal#`someSetter`. implementation reference // ^^^^^^ reference scip-dart pub dart:core 2.19.0 dart:core/`string.dart`/String# // ^ definition local 1 } From 7de6381c1108818bf0fe3045d72d61fa91f93556 Mon Sep 17 00:00:00 2001 From: Matthew Nitschke Date: Thu, 26 Sep 2024 22:52:12 -0600 Subject: [PATCH 4/4] fmt --- lib/src/relationship_generator.dart | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/lib/src/relationship_generator.dart b/lib/src/relationship_generator.dart index ec3364e..c5a8526 100644 --- a/lib/src/relationship_generator.dart +++ b/lib/src/relationship_generator.dart @@ -27,7 +27,9 @@ List? relationshipsFor( // Since mixins do not support inheritance, we only care about // methods that exist on classes - if (element is MethodElement || element is FieldElement || element is PropertyAccessorElement) { + if (element is MethodElement || + element is FieldElement || + element is PropertyAccessorElement) { final parentNode = node.thisOrAncestorOfType(); final parentElement = parentNode?.declaredElement; @@ -38,20 +40,21 @@ List? relationshipsFor( late final Iterable referencingElements; if (element is MethodElement) { referencingElements = parentElement.allSupertypes - .expand((type) => type.methods) - .where((type) => type.name == element.name); + .expand((type) => type.methods) + .where((type) => type.name == element.name); } else if (element is FieldElement) { referencingElements = parentElement.allSupertypes - .expand((type) => type.accessors) - .map((acc) => acc.variable) - .where((variable) => variable.name == element.name) - .toSet(); // remove any duplicates caused from synthetic getters/setters - } if (element is PropertyAccessorElement) { + .expand((type) => type.accessors) + .map((acc) => acc.variable) + .where((variable) => variable.name == element.name) + .toSet(); // remove any duplicates caused from synthetic getters/setters + } + if (element is PropertyAccessorElement) { referencingElements = parentElement.allSupertypes - .expand((type) => type.accessors) - .where((acc) => acc.isSetter == element.isSetter) - .where((acc) => acc.isGetter == element.isGetter) - .where((acc) => acc.variable.name == element.variable.name); + .expand((type) => type.accessors) + .where((acc) => acc.isSetter == element.isSetter) + .where((acc) => acc.isGetter == element.isGetter) + .where((acc) => acc.variable.name == element.variable.name); } return referencingElements