-
Notifications
You must be signed in to change notification settings - Fork 189
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
getStructure #346
getStructure #346
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @cancerberoSgx, looks great overall! Thanks a lot! I made a lot of comments because there's still a bit of work to do here, but hopefully it will help out. I think you're on the right track.
By the way, if at any time you want to merge this I can merge it into a branch and then I'll pick up the work to finish it off.
package-lock.json
Outdated
@@ -16,7 +16,7 @@ | |||
"@mrmlnc/readdir-enhanced": { | |||
"version": "2.2.1", | |||
"resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", | |||
"integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", | |||
"integrity": "sha1-UkryQNGjYFJ7cwR17PoTRKpUDd4=", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you revert this file? I think it's using an old version of npm which uses sha1 https://stackoverflow.com/a/47834854/188246
src/compiler/base/BodiedNode.ts
Outdated
@@ -49,5 +50,16 @@ export function BodiedNode<T extends Constructor<BodiedNodeExtensionType>>(Base: | |||
|
|||
return this; | |||
} | |||
|
|||
getStructure() { | |||
let bodyText = this.getBody().getText().trim(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'll have to improve this because right now this includes the indentation. If someone sets the body with this text it will be indented double the amount and might include a leading newline.
Probably instead get the statements within the body and then get the text within the source file from statements[0].getNonWhitespaceStart()
to statements[statements.length - 1].getTrailingTriviaEnd()
. Once that text is found, we'll have to remove the leading spaces from every line (so remove statements[0].getIndentationText()
from every line).
src/compiler/base/BodyableNode.ts
Outdated
@@ -105,5 +106,28 @@ export function BodyableNode<T extends Constructor<BodyableNodeExtensionType>>(B | |||
|
|||
return this; | |||
} | |||
|
|||
getStructure() { | |||
// TODO: This complication is because we need to remove body text wrapping braces. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment in BodiedNode
. We should be able to use almost the same code here, but handle for when body is undefined.
src/compiler/base/ExportableNode.ts
Outdated
getStructure() { | ||
return callBaseGetStructure<ExportableNodeStructure>(Base.prototype, this, { | ||
isExported: this.isExported(), | ||
isDefaultExport: this.isDefaultExport() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use this.hasDefaultKeyword()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reason is because this.isDefaultExport()
uses the symbols to figure that out, while this.hasDefaultKeyword()
looks at only the AST, which is what we're interested in here.
// and also recreate the AST using structure and compare getText() of generated code with original node's | ||
const aux = sourceFile.addStatements("class __AuxClass{}"); | ||
const decl = aux[0]; | ||
if (!TypeGuards.isClassDeclaration(decl)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't worry about adding this. It's obvious from above that it's a class so just assert it.
@@ -202,4 +221,36 @@ describe(nameof(MethodDeclaration), () => { | |||
}); | |||
}); | |||
}); | |||
|
|||
describe(nameof<MethodDeclaration>(d => d.getStructure), () => { | |||
function doTest(code: string, expectedStructure: MethodDeclarationStructure) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try using MakeRequired<MethodDeclarationStructure>
@@ -129,4 +130,25 @@ describe(nameof(ParameterDeclaration), () => { | |||
doTest("function identifier(param, param2, param3) {}", "param2", "function identifier(param, param3) {}"); | |||
}); | |||
}); | |||
|
|||
describe(nameof<ParameterDeclaration>(d => d.getStructure), () => { | |||
function doTest(code: string, expectedStructure: ParameterDeclarationStructure) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MakeRequired<ParameterDeclarationStructure>
function doTest(code: string, expectedStructure: ParameterDeclarationStructure) { | ||
const {descendant} = getInfoFromTextWithDescendant<ParameterDeclaration>(code, SyntaxKind.Parameter); | ||
const structure = descendant.getStructure(); | ||
expect(structure).to.contain(expectedStructure); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should do an exact comparison in case anything changes. expect(structure).to.deep.equal(expectedStructure)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure, BTW right now for quickly testing I'm not doing what I've should, this is asserting on the structure object itself instead of re-render a new node asserting against the node.getText() - but at least it gives me some confidence I'm doing things OK and that it works ll the way down to text. Thank you very much for the review - i'm on it! :)
So, I made all the changes you asked David, with the exception of
|
Regarding:
I would really like to have this feature in the library since I'm generating a log of code in my projects and basically working with my handcrafted "getStructure" methods. If you think it's more practical that you finish off the work in your own branch then go ahead (I feel you wasted more time in th elast review than if you implemented by yourself.) But to be sincere I would like to keep working on this and give support for getStructure to the rest of the nodes. But primariy, as I said before I would really need this integrated in master ASAP. Thanks! |
@cancerberoSgx I don't view it as wasting time because you taking on this work saves me a lot of time and plus it's another person who learns the inner workings of the library, which is always a plus. I just provided that as an option in case you didn't want to spend the time changing all my comments. I'm going to be moving over the next week (lots of time spent packing) and attending some family events so I won't have time to work on this for the next while. Please continue working on it 😄 |
Nice thanks! BTW I also want to take this opportunity to learn about the inners of the library. I must say it was kind of intuitive once you point me how to workaround that mysterious build error :) Also I must say you are a very careful developer (compared to me) :P What do you think is missing in order to merge this work ? SHould I keep implementing getStructure for the rest of Node kinds ? As I said before I'm kind o fan urgency of having this feature and I woulnd't want to use my own branch... Please advice. BTW I'm using the library to build TLS plugins for code fixes and refactors common in other typed languages / ides like Java/eclipse. See https://github.com/cancerberoSgx/typescript-plugins-of-mine/tree/master/typescript-plugin-proactive-code-fixes - there are some .gifs at the bottom. I bet you didn't imagine tsa being used like this. It saved me a lot of time although some of the refactors could take more than one second to apply ... Just experimenting and learning - let's see if I reach a production - ready product some day. THanks! |
For it to be merged into master this would have to be complete. So for the definition of complete I would say:
If you urgently need this feature, then I recommend publishing your fork to npm and using that package in what you need RE the plugins: very cool! For performance, have you looked into why it's taking so long? Should be pretty quick if you're just looking at the AST and not any symbols or types, but yes, it could be a bit slow otherwise. By the way, see the performance tip I recently added here: https://dsherret.github.io/ts-simple-ast/manipulation/performance -- not sure if it would help though. |
Re plugins performance, I'm creating a new project every time a refactor is applied. Probably this can be improved - but the most slow thing is typeChecker.getTypeAtPosition or type inferring in general - no matter if the project is reused or not. Sincerily didn't put much focus in performance right now but I will, thanks! |
This is merged now, but will be released in v15. Thanks for the help @cancerberoSgx! This was so much work. |
Hey @cancerberoSgx, this is released now and seems to work well (in 15.0.1). The |
I think this is ready: