Skip to content
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

feat(map): Resolve namespace resolution for Map Types #9

Merged
merged 11 commits into from
Oct 20, 2023

Conversation

jonathan-casey
Copy link
Member

@jonathan-casey jonathan-casey commented Sep 26, 2023

Description

Handle MapDeclaration cases for the resolve command.

Author Checklist

  • Ensure you provide a DCO sign-off for your commits using the --signoff option of git commit.
  • Vital features and changes captured in unit and/or integration tests
  • Commits messages follow AP format

@jonathan-casey jonathan-casey requested a review from a team September 26, 2023 14:50
@jonathan-casey jonathan-casey changed the title feat(map): resolution feat(map): Resolve namespace resolution for Map Types Sep 26, 2023
@jonathan-casey jonathan-casey force-pushed the jonathan/patch_resolution branch from bacbf59 to 595838c Compare September 26, 2023 14:53
Signed-off-by: Jonathan Casey <[email protected]>
Comment on lines 160 to 163
const nameK = metaModel.key.$class === `${MetaModelNamespace}.ObjectMapKeyType` ? metaModel.key.type.name : ModelUtil.getShortName(metaModel.key.$class);
metaModel.key.$class === `${MetaModelNamespace}.ObjectMapKeyType` ? metaModel.key.type.namespace = resolveName(nameK, table) : metaModel.key.namespace = resolveName(nameK, table);
const nameV = metaModel.value.$class === `${MetaModelNamespace}.ObjectMapValueType` ? metaModel.value.type.name : ModelUtil.getShortName(metaModel.value.$class);
metaModel.key.$class === `${MetaModelNamespace}.ObjectMapKeyType` ? metaModel.value.type.namespace = resolveName(nameV, table) : metaModel.value.namespace = resolveName(nameV, table);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, please refactor this to have a branch for ObjectMapKeyType and an else case. This will make this easier to read and DRY the repeated tenary operators.

Copy link
Contributor

@dselman dselman Oct 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have a new case for MapDeclaration which calls resolveTypeNames on both key and value (recursion).

There should then be cases for ObjectMapKeyType and ObjectMapValueType that follows the established pattern:

        const name = metaModel.type.name;
        metaModel.type.namespace = resolveName(name, table);
        (metaModel.decorators || []).forEach((decorator) => {
            resolveTypeNames(decorator, table);
        });

A good test-case to add would be:

namespace A

scalar MyScalar extends String

namespace B
map EventMap {
   o MyScalar
   o Event // requires implicit resolution using `concerto` namespace
}

Copy link
Contributor

@dselman dselman Oct 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we may also have a bug here with ScalarDeclaration missing? Can you test and create an issue for that please?

@@ -64,6 +65,14 @@ function createNameTable(priorModels, metaModel) {
'Participant': concertoNs,
'Transaction ': concertoNs,
'Event': concertoNs,
'StringMapKeyType': concertoNs,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand this. StringMapKeyType is not defined in the [email protected] namespace - that is a type from the metamodel. What are we trying to do here?

Copy link
Member Author

@jonathan-casey jonathan-casey Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention is that any type used within a map context should have its namespace resolved.

I guess my question is - why differentiate between types on the metamodel vs those on the root model when resolving namespace - why should namespace apply to only root types, but not in the case of primitives? The metamodel is versioned, after all.

If I think about this from the point of view that a primitive type will always be a primitive type it doesn't really make sense to version it to a namespace, and in that case there is no need to generate namespace values for primitives in the context of a resolve command output.

Feels like I may not be seeing the forest for the trees.., it would be useful if you can share a scenario under which the resolve function is necessary, from a client perspective.

Copy link
Contributor

@dselman dselman Oct 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What the createNameTable code is doing (before you changes) is saying that anywhere we see the unqualified type Event being used (et al) it should be resolved as [email protected].

The concerto namespace is special in that it is managed by the ModelManager implicitly. I.e. any model file can use Event without having to import it. Here is the code that adds the concerto namespace to the model manager on construction.
https://github.com/accordproject/concerto/blob/main/packages/concerto-core/lib/basemodelmanager.js#L126

Your code change is saying that StringMapKeyType is also defined in the concerto namespace, which is not correct.

I don't think you need to update the logic in createNameTable - it uses the imported types to build the name resolution table (resolving from a short type name to a namespace). Given that maps must import their types to use them as keys or values this should just work...

Copy link
Contributor

@dselman dselman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "resolution" process takes an AST with imports and unqualified type names and uses the imports to set the namespace property on all the TypeIdentifier nodes. In effect it is an optimisation that makes it easier for consumers of the AST: they no longer need to do the (somewhat complex) import resolution logic.

Comment on lines 160 to 163
const nameK = metaModel.key.$class === `${MetaModelNamespace}.ObjectMapKeyType` ? metaModel.key.type.name : ModelUtil.getShortName(metaModel.key.$class);
metaModel.key.$class === `${MetaModelNamespace}.ObjectMapKeyType` ? metaModel.key.type.namespace = resolveName(nameK, table) : metaModel.key.namespace = resolveName(nameK, table);
const nameV = metaModel.value.$class === `${MetaModelNamespace}.ObjectMapValueType` ? metaModel.value.type.name : ModelUtil.getShortName(metaModel.value.$class);
metaModel.key.$class === `${MetaModelNamespace}.ObjectMapKeyType` ? metaModel.value.type.namespace = resolveName(nameV, table) : metaModel.value.namespace = resolveName(nameV, table);
Copy link
Contributor

@dselman dselman Oct 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should have a new case for MapDeclaration which calls resolveTypeNames on both key and value (recursion).

There should then be cases for ObjectMapKeyType and ObjectMapValueType that follows the established pattern:

        const name = metaModel.type.name;
        metaModel.type.namespace = resolveName(name, table);
        (metaModel.decorators || []).forEach((decorator) => {
            resolveTypeNames(decorator, table);
        });

A good test-case to add would be:

namespace A

scalar MyScalar extends String

namespace B
map EventMap {
   o MyScalar
   o Event // requires implicit resolution using `concerto` namespace
}

Comment on lines 160 to 163
const nameK = metaModel.key.$class === `${MetaModelNamespace}.ObjectMapKeyType` ? metaModel.key.type.name : ModelUtil.getShortName(metaModel.key.$class);
metaModel.key.$class === `${MetaModelNamespace}.ObjectMapKeyType` ? metaModel.key.type.namespace = resolveName(nameK, table) : metaModel.key.namespace = resolveName(nameK, table);
const nameV = metaModel.value.$class === `${MetaModelNamespace}.ObjectMapValueType` ? metaModel.value.type.name : ModelUtil.getShortName(metaModel.value.$class);
metaModel.key.$class === `${MetaModelNamespace}.ObjectMapKeyType` ? metaModel.value.type.namespace = resolveName(nameV, table) : metaModel.value.namespace = resolveName(nameV, table);
Copy link
Contributor

@dselman dselman Oct 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like we may also have a bug here with ScalarDeclaration missing? Can you test and create an issue for that please?

Signed-off-by: Jonathan Casey <[email protected]>
@coveralls
Copy link

coveralls commented Oct 20, 2023

Pull Request Test Coverage Report for Build 6588566313

  • 9 of 11 (81.82%) changed or added relevant lines in 1 file are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage decreased (-0.4%) to 93.671%

Changes Missing Coverage Covered Lines Changed/Added Lines %
lib/metamodelutil.js 9 11 81.82%
Totals Coverage Status
Change from base Build 5830242667: -0.4%
Covered Lines: 92
Relevant Lines: 95

💛 - Coveralls

package.json Outdated Show resolved Hide resolved
test/cto/model.cto Outdated Show resolved Hide resolved
test/metamodelutil.js Outdated Show resolved Hide resolved
package.json Show resolved Hide resolved
Copy link
Contributor

@dselman dselman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@jonathan-casey jonathan-casey merged commit 5ead0b9 into main Oct 20, 2023
9 checks passed
@jonathan-casey jonathan-casey deleted the jonathan/patch_resolution branch October 20, 2023 13:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants