Merge branch 'master' into forwardRefsInEnumInitializers

This commit is contained in:
Vladimir Matveev
2015-07-27 17:51:20 -07:00
40 changed files with 1223 additions and 185 deletions

View File

@@ -0,0 +1,22 @@
tests/cases/compiler/aliasesInSystemModule1.ts(2,24): error TS2307: Cannot find module 'foo'.
==== tests/cases/compiler/aliasesInSystemModule1.ts (1 errors) ====
import alias = require('foo');
~~~~~
!!! error TS2307: Cannot find module 'foo'.
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}

View File

@@ -0,0 +1,42 @@
//// [aliasesInSystemModule1.ts]
import alias = require('foo');
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}
//// [aliasesInSystemModule1.js]
System.register(['foo'], function(exports_1) {
var alias;
var cls, cls2, x, y, z, M;
return {
setters:[
function (_alias) {
alias = _alias;
}],
execute: function() {
cls = alias.Class;
exports_1("cls2", cls2 = alias.Class);
x = new alias.Class();
y = new cls();
z = new cls2();
(function (M) {
M.cls = alias.Class;
var x = new alias.Class();
var y = new M.cls();
var z = new cls2();
})(M || (M = {}));
}
}
});

View File

@@ -0,0 +1,21 @@
tests/cases/compiler/aliasesInSystemModule2.ts(2,21): error TS2307: Cannot find module 'foo'.
==== tests/cases/compiler/aliasesInSystemModule2.ts (1 errors) ====
import {alias} from "foo";
~~~~~
!!! error TS2307: Cannot find module 'foo'.
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}

View File

@@ -0,0 +1,41 @@
//// [aliasesInSystemModule2.ts]
import {alias} from "foo";
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}
//// [aliasesInSystemModule2.js]
System.register(["foo"], function(exports_1) {
var foo_1;
var cls, cls2, x, y, z, M;
return {
setters:[
function (_foo_1) {
foo_1 = _foo_1;
}],
execute: function() {
cls = foo_1.alias.Class;
exports_1("cls2", cls2 = foo_1.alias.Class);
x = new foo_1.alias.Class();
y = new cls();
z = new cls2();
(function (M) {
M.cls = foo_1.alias.Class;
var x = new foo_1.alias.Class();
var y = new M.cls();
var z = new cls2();
})(M || (M = {}));
}
}
});

View File

@@ -1,7 +0,0 @@
error TS5043: Option 'sourceMap' cannot be specified with option 'isolatedModules'.
!!! error TS5043: Option 'sourceMap' cannot be specified with option 'isolatedModules'.
==== tests/cases/compiler/isolatedModulesSourceMap.ts (0 errors) ====
export var x;

View File

@@ -1,7 +1,7 @@
//// [isolatedModulesSourceMap.ts]
export var x;
export var x = 1;
//// [isolatedModulesSourceMap.js]
export var x;
export var x = 1;
//# sourceMappingURL=isolatedModulesSourceMap.js.map

View File

@@ -1,2 +1,2 @@
//// [isolatedModulesSourceMap.js.map]
{"version":3,"file":"isolatedModulesSourceMap.js","sourceRoot":"","sources":["isolatedModulesSourceMap.ts"],"names":[],"mappings":"AACA,WAAW,CAAC,CAAC"}
{"version":3,"file":"isolatedModulesSourceMap.js","sourceRoot":"","sources":["isolatedModulesSourceMap.ts"],"names":[],"mappings":"AACA,WAAW,CAAC,GAAG,CAAC,CAAC"}

View File

@@ -8,20 +8,26 @@ sources: isolatedModulesSourceMap.ts
emittedFile:tests/cases/compiler/isolatedModulesSourceMap.js
sourceFile:isolatedModulesSourceMap.ts
-------------------------------------------------------------------
>>>export var x;
>>>export var x = 1;
1 >
2 >^^^^^^^^^^^
3 > ^
4 > ^
5 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
4 > ^^^
5 > ^
6 > ^
7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
1 >
>
2 >export var
3 > x
4 > ;
4 > =
5 > 1
6 > ;
1 >Emitted(1, 1) Source(2, 1) + SourceIndex(0)
2 >Emitted(1, 12) Source(2, 12) + SourceIndex(0)
3 >Emitted(1, 13) Source(2, 13) + SourceIndex(0)
4 >Emitted(1, 14) Source(2, 14) + SourceIndex(0)
4 >Emitted(1, 16) Source(2, 16) + SourceIndex(0)
5 >Emitted(1, 17) Source(2, 17) + SourceIndex(0)
6 >Emitted(1, 18) Source(2, 18) + SourceIndex(0)
---
>>>//# sourceMappingURL=isolatedModulesSourceMap.js.map

View File

@@ -0,0 +1,5 @@
=== tests/cases/compiler/isolatedModulesSourceMap.ts ===
export var x = 1;
>x : Symbol(x, Decl(isolatedModulesSourceMap.ts, 1, 10))

View File

@@ -0,0 +1,6 @@
=== tests/cases/compiler/isolatedModulesSourceMap.ts ===
export var x = 1;
>x : number
>1 : number

View File

@@ -0,0 +1,21 @@
//// [tests/cases/compiler/jsxImportInAttribute.tsx] ////
//// [component.d.ts]
declare module "Test" {
export default class Text { }
}
//// [consumer.tsx]
/// <reference path="component.d.ts" />
import Test from 'Test';
let x = Test; // emit test_1.default
<anything attr={Test} />; // ?
//// [consumer.jsx]
/// <reference path="component.d.ts" />
var Test_1 = require('Test');
var x = Test_1["default"]; // emit test_1.default
<anything attr={Test_1["default"]}/>; // ?

View File

@@ -0,0 +1,19 @@
=== tests/cases/compiler/consumer.tsx ===
/// <reference path="component.d.ts" />
import Test from 'Test';
>Test : Symbol(Test, Decl(consumer.tsx, 1, 6))
let x = Test; // emit test_1.default
>x : Symbol(x, Decl(consumer.tsx, 3, 3))
>Test : Symbol(Test, Decl(consumer.tsx, 1, 6))
<anything attr={Test} />; // ?
>attr : Symbol(unknown)
=== tests/cases/compiler/component.d.ts ===
declare module "Test" {
export default class Text { }
>Text : Symbol(Text, Decl(component.d.ts, 1, 23))
}

View File

@@ -0,0 +1,22 @@
=== tests/cases/compiler/consumer.tsx ===
/// <reference path="component.d.ts" />
import Test from 'Test';
>Test : typeof Test
let x = Test; // emit test_1.default
>x : typeof Test
>Test : typeof Test
<anything attr={Test} />; // ?
><anything attr={Test} /> : any
>anything : any
>attr : any
>Test : any
=== tests/cases/compiler/component.d.ts ===
declare module "Test" {
export default class Text { }
>Text : Text
}

View File

@@ -1,8 +1,7 @@
tests/cases/compiler/strictModeInConstructor.ts(9,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
tests/cases/compiler/strictModeInConstructor.ts(27,5): error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
==== tests/cases/compiler/strictModeInConstructor.ts (2 errors) ====
==== tests/cases/compiler/strictModeInConstructor.ts (1 errors) ====
class A {
}
@@ -12,14 +11,9 @@ tests/cases/compiler/strictModeInConstructor.ts(27,5): error TS2376: A 'super' c
public s: number = 9;
constructor () {
~~~~~~~~~~~~~~~~
"use strict"; // No error
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
super();
~~~~~~~~~~~~~~~~
}
~~~~~
!!! error TS2376: A 'super' call must be the first statement in the constructor when a class contains initialized properties or has parameter properties.
}
class C extends A {

View File

@@ -0,0 +1,18 @@
// @module: system
// @isolatedModules: true
import alias = require('foo');
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}

View File

@@ -0,0 +1,17 @@
// @module: system
// @isolatedModules: true
import {alias} from "foo";
import cls = alias.Class;
export import cls2 = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
module M {
export import cls = alias.Class;
let x = new alias.Class();
let y = new cls();
let z = new cls2();
}

View File

@@ -3,4 +3,4 @@
// @target: es6
// @filename: file1.ts
export var x;
export var x = 1;

View File

@@ -0,0 +1,14 @@
//@jsx: preserve
//@module: commonjs
//@filename: component.d.ts
declare module "Test" {
export default class Text { }
}
//@filename: consumer.tsx
/// <reference path="component.d.ts" />
import Test from 'Test';
let x = Test; // emit test_1.default
<anything attr={Test} />; // ?

View File

@@ -1,7 +1,8 @@
/// <reference path="fourslash.ts" />
//// /*1*/function parseInt(s/*2*/:string):number;
goTo.marker('2');
edit.deleteAtCaret(':string'.length);
goTo.marker('1');
edit.insert('declare ');
edit.insert('declare ');

View File

@@ -29,7 +29,34 @@
// type 'fs.' as an alternate way of accessing the top-level objects
// (e.g. 'fs.goTo.eof();')
//---------------------------------------
// For API editors:
// When editting this file, and only while editing this file, enable the reference comments
// and comment out the declarations in this section to get proper type information.
// Undo these changes before compiling/committing/editing any other fourslash tests.
// The test suite will likely crash if you try 'jake runtests' with reference comments enabled.
//
// Explanation:
// We want type-completion while we edit this file, but at compile time/while editting fourslash tests,
// we don't want to include the following reference because we are compiling this file in "--out" mode and don't want to rope
// in the entire codebase into the compilation each fourslash test. Additionally, we don't want to expose the
// src/harness/fourslash.ts API's (or the rest of the compiler) because they are unstable and complicate the
// fourslash testing DSL. Finally, in this case, runtime reflection is (much) faster.
//
// TODO: figure out a better solution to the API exposure problem.
// /// <reference path="../../../built/local/typescriptServices.d.ts"/>
// /// <reference path="../../../src/harness/fourslash.ts"/>
declare var FourSlash;
module ts {
export interface SymbolDisplayPart {
text: string;
kind: string;
}
}
//---------------------------------------------
// Return code used by getEmitOutput function to indicate status of the function
// It is a duplicate of the one in types.ts to expose it to testcases in fourslash
@@ -42,7 +69,6 @@ enum EmitReturnStatus {
}
module FourSlashInterface {
declare var FourSlash;
export interface Marker {
fileName: string;
@@ -201,15 +227,6 @@ module FourSlashInterface {
FourSlash.currentTestState.verifyReferencesAtPositionListContains(range.fileName, range.start, range.end, isWriteAccess);
}
public implementorsCountIs(count: number) {
FourSlash.currentTestState.verifyImplementorsCountIs(count);
}
// Add tests for this.
public currentParameterIsVariable() {
FourSlash.currentTestState.verifyCurrentParameterIsVariable(!this.negative);
}
public signatureHelpPresent() {
FourSlash.currentTestState.verifySignatureHelpPresent(!this.negative);
}
@@ -361,14 +378,11 @@ module FourSlashInterface {
FourSlash.currentTestState.verifyNoMatchingBracePosition(bracePosition);
}
public setVerifyDocComments(val: boolean) {
FourSlash.currentTestState.setVerifyDocComments(val);
}
public getScriptLexicalStructureListCount(count: number) {
FourSlash.currentTestState.verifyGetScriptLexicalStructureListCount(count);
}
// TODO: figure out what to do with the unused arguments.
public getScriptLexicalStructureListContains(
name: string,
kind: string,
@@ -376,13 +390,7 @@ module FourSlashInterface {
parentName?: string,
isAdditionalSpan?: boolean,
markerPosition?: number) {
FourSlash.currentTestState.verifGetScriptLexicalStructureListContains(
name,
kind,
fileName,
parentName,
isAdditionalSpan,
markerPosition);
FourSlash.currentTestState.verifyGetScriptLexicalStructureListContains(name, kind);
}
public navigationItemsListCount(count: number, searchValue: string, matchKind?: string) {
@@ -698,12 +706,7 @@ module fs {
export var format = new FourSlashInterface.format();
export var cancellation = new FourSlashInterface.cancellation();
}
module ts {
export interface SymbolDisplayPart {
text: string;
kind: string;
}
}
function verifyOperationIsCancelled(f) {
FourSlash.verifyOperationIsCancelled(f);
}

View File

@@ -0,0 +1,447 @@
/// <reference path="..\..\..\src\harness\harness.ts" />
namespace ts.server {
let lastWrittenToHost: string;
const mockHost: ServerHost = {
args: [],
newLine: "\n",
useCaseSensitiveFileNames: true,
write(s): void { lastWrittenToHost = s; },
readFile(): string { return void 0; },
writeFile(): void {},
resolvePath(): string { return void 0; },
fileExists: () => false,
directoryExists: () => false,
createDirectory(): void {},
getExecutingFilePath(): string { return void 0; },
getCurrentDirectory(): string { return void 0; },
readDirectory(): string[] { return []; },
exit(): void {}
};
const mockLogger: Logger = {
close(): void {},
isVerbose(): boolean { return false; },
loggingEnabled(): boolean { return false; },
perftrc(s: string): void {},
info(s: string): void {},
startGroup(): void {},
endGroup(): void {},
msg(s: string, type?: string): void {},
};
describe("the Session class", () => {
let session: Session;
let lastSent: protocol.Message;
beforeEach(() => {
session = new Session(mockHost, Buffer.byteLength, process.hrtime, mockLogger);
session.send = (msg: protocol.Message) => {
lastSent = msg;
};
});
describe("executeCommand", () => {
it("should throw when commands are executed with invalid arguments", () => {
const req: protocol.FileRequest = {
command: CommandNames.Open,
seq: 0,
type: "command",
arguments: {
file: undefined
}
};
expect(() => session.executeCommand(req)).to.throw();
});
it("should output an error response when a command does not exist", () => {
const req: protocol.Request = {
command: "foobar",
seq: 0,
type: "command"
};
session.executeCommand(req);
expect(lastSent).to.deep.equal(<protocol.Response>{
command: CommandNames.Unknown,
type: "response",
seq: 0,
message: "Unrecognized JSON command: foobar",
request_seq: 0,
success: false
});
});
it("should return a tuple containing the response and if a response is required on success", () => {
const req: protocol.ConfigureRequest = {
command: CommandNames.Configure,
seq: 0,
type: "command",
arguments: {
hostInfo: "unit test",
formatOptions: {
newLineCharacter: "`n"
}
}
};
expect(session.executeCommand(req)).to.deep.equal({
responseRequired: false
});
expect(lastSent).to.deep.equal({
command: CommandNames.Configure,
type: "response",
success: true,
request_seq: 0,
seq: 0,
body: undefined
});
});
});
describe("onMessage", () => {
it("should not throw when commands are executed with invalid arguments", () => {
let i = 0;
for (name in CommandNames) {
if (!Object.prototype.hasOwnProperty.call(CommandNames, name)) {
continue;
}
const req: protocol.Request = {
command: name,
seq: i++,
type: "command"
};
session.onMessage(JSON.stringify(req));
req.seq = i++;
req.arguments = {};
session.onMessage(JSON.stringify(req));
req.seq = i++;
req.arguments = null;
session.onMessage(JSON.stringify(req));
req.seq = i++;
req.arguments = "";
session.onMessage(JSON.stringify(req));
req.seq = i++;
req.arguments = 0;
session.onMessage(JSON.stringify(req));
req.seq = i++;
req.arguments = [];
session.onMessage(JSON.stringify(req));
}
session.onMessage("GARBAGE NON_JSON DATA");
});
it("should output the response for a correctly handled message", () => {
const req: protocol.ConfigureRequest = {
command: CommandNames.Configure,
seq: 0,
type: "command",
arguments: {
hostInfo: "unit test",
formatOptions: {
newLineCharacter: "`n"
}
}
};
session.onMessage(JSON.stringify(req));
expect(lastSent).to.deep.equal(<protocol.ConfigureResponse>{
command: CommandNames.Configure,
type: "response",
success: true,
request_seq: 0,
seq: 0,
body: undefined
});
});
});
describe("send", () => {
it("is an overrideable handle which sends protocol messages over the wire", () => {
const msg = {seq: 0, type: "none"};
const strmsg = JSON.stringify(msg);
const len = 1 + Buffer.byteLength(strmsg, "utf8");
const resultMsg = `Content-Length: ${len}\r\n\r\n${strmsg}\n`;
session.send = Session.prototype.send;
assert(session.send);
expect(session.send(msg)).to.not.exist;
expect(lastWrittenToHost).to.equal(resultMsg);
});
});
describe("addProtocolHandler", () => {
it("can add protocol handlers", () => {
const respBody = {
item: false
};
const command = "newhandle";
const result = {
response: respBody,
responseRequired: true
};
session.addProtocolHandler(command, (req) => result);
expect(session.executeCommand({
command,
seq: 0,
type: "command"
})).to.deep.equal(result);
});
it("throws when a duplicate handler is passed", () => {
const respBody = {
item: false
};
const resp = {
response: respBody,
responseRequired: true
};
const command = "newhandle";
session.addProtocolHandler(command, (req) => resp);
expect(() => session.addProtocolHandler(command, (req) => resp))
.to.throw(`Protocol handler already exists for command "${command}"`);
});
});
describe("event", () => {
it("can format event responses and send them", () => {
const evt = "notify-test";
const info = {
test: true
};
session.event(info, evt);
expect(lastSent).to.deep.equal({
type: "event",
seq: 0,
event: evt,
body: info
});
});
});
describe("output", () => {
it("can format command responses and send them", () => {
const body = {
block: {
key: "value"
}
};
const command = "test";
session.output(body, command);
expect(lastSent).to.deep.equal({
seq: 0,
request_seq: 0,
type: "response",
command,
body: body,
success: true
});
});
});
});
describe("how Session is extendable via subclassing", () => {
class TestSession extends Session {
lastSent: protocol.Message;
customHandler = "testhandler";
constructor() {
super(mockHost, Buffer.byteLength, process.hrtime, mockLogger);
this.addProtocolHandler(this.customHandler, () => {
return {response: undefined, responseRequired: true};
});
}
send(msg: protocol.Message) {
this.lastSent = msg;
}
};
it("can override methods such as send", () => {
const session = new TestSession();
const body = {
block: {
key: "value"
}
};
const command = "test";
session.output(body, command);
expect(session.lastSent).to.deep.equal({
seq: 0,
request_seq: 0,
type: "response",
command,
body: body,
success: true
});
});
it("can add and respond to new protocol handlers", () => {
const session = new TestSession();
expect(session.executeCommand({
seq: 0,
type: "command",
command: session.customHandler
})).to.deep.equal({
response: undefined,
responseRequired: true
});
});
it("has access to the project service", () => {
class ServiceSession extends TestSession {
constructor() {
super();
assert(this.projectService);
expect(this.projectService).to.be.instanceOf(ProjectService);
}
};
new ServiceSession();
});
});
describe("an example of using the Session API to create an in-process server", () => {
class InProcSession extends Session {
private queue: protocol.Request[] = [];
constructor(private client: InProcClient) {
super(mockHost, Buffer.byteLength, process.hrtime, mockLogger);
this.addProtocolHandler("echo", (req: protocol.Request) => ({
response: req.arguments,
responseRequired: true
}));
}
send(msg: protocol.Message) {
this.client.handle(msg);
}
enqueue(msg: protocol.Request) {
this.queue.unshift(msg);
}
handleRequest(msg: protocol.Request) {
let response: protocol.Response;
try {
({response} = this.executeCommand(msg));
}
catch (e) {
this.output(undefined, msg.command, msg.seq, e.toString());
return;
}
if (response) {
this.output(response, msg.command, msg.seq);
}
}
consumeQueue() {
while (this.queue.length > 0) {
const elem = this.queue.pop();
this.handleRequest(elem);
}
}
}
class InProcClient {
private server: InProcSession;
private seq = 0;
private callbacks: ts.Map<(resp: protocol.Response) => void> = {};
private eventHandlers: ts.Map<(args: any) => void> = {};
handle(msg: protocol.Message): void {
if (msg.type === "response") {
const response = <protocol.Response>msg;
if (this.callbacks[response.request_seq]) {
this.callbacks[response.request_seq](response);
delete this.callbacks[response.request_seq];
}
}
else if (msg.type === "event") {
const event = <protocol.Event>msg;
this.emit(event.event, event.body);
}
}
emit(name: string, args: any): void {
if (this.eventHandlers[name]) {
this.eventHandlers[name](args);
}
}
on(name: string, handler: (args: any) => void): void {
this.eventHandlers[name] = handler;
}
connect(session: InProcSession): void {
this.server = session;
}
execute(command: string, args: any, callback: (resp: protocol.Response) => void): void {
if (!this.server) {
return;
}
this.seq++;
this.server.enqueue({
seq: this.seq,
type: "command",
command,
arguments: args
});
this.callbacks[this.seq] = callback;
}
};
it("can be constructed and respond to commands", (done) => {
const cli = new InProcClient();
const session = new InProcSession(cli);
const toEcho = {
data: true
};
const toEvent = {
data: false
};
let responses = 0;
// Connect the client
cli.connect(session);
// Add an event handler
cli.on("testevent", (eventinfo) => {
expect(eventinfo).to.equal(toEvent);
responses++;
expect(responses).to.equal(1);
});
// Trigger said event from the server
session.event(toEvent, "testevent");
// Queue an echo command
cli.execute("echo", toEcho, (resp) => {
assert(resp.success, resp.message);
responses++;
expect(responses).to.equal(2);
expect(resp.body).to.deep.equal(toEcho);
});
// Queue a configure command
cli.execute("configure", {
hostInfo: "unit test",
formatOptions: {
newLineCharacter: "`n"
}
}, (resp) => {
assert(resp.success, resp.message);
responses++;
expect(responses).to.equal(3);
done();
});
// Consume the queue and trigger the callbacks
session.consumeQueue();
});
});
}

View File

@@ -2,58 +2,120 @@
module ts {
describe("Transpile", () => {
function runTest(input: string, compilerOptions: ts.CompilerOptions = {}, fileName?: string, moduleName?: string, expectedOutput?: string, expectedDiagnosticCodes: number[] = []): void {
let diagnostics: Diagnostic[] = [];
let result = transpile(input, compilerOptions, fileName || "file.ts", diagnostics, moduleName);
interface TranspileTestSettings {
options?: TranspileOptions;
expectedOutput?: string;
expectedDiagnosticCodes?: number[];
}
function checkDiagnostics(diagnostics: Diagnostic[], expectedDiagnosticCodes?: number[]) {
if(!expectedDiagnosticCodes) {
return;
}
for (let i = 0; i < expectedDiagnosticCodes.length; i++) {
assert.equal(expectedDiagnosticCodes[i], diagnostics[i] && diagnostics[i].code, `Could not find expeced diagnostic.`);
}
assert.equal(diagnostics.length, expectedDiagnosticCodes.length, "Resuting diagnostics count does not match expected");
if (expectedOutput !== undefined) {
assert.equal(result, expectedOutput);
}
assert.equal(diagnostics.length, expectedDiagnosticCodes.length, "Resuting diagnostics count does not match expected");
}
function test(input: string, testSettings: TranspileTestSettings): void {
let diagnostics: Diagnostic[] = [];
let transpileOptions: TranspileOptions = testSettings.options || {};
let transpileResult = transpile(input, transpileOptions.compilerOptions, transpileOptions.fileName, diagnostics, transpileOptions.moduleName);
transpileOptions.reportDiagnostics = true;
let transpileModuleResult = transpileModule(input, transpileOptions);
checkDiagnostics(diagnostics, testSettings.expectedDiagnosticCodes);
checkDiagnostics(transpileModuleResult.diagnostics, testSettings.expectedDiagnosticCodes);
if (testSettings.expectedOutput !== undefined) {
assert.equal(transpileResult, testSettings.expectedOutput);
assert.equal(transpileModuleResult.outputText, testSettings.expectedOutput);
}
// check source maps
if (!transpileOptions.compilerOptions) {
transpileOptions.compilerOptions = {};
}
if (!transpileOptions.fileName) {
transpileOptions.fileName = "file.ts";
}
transpileOptions.compilerOptions.sourceMap = true;
let transpileModuleResultWithSourceMap = transpileModule(input, transpileOptions);
assert.isTrue(transpileModuleResultWithSourceMap.sourceMapText !== undefined);
let expectedSourceMapFileName = removeFileExtension(transpileOptions.fileName) + ".js.map";
let expectedSourceMappingUrlLine = `//# sourceMappingURL=${expectedSourceMapFileName}`;
if (testSettings.expectedOutput !== undefined) {
assert.equal(transpileModuleResultWithSourceMap.outputText, testSettings.expectedOutput + expectedSourceMappingUrlLine);
}
else {
// expected output is not set, just verify that output text has sourceMappingURL as a last line
let output = transpileModuleResultWithSourceMap.outputText;
assert.isTrue(output.length >= expectedSourceMappingUrlLine.length);
if (output.length === expectedSourceMappingUrlLine.length) {
assert.equal(output, expectedSourceMappingUrlLine);
}
else {
let suffix = getNewLineCharacter(transpileOptions.compilerOptions) + expectedSourceMappingUrlLine
assert.isTrue(output.indexOf(suffix, output.length - suffix.length) !== -1);
}
}
}
it("Generates correct compilerOptions diagnostics", () => {
// Expecting 5047: "Option 'isolatedModules' can only be used when either option'--module' is provided or option 'target' is 'ES6' or higher."
runTest(`var x = 0;`, {}, /*fileName*/ undefined, /*moduleName*/undefined, /*expectedOutput*/ undefined, /*expectedDiagnosticCodes*/ [5047]);
test(`var x = 0;`, { expectedDiagnosticCodes: [5047] });
});
it("Generates no diagnostics with valid inputs", () => {
// No errors
runTest(`var x = 0;`, { module: ModuleKind.CommonJS }, /*fileName*/ undefined, /*moduleName*/undefined, /*expectedOutput*/ undefined, /*expectedDiagnosticCodes*/ []);
test(`var x = 0;`, { options: { compilerOptions: { module: ModuleKind.CommonJS } } });
});
it("Generates no diagnostics for missing file references", () => {
runTest(`/// <reference path="file2.ts" />
var x = 0;`,
{ module: ModuleKind.CommonJS }, /*fileName*/ undefined, /*moduleName*/undefined, /*expectedOutput*/ undefined, /*expectedDiagnosticCodes*/ []);
test(`/// <reference path="file2.ts" />
var x = 0;`,
{ options: { compilerOptions: { module: ModuleKind.CommonJS } } });
});
it("Generates no diagnostics for missing module imports", () => {
runTest(`import {a} from "module2";`,
{ module: ModuleKind.CommonJS }, /*fileName*/ undefined,/*moduleName*/undefined, /*expectedOutput*/ undefined, /*expectedDiagnosticCodes*/ []);
test(`import {a} from "module2";`,
{ options: { compilerOptions: { module: ModuleKind.CommonJS } } });
});
it("Generates expected syntactic diagnostics", () => {
runTest(`a b`,
{ module: ModuleKind.CommonJS }, /*fileName*/ undefined, /*moduleName*/undefined, /*expectedOutput*/ undefined, /*expectedDiagnosticCodes*/ [1005]); /// 1005: ';' Expected
test(`a b`,
{ options: { compilerOptions: { module: ModuleKind.CommonJS } }, expectedDiagnosticCodes: [1005] }); /// 1005: ';' Expected
});
it("Does not generate semantic diagnostics", () => {
runTest(`var x: string = 0;`,
{ module: ModuleKind.CommonJS }, /*fileName*/ undefined, /*moduleName*/undefined, /*expectedOutput*/ undefined, /*expectedDiagnosticCodes*/ []);
test(`var x: string = 0;`,
{ options: { compilerOptions: { module: ModuleKind.CommonJS } } });
});
it("Generates module output", () => {
runTest(`var x = 0;`, { module: ModuleKind.AMD }, /*fileName*/ undefined, /*moduleName*/undefined, `define(["require", "exports"], function (require, exports) {\r\n var x = 0;\r\n});\r\n`);
test(`var x = 0;`,
{
options: { compilerOptions: { module: ModuleKind.AMD } },
expectedOutput: `define(["require", "exports"], function (require, exports) {\r\n var x = 0;\r\n});\r\n`
});
});
it("Uses correct newLine character", () => {
runTest(`var x = 0;`, { module: ModuleKind.CommonJS, newLine: NewLineKind.LineFeed }, /*fileName*/ undefined, /*moduleName*/undefined, `var x = 0;\n`, /*expectedDiagnosticCodes*/ []);
test(`var x = 0;`,
{
options: { compilerOptions: { module: ModuleKind.CommonJS, newLine: NewLineKind.LineFeed } },
expectedOutput: `var x = 0;\n`
});
});
it("Sets module name", () => {
@@ -66,12 +128,15 @@ var x = 0;`,
` }\n` +
` }\n` +
`});\n`;
runTest("var x = 1;", { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, /*fileName*/ undefined, "NamedModule", output)
test("var x = 1;",
{
options: { compilerOptions: { module: ModuleKind.System, newLine: NewLineKind.LineFeed }, moduleName: "NamedModule" },
expectedOutput: output
})
});
it("No extra errors for file without extension", () => {
runTest(`var x = 0;`, { module: ModuleKind.CommonJS }, "file", /*moduleName*/undefined, /*expectedOutput*/ undefined, /*expectedDiagnosticCodes*/[]);
test(`var x = 0;`, { options: { compilerOptions: { module: ModuleKind.CommonJS }, fileName: "file" } });
});
});
}