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

add Preprocessor.parse #22

Merged
merged 5 commits into from
Sep 22, 2023
Merged

Conversation

zvkemp
Copy link
Contributor

@zvkemp zvkemp commented Sep 14, 2023

fixes #19. We still need to review test assertions and do a fair bit of cleanup

src/bindings.rs Outdated Show resolved Hide resolved
src/bindings.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
@ef4
Copy link
Collaborator

ef4 commented Sep 14, 2023

Thanks for working on this.

I think the other PR I landed today ensures that all the spans you need are already available in the AST. So that might simplify some of this.

Co-authored-by: zvkemp <[email protected]>
Co-authored-by: chancancode <[email protected]>
@zvkemp zvkemp marked this pull request as ready for review September 19, 2023 22:13
let result = self
.core
.parse(&src)
.map_err(|_err| self.process(src, filename).unwrap_err())?;
Copy link
Contributor

Choose a reason for hiding this comment

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

This calls process just to get the error, eventually it can be extracted out into some common method, but this works for now

.parse(&src)
.map_err(|_err| self.process(src, filename).unwrap_err())?;
let serialized = serde_json::to_string(&result)
.map_err(|err| js_error(format!("Unexpected serialization error; please open an issue with the following debug info: {err:#?}").into()))?;
Copy link
Contributor

Choose a reason for hiding this comment

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

This should never happen, so if it does it is a bug

src/lib.rs Outdated Show resolved Hide resolved
fn from(value: &Span) -> Self {
Range {
start: value.lo.0 as usize - 1,
end: value.hi.0 as usize - 1,
Copy link
Contributor

Choose a reason for hiding this comment

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

It appears that SWC spans are 1-based for some reason, while our existing API expects them to be 0-based. Or that there is a bug in the swc fork. Either way, this fixes the issue and satisfies the existing expectations. If it is indeed a bug upstream and we fix it, we can potentially remove the -1 here but we shouldn't change the expectations in the tests.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, they are weirdly 1-based and they reserve 0 to mean the dummy span.

start: 16,
end: 27
}
},
Copy link
Contributor

Choose a reason for hiding this comment

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

The API is slightly different from the existing one, in that we normalized all the ranges to { start: number, end: number }, whereas the existing API uses [start: number, end: number] for some seemingly randomly

test/node-api.js Outdated Show resolved Hide resolved

it("preceded by a slash character", function() {
let p = new Preprocessor();
// What is this testing?
Copy link
Contributor

Choose a reason for hiding this comment

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

the ember-templace-imports parser historically broke every time you had a / before <template>

);
}).to.throw(`Parse Error at path/to/my/component.gjs:2:15: 2:15`);
});
});
Copy link
Contributor

@NullVoxPopuli NullVoxPopuli Sep 19, 2023

Choose a reason for hiding this comment

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

do you think it's worth adding a test for a multi-line <template> tag?

and then maybe one with:

<template>
  y
  <template>x</template>
  z
</template>

This should parse out to 1 set of ranges, because the inner <template> is just HTML

Copy link
Collaborator

Choose a reason for hiding this comment

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

That is actually not legal. The first </template> closes the content tag. Because content-tag is deliberately agnostic to the interior language, it doesn't know anything about delimiter pairing.

Copy link
Collaborator

@ef4 ef4 left a comment

Choose a reason for hiding this comment

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

Thanks.

I think this suffers the same bug that I had in my first visitor (#16), which is that there's no automatic recursion in visitors, your own hooks decide whether to allow the visitor to recurse into child nodes.

fn from(value: &Span) -> Self {
Range {
start: value.lo.0 as usize - 1,
end: value.hi.0 as usize - 1,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, they are weirdly 1-based and they reserve 0 to mean the dummy span.

src/lib.rs Outdated Show resolved Hide resolved
src/lib.rs Outdated
end_range: closing.span.into(),
start_range: opening.span.into(),
tag_name: "template".to_owned(),
kind: "template-tag".to_owned(),
Copy link
Collaborator

Choose a reason for hiding this comment

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

kind: "template-tag" is not doing anything useful here, since it's the only kind that's supported and that will likely ever be supported. In the earlier implementation it existed to distinguish between this and the hbs-backticks alternative proposal.

Instead, we should change this to have the value "expression" or "class-member" because that is highly-salient information that is already present in the AST. There were significant hacks required to work around not having that information in places like the eslint plugin, which is a big part of what motivated content-tag in the first place.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed in 05425a2

Copy link
Contributor

Choose a reason for hiding this comment

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

The AST doesn't currently differentiate it, so it's outside of the scope of the current PR, but we should eventually have a declaration kind too. The current AST just treat it as a top-level free-floating expression which isn't quite right. However, I want to refactor the AST to have a common ContentTag node, which ContentTagExpression and ContentTagMember can wrap, similar to how Function is the shared type for FunctionExpression and Getter, etc. That should make it easier to share code between the AST visitors.

Copy link
Contributor

Choose a reason for hiding this comment

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

As for the use case for declaration: for example it would make it easier for the downstream tools to enforce that there can only be one per module, which isn't necessarily the case for all use cases of content tag, but it is for the <template> specification.

test/node-api.js Outdated Show resolved Hide resolved
test/node-api.js Show resolved Hide resolved
src/lib.rs Outdated Show resolved Hide resolved
@ef4 ef4 merged commit b8731d5 into embroider-build:main Sep 22, 2023
1 check passed
@ef4
Copy link
Collaborator

ef4 commented Sep 22, 2023

Published in 1.1.0

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.

Add an API for parse metadata so that content-tag can be used with eslint, prettier, and glint
5 participants