Merge remote-tracking branch 'origin/master' into tsserver-typings

This commit is contained in:
Vladimir Matveev 2016-08-18 14:57:34 -07:00
commit 27deb313cc
32 changed files with 571 additions and 73 deletions

View File

@ -209,7 +209,8 @@ var harnessSources = harnessCoreSources.concat([
"convertCompilerOptionsFromJson.ts",
"convertTypingOptionsFromJson.ts",
"tsserverProjectSystem.ts",
"matchFiles.ts"
"matchFiles.ts",
"initializeTSConfig.ts",
].map(function (f) {
return path.join(unittestsDirectory, f);
})).concat([

View File

@ -1,4 +1,4 @@
/// <reference path="../src/harness/external/node.d.ts" />
/// <reference types="node"/>
import fs = require('fs');
import path = require('path');

View File

@ -126,6 +126,10 @@ namespace ts {
type: "boolean",
description: Diagnostics.Do_not_emit_outputs_if_any_errors_were_reported,
},
{
name: "noErrorTruncation",
type: "boolean"
},
{
name: "noImplicitAny",
type: "boolean",
@ -462,6 +466,14 @@ namespace ts {
shortOptionNames: Map<string>;
}
/* @internal */
export const defaultInitCompilerOptions: CompilerOptions = {
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
sourceMap: false,
};
let optionNameMapCache: OptionNameMap;
/* @internal */
@ -667,6 +679,94 @@ namespace ts {
}
}
/**
* Generate tsconfig configuration when running command line "--init"
* @param options commandlineOptions to be generated into tsconfig.json
* @param fileNames array of filenames to be generated into tsconfig.json
*/
/* @internal */
export function generateTSConfig(options: CompilerOptions, fileNames: string[]): { compilerOptions: Map<CompilerOptionsValue> } {
const compilerOptions = extend(options, defaultInitCompilerOptions);
const configurations: any = {
compilerOptions: serializeCompilerOptions(compilerOptions)
};
if (fileNames && fileNames.length) {
// only set the files property if we have at least one file
configurations.files = fileNames;
}
return configurations;
function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map<string | number> | undefined {
if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") {
// this is of a type CommandLineOptionOfPrimitiveType
return undefined;
}
else if (optionDefinition.type === "list") {
return getCustomTypeMapOfCommandLineOption((<CommandLineOptionOfListType>optionDefinition).element);
}
else {
return (<CommandLineOptionOfCustomType>optionDefinition).type;
}
}
function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: MapLike<string | number>): string | undefined {
// There is a typeMap associated with this command-line option so use it to map value back to its name
for (const key in customTypeMap) {
if (customTypeMap[key] === value) {
return key;
}
}
return undefined;
}
function serializeCompilerOptions(options: CompilerOptions): Map<CompilerOptionsValue> {
const result = createMap<CompilerOptionsValue>();
const optionsNameMap = getOptionNameMap().optionNameMap;
for (const name in options) {
if (hasProperty(options, name)) {
// tsconfig only options cannot be specified via command line,
// so we can assume that only types that can appear here string | number | boolean
switch (name) {
case "init":
case "watch":
case "version":
case "help":
case "project":
break;
default:
const value = options[name];
let optionDefinition = optionsNameMap[name.toLowerCase()];
if (optionDefinition) {
const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
if (!customTypeMap) {
// There is no map associated with this compiler option then use the value as-is
// This is the case if the value is expect to be string, number, boolean or list of string
result[name] = value;
}
else {
if (optionDefinition.type === "list") {
const convertedValue: string[] = [];
for (const element of value as (string | number)[]) {
convertedValue.push(getNameOfCompilerOptionValue(element, customTypeMap));
}
result[name] = convertedValue;
}
else {
// There is a typeMap associated with this command-line option so use it to map value back to its name
result[name] = getNameOfCompilerOptionValue(value, customTypeMap);
}
}
}
break;
}
}
}
return result;
}
}
/**
* Remove the comments from a json like text.
* Comments can be single line comments (starting with # or //) or multiline comments using / * * /

View File

@ -5311,6 +5311,21 @@ const _super = (function (geti, seti) {
emitSignatureParameters(ctor);
}
else {
// The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation:
// If constructor is empty, then
// If ClassHeritag_eopt is present and protoParent is not null, then
// Let constructor be the result of parsing the source text
// constructor(...args) { super (...args);}
// using the syntactic grammar with the goal symbol MethodDefinition[~Yield].
// Else,
// Let constructor be the result of parsing the source text
// constructor( ){ }
// using the syntactic grammar with the goal symbol MethodDefinition[~Yield].
//
// While we could emit the '...args' rest parameter, certain later tools in the pipeline might
// downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array.
// Instead, we'll avoid using a rest parameter and spread into the super call as
// 'super(...arguments)' instead of 'super(...args)', as you can see below.
write("()");
}
}
@ -5349,6 +5364,7 @@ const _super = (function (geti, seti) {
write("_super.apply(this, arguments);");
}
else {
// See comment above on using '...arguments' instead of '...args'.
write("super(...arguments);");
}
emitEnd(baseTypeElement);

View File

@ -828,14 +828,6 @@ namespace ts {
: { resolvedModule: undefined, failedLookupLocations };
}
/* @internal */
export const defaultInitCompilerOptions: CompilerOptions = {
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
sourceMap: false,
};
interface OutputFingerprint {
hash: string;
byteOrderMark: boolean;

View File

@ -763,67 +763,11 @@ namespace ts {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined);
}
else {
const compilerOptions = extend(options, defaultInitCompilerOptions);
const configurations: any = {
compilerOptions: serializeCompilerOptions(compilerOptions)
};
if (fileNames && fileNames.length) {
// only set the files property if we have at least one file
configurations.files = fileNames;
}
else {
configurations.exclude = ["node_modules"];
if (compilerOptions.outDir) {
configurations.exclude.push(compilerOptions.outDir);
}
}
sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
sys.writeFile(file, JSON.stringify(generateTSConfig(options, fileNames), undefined, 4));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined);
}
return;
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
const result = createMap<string | number | boolean>();
const optionsNameMap = getOptionNameMap().optionNameMap;
for (const name in options) {
if (hasProperty(options, name)) {
// tsconfig only options cannot be specified via command line,
// so we can assume that only types that can appear here string | number | boolean
const value = <string | number | boolean>options[name];
switch (name) {
case "init":
case "watch":
case "version":
case "help":
case "project":
break;
default:
let optionDefinition = optionsNameMap[name.toLowerCase()];
if (optionDefinition) {
if (typeof optionDefinition.type === "string") {
// string, number or boolean
result[name] = value;
}
else {
// Enum
const typeMap = <Map<number>>optionDefinition.type;
for (const key in typeMap) {
if (typeMap[key] === value) {
result[name] = key;
}
}
}
}
break;
}
}
}
return result;
}
}
}

View File

@ -2767,7 +2767,7 @@ namespace ts {
/* @internal */
export interface CommandLineOptionOfCustomType extends CommandLineOptionBase {
type: Map<number | string>; // an object literal mapping named values to actual values
type: Map<number | string>; // an object literal mapping named values to actual values
}
/* @internal */

View File

@ -1673,10 +1673,10 @@ namespace Harness {
const encoded_actual = Utils.encodeString(actual);
if (expected !== encoded_actual) {
if (actual === NoContent) {
IO.writeFile(relativeFileName + ".delete", "");
IO.writeFile(localPath(relativeFileName + ".delete"), "");
}
else {
IO.writeFile(relativeFileName, actual);
IO.writeFile(localPath(relativeFileName), actual);
}
// Overwrite & issue error
const errMsg = "The baseline file " + relativeFileName + " has changed.";
@ -1684,6 +1684,7 @@ namespace Harness {
}
}
export function runBaseline(
descriptionForDescribe: string,
relativeFileName: string,

View File

@ -198,7 +198,8 @@ namespace RWC {
}
// Do not include the library in the baselines to avoid noise
const baselineFiles = inputFiles.concat(otherFiles).filter(f => !Harness.isDefaultLibraryFile(f.unitName));
return Harness.Compiler.getErrorBaseline(baselineFiles, compilerResult.errors);
const errors = compilerResult.errors.filter(e => !Harness.isDefaultLibraryFile(e.file.fileName));
return Harness.Compiler.getErrorBaseline(baselineFiles, errors);
}, false, baselineOpts);
});

View File

@ -89,6 +89,7 @@
"./unittests/convertCompilerOptionsFromJson.ts",
"./unittests/convertTypingOptionsFromJson.ts",
"./unittests/tsserverProjectSystem.ts",
"./unittests/matchFiles.ts"
"./unittests/matchFiles.ts",
"./unittests/initializeTSConfig.ts"
]
}

View File

@ -0,0 +1,44 @@
/// <reference path="..\harness.ts" />
/// <reference path="..\..\compiler\commandLineParser.ts" />
namespace ts {
describe("initTSConfig", () => {
function initTSConfigCorrectly(name: string, commandLinesArgs: string[]) {
describe(name, () => {
const commandLine = parseCommandLine(commandLinesArgs);
const initResult = generateTSConfig(commandLine.options, commandLine.fileNames);
const outputFileName = `tsConfig/${name.replace(/[^a-z0-9\-. ]/ig, "")}/tsconfig.json`;
it(`Correct output for ${outputFileName}`, () => {
Harness.Baseline.runBaseline("Correct output", outputFileName, () => {
if (initResult) {
return JSON.stringify(initResult, undefined, 4);
}
else {
// This can happen if compiler recieve invalid compiler-options
/* tslint:disable:no-null-keyword */
return null;
/* tslint:enable:no-null-keyword */
}
});
});
});
}
initTSConfigCorrectly("Default initialized TSConfig", ["--init"]);
initTSConfigCorrectly("Initialized TSConfig with files options", ["--init", "file0.st", "file1.ts", "file2.ts"]);
initTSConfigCorrectly("Initialized TSConfig with boolean value compiler options", ["--init", "--noUnusedLocals"]);
initTSConfigCorrectly("Initialized TSConfig with enum value compiler options", ["--init", "--target", "es5", "--jsx", "react"]);
initTSConfigCorrectly("Initialized TSConfig with list compiler options", ["--init", "--types", "jquery,mocha"]);
initTSConfigCorrectly("Initialized TSConfig with list compiler options with enum value", ["--init", "--lib", "es5,es2015.core"]);
initTSConfigCorrectly("Initialized TSConfig with incorrect compiler option", ["--init", "--someNonExistOption"]);
initTSConfigCorrectly("Initialized TSConfig with incorrect compiler option value", ["--init", "--lib", "nonExistLib,es5,es2015.promise"]);
});
}

View File

@ -3876,7 +3876,11 @@ namespace ts {
// other than those within the declared type.
isNewIdentifierLocation = true;
// If the object literal is being assigned to something of type 'null | { hello: string }',
// it clearly isn't trying to satisfy the 'null' type. So we grab the non-nullable type if possible.
typeForObject = typeChecker.getContextualType(<ObjectLiteralExpression>objectLikeContainer);
typeForObject = typeForObject && typeForObject.getNonNullableType();
existingMembers = (<ObjectLiteralExpression>objectLikeContainer).properties;
}
else if (objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern) {
@ -3888,7 +3892,7 @@ namespace ts {
// We don't want to complete using the type acquired by the shape
// of the binding pattern; we are only interested in types acquired
// through type declaration or inference.
// Also proceed if rootDeclaration is parameter and if its containing function expression\arrow function is contextually typed -
// Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
// type of parameter will flow in from the contextual type of the function
let canGetType = !!(rootDeclaration.initializer || rootDeclaration.type);
if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) {

View File

@ -0,0 +1,33 @@
//// [tests/cases/compiler/exportDefaultProperty2.ts] ////
//// [a.ts]
// This test is just like exportEqualsProperty2, but with `export default`.
class C {
static B: number;
}
namespace C {
export interface B { c: number }
}
export default C.B;
//// [b.ts]
import B from "./a.ts";
const x: B = { c: B };
//// [a.js]
// This test is just like exportEqualsProperty2, but with `export default`.
"use strict";
var C = (function () {
function C() {
}
return C;
}());
exports.__esModule = true;
exports["default"] = C.B;
//// [b.js]
"use strict";
var a_ts_1 = require("./a.ts");
var x = { c: a_ts_1["default"] };

View File

@ -0,0 +1,32 @@
=== tests/cases/compiler/a.ts ===
// This test is just like exportEqualsProperty2, but with `export default`.
class C {
>C : Symbol(C, Decl(a.ts, 0, 0), Decl(a.ts, 4, 1))
static B: number;
>B : Symbol(default, Decl(a.ts, 2, 9), Decl(a.ts, 5, 13))
}
namespace C {
>C : Symbol(C, Decl(a.ts, 0, 0), Decl(a.ts, 4, 1))
export interface B { c: number }
>B : Symbol(B, Decl(a.ts, 2, 9), Decl(a.ts, 5, 13))
>c : Symbol(B.c, Decl(a.ts, 6, 24))
}
export default C.B;
>C.B : Symbol(default, Decl(a.ts, 2, 9), Decl(a.ts, 5, 13))
>C : Symbol(C, Decl(a.ts, 0, 0), Decl(a.ts, 4, 1))
>B : Symbol(default, Decl(a.ts, 2, 9), Decl(a.ts, 5, 13))
=== tests/cases/compiler/b.ts ===
import B from "./a.ts";
>B : Symbol(B, Decl(b.ts, 0, 6))
const x: B = { c: B };
>x : Symbol(x, Decl(b.ts, 1, 5))
>B : Symbol(B, Decl(b.ts, 0, 6))
>c : Symbol(c, Decl(b.ts, 1, 14))
>B : Symbol(B, Decl(b.ts, 0, 6))

View File

@ -0,0 +1,33 @@
=== tests/cases/compiler/a.ts ===
// This test is just like exportEqualsProperty2, but with `export default`.
class C {
>C : C
static B: number;
>B : number
}
namespace C {
>C : typeof C
export interface B { c: number }
>B : B
>c : number
}
export default C.B;
>C.B : number
>C : typeof C
>B : number
=== tests/cases/compiler/b.ts ===
import B from "./a.ts";
>B : number
const x: B = { c: B };
>x : B
>B : B
>{ c: B } : { c: number; }
>c : number
>B : number

View File

@ -0,0 +1,32 @@
//// [tests/cases/compiler/exportEqualsProperty2.ts] ////
//// [a.ts]
// This test is just like exportDefaultProperty2, but with `export =`.
class C {
static B: number;
}
namespace C {
export interface B { c: number }
}
export = C.B;
//// [b.ts]
import B = require("./a.ts");
const x: B = { c: B };
//// [a.js]
// This test is just like exportDefaultProperty2, but with `export =`.
"use strict";
var C = (function () {
function C() {
}
return C;
}());
module.exports = C.B;
//// [b.js]
"use strict";
var B = require("./a.ts");
var x = { c: B };

View File

@ -0,0 +1,32 @@
=== tests/cases/compiler/b.ts ===
import B = require("./a.ts");
>B : Symbol(B, Decl(b.ts, 0, 0))
const x: B = { c: B };
>x : Symbol(x, Decl(b.ts, 1, 5))
>B : Symbol(B, Decl(b.ts, 0, 0))
>c : Symbol(c, Decl(b.ts, 1, 14))
>B : Symbol(B, Decl(b.ts, 0, 0))
=== tests/cases/compiler/a.ts ===
// This test is just like exportDefaultProperty2, but with `export =`.
class C {
>C : Symbol(C, Decl(a.ts, 0, 0), Decl(a.ts, 4, 1))
static B: number;
>B : Symbol(C.B, Decl(a.ts, 2, 9), Decl(a.ts, 5, 13))
}
namespace C {
>C : Symbol(C, Decl(a.ts, 0, 0), Decl(a.ts, 4, 1))
export interface B { c: number }
>B : Symbol(B, Decl(a.ts, 2, 9), Decl(a.ts, 5, 13))
>c : Symbol(B.c, Decl(a.ts, 6, 24))
}
export = C.B;
>C.B : Symbol(C.B, Decl(a.ts, 2, 9), Decl(a.ts, 5, 13))
>C : Symbol(C, Decl(a.ts, 0, 0), Decl(a.ts, 4, 1))
>B : Symbol(C.B, Decl(a.ts, 2, 9), Decl(a.ts, 5, 13))

View File

@ -0,0 +1,33 @@
=== tests/cases/compiler/b.ts ===
import B = require("./a.ts");
>B : number
const x: B = { c: B };
>x : B
>B : B
>{ c: B } : { c: number; }
>c : number
>B : number
=== tests/cases/compiler/a.ts ===
// This test is just like exportDefaultProperty2, but with `export =`.
class C {
>C : C
static B: number;
>B : number
}
namespace C {
>C : typeof C
export interface B { c: number }
>B : B
>c : number
}
export = C.B;
>C.B : number
>C : typeof C
>B : number

View File

@ -0,0 +1,22 @@
tests/cases/compiler/noErrorTruncation.ts(10,7): error TS2322: Type 'number' is not assignable to type '{ someLongOptionA: string; } | { someLongOptionB: string; } | { someLongOptionC: string; } | { someLongOptionD: string; } | { someLongOptionE: string; } | { someLongOptionF: string; }'.
==== tests/cases/compiler/noErrorTruncation.ts (1 errors) ====
// @noErrorTruncation
type SomeLongOptionA = { someLongOptionA: string }
type SomeLongOptionB = { someLongOptionB: string }
type SomeLongOptionC = { someLongOptionC: string }
type SomeLongOptionD = { someLongOptionD: string }
type SomeLongOptionE = { someLongOptionE: string }
type SomeLongOptionF = { someLongOptionF: string }
const x: SomeLongOptionA
~
!!! error TS2322: Type 'number' is not assignable to type '{ someLongOptionA: string; } | { someLongOptionB: string; } | { someLongOptionC: string; } | { someLongOptionD: string; } | { someLongOptionE: string; } | { someLongOptionF: string; }'.
| SomeLongOptionB
| SomeLongOptionC
| SomeLongOptionD
| SomeLongOptionE
| SomeLongOptionF = 42;

View File

@ -0,0 +1,21 @@
//// [noErrorTruncation.ts]
// @noErrorTruncation
type SomeLongOptionA = { someLongOptionA: string }
type SomeLongOptionB = { someLongOptionB: string }
type SomeLongOptionC = { someLongOptionC: string }
type SomeLongOptionD = { someLongOptionD: string }
type SomeLongOptionE = { someLongOptionE: string }
type SomeLongOptionF = { someLongOptionF: string }
const x: SomeLongOptionA
| SomeLongOptionB
| SomeLongOptionC
| SomeLongOptionD
| SomeLongOptionE
| SomeLongOptionF = 42;
//// [noErrorTruncation.js]
// @noErrorTruncation
var x = 42;

View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false
}
}

View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false,
"noUnusedLocals": true
}
}

View File

@ -0,0 +1,9 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false,
"jsx": "react"
}
}

View File

@ -0,0 +1,13 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false
},
"files": [
"file0.st",
"file1.ts",
"file2.ts"
]
}

View File

@ -0,0 +1,12 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false,
"lib": [
"es5",
"es2015.promise"
]
}
}

View File

@ -0,0 +1,8 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false
}
}

View File

@ -0,0 +1,12 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false,
"lib": [
"es5",
"es2015.core"
]
}
}

View File

@ -0,0 +1,12 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"noImplicitAny": false,
"sourceMap": false,
"types": [
"jquery",
"mocha"
]
}
}

View File

@ -0,0 +1,15 @@
// This test is just like exportEqualsProperty2, but with `export default`.
// @Filename: a.ts
class C {
static B: number;
}
namespace C {
export interface B { c: number }
}
export default C.B;
// @Filename: b.ts
import B from "./a.ts";
const x: B = { c: B };

View File

@ -0,0 +1,15 @@
// This test is just like exportDefaultProperty2, but with `export =`.
// @Filename: a.ts
class C {
static B: number;
}
namespace C {
export interface B { c: number }
}
export = C.B;
// @Filename: b.ts
import B = require("./a.ts");
const x: B = { c: B };

View File

@ -0,0 +1,15 @@
// @noErrorTruncation
type SomeLongOptionA = { someLongOptionA: string }
type SomeLongOptionB = { someLongOptionB: string }
type SomeLongOptionC = { someLongOptionC: string }
type SomeLongOptionD = { someLongOptionD: string }
type SomeLongOptionE = { someLongOptionE: string }
type SomeLongOptionF = { someLongOptionF: string }
const x: SomeLongOptionA
| SomeLongOptionB
| SomeLongOptionC
| SomeLongOptionD
| SomeLongOptionE
| SomeLongOptionF = 42;

View File

@ -0,0 +1,28 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////interface Thing {
//// hello: number;
//// world: string;
////}
////
////declare function funcA(x : Thing): void;
////declare function funcB(x?: Thing): void;
////declare function funcC(x : Thing | null): void;
////declare function funcD(x : Thing | undefined): void;
////declare function funcE(x : Thing | null | undefined): void;
////declare function funcF(x?: Thing | null | undefined): void;
////
////funcA({ /*A*/ });
////funcB({ /*B*/ });
////funcC({ /*C*/ });
////funcD({ /*D*/ });
////funcE({ /*E*/ });
////funcF({ /*F*/ });
for (const marker of test.markers()) {
goTo.position(marker.position);
verify.completionListContains("hello");
verify.completionListContains("world");
}