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

How do you do a straight TS emit? #1651

Closed
ctaggart opened this issue Jan 13, 2015 · 13 comments
Closed

How do you do a straight TS emit? #1651

ctaggart opened this issue Jan 13, 2015 · 13 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@ctaggart
Copy link
Contributor

I want to be able to programmatically create a TS file and emit it.

@DanielRosenwasser mentioned last week:

It honestly may be better to do a straight TS emit if what you're looking for is definition file emit, if you're looking to use it as a verification pass for an intermediate language, or if you're looking to take advantage of our downlevel emit functionality.

How do do a straight TS emit?

In the Using the Compiler API it says:

Emitter: Output generated from a set of inputs (.ts and .d.ts) files can be one of: JavaScript (.js), definitions (.d.ts), or source maps (.js.map)

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?

@DanielRosenwasser
Copy link
Member

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.

@DanielRosenwasser DanielRosenwasser added the Question An issue which isn't directly actionable in code label Jan 13, 2015
@ctaggart
Copy link
Contributor Author

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:

image

@DanielRosenwasser
Copy link
Member

Why do you need that function? getFormattingEditsForDocument internally just calls that function and that is what we've chosen to expose.

@ctaggart
Copy link
Contributor Author

Is there any easy way to apply the TextChanges 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);

@DanielRosenwasser
Copy link
Member

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.

@ctaggart
Copy link
Contributor Author

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.

@ctaggart
Copy link
Contributor Author

Cleaned up for the formatting code and put the example here. :)
http://blog.ctaggart.com/2015/01/format-typescript-with-v14-language.html

@mhegazy
Copy link
Contributor

mhegazy commented Jan 15, 2015

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!

@ctaggart
Copy link
Contributor Author

@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

@DanielRosenwasser
Copy link
Member

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.

@ctaggart
Copy link
Contributor Author

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.

  • An F# Type Provider could be written that exposes types from .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.
  • An F# Type Provider could support inline TypeScript like Edge.js inlines JavaScript, but everything would be type safe.
  • F# programs can create TypeScipt code in order to create JavaScript code. I'd like to projects like FunScript more to this.

/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.

@DanielRosenwasser
Copy link
Member

@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.

@ctaggart
Copy link
Contributor Author

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

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

3 participants