TypeWriter logic for identifiers

This commit is contained in:
Jason Freeman 2014-08-11 16:01:30 -07:00
parent 3c6c0353b3
commit 96fba4d867
3 changed files with 65 additions and 9 deletions

View file

@ -52,7 +52,6 @@ class CompilerBaselineRunner extends RunnerBase {
var rootDir = lastUnit.originalFilePath.indexOf('conformance') === -1 ? 'tests/cases/compiler/' : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf('/')) + '/'; var rootDir = lastUnit.originalFilePath.indexOf('conformance') === -1 ? 'tests/cases/compiler/' : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf('/')) + '/';
var result: Harness.Compiler.CompilerResult; var result: Harness.Compiler.CompilerResult;
var program: ts.Program;
var checker: ts.TypeChecker; var checker: ts.TypeChecker;
var options: ts.CompilerOptions; var options: ts.CompilerOptions;
// equivalent to the files that will be passed on the command line // equivalent to the files that will be passed on the command line
@ -87,10 +86,9 @@ class CompilerBaselineRunner extends RunnerBase {
}); });
} }
options = harnessCompiler.compileFiles(toBeCompiled, otherFiles, function (compileResult, _program, _checker) { options = harnessCompiler.compileFiles(toBeCompiled, otherFiles, function (compileResult, _checker) {
result = compileResult; result = compileResult;
// The program and checker will be used by typeWriter // The checker will be used by typeWriter
program = _program;
checker = _checker; checker = _checker;
}, function (settings) { }, function (settings) {
harnessCompiler.setCompilerSettings(tcSettings); harnessCompiler.setCompilerSettings(tcSettings);
@ -262,7 +260,7 @@ class CompilerBaselineRunner extends RunnerBase {
var allFiles = toBeCompiled.concat(otherFiles); var allFiles = toBeCompiled.concat(otherFiles);
var typeLines: string[] = []; var typeLines: string[] = [];
var typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {}; var typeMap: { [fileName: string]: { [lineNum: number]: string[]; } } = {};
var walker = new TypeWriterWalker(program, checker); var walker = new TypeWriterWalker(checker);
allFiles.forEach(file => { allFiles.forEach(file => {
var codeLines = file.content.split('\n'); var codeLines = file.content.split('\n');
walker.getTypes(file.unitName).forEach(result => { walker.getTypes(file.unitName).forEach(result => {

View file

@ -609,7 +609,7 @@ module Harness {
public compileFiles(inputFiles: { unitName: string; content: string }[], public compileFiles(inputFiles: { unitName: string; content: string }[],
otherFiles: { unitName: string; content?: string }[], otherFiles: { unitName: string; content?: string }[],
onComplete: (result: CompilerResult, program: ts.Program, checker: ts.TypeChecker) => void, onComplete: (result: CompilerResult, checker: ts.TypeChecker) => void,
settingsCallback?: (settings: ts.CompilerOptions) => void, settingsCallback?: (settings: ts.CompilerOptions) => void,
options?: ts.CompilerOptions) { options?: ts.CompilerOptions) {
@ -755,7 +755,7 @@ module Harness {
var result = new CompilerResult(fileOutputs, errors, []); var result = new CompilerResult(fileOutputs, errors, []);
// Covert the source Map data into the baseline // Covert the source Map data into the baseline
result.updateSourceMapRecord(program, emitResult ? emitResult.sourceMaps : undefined); result.updateSourceMapRecord(program, emitResult ? emitResult.sourceMaps : undefined);
onComplete(result, program, checker); onComplete(result, checker);
// reset what newline means in case the last test changed it // reset what newline means in case the last test changed it
sys.newLine = '\r\n'; sys.newLine = '\r\n';

View file

@ -7,9 +7,67 @@ interface TypeWriterResult {
} }
class TypeWriterWalker { class TypeWriterWalker {
constructor(public program: ts.Program, public checker: ts.TypeChecker) { results: TypeWriterResult[];
currentSourceFile: ts.SourceFile;
constructor(public checker: ts.TypeChecker) {
} }
public getTypes(fileName: string): TypeWriterResult[] { public getTypes(fileName: string): TypeWriterResult[] {
return []; var sourceFile = this.checker.getProgram().getSourceFile(fileName);
this.currentSourceFile = sourceFile;
this.results = [];
this.visitNode(sourceFile);
return this.results;
}
private visitNode(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.Identifier) {
var identifier = <ts.Identifier>node;
if (!this.isLabel(identifier)) {
var type = this.getTypeOfIdentifier(identifier);
this.log(node, type);
}
}
else if (node.kind === ts.SyntaxKind.ThisKeyword) {
this.log(node, undefined);
}
else {
ts.forEachChild(node, child => this.visitNode(child));
}
}
private isLabel(identifier: ts.Identifier): boolean {
var parent = identifier.parent;
switch (parent.kind) {
case ts.SyntaxKind.ContinueStatement:
case ts.SyntaxKind.BreakStatement:
return (<ts.BreakOrContinueStatement>parent).label === identifier;
case ts.SyntaxKind.LabelledStatement:
return (<ts.LabelledStatement>parent).label === identifier;
}
return false;
}
private log(node: ts.Node, type: ts.Type): void {
var actualPos = ts.skipTrivia(this.currentSourceFile.text, node.pos);
var lineAndCharacter = this.currentSourceFile.getLineAndCharacterFromPosition(actualPos);
var name = ts.getSourceTextOfNodeFromSourceText(this.currentSourceFile.text, node);
this.results.push({
line: lineAndCharacter.line - 1,
column: lineAndCharacter.character,
syntaxKind: ts.SyntaxKind[node.kind],
identifierName: name,
type: this.checker.typeToString(type)
});
}
private getTypeOfIdentifier(node: ts.Identifier): ts.Type {
var identifierSymbol = this.checker.getSymbolInfo(node);
ts.Debug.assert(identifierSymbol, "symbol doesn't exist");
var type = this.checker.getTypeOfSymbol(identifierSymbol);
ts.Debug.assert(type, "type doesn't exist");
return type;
} }
} }