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 cloneDeepWithoutLoc #10680

Merged
merged 12 commits into from Mar 16, 2020

Conversation

Taym95
Copy link
Contributor

@Taym95 Taym95 commented Nov 8, 2019

Fixes #10670

@existentialism existentialism added PR: New Feature 🚀 A type of pull request used for our changelog categories pkg: types labels Nov 8, 2019
Copy link
Member

@jridgewell jridgewell left a comment

Choose a reason for hiding this comment

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

Thanks for the PR!

packages/babel-types/scripts/generators/flow.js Outdated Show resolved Hide resolved
packages/babel-types/scripts/generators/typescript.js Outdated Show resolved Hide resolved
packages/babel-types/src/clone/cloneDeepWithoutLoc.js Outdated Show resolved Hide resolved
packages/babel-types/src/clone/cloneNode.js Show resolved Hide resolved
packages/babel-types/src/clone/cloneNode.js Outdated Show resolved Hide resolved
packages/babel-types/test/cloning.js Show resolved Hide resolved
packages/babel-types/test/cloning.js Show resolved Hide resolved
packages/babel-types/test/cloning.js Outdated Show resolved Hide resolved
@Taym95 Taym95 changed the title Add cloneDeepWithoutLoc WIP: Add cloneDeepWithoutLoc Nov 8, 2019
packages/babel-types/src/clone/cloneNode.js Outdated Show resolved Hide resolved
packages/babel-types/src/clone/cloneWithoutLoc.js Outdated Show resolved Hide resolved
@JLHwung
Copy link
Contributor

JLHwung commented Nov 11, 2019

@Taym95 The CI error is related to this PR, could you check why it does not work as intended?

export default function cloneNode<T: Object>(
node: T,
deep: boolean = true,
withoutLoc: boolean = false,
Copy link
Member

Choose a reason for hiding this comment

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

Deep clones also need to receive the withoutLoc param, which is why the tests are failing.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I will fix it!

Copy link
Contributor Author

@Taym95 Taym95 Nov 19, 2019

Choose a reason for hiding this comment

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

Hey @jridgewell, I added withoutLoc to deep clones which means cloned.declarations[0].id.loc needs to be null but I am still receiving {} in the test, any idea why?

Copy link
Member

Choose a reason for hiding this comment

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

This looks like is working.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah yes, sorry 😅!

@JLHwung JLHwung added the PR: Ready to be Merged A pull request with already two approvals, but waiting for the next minor release label Nov 19, 2019
@JLHwung JLHwung added this to the v7.8.0 milestone Nov 19, 2019
@Taym95 Taym95 changed the title WIP: Add cloneDeepWithoutLoc Add cloneDeepWithoutLoc Nov 19, 2019
newNode.loc = null;
} else {
newNode.loc = node.loc;
}
}
if (has(node, "leadingComments")) {
newNode.leadingComments = node.leadingComments;
Copy link
Contributor

Choose a reason for hiding this comment

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

when both deep and withoutLoc is true, we should apply cloneIfNodeOrArray on these comment nodes, same applied to innerComments and trailingComments.

Copy link
Contributor Author

@Taym95 Taym95 Nov 19, 2019

Choose a reason for hiding this comment

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

something like this?

newNode.leadingComments = deep && withoutLoc ?
cloneIfNodeOrArray(node.leadingComments, true, true) : node.leadingComments;

Copy link
Contributor

Choose a reason for hiding this comment

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

Yep! And please add a test on the new behaviour.

@JLHwung JLHwung removed the PR: Ready to be Merged A pull request with already two approvals, but waiting for the next minor release label Nov 19, 2019
const cloned = t.cloneNode(node, /* deep */ true, /* withoutLoc */ true);
expect(cloned.loc).toBeNull();
expect(cloned.declarations[0].id.loc).toBeNull();
expect(cloned.declarations[0].id.leadingComments).toEqual(
Copy link
Contributor

Choose a reason for hiding this comment

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

The cloned.declarations[0].id.leadingComments will be undefined given that we did not add such comments when constructing node.

Similar to what we did in node.declarations[0].id, we can create the leading comments node

node.leadingComments = [{ loc: {} }]

And then we assert that after it is cloned, the loc will be null:

expect(cloned.leadingComments[0].loc).toBeNull()

Tip: you can view the node structures on this website, and cloneWithoutLoc aims to eliminate all the loc location information from the AST nodes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank you for the tip and the link, now I understand what I am doing!

@@ -11,24 +11,29 @@ function cloneIfNode(obj, deep) {
obj.type !== "CommentLine" &&
obj.type !== "CommentBlock"
Copy link
Contributor Author

@Taym95 Taym95 Nov 21, 2019

Choose a reason for hiding this comment

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

@JLHwung because of this condition cloneNode will never be called on comments so comment.loc will never be null! I am adding comments to node using:

t.addComment(node, "leading", "leadingComments", true);
node.leadingComments[0].loc = {};

test:

expect(cloned.leadingComments[0].loc).not.toBeNull();

comment type is either CommentLine or CommentBlock! any idea?
Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

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

Good catch! I think we should short-circuit this condition when withoutLoc and deep are both true. Otherwise it is inconsistent that after cloneWithoutLoc, the cloned CommentLine still contain loc.

Copy link
Contributor Author

@Taym95 Taym95 Nov 21, 2019

Choose a reason for hiding this comment

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

Yes, we can use this:

((deep && withoutLoc) ||
      (obj.type !== "CommentLine" && obj.type !== "CommentBlock"))

But this will throw an error here:

} else if (!has(NODE_FIELDS, type)) {

Unknown node type: "CommentBlock"
Unknown node type: "CommentLine"

Copy link
Member

Choose a reason for hiding this comment

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

@Taym95 Sorry for the long delay! Maybe we could special-case comments and have a small helper function (not exposed as part of the API) cloneCommentWithoutLoc?

@nicolo-ribaudo nicolo-ribaudo modified the milestones: v7.8.0, v7.9.0 Jan 6, 2020
@github-actions github-actions bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label Jun 16, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 16, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
outdated A closed issue/PR that is archived due to age. Recommended to make a new issue pkg: types PR: New Feature 🚀 A type of pull request used for our changelog categories PR: Ready to be Merged A pull request with already two approvals, but waiting for the next minor release
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add cloneDeepWithoutLoc
5 participants