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

Account for class only having template tag in no-empty-glimmer-component-classes rule #1866

Conversation

chrisrng
Copy link
Contributor

@chrisrng chrisrng commented May 18, 2023

Fix the no-empty-glimmer-component-classes lint rule to avoid creating empty backing classes for Glimmer template tag only components.

The sample AST of the glimmer template tag is something like:

import Component from '@glimmer/component';
export default class Chris extends Component {
  [__GLIMMER_TEMPLATE(`...`, true)];
}

@lin-ll lin-ll added the Bug label May 18, 2023
Copy link

@chriskrycho chriskrycho left a comment

Choose a reason for hiding this comment

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

👍🏼

Copy link
Collaborator

@lin-ll lin-ll left a comment

Choose a reason for hiding this comment

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

Do you mind updating the docs for this rule as well? Changes look good

@bmish
Copy link
Member

bmish commented May 18, 2023

Do you think we should consider this a bug fix or a more substantial breaking change?

@chriskrycho
Copy link

I'd call it a bug fix – the semantics of a class with <template> in its body are identical to those of an empty class with a colocated .hbs file. And to be clear, I am not exaggerating for effect: they are literally identical.

@bmish bmish changed the title Fix no-empty-glimmer-component-classes to account for only template tag too Account for only having template tag in no-empty-glimmer-component-classes rule May 18, 2023
Copy link
Member

@bmish bmish left a comment

Choose a reason for hiding this comment

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

Thanks!

@bmish bmish merged commit 55b987c into ember-cli:master May 19, 2023
8 checks passed
@bmish bmish changed the title Account for only having template tag in no-empty-glimmer-component-classes rule Account for class only having template tag in no-empty-glimmer-component-classes rule May 19, 2023
bmish added a commit to bmish/eslint-plugin-ember that referenced this pull request May 21, 2023
* master: (88 commits)
  Release 11.7.0
  build(deps-dev): Bump @typescript-eslint/parser from 5.59.5 to 5.59.6 (ember-cli#1863)
  Account for only having template tag in `no-empty-glimmer-component-classes` rule (ember-cli#1866)
  Support autofix of numerical property access and ternary expressions in `no-get` rule (ember-cli#1865)
  Release 11.6.0
  build(deps-dev): Bump prettier from 2.8.7 to 2.8.8 (ember-cli#1842)
  build(deps-dev): Bump @typescript-eslint/parser from 5.58.0 to 5.59.5 (ember-cli#1860)
  build(deps-dev): Bump @babel/eslint-parser from 7.21.3 to 7.21.8 (ember-cli#1856)
  build(deps-dev): Bump markdownlint-cli from 0.33.0 to 0.34.0 (ember-cli#1848)
  build(deps-dev): Bump jquery from 3.6.4 to 3.7.0 (ember-cli#1861)
  build(deps-dev): Bump release-it from 15.10.1 to 15.10.3 (ember-cli#1859)
  build(deps): Bump vm2 from 3.9.17 to 3.9.18 (ember-cli#1862)
  Support autofix in gts files (ember-cli#1853)
  Only show `no-undef` errors for templates in gts files (ember-cli#1852)
  Release 11.5.2
  Fix a bug in autofixer and autofix additional cases with `firstObject and `lastObject` in `no-get` rule (ember-cli#1841)
  build(deps-dev): Bump eslint from 8.37.0 to 8.38.0 (ember-cli#1830)
  build(deps-dev): Bump @typescript-eslint/parser from 5.57.0 to 5.58.0 (ember-cli#1837)
  build(deps-dev): Bump typescript from 5.0.3 to 5.0.4 (ember-cli#1832)
  build(deps): Bump vm2 from 3.9.11 to 3.9.17 (ember-cli#1839)
  ...
@chriskrycho
Copy link

chriskrycho commented May 22, 2023

We noticed that this needs a follow-on: it should be legal to have template-only components in a class body for the specific case where you need the component to be generic over part of its signature. For example:

import Component from '@glimmer/component';

interface ListSignature<T> {
  Args: {
    items: Array<T>;
  };
  Blocks: {
    default: [item: T]
  };
}

export default class List<T> extends Component<ListSignature<T>> {
  <template>
    <ul>
      {{#each @items as |item|}}
        <li>
          {{yield item}}
        </li>
      {{/each}}
    </ul>
  </template>
}

While it is possible to write this without the backing class, it is… not great:

import { ComponentLike } from '@glint/template';

interface ListSignature<T> {
  // snip...
}

const List: abstract new <T>() => ComponentLike<ListSignature<T>> = <template>
  <ul>
    {{#each @items as |item|}}
      <li>
        {{yield item}}
      </li>
    {{/each}}
  </ul>
</template>;

export default List;

Accordingly, we should allow it in this one specific case.

(Unfortunately, you cannot even write a type utility to make that easier: the only place you're allowed to have a free-floating type parameter in the appropriate position for our needs is on a function definition, inclusive of constructor definitions, and for a host of reasons we need a constructor type specifically to make TS do the right things with our component types.)

@chrisrng
Copy link
Contributor Author

#1876 PR to address ^

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants