Closed ctaggart closed 9 years ago
What I meant is that you shouldn't use our trees as a direct target, you should simply find a way to transform FunScript code to TypeScript, or emit straight to JavaScript.
Is there any way to emit a .ts file?
I'm not sure what you're trying to achieve. It depends what your input is. If your input is TypeScript, then yes, we have a formatter.
Is there anything that can 'pretty print' a TS AST?
Yes, but you'll need an actual TypeScript source file as input. As part of our services API, we provide the following functions:
getFormattingEditsForRange
getFormattingEditsForDocument
getFormattingEditsAfterKeystroke
I think what you might be looking for getFormattingEditsForDocument
. Once you've gotten the appropriate edit ranges, you can easily apply them in reverse and fix up the original source text.
For this issue, I'm just interested in emitting TypeScript code using Node.js & TypeScript. services\formatting\formatting.ts
does indeed look like it could be helpful. I'd really like to use:
function formatDocument(sourceFile: SourceFile, rulesProvider: RulesProvider, options: FormatCodeOptions): TextChange[];
It looks like you can pass in a SourceFile
and FormatCodeOptions
to get back a list of TextChange
edits. Each TextChange
has a span
and the newText
. I'm hoping I would then have the newText
for the SourceFile
. What could I add to typescript.d.ts
to expose that function? In Jakefile
definitionRoots
I tried adding services/formatting/formatting.d.ts
, but it showed up invalid and I'm not sure what the valid TypeScript
should be instead of:
Why do you need that function? getFormattingEditsForDocument
internally just calls that function and that is what we've chosen to expose.
Is there any easy way to apply the TextChange
s returned by getFormattingEditsForDocument
in order to get a string
back with it formatted. A clearly wrong and poor attempt is:
https://github.com/ctaggart/TsAst/blob/format/app.ts#L67-L76
var sf = services.getSourceFile("file1.ts");
textChanges.forEach(tc => {
var tcr: ts.TextChangeRange = {
span: tc.span,
newLength: tc.newText.length,
}
var b = sf.update(tc.newText, tcr);
console.log('b.text: ' + b.text);
});
console.log('sf.text: ' + sf.text);
The most simple way is just to apply the changes in reverse:
function formatCode(orig: string, changes: TextChange[]): string {
var result = orig;
for (var i = changes.length - 1; i >= 0; i--) {
var change = changes[i];
var head = result.slice(0, change.span.start);
var tail = result.slice(change.span.start + change.span.length)
result = head + change.newText + tail;
}
return result;
}
Let me know if you have any more questions.
PS: I thought about it a bit more and I can see why you probably wanted to use formatDocument
.
Thanks! Formatting works now.
My original goal was to be able to create the nodes from scratch and have a function that writes out the TypeScript source to a string. I reviewed src/compiler/emitter.fs and src/services/formatting/formatting.ts yesterday and witnessed what was mentioned:
I've spoken with others on the team; there are difficulties associated with dynamically creating an AST and using our emitter. For one thing, there are times in which we look back at the source text for certain operations, so you need to have a valid TypeScript corpus to base some checking/emit off of. I don't think an AST-to-AST transformation is going to work as very ideally.
Indeed, there are a few calls to getSourceTextOfNodeFromSourceFile
which are problematic in emitter.fs
for this. Emitter currently only supports .d.ts
definition files and not regular .ts
source files. I just thought I would ensure that it wasn't done already before trying to build something. I don't think it will be too hard to create a similar function to emitNode that returns formatted a string
representing the Node
passed in. Thoughts? I could be wrong. I would love to see this built in.
Cleaned up for the formatting code and put the example here. :) http://blog.ctaggart.com/2015/01/format-typescript-with-v14-language.html
thanks @ctaggart for sharing. i have left a few comments. i am also working on cleaning up the host API so it can be easier to use. your feedback would be highly appreciated!
@mhegazy I made the corrections that you recommended. I also have a new blog post that shows how to call the format
function from F#. :)
http://blog.ctaggart.com/2015/01/format-typescript-with-f.html
Hey, very cool! We appreciate you working on this and sharing it with us.
Completely unrelated, I realize you could write TypeScript code in your Edge app and use the compiler at runtime to generate the appropriate JavaScript. Huh.
Thank you guys! I really appreciate the move to GitHub. It is fun watching how quickly things progress on this project. The Compiler API is a great addition. My immediate need is to be able to generate TypeScript code for web clients when there is a defined web API contract (not necessary .NET Web API). I've created such clients in the past using printf
style hacks, but I think using the AST
is a more robust solution. The thing that I'm missing is a pretty printer from the TypeScript AST, but I'm hoping that isn't to hard for me to write.
Yes, there are several very cool possibilities when combining F# + Edge.js + TypeScript.
.d.ts
files. FunScript does this today via FParsec parsing of the file, but I think using TypeScript Compiler API would be a better solution./cc @tjanczuk @alfonsogarciacaro
Hopefully this thread won't get too off track. :) The goal of this thread being how to emit or pretty print .ts
code.
@ctaggart would you feel comfortable with us adapting your pretty printer for use on Using the Compiler API? Of course, we'd give attribution and link to your blog post as the original source.
Sure, feel free to adapt stuff from my blog. I don't have anything on pretty printing yet. My last blog was about using the Compiler API to do formatting: http://blog.ctaggart.com/2015/01/format-typescript-with-v14-language.html
I want to be able to programmatically create a TS file and emit it.
@DanielRosenwasser mentioned last week:
How do do a
straight TS emit
?In the Using the Compiler API it says:
That is cool that you can emit a
.d.ts
definition. Is there any way to emit a.ts
file? Is there anything that can "pretty print" a TS AST?