Skip to content

How to get sourceFile with parentNode set? #14808

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

Closed
octref opened this issue Mar 23, 2017 · 4 comments
Closed

How to get sourceFile with parentNode set? #14808

octref opened this issue Mar 23, 2017 · 4 comments

Comments

@octref
Copy link

octref commented Mar 23, 2017

TypeScript Version: 2.2.1

I'm looking at the Compiler API and trying to figure out a way to parse a object literal like so:

export default {
  name: 'foo',
  props: ['bar', 'baz'],
  methods: {
    a () { return 1; },
    b () { return 2; }
  }
}

// Want to get object like this:
const info = {
  name: 'foo',
  props: ['bar', 'baz'],
  methods: ['a', 'b']
}

When I try to do it this way:

let program = ts.createProgram(['test.ts'], {
  target: ts.ScriptTarget.ES5, module: ts.ModuleKind.CommonJS
});
const sourceFile = program.getSourceFile('test.ts');
const exportDefaultObject = find(sourceFile.statements, st => st.kind === ts.SyntaxKind.ExportAssignment &&
  (st as ts.ExportAssignment).expression.kind === ts.SyntaxKind.ObjectLiteralExpression);
ts.forEachChild((exportDefaultObject as ts.ExportAssignment).expression, (literal: ts.ObjectLiteralExpression) => {
  const children = literal.getChildren();
  ...
}

literal.getChildren() or literal.getText() throws exception:

TypeError: Cannot read property 'text' of undefined

However, if I'm creating the sourceFile this way:

const sourceFile = ts.createSourceFile('test.ts', fs.readFileSync('test.ts').toString(), ts.ScriptTarget.ES5, true);

The same code works fine.

However, with setParentNodes as false, it throws same exception Cannot read property 'text'.

Full Code: https://github.com/octref/vueinfo/blob/master/index.ts#L13-L25

So my two questions are:

  1. What's the difference between these two ways of creating sourceFile, and why am I getting Cannot read property 'text' in one of them?
  2. Is there anyway I can use program.getSourceFile with setParentNodes, so I can access the AST behind it?
@ajafff
Copy link
Contributor

ajafff commented Mar 23, 2017

Call program.getTypeChecker(). This set's the parent property on all nodes. The result can be ignored.

@octref
Copy link
Author

octref commented Mar 24, 2017

@ajafff It worked! Wondering why the lack of parent property would cause property text not set, though.

@ajafff
Copy link
Contributor

ajafff commented Mar 24, 2017

node.getText() internally does something like node.getSouceFile().text.substring(start, end)

getSourceFile() walks up the parent chain until it finds ts.SourceFile or undefined

you could avoid that by passing the sourceFile to getText, getChildren, getStart, etc ... basically every function or method that has an optional sourceFile parameter (which you should do anyways to avoid unnecessary cpu work)

node.getText(sourceFile); // works even if parent is not set

@octref
Copy link
Author

octref commented Mar 24, 2017

Oh I see -- but TypeChecker seems pretty useful too.
Thanks for the detailed explanation. I guess I'll always pass the sourceFile as a rule of thumb.

@octref octref closed this as completed Mar 24, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants