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

is there an example of how to transform AST of a file and emit it? #7580

Closed
zpdDG4gta8XKpMCd opened this issue Mar 18, 2016 · 16 comments
Closed
Labels
API Relates to the public API for TypeScript Question An issue which isn't directly actionable in code

Comments

@zpdDG4gta8XKpMCd
Copy link

I would like to make a tool to replace imports of old style to imports of new style:

// before
import dsa = require('data/search/account');
// after
import * as dsa from 'data/search/account';

is it possible to do via public compiler api?
if so, can anyone outline the steps?

@zpdDG4gta8XKpMCd
Copy link
Author

another example is enforcing curly braces on if statements and such:

// before
if (isThis())
   thenThat();
// after
if (isThis()) {
   thenThat();
}

@DanielRosenwasser DanielRosenwasser added Question An issue which isn't directly actionable in code API Relates to the public API for TypeScript labels Mar 18, 2016
@DanielRosenwasser
Copy link
Member

Ideally you could do this with #5595 (see also #3241), but until we have an API for that, you can use our language service API.

Then:

  1. aggregate the nodes of interest
  2. generate the intended replacement text for each node
  3. and apply replacements in reverse

Something like this might work:

import * as ts from "typescript";
import * as fs from "fs";

interface Replacement {
    start: number;
    end: number;
    replacementText: string;
}

function transformProgram(program: ts.Program) {
    for (const file of program.getSourceFiles()) {
        const replacements = getReplacements(file);
        replacements.reverse();

        const newText = getNewText(file.getText(), replacements);
        fs.writeFileSync(file.fileName, newText);
    }
}

function getReplacements(sourceFile: ts.SourceFile) {
    const replacements: Replacement[] = [];
    for (const statement of sourceFile.statements) {
        if (statement.kind !== ts.SyntaxKind.ImportEqualsDeclaration) {
            continue;
        }

        const importEquals = statement as ts.ImportEqualsDeclaration;
        if (importEquals.moduleReference.kind !== ts.SyntaxKind.ExternalModuleReference) {
            continue;
        }

        const importString = (importEquals.moduleReference as ts.ExternalModuleReference).expression as ts.StringLiteral;
        if (!importString || importString.kind !== ts.SyntaxKind.StringLiteral) {
            continue;
        }

        replacements.push({
            start: statement.getStart(),
            end: statement.getEnd(),
            replacementText: `import ${ importEquals.name.getText() } from "${ importString.getText() }";`
        });
    }
    return replacements;
}

function getNewText(sourceText: string, replacementsInReverse: Replacement[]) {
    for (const { start, end, replacementText } of replacementsInReverse) {
        sourceText = sourceText.slice(0, start) + replacementText + sourceText.slice(end)
    }

    return sourceText;
}

Don't hold me to it though, I haven't tested it out yet.

@DanielRosenwasser
Copy link
Member

Also check out https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#pretty-printer-using-the-ls-formatter

@wclr
Copy link

wclr commented Sep 4, 2016

Is it possible now to make source transformation using alternations in AST not via text replacement as shown?

@kitsonk
Copy link
Contributor

kitsonk commented Sep 4, 2016

When #5595 lands, yes... it should be in master soon

@wclr
Copy link

wclr commented Sep 7, 2016

So #5595 seem to land? Is there some docs/info about transforming AST?

@kitsonk
Copy link
Contributor

kitsonk commented Sep 7, 2016

No, not yet... the team have been burning the midnight oil to get it into master. If you don't feel comfortable spelunking in the source code for TypeScript, I think you are going to have to wait a while until there is any sort of decent documentation. Likely though, especially when it comes to using the services and other internals of TypeScript, it is really up to the wider community to start providing the "how to" instead of official documentation.

@wclr
Copy link

wclr commented Sep 7, 2016

@kitsonk Ok, thanks for response) I'm quite comfortable with source/tests code. Here is what I want to do:

  1. I have a source TS file
  2. Need to load it and get AST (I assume it is done using ts.createSourceFile)
  3. Need a way to change AST (not sure how)
  4. Compile changed AST
  5. (as a bonus) Access resulting AST

Are step 3-5 possible now? If yest could you direct to the source that should be investigated?

@rbuckton
Copy link
Member

rbuckton commented Sep 8, 2016

We do not currently expose the transformation API as part of the language service. This is something we are considering. Once we make it available as a public API we will provide documentation on its use.

@wclr
Copy link

wclr commented Sep 8, 2016

@rbuckton so it is not possible at all? ok can be hacked around?

@zpdDG4gta8XKpMCd
Copy link
Author

i think he said that it is in private api that isnt exposed to public, can you use private API of TypeScript? sure, just take a full ownership of it meaning write your code right in it or modify it so that it is public

@wclr
Copy link

wclr commented Sep 8, 2016

Ok, I get it, now I ask where to look for this private API in particular?

@zpdDG4gta8XKpMCd
Copy link
Author

here is a list of all code cjanges related to AST transformations, at this point i'd say there is no better way to learn it other than by looking at what was done

@cape-dev
Copy link

cape-dev commented Oct 13, 2016

We do not currently expose the transformation API as part of the language service. This is something we are considering. Once we make it available as a public API we will provide documentation on its use.

@rbuckton Is there an entry on the roadmap for making the AST transformation API public? Or can you estimate when this will happen?

@whitecolor Did you find a way to achieve your goals?

@wclr
Copy link

wclr commented Oct 19, 2016

@kamekazemaster no i didn't look close yet

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

No branches or pull requests

7 participants