Add a dedicated 'EndOfFile' token to a SourceFile.

This is important for incremental parsing, as it is where we can attach parse errors at the end of
the file to.  Also, it helps with things like emitting comments at the end of the file.
This commit is contained in:
Cyrus Najmabadi 2014-12-02 16:09:41 -08:00
parent 6e945afdf5
commit 5a7500ca5e
46 changed files with 636 additions and 3 deletions

View File

@ -3443,6 +3443,7 @@ module ts {
// Start new file on new line
writeLine();
emitDetachedComments(node);
// emit prologue directives prior to __extends
var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false);
if (!extendsEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitExtends) {
@ -3474,6 +3475,8 @@ module ts {
emitCaptureThisForNodeIfNecessary(node);
emitLinesStartingAt(node.statements, startIndex);
}
emitLeadingComments(node.endOfFileToken);
}
function emitNode(node: Node): void {

View File

@ -313,8 +313,10 @@ module ts {
case SyntaxKind.FinallyBlock:
case SyntaxKind.FunctionBlock:
case SyntaxKind.ModuleBlock:
case SyntaxKind.SourceFile:
return children((<Block>node).statements);
case SyntaxKind.SourceFile:
return children((<SourceFile>node).statements) ||
child((<SourceFile>node).endOfFileToken);
case SyntaxKind.VariableStatement:
return children(node.modifiers) ||
children((<VariableStatement>node).declarations);
@ -4294,6 +4296,9 @@ module ts {
sourceFile.amdModuleName = referenceComments.amdModuleName;
sourceFile.statements = parseList(ParsingContext.SourceElements, /*checkForStrictMode*/ true, parseSourceElement);
Debug.assert(token === SyntaxKind.EndOfFileToken);
sourceFile.endOfFileToken = parseTokenNode();
sourceFile.externalModuleIndicator = getExternalModuleIndicator();
sourceFile.nodeCount = nodeCount;

View File

@ -786,6 +786,7 @@ module ts {
// Source files are declarations when they are external modules.
export interface SourceFile extends Declaration {
statements: NodeArray<ModuleElement>;
endOfFileToken: Node;
filename: string;
text: string;

View File

@ -722,6 +722,9 @@ module ts {
public filename: string;
public text: string;
public statements: NodeArray<Statement>;
public endOfFileToken: Node;
// These methods will have their implementation provided by the implementation the
// compiler actually exports off of SourceFile.
public getLineAndCharacterFromPosition: (position: number) => LineAndCharacter;
@ -743,7 +746,6 @@ module ts {
public nodeCount: number;
public identifierCount: number;
public symbolCount: number;
public statements: NodeArray<Statement>;
public version: string;
public isOpen: boolean;
public languageVersion: ScriptTarget;

View File

@ -83,3 +83,8 @@ function foo(x, y, z) {
y = a;
z = a;
}
//function foo<T, U extends T, V extends Date>(x: T, y: U, z: V) {
// x = a;
// y = a;
// z = a;
//}

View File

@ -52,3 +52,4 @@ var c5c = (function () {
};
return c5c;
})();
//import c5c = require('');

View File

@ -105,3 +105,6 @@ var e6b;
(function (e6b) {
e6b.y = 2;
})(e6b || (e6b = {})); // should be error
// enum then import, messes with error reporting
//enum e7 { One }
//import e7 = require(''); // should be error

View File

@ -40,3 +40,5 @@ var e2 = (function () {
};
return e2;
})();
//enum then enum - covered
//enum then import - covered

View File

@ -93,3 +93,6 @@ var y5b;
})(y5b || (y5b = {})); // should be an error
function y5c() {
}
// function then import, messes with other errors
//function y6() { }
//import y6 = require('');

View File

@ -48,3 +48,4 @@ var i3;
i3[i3["One"] = 0] = "One";
})(i3 || (i3 = {}));
;
//import i4 = require(''); // error

View File

@ -268,3 +268,4 @@ var m6;
(function (m6) {
m6.y = 2;
})(m6 || (m6 = {}));
//import m6 = require('');

View File

@ -80,3 +80,6 @@ var x6b;
(function (x6b) {
x6b.y = 2;
})(x6b || (x6b = {})); // error
// var then import, messes with other error reporting
//var x7 = 1;
//import x7 = require('');

View File

@ -45,3 +45,37 @@ var Derived = (function (_super) {
})(Base);
var x = null;
var y = x[0];
/*
// Note - the equivalent for normal interface methods works fine:
interface A {
foo(): Base;
}
interface B<TBase extends Base> extends A {
foo(): TBase;
}
var b: B<Derived> = null;
var z: Derived = b.foo();
class Base { private a: string; }
class Derived extends Base { private b: string; }
// Note - commmenting "extends Foo" prevents the error
interface Foo {
[i: number]: Base;
}
interface FooOf<TBase extends Base> extends Foo {
[i: number]: TBase;
}
var x: FooOf<Derived> = null;
var y: Derived = x[0];
/*
// Note - the equivalent for normal interface methods works fine:
interface A {
foo(): Base;
}
interface B<TBase extends Base> extends A {
foo(): TBase;
}
var b: B<Derived> = null;
var z: Derived = b.foo();

View File

@ -0,0 +1,22 @@
//// [commentEmitAtEndOfFile1.ts]
// test
var f = ''
// test #2
module foo {
function bar() { }
}
// test #3
module empty {
}
// test #4
//// [commentEmitAtEndOfFile1.js]
// test
var f = '';
// test #2
var foo;
(function (foo) {
function bar() {
}
})(foo || (foo = {}));
// test #4

View File

@ -0,0 +1,17 @@
=== tests/cases/compiler/commentEmitAtEndOfFile1.ts ===
// test
var f = ''
>f : string
// test #2
module foo {
>foo : typeof foo
function bar() { }
>bar : () => void
}
// test #3
module empty {
>empty : unknown
}
// test #4

View File

@ -6,3 +6,4 @@ Input:
//// [commentsAtEndOfFile1.js]
Input: ;
//Testing two

View File

@ -501,3 +501,4 @@ var r8b8 = b8 !== a8;
var r8b9 = b9 !== a9;
var r8b10 = b10 !== a10;
var r8b11 = b11 !== a11;
//var r8b12 = b12 !== a12;

View File

@ -427,3 +427,4 @@ var r8b6 = b6 !== a6;
var r8b7 = b7 !== a7;
var r8b8 = b8 !== a8;
var r8b9 = b9 !== a9;
//var r8b10 = b10 !== a10;

View File

@ -316,3 +316,4 @@ var r8b3 = b3 !== a3;
var r8b4 = b4 !== a4;
var r8b5 = b5 !== a5;
var r8b6 = b6 !== a6;
//var r8b7 = b7 !== a7;

View File

@ -316,3 +316,4 @@ var r8b3 = b3 !== a3;
var r8b4 = b4 !== a4;
var r8b5 = b5 !== a5;
var r8b6 = b6 !== a6;
//var r8b7 = b7 !== a7;

View File

@ -43,3 +43,48 @@ interface Array<T> {
var fa;
fa = fa.concat([0]);
fa = fa.concat(0);
/*
declare class C<T> {
public m(p1: C<C<T>>): C<T>;
//public p: T;
}
var c: C<number>;
var cc: C<C<number>>;
c = c.m(cc);
var n1: number[];
/*
interface Array<T> {
concat(...items: T[][]): T[]; // Note: This overload needs to be picked for arrays of arrays, even though both are applicable
concat(...items: T[]): T[];
}
*/
var fa: number[];
fa = fa.concat([0]);
fa = fa.concat(0);
/*
declare class C<T> {
public m(p1: C<C<T>>): C<T>;
//public p: T;
}
var c: C<number>;
var cc: C<C<number>>;
c = c.m(cc);

View File

@ -25,3 +25,13 @@
//// [conformanceFunctionOverloads.js]
// Function overloads do not emit code
// Function overload signature with optional parameter
// Function overload signature with optional parameter
// Function overloads with generic and non-generic overloads
// Function overloads whose only difference is returning different unconstrained generic parameters
// Function overloads whose only difference is returning different constrained generic parameters
// Function overloads that differ only by type parameter constraints
// Function overloads with matching accessibility
// Function overloads with matching export
// Function overloads with more params than implementation signature
// Function overloads where return types are same infinitely recursive type reference

View File

@ -29,3 +29,29 @@
//// [emitCommentsOnlyFile.js]
/**
* @name Foo
* @class
*/
/**#@+
* @memberOf Foo#
* @field
*/
/**
* @name bar
* @type Object[]
*/
/**#@-*/
/**
* @name Foo2
* @class
*/
/**#@+
* @memberOf Foo2#
* @field
*/
/**
* @name bar
* @type Object[]
*/
/**#@-*/

View File

@ -31,3 +31,29 @@ var y = 10;
//// [emitPostComments.js]
var y = 10;
/**
* @name Foo
* @class
*/
/**#@+
* @memberOf Foo#
* @field
*/
/**
* @name bar
* @type Object[]
*/
/**#@-*/
/**
* @name Foo2
* @class
*/
/**#@+
* @memberOf Foo2#
* @field
*/
/**
* @name bar
* @type Object[]
*/
/**#@-*/

View File

@ -33,3 +33,29 @@ var y = 10;
//// [emitPreComments.js]
// This is pre comment
var y = 10;
/**
* @name Foo
* @class
*/
/**#@+
* @memberOf Foo#
* @field
*/
/**
* @name bar
* @type Object[]
*/
/**#@-*/
/**
* @name Foo2
* @class
*/
/**#@+
* @memberOf Foo2#
* @field
*/
/**
* @name bar
* @type Object[]
*/
/**#@-*/

View File

@ -20,3 +20,4 @@ var Foo = (function () {
var baz = Foo.b;
// Foo.b won't bind.
baz.concat("y");
// So we don't want an error on 'concat'.

View File

@ -113,3 +113,8 @@ function foo(x, y, z) {
a = y;
a = z;
}
//function foo<T, U extends T, V extends Date>(x: T, y: U, z: V) {
// a = x;
// a = y;
// a = z;
//}

View File

@ -113,3 +113,7 @@ function foo2(x, y) {
foo(x);
foo(y);
}
//function foo2<T extends { (): void }, U extends T>(x: T, y: U) {
// foo(x);
// foo(y);
//}

View File

@ -57,3 +57,10 @@ function other3(arg) {
// BUG 821629
//var u: U = r2[1]; // ok
}
//function other3<T extends U, U extends Date>(arg: T) {
// var b: { [x: number]: T };
// var r2 = foo(b);
// var d = r2[1];
// // BUG 821629
// //var u: U = r2[1]; // ok
//}

View File

@ -58,3 +58,10 @@ function other3(arg) {
// BUG 821629
//var u: U = r2['hm']; // ok
}
//function other3<T extends U, U extends Date>(arg: T) {
// var b: { [x: string]: T };
// var r2 = foo(b);
// var d: Date = r2['hm']; // ok
// // BUG 821629
// //var u: U = r2['hm']; // ok
//}

View File

@ -241,3 +241,28 @@ function foo4(t, u) {
var j = [u, derived]; // Derived[]
var k = [t, u];
}
//function foo3<T extends U, U extends Derived>(t: T, u: U) {
// var a = [t, t]; // T[]
// var b = [t, null]; // T[]
// var c = [t, u]; // {}[]
// var d = [t, 1]; // {}[]
// var e = [() => t, () => u]; // {}[]
// var f = [() => t, () => u, () => null]; // { (): any }[]
// var g = [t, base]; // Base[]
// var h = [t, derived]; // Derived[]
// var i = [u, base]; // Base[]
// var j = [u, derived]; // Derived[]
//}
//function foo4<T extends U, U extends Base>(t: T, u: U) {
// var a = [t, t]; // T[]
// var b = [t, null]; // T[]
// var c = [t, u]; // BUG 821629
// var d = [t, 1]; // {}[]
// var e = [() => t, () => u]; // {}[]
// var f = [() => t, () => u, () => null]; // { (): any }[]
// var g = [t, base]; // Base[]
// var h = [t, derived]; // Derived[]
// var i = [u, base]; // Base[]
// var j = [u, derived]; // Derived[]
// var k: Base[] = [t, u];
//}

View File

@ -47,3 +47,11 @@ function f2() {
var x;
x.getDate();
}
//function f2<T extends Date, U extends T>() {
// function g<T extends Number, U extends T>() {
// var x: U;
// x.toFixed();
// }
// var x: U;
// x.getDate();
//}

View File

@ -66,3 +66,13 @@ var C2 = (function () {
};
return C2;
})();
//class C2<T extends Date, U extends T> {
// g<T extends Number, U extends T>() {
// var x: U;
// x.toFixed();
// }
// h() {
// var x: U;
// x.getDate();
// }
//}

View File

@ -18,3 +18,5 @@ var M;
//var p: M.P;
//var m: M = M;
var x1 = M.a;
//var x2 = m.a;
//var q: m.P;

View File

@ -80,3 +80,8 @@ function foo(x, y, z) {
y = null;
z = null;
}
//function foo<T, U extends T, V extends Date>(x: T, y: U, z: V) {
// x = null;
// y = null;
// z = null;
//}

View File

@ -17,3 +17,11 @@
//// [parserS7.6.1.1_A1.10.js]
// Copyright 2009 the Sputnik authors. All rights reserved.
// This code is governed by the BSD license found in the LICENSE file.
/**
* The "for" token can not be used as identifier
*
* @path ch07/7.6/7.6.1/7.6.1.1/S7.6.1.1_A1.10.js
* @description Checking if execution of "for=1" fails
* @negative
*/
//for = 1;

View File

@ -289,3 +289,220 @@
// [index: number]: string;
// }
//}
//import fs = module("fs");
//module TypeScriptAllInOne {
// export class Program {
// static Main(...args: string[]) {
// try {
// var bfs = new BasicFeatures();
// var retValue: number = 0;
// retValue = bfs.VARIABLES();
// if (retValue != 0) {
// return 1;
// }
// retValue = bfs.STATEMENTS(4);
// if (retValue != 0) {
// return 1;
// }
// retValue = bfs.TYPES();
// if (retValue != 0) {
// return 1;
// }
// retValue = bfs.OPERATOR();
// if (retValue != 0) {
// return 1;
// }
// }
// catch (e) {
// console.log(e);
// }
// finally {
// }
// console.log('Done');
// return 0;
// }
// }
// class BasicFeatures {
// /// <summary>
// /// Test various of variables. Including nullable,key world as variable,special format
// /// </summary>
// /// <returns></returns>
// public VARIABLES(): number {
// var local = Number.MAX_VALUE;
// var min = Number.MIN_VALUE;
// var inf = Number.NEGATIVE_INFINITY;
// var nan = Number.NaN;
// var undef = undefined;
// var п = local;
// var м = local;
// var local5 = <fs.File>null;
// var local6 = local5 instanceof fs.File;
// var hex = 0xBADC0DE, Hex = 0XDEADBEEF;
// var float = 6.02e23, float2 = 6.02E-23
// var char = 'c', \u0066 = '\u0066', hexchar = '\x42';
// var quoted = '"', quoted2 = "'";
// var reg = /\w*/;
// var objLit = { "var": number = 42, equals: function (x) { return x["var"] === 42; }, toString: () => 'objLit{42}' };
// var weekday = Weekdays.Monday;
// var con = char + f + hexchar + float.toString() + float2.toString() + reg.toString() + objLit + weekday;
// //
// var any = 0;
// var boolean = 0;
// var declare = 0;
// var constructor = 0;
// var get = 0;
// var implements = 0;
// var interface = 0;
// var let = 0;
// var module = 0;
// var number = 0;
// var package = 0;
// var private = 0;
// var protected = 0;
// var public = 0;
// var set = 0;
// var static = 0;
// var string = 0;
// var yield = 0;
// var sum3 = any + boolean + declare + constructor + get + implements + interface + let + module + number + package + private + protected + public + set + static + string + yield;
// return 0;
// }
// /// <summary>
// /// Test different statements. Including if-else,swith,foreach,(un)checked,lock,using,try-catch-finally
// /// </summary>
// /// <param name="i"></param>
// /// <returns></returns>
// STATEMENTS(i: number): number {
// var retVal = 0;
// if (i == 1)
// retVal = 1;
// else
// retVal = 0;
// switch (i) {
// case 2:
// retVal = 1;
// break;
// case 3:
// retVal = 1;
// break;
// default:
// break;
// }
// for (var x in { x: 0, y: 1 }) {
// }
// try {
// throw null;
// }
// catch (Exception) {
// }
// finally {
// try { }
// catch (Exception) { }
// }
// return retVal;
// }
// /// <summary>
// /// Test types in ts language. Including class,struct,interface,delegate,anonymous type
// /// </summary>
// /// <returns></returns>
// public TYPES(): number {
// var retVal = 0;
// var c = new CLASS();
// var xx: IF = c;
// retVal += c.Property;
// retVal += c.Member();
// retVal += xx ^= Foo() ? 0 : 1;
// //anonymous type
// var anony = { a: new CLASS() };
// retVal += anony.a.d();
// return retVal;
// }
// ///// <summary>
// ///// Test different operators
// ///// </summary>
// ///// <returns></returns>
// public OPERATOR(): number {
// var a: number[] = [1, 2, 3, 4, implements , ];/*[] bug*/ // YES []
// var i = a[1];/*[]*/
// i = i + i - i * i / i % i & i | i ^ i;/*+ - * / % & | ^*/
// var b = true && false || true ^ false;/*& | ^*/
// b = !b;/*!*/
// i = ~i;/*~i*/
// b = i < (i - continue ) && (i + 1) > i;/*< && >*/
// var f = true ? 1 : 0;/*? :*/ // YES :
// i++;/*++*/
// i--;/*--*/
// b = true && false || true;/*&& ||*/
// i = i << 5;/*<<*/
// i = i >> 5;/*>>*/
// var j = i;
// b = i == j && i != j && i <= j && i >= j;/*= == && != <= >=*/
// i += <number>5.0;/*+=*/
// i -= i;/*-=*/
// i *= i;/**=*/
// if (i == 0)
// i++;
// i /= i;/*/=*/
// i %= i;/*%=*/
// i &= i;/*&=*/
// i |= i;/*|=*/
// i ^= i;/*^=*/
// i <<= i;/*<<=*/
// i >>= i;/*>>=*/
// if (i == 0 && !b && f == 1)
// return 0;
// else return 1;
// }
// }
// interface IF {
// Foo <!-- ): boolean;
// }
// class CLASS implements IF {
// public d = () => ' return 0; };
// public get Property() { return 0; }
// public Member() {
// return 0;
// }
// public Foo(): boolean {
// var myEvent = () => { return 1; };
// if (myEvent() == 1)
// return true;
// else
// return false;
// }
// }
// // todo: use these
// class A {
// public method1(val:number) {
// return val;
// }
// public method2() {
// return 2 * this.method1(2);
// }
// }
// class B extends A {
// public method2() {
// return this.method1(2);
// }
// }
// class Overloading {
// private otherValue = 42;
// constructor(private value: number, public name: string) { }
// public Overloads(value: string);
// public Overloads(value: string, ...rest: string[]) { }
// public DefaultValue(value?: string = "Hello") { }
// }
//}
//enum Weekdays {
// Monday,
// Tuesday,
// Weekend,
//}
//enum Fruit {
// Apple,
// Pear
//}
//interface IDisposable {
// Dispose(): void;
//}
//TypeScriptAllInOne.Program.Main();

View File

@ -62,3 +62,44 @@ var MsPortal;
})(Base = Controls.Base || (Controls.Base = {}));
})(Controls = MsPortal.Controls || (MsPortal.Controls = {}));
})(MsPortal || (MsPortal = {}));
// Generates:
/*
declare module MsPortal.Controls.Base.ItemList {
interface Interface<TValue> {
options: ViewModel<TValue>;
}
class ItemValue<T> {
constructor(value: T);
}
class ViewModel<TValue> extends ItemValue<TValue> {
}
}
module MsPortal.Controls.Base.ItemList {
export interface Interface<TValue> {
// Removing this line fixes the constructor of ItemValue
options: ViewModel<TValue>;
}
export class ItemValue<T> {
constructor(value: T) {
}
}
export class ViewModel<TValue> extends ItemValue<TValue> {
}
}
// Generates:
/*
declare module MsPortal.Controls.Base.ItemList {
interface Interface<TValue> {
options: ViewModel<TValue>;
}
class ItemValue<T> {
constructor(value: T);
}
class ViewModel<TValue> extends ItemValue<TValue> {
}
}

View File

@ -2,4 +2,5 @@
// Comment
//// [sourceMap-Comment1.js]
// Comment
//# sourceMappingURL=sourceMap-Comment1.js.map

View File

@ -1,2 +1,2 @@
//// [sourceMap-Comment1.js.map]
{"version":3,"file":"sourceMap-Comment1.js","sourceRoot":"","sources":["sourceMap-Comment1.ts"],"names":[],"mappings":""}
{"version":3,"file":"sourceMap-Comment1.js","sourceRoot":"","sources":["sourceMap-Comment1.ts"],"names":[],"mappings":"AAAA,UAAU"}

View File

@ -4,4 +4,17 @@ mapUrl: sourceMap-Comment1.js.map
sourceRoot:
sources: sourceMap-Comment1.ts
===================================================================
-------------------------------------------------------------------
emittedFile:tests/cases/compiler/sourceMap-Comment1.js
sourceFile:sourceMap-Comment1.ts
-------------------------------------------------------------------
>>>// Comment
1 >
2 >^^^^^^^^^^
3 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
1 >
2 >// Comment
1 >Emitted(1, 1) Source(1, 1) + SourceIndex(0)
2 >Emitted(1, 11) Source(1, 11) + SourceIndex(0)
---
>>>//# sourceMappingURL=sourceMap-Comment1.js.map

View File

@ -39,3 +39,13 @@ var C = (function () {
}
return C;
})();
//function foo<T, U extends T>(x: T, y: U) {
// foo<U, U>(y, y);
// return new C<U, T>();
//}
//class C<T extends U, U> {
// x: T;
//}
//interface I<T, U extends T> {
// x: C<U, T>;
//}

View File

@ -53,3 +53,15 @@ interface I2<V, T, U> {
//// [typeParameterUsedAsTypeParameterConstraint3.js]
// Type parameters are in scope in their own and other type parameter lists
// Object types
//interface I < T, U extends T, V extends U > {
// x: T;
// y: U;
// z: V;
// foo<W extends V>(x: W): T;
//}
//interface I2<V extends U, T, U extends T> {
// x: T;
// y: U;
// z: V;
// foo<W extends V>(x: W): T;
//}

View File

@ -79,3 +79,8 @@ function foo(x, y, z) {
y = undefined;
z = undefined;
}
//function foo<T, U extends T, V extends Date>(x: T, y: U, z: V) {
// x = undefined;
// y = undefined;
// z = undefined;
//}

View File

@ -269,3 +269,4 @@ var C3 = (function () {
})();
var qq = C3.q;
var qq;
// Parentheses - tested a bunch above

View File

@ -0,0 +1,10 @@
// test
var f = ''
// test #2
module foo {
function bar() { }
}
// test #3
module empty {
}
// test #4