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

[labs/analyzer] add mixin support #4147

Open
wants to merge 47 commits into
base: main
Choose a base branch
from
Open

Conversation

43081j
Copy link
Collaborator

@43081j 43081j commented Aug 26, 2023

Replaces #4120.

This is actually kevin's branch but caught up from main, and various tests added.

@changeset-bot
Copy link

changeset-bot bot commented Aug 26, 2023

🦋 Changeset detected

Latest commit: 0f47969

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@lit-labs/analyzer Patch
@lit-labs/gen-manifest Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@43081j
Copy link
Collaborator Author

43081j commented Aug 26, 2023

i've also tried to update all occurrences of throw new DiagnosticsError or throw new Error to instead create/add a diagnostic and return undefined.

seems to be what we do elsewhere in the codebase, but do correct me if im wrong

edit:

i've also dropped a test we had for static methods since it seems like it belongs in its own PR and was failing for unrelated reasons (think i lost some of the fixture code in merge).

@43081j 43081j marked this pull request as ready for review August 29, 2023 19:38
@43081j
Copy link
Collaborator Author

43081j commented Aug 29, 2023

fyi i've marked for review but i have some tests to write still

there's also a comment or two i left myself which would be good to resolve first

@43081j
Copy link
Collaborator Author

43081j commented Sep 2, 2023

FYI i've also now updated gen-manifest to support mixins.

i still need to update the goldens at some point, though.

packages/labs/analyzer/src/lib/javascript/classes.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/javascript/classes.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/javascript/mixins.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/javascript/classes.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/javascript/mixins.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/javascript/mixins.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/model.ts Outdated Show resolved Hide resolved
@43081j
Copy link
Collaborator Author

43081j commented Dec 21, 2023

just did the minor changes @augustjk suggested (some package name updates) FYI

};
};

const findSuperClassArgIndexFromHeritage = (
Copy link
Contributor

Choose a reason for hiding this comment

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

Documentation on this function would be helpful since it's quite impressive what this function is doing, and it took me a while to understand it.

If I understand correctly, this function is finding which argument is the superClass. And it also is able to walk through the arguments.

Could this function be tricked to return the wrong super class with the following example:

const myMixin = (superClass, someArg) => {
  // This other mixin takes `someArg` as its first argument.
  class MyMixin extends someOtherMixin(someArg, superClass) {
    ...
  }
}

In this case I think someArg would be detected as the super class.

Copy link
Contributor

Choose a reason for hiding this comment

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

I may be completely misunderstanding this function as well, but it may be worth adding an additional test case where a mixin applies some other mixin.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

you understood correctly i think

it'll basically recursively resolve your example:

  • initially it'll have the expression someOtherMixin(someArg, superClass) and some possible names of ['superClass', 'someArg']
  • it'll then check if someArg is one of the possible names
  • it is so it'll return index 1 (because its [1] of the possible names)

so you're right, it'll pick up someArg as the class arg rather than superClass

not sure what we can do about that though 🤔

Copy link
Member

Choose a reason for hiding this comment

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

Good catch here, this does seem wrong. I think in the isCallExpression branch, rather than recursing into findSuperClassArgIndexFromHeritage(), this function likely needs to try to look up / dereference the mixin that's being called and return the index of its own argument passed into the mixin's superclass argument; that will recurse until a mixin extends one of its arguments directly (iow, taking the isIdentifier branch) rather than calling another mixin.

So in the example, we'd look up someOtherMixin, it would have a superClassArgIdx of 1, and so we'd find the index of the superClass argument, and search the current mixin's arg list for that name and return 0.

As Justin said in the other comment, the name searches could be likely be done with symbol declaration identity, but that could be a separate change.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think we might need to add something to the custom elements manifest here to identify which parameter of a mixin is the superclass.

We can do something internally to the analyzer in the mean time by just adding that to the model object.

Copy link
Contributor

@AndrewJakubowicz AndrewJakubowicz left a comment

Choose a reason for hiding this comment

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

Some minor comments, but overall this is awesome! pre-approving!

Only blocking comments from me are:

  1. The license date that was updated in an old file.
  2. Clarifying that findSuperClassArgIndexFromHeritage works correctly.

Thank you so much!

classDeclarationName,
analyzer,
undefined,
true /* isMixinClass */
Copy link
Collaborator

Choose a reason for hiding this comment

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

No action needed now (unless you want!), but this is enough parameters, especially with booleans and other literals, that I would generally go for named arguments.

packages/labs/analyzer/src/lib/javascript/functions.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/model.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/model.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/javascript/mixins.ts Outdated Show resolved Hide resolved
packages/labs/analyzer/src/lib/javascript/mixins.ts Outdated Show resolved Hide resolved
};
};

const findSuperClassArgIndexFromHeritage = (
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this finding the index in the mixin function's parameter list or the heritage call expression's argument list?

Note that in general, the superclass arg could be a named property too. I'm not sure what TypeScript's rules are.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

it is the index in the function's parameter list, based on the heritage of the class

i think if we want to change this, we should probably do it in a follow-up since it could be a bit of a refactor to allow an object to be used as a parameter

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm not sure we should fix this, especially if TypeScript is strict about recognizing mixins. We can keep an eye on it.

packages/labs/analyzer/src/lib/javascript/mixins.ts Outdated Show resolved Hide resolved
@justinfagnani
Copy link
Collaborator

I think we should merge this now and open an issue to address known problems in the mixin superclass lookup.

@e111077 e111077 dismissed kevinpschaaf’s stale review May 17, 2024 18:27

Kevin said it’s ok in chat

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.

None yet

7 participants