Merge branch 'master' into release-3.0

This commit is contained in:
Mohamed Hegazy
2018-07-16 13:18:08 -07:00
52 changed files with 659 additions and 190 deletions
+26 -30
View File
@@ -336,8 +336,8 @@ namespace ts {
}
function addUnusedDiagnostics() {
checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(file), (kind, diag) => {
if (!unusedIsError(kind)) {
checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(file), (containingNode, kind, diag) => {
if (!containsParseError(containingNode) && !unusedIsError(kind)) {
(diagnostics || (diagnostics = [])).push({ ...diag, category: DiagnosticCategory.Suggestion });
}
});
@@ -646,7 +646,8 @@ namespace ts {
Local,
Parameter,
}
type AddUnusedDiagnostic = (type: UnusedKind, diagnostic: DiagnosticWithLocation) => void;
/** @param containingNode Node to check for parse error */
type AddUnusedDiagnostic = (containingNode: Node, type: UnusedKind, diagnostic: DiagnosticWithLocation) => void;
const builtinGlobals = createSymbolTable();
builtinGlobals.set(undefinedSymbol.escapedName, undefinedSymbol);
@@ -4682,13 +4683,7 @@ namespace ts {
}
}
// Use contextual parameter type if one is available
let type: Type | undefined;
if (declaration.symbol.escapedName === "this") {
type = getContextualThisParameterType(func);
}
else {
type = getContextuallyTypedParameterType(declaration);
}
const type = declaration.symbol.escapedName === "this" ? getContextualThisParameterType(func) : getContextuallyTypedParameterType(declaration);
if (type) {
return addOptionality(type, isOptional);
}
@@ -16209,7 +16204,7 @@ namespace ts {
// If the given type is an object or union type with a single signature, and if that signature has at
// least as many parameters as the given function, return the signature. Otherwise return undefined.
function getContextualCallSignature(type: Type, node: FunctionExpression | ArrowFunction | MethodDeclaration): Signature | undefined {
function getContextualCallSignature(type: Type, node: SignatureDeclaration): Signature | undefined {
const signatures = getSignaturesOfType(type, SignatureKind.Call);
if (signatures.length === 1) {
const signature = signatures[0];
@@ -16220,7 +16215,7 @@ namespace ts {
}
/** If the contextual signature has fewer parameters than the function expression, do not use it */
function isAritySmaller(signature: Signature, target: FunctionExpression | ArrowFunction | MethodDeclaration) {
function isAritySmaller(signature: Signature, target: SignatureDeclaration) {
let targetParameterCount = 0;
for (; targetParameterCount < target.parameters.length; targetParameterCount++) {
const param = target.parameters[targetParameterCount];
@@ -23538,12 +23533,13 @@ namespace ts {
// yielded values. The only way to trigger these errors is to try checking its return type.
getReturnTypeOfSignature(getSignatureFromDeclaration(node));
}
// A js function declaration can have a @type tag instead of a return type node, but that type must have a call signature
if (isInJavaScriptFile(node)) {
const typeTag = getJSDocTypeTag(node);
if (typeTag && typeTag.typeExpression && !getSignaturesOfType(getTypeFromTypeNode(typeTag.typeExpression), SignatureKind.Call).length) {
error(typeTag, Diagnostics.The_type_of_a_function_declaration_must_be_callable);
}
}
// A js function declaration can have a @type tag instead of a return type node, but that type must have a call signature
if (isInJavaScriptFile(node)) {
const typeTag = getJSDocTypeTag(node);
if (typeTag && typeTag.typeExpression && !getContextualCallSignature(getTypeFromTypeNode(typeTag.typeExpression), node)) {
error(typeTag, Diagnostics.The_type_of_a_function_declaration_must_match_the_function_s_signature);
}
}
}
@@ -23617,7 +23613,7 @@ namespace ts {
function errorUnusedLocal(declaration: Declaration, name: string, addDiagnostic: AddUnusedDiagnostic) {
const node = getNameOfDeclaration(declaration) || declaration;
const message = isTypeDeclaration(declaration) ? Diagnostics._0_is_declared_but_never_used : Diagnostics._0_is_declared_but_its_value_is_never_read;
addDiagnostic(UnusedKind.Local, createDiagnosticForNode(node, message, name));
addDiagnostic(declaration, UnusedKind.Local, createDiagnosticForNode(node, message, name));
}
function isIdentifierThatStartsWithUnderscore(node: Node) {
@@ -23638,13 +23634,13 @@ namespace ts {
}
const symbol = getSymbolOfNode(member);
if (!symbol.isReferenced && hasModifier(member, ModifierFlags.Private)) {
addDiagnostic(UnusedKind.Local, createDiagnosticForNode(member.name!, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol)));
addDiagnostic(member, UnusedKind.Local, createDiagnosticForNode(member.name!, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolToString(symbol)));
}
break;
case SyntaxKind.Constructor:
for (const parameter of (<ConstructorDeclaration>member).parameters) {
if (!parameter.symbol.isReferenced && hasModifier(parameter, ModifierFlags.Private)) {
addDiagnostic(UnusedKind.Local, createDiagnosticForNode(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol)));
addDiagnostic(parameter, UnusedKind.Local, createDiagnosticForNode(parameter.name, Diagnostics.Property_0_is_declared_but_its_value_is_never_read, symbolName(parameter.symbol)));
}
}
break;
@@ -23669,7 +23665,7 @@ namespace ts {
if (!(node.flags & NodeFlags.Ambient) && last(getSymbolOfNode(node).declarations) === node) {
for (const typeParameter of typeParameters) {
if (!(getMergedSymbol(typeParameter.symbol).isReferenced! & SymbolFlags.TypeParameter) && !isIdentifierThatStartsWithUnderscore(typeParameter.name)) {
addDiagnostic(UnusedKind.Parameter, createDiagnosticForNode(typeParameter.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(typeParameter.symbol)));
addDiagnostic(typeParameter, UnusedKind.Parameter, createDiagnosticForNode(typeParameter.name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(typeParameter.symbol)));
}
}
}
@@ -23728,7 +23724,7 @@ namespace ts {
const name = local.valueDeclaration && getNameOfDeclaration(local.valueDeclaration);
if (parameter && name) {
if (!isParameterPropertyDeclaration(parameter) && !parameterIsThisKeyword(parameter) && !isIdentifierThatStartsWithUnderscore(name)) {
addDiagnostic(UnusedKind.Parameter, createDiagnosticForNode(name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(local)));
addDiagnostic(parameter, UnusedKind.Parameter, createDiagnosticForNode(name, Diagnostics._0_is_declared_but_its_value_is_never_read, symbolName(local)));
}
}
else {
@@ -23744,7 +23740,7 @@ namespace ts {
(importClause.namedBindings.kind === SyntaxKind.NamespaceImport ? 1 : importClause.namedBindings.elements.length)
: 0);
if (nDeclarations === unuseds.length) {
addDiagnostic(UnusedKind.Local, unuseds.length === 1
addDiagnostic(importDecl, UnusedKind.Local, unuseds.length === 1
? createDiagnosticForNode(importDecl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(first(unuseds).name!))
: createDiagnosticForNode(importDecl, Diagnostics.All_imports_in_import_declaration_are_unused));
}
@@ -23759,26 +23755,26 @@ namespace ts {
addToGroup(unusedVariables, bindingPattern.parent.parent, bindingPattern.parent, getNodeId);
}
else {
addDiagnostic(kind, bindingElements.length === 1
addDiagnostic(bindingPattern, kind, bindingElements.length === 1
? createDiagnosticForNode(bindingPattern, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(cast(first(bindingElements).name, isIdentifier)))
: createDiagnosticForNode(bindingPattern, Diagnostics.All_destructured_elements_are_unused));
}
}
else {
for (const e of bindingElements) {
addDiagnostic(kind, createDiagnosticForNode(e, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(cast(e.name, isIdentifier))));
addDiagnostic(e, kind, createDiagnosticForNode(e, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(cast(e.name, isIdentifier))));
}
}
});
unusedVariables.forEach(([declarationList, declarations]) => {
if (declarationList.declarations.length === declarations.length) {
addDiagnostic(UnusedKind.Local, declarations.length === 1
addDiagnostic(declarationList, UnusedKind.Local, declarations.length === 1
? createDiagnosticForNode(first(declarations).name, Diagnostics._0_is_declared_but_its_value_is_never_read, bindingNameText(first(declarations).name))
: createDiagnosticForNode(declarationList.parent.kind === SyntaxKind.VariableStatement ? declarationList.parent : declarationList, Diagnostics.All_variables_are_unused));
}
else {
for (const decl of declarations) {
addDiagnostic(UnusedKind.Local, createDiagnosticForNode(decl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(cast(decl.name, isIdentifier))));
addDiagnostic(decl, UnusedKind.Local, createDiagnosticForNode(decl, Diagnostics._0_is_declared_but_its_value_is_never_read, idText(cast(decl.name, isIdentifier))));
}
}
});
@@ -26631,8 +26627,8 @@ namespace ts {
}
if (!node.isDeclarationFile && (compilerOptions.noUnusedLocals || compilerOptions.noUnusedParameters)) {
checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(node), (kind, diag) => {
if (unusedIsError(kind)) {
checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(node), (containingNode, kind, diag) => {
if (!containsParseError(containingNode) && unusedIsError(kind)) {
diagnostics.add(diag);
}
});
+1 -1
View File
@@ -4021,7 +4021,7 @@
"category": "Error",
"code": 8029
},
"The type of a function declaration must be callable.": {
"The type of a function declaration must match the function's signature.": {
"category": "Error",
"code": 8030
},
+5
View File
@@ -4355,6 +4355,11 @@ namespace ts {
case SyntaxKind.ConditionalExpression:
node = (<ConditionalExpression>node).condition;
continue;
case SyntaxKind.TaggedTemplateExpression:
node = (<TaggedTemplateExpression>node).tag;
continue;
case SyntaxKind.CallExpression:
if (stopAtCallExpressions) {
return node;
+2 -1
View File
@@ -592,6 +592,7 @@ namespace ts {
const programDiagnostics = createDiagnosticCollection();
const currentDirectory = host.getCurrentDirectory();
const supportedExtensions = getSupportedExtensions(options);
const supportedExtensionsWithJsonIfResolveJsonModule = options.resolveJsonModule ? [...supportedExtensions, Extension.Json] : undefined;
// Map storing if there is emit blocking diagnostics for given input
const hasEmitBlockingDiagnostics = createMap<boolean>();
@@ -1925,7 +1926,7 @@ namespace ts {
refFile?: SourceFile): SourceFile | undefined {
if (hasExtension(fileName)) {
if (!options.allowNonTsExtensions && !forEach(supportedExtensions, extension => fileExtensionIs(host.getCanonicalFileName(fileName), extension))) {
if (!options.allowNonTsExtensions && !forEach(supportedExtensionsWithJsonIfResolveJsonModule || supportedExtensions, extension => fileExtensionIs(host.getCanonicalFileName(fileName), extension))) {
if (fail) fail(Diagnostics.File_0_has_unsupported_extension_The_only_supported_extensions_are_1, fileName, "'" + supportedExtensions.join("', '") + "'");
return undefined;
}
+12 -11
View File
@@ -503,6 +503,7 @@ namespace ts {
/*@internal*/ setBlocking?(): void;
base64decode?(input: string): string;
base64encode?(input: string): string;
/*@internal*/ bufferFrom?(input: string, encoding?: string): Buffer;
}
export interface FileWatcher {
@@ -558,7 +559,7 @@ namespace ts {
getEnvironmentVariable?(name: string): string;
};
// TODO: this is used as if it's certainly defined in many places.
// TODO: GH#18217 this is used as if it's certainly defined in many places.
export let sys: System = (() => {
// NodeJS detects "\uFEFF" at the start of the string and *replaces* it with the actual
// byte order mark from the specified encoding. Using any other byte order mark does
@@ -675,19 +676,19 @@ namespace ts {
process.stdout._handle.setBlocking(true);
}
},
base64decode: Buffer.from ? input => {
return Buffer.from!(input, "base64").toString("utf8");
} : input => {
return new Buffer(input, "base64").toString("utf8");
},
base64encode: Buffer.from ? input => {
return Buffer.from!(input).toString("base64");
} : input => {
return new Buffer(input).toString("base64");
}
bufferFrom,
base64decode: input => bufferFrom(input, "base64").toString("utf8"),
base64encode: input => bufferFrom(input).toString("base64"),
};
return nodeSystem;
function bufferFrom(input: string, encoding?: string): Buffer {
// See https://github.com/Microsoft/TypeScript/issues/25652
return Buffer.from && (Buffer.from as Function) !== Int8Array.from
? Buffer.from(input, encoding)
: new Buffer(input, encoding);
}
function isFileSystemCaseSensitive(): boolean {
// win32\win64 are case insensitive platforms
if (platform === "win32" || platform === "win64") {
+1
View File
@@ -488,6 +488,7 @@ namespace ts {
}
if (watch) {
builder.buildAllProjects();
builder.startWatching();
return undefined;
}
+7 -8
View File
@@ -475,16 +475,15 @@ namespace ts {
// From tsc we want to get already parsed result and hence check for rootFileNames
let newLine = updateNewLine();
if (configFileName && host.configFileParsingResult) {
setConfigFileParsingResult(host.configFileParsingResult);
newLine = updateNewLine();
}
reportWatchDiagnostic(Diagnostics.Starting_compilation_in_watch_mode);
if (configFileName) {
if (configFileName && !host.configFileParsingResult) {
newLine = getNewLineCharacter(optionsToExtendForConfigFile, () => host.getNewLine());
if (host.configFileParsingResult) {
setConfigFileParsingResult(host.configFileParsingResult);
}
else {
Debug.assert(!rootFileNames);
parseConfigFile();
}
Debug.assert(!rootFileNames);
parseConfigFile();
newLine = updateNewLine();
}
+1 -1
View File
@@ -434,7 +434,7 @@ namespace ts {
function createFileWatcherWithTriggerLogging<H, T, U, V, X, Y>(host: H, file: string, cb: WatchCallback<U, V>, flags: T, passThrough: V | undefined, detailInfo1: X | undefined, detailInfo2: Y | undefined, addWatch: AddWatch<H, T, U, undefined>, log: (s: string) => void, watchCaption: string, getDetailWatchInfo: GetDetailWatchInfo<X, Y> | undefined): FileWatcher {
return addWatch(host, file, (fileName, cbOptional) => {
const triggerredInfo = `${watchCaption}:: Triggered with ${fileName}${cbOptional !== undefined ? cbOptional : ""}:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
const triggerredInfo = `${watchCaption}:: Triggered with ${fileName} ${cbOptional !== undefined ? cbOptional : ""}:: ${getWatchInfo(file, flags, detailInfo1, detailInfo2, getDetailWatchInfo)}`;
log(triggerredInfo);
const start = timestamp();
cb(fileName, cbOptional, passThrough);
+1 -1
View File
@@ -148,7 +148,7 @@ namespace documents {
public static fromUrl(url: string) {
const match = SourceMap._dataURLRegExp.exec(url);
return match ? new SourceMap(/*mapFile*/ undefined, (Buffer.from ? Buffer.from(match[1], "base64") : new Buffer(match[1], "base64")).toString("utf8")) : undefined;
return match ? new SourceMap(/*mapFile*/ undefined, ts.sys.base64decode!(match[1])) : undefined;
}
public static fromSource(text: string): SourceMap | undefined {
+1 -4
View File
@@ -66,11 +66,8 @@ namespace Utils {
export let currentExecutionEnvironment = getExecutionEnvironment();
// Thanks to browserify, Buffer is always available nowadays
const Buffer: typeof global.Buffer = require("buffer").Buffer;
export function encodeString(s: string): string {
return Buffer.from(s).toString("utf8");
return ts.sys.bufferFrom!(s).toString("utf8");
}
export function byteLength(s: string, encoding?: string): number {
+2 -2
View File
@@ -683,7 +683,7 @@ namespace vfs {
if (isDirectory(node)) throw createIOError("EISDIR");
if (!isFile(node)) throw createIOError("EBADF");
node.buffer = Buffer.isBuffer(data) ? data.slice() : Buffer.from("" + data, encoding || "utf8");
node.buffer = Buffer.isBuffer(data) ? data.slice() : ts.sys.bufferFrom!("" + data, encoding || "utf8");
node.size = node.buffer.byteLength;
node.mtimeMs = time;
node.ctimeMs = time;
@@ -1204,7 +1204,7 @@ namespace vfs {
}
},
readFileSync(path: string): Buffer {
return Buffer.from(host.readFile(path)!, "utf8"); // TODO: GH#18217
return ts.sys.bufferFrom!(host.readFile(path)!, "utf8"); // TODO: GH#18217
}
};
}
+4 -4
View File
@@ -1125,15 +1125,15 @@ interface Array<T> {
* Returns a string representation of an array. The elements are converted to string using their toLocalString methods.
*/
toLocaleString(): string;
/**
* Removes the last element from an array and returns it.
*/
pop(): T | undefined;
/**
* Appends new elements to an array, and returns the new length of the array.
* @param items New elements of the Array.
*/
push(...items: T[]): number;
/**
* Removes the last element from an array and returns it.
*/
pop(): T | undefined;
/**
* Combines two or more arrays.
* @param items Additional items to add to the end of array1.
+26 -24
View File
@@ -18,31 +18,33 @@ namespace ts.codefix {
Debug.assert(statement.getStart(sourceFile) === token.getStart(sourceFile));
const container = (isBlock(statement.parent) ? statement.parent : statement).parent;
switch (container.kind) {
case SyntaxKind.IfStatement:
if ((container as IfStatement).elseStatement) {
if (isBlock(statement.parent)) {
changes.deleteNodeRange(sourceFile, first(statement.parent.statements), last(statement.parent.statements));
if (!isBlock(statement.parent) || statement === first(statement.parent.statements)) {
switch (container.kind) {
case SyntaxKind.IfStatement:
if ((container as IfStatement).elseStatement) {
if (isBlock(statement.parent)) {
break;
}
else {
changes.replaceNode(sourceFile, statement, createBlock(emptyArray));
}
return;
}
else {
changes.replaceNode(sourceFile, statement, createBlock(emptyArray));
}
break;
}
// falls through
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
changes.delete(sourceFile, container);
break;
default:
if (isBlock(statement.parent)) {
const end = start + length;
const lastStatement = Debug.assertDefined(lastWhere(sliceAfter(statement.parent.statements, statement), s => s.pos < end));
changes.deleteNodeRange(sourceFile, statement, lastStatement);
}
else {
changes.delete(sourceFile, statement);
}
// falls through
case SyntaxKind.WhileStatement:
case SyntaxKind.ForStatement:
changes.delete(sourceFile, container);
return;
}
}
if (isBlock(statement.parent)) {
const end = start + length;
const lastStatement = Debug.assertDefined(lastWhere(sliceAfter(statement.parent.statements, statement), s => s.pos < end));
changes.deleteNodeRange(sourceFile, statement, lastStatement);
}
else {
changes.delete(sourceFile, statement);
}
}
+12 -12
View File
@@ -975,7 +975,6 @@ namespace ts.formatting {
// split comment in lines
let startLine = sourceFile.getLineAndCharacterOfPosition(commentRange.pos).line;
const endLine = sourceFile.getLineAndCharacterOfPosition(commentRange.end).line;
let parts: TextRange[];
if (startLine === endLine) {
if (!firstLineIsIndented) {
// treat as single line comment
@@ -983,20 +982,21 @@ namespace ts.formatting {
}
return;
}
else {
parts = [];
let startPos = commentRange.pos;
for (let line = startLine; line < endLine; line++) {
const endOfLine = getEndLinePosition(line, sourceFile);
parts.push({ pos: startPos, end: endOfLine });
startPos = getStartPositionOfLine(line + 1, sourceFile);
}
if (indentFinalLine) {
parts.push({ pos: startPos, end: commentRange.end });
}
const parts: TextRange[] = [];
let startPos = commentRange.pos;
for (let line = startLine; line < endLine; line++) {
const endOfLine = getEndLinePosition(line, sourceFile);
parts.push({ pos: startPos, end: endOfLine });
startPos = getStartPositionOfLine(line + 1, sourceFile);
}
if (indentFinalLine) {
parts.push({ pos: startPos, end: commentRange.end });
}
if (parts.length === 0) return;
const startLinePos = getStartPositionOfLine(startLine, sourceFile);
const nonWhitespaceColumnInFirstPart =
+6 -10
View File
@@ -351,7 +351,10 @@ namespace ts.formatting {
getListIfStartEndIsInListRange((<SignatureDeclaration>node.parent).parameters, start, end);
}
case SyntaxKind.ClassDeclaration:
return getListIfStartEndIsInListRange((<ClassDeclaration>node.parent).typeParameters, node.getStart(sourceFile), end);
case SyntaxKind.ClassExpression:
case SyntaxKind.InterfaceDeclaration:
case SyntaxKind.TypeAliasDeclaration:
return getListIfStartEndIsInListRange((<ClassDeclaration | ClassExpression | InterfaceDeclaration | TypeAliasDeclaration>node.parent).typeParameters, node.getStart(sourceFile), end);
case SyntaxKind.NewExpression:
case SyntaxKind.CallExpression: {
const start = node.getStart(sourceFile);
@@ -576,17 +579,10 @@ namespace ts.formatting {
function isControlFlowEndingStatement(kind: SyntaxKind, parent: TextRangeWithKind): boolean {
switch (kind) {
case SyntaxKind.ReturnStatement:
case SyntaxKind.ThrowStatement: {
if (parent.kind !== SyntaxKind.Block) {
return true;
}
const grandParent = (parent as Node).parent;
// In a function, we may want to write inner functions after this.
return !(grandParent && grandParent.kind === SyntaxKind.FunctionExpression || grandParent.kind === SyntaxKind.FunctionDeclaration);
}
case SyntaxKind.ThrowStatement:
case SyntaxKind.ContinueStatement:
case SyntaxKind.BreakStatement:
return true;
return parent.kind !== SyntaxKind.Block;
default:
return false;
}
+5 -5
View File
@@ -11,7 +11,7 @@ namespace ts.JsDoc {
"borrows",
"callback",
"class",
"classDesc",
"classdesc",
"constant",
"constructor",
"constructs",
@@ -28,16 +28,16 @@ namespace ts.JsDoc {
"external",
"field",
"file",
"fileOverview",
"fileoverview",
"fires",
"function",
"generator",
"global",
"hideConstructor",
"hideconstructor",
"host",
"ignore",
"implements",
"inheritDoc",
"inheritdoc",
"inner",
"instance",
"interface",
@@ -46,7 +46,7 @@ namespace ts.JsDoc {
"license",
"listens",
"member",
"memberOf",
"memberof",
"method",
"mixes",
"module",
+16 -9
View File
@@ -133,7 +133,7 @@ namespace ts.NavigationBar {
/** Call after calling `startNode` and adding children to it. */
function endNode(): void {
if (parent.children) {
mergeChildren(parent.children);
mergeChildren(parent.children, parent);
sortChildren(parent.children);
}
parent = parentsStack.pop()!;
@@ -304,7 +304,7 @@ namespace ts.NavigationBar {
}
/** Merge declarations of the same kind. */
function mergeChildren(children: NavigationBarNode[]): void {
function mergeChildren(children: NavigationBarNode[], node: NavigationBarNode): void {
const nameToItems = createMap<NavigationBarNode | NavigationBarNode[]>();
filterMutate(children, child => {
const declName = getNameOfDeclaration(<Declaration>child.node);
@@ -322,7 +322,7 @@ namespace ts.NavigationBar {
if (itemsWithSameName instanceof Array) {
for (const itemWithSameName of itemsWithSameName) {
if (tryMerge(itemWithSameName, child)) {
if (tryMerge(itemWithSameName, child, node)) {
return false;
}
}
@@ -331,7 +331,7 @@ namespace ts.NavigationBar {
}
else {
const itemWithSameName = itemsWithSameName;
if (tryMerge(itemWithSameName, child)) {
if (tryMerge(itemWithSameName, child, node)) {
return false;
}
nameToItems.set(name, [itemWithSameName, child]);
@@ -340,8 +340,8 @@ namespace ts.NavigationBar {
});
}
function tryMerge(a: NavigationBarNode, b: NavigationBarNode): boolean {
if (shouldReallyMerge(a.node, b.node)) {
function tryMerge(a: NavigationBarNode, b: NavigationBarNode, parent: NavigationBarNode): boolean {
if (shouldReallyMerge(a.node, b.node, parent)) {
merge(a, b);
return true;
}
@@ -349,8 +349,8 @@ namespace ts.NavigationBar {
}
/** a and b have the same name, but they may not be mergeable. */
function shouldReallyMerge(a: Node, b: Node): boolean {
if (a.kind !== b.kind) {
function shouldReallyMerge(a: Node, b: Node, parent: NavigationBarNode): boolean {
if (a.kind !== b.kind || a.parent !== b.parent && !(isOwnChild(a, parent) && isOwnChild(b, parent))) {
return false;
}
switch (a.kind) {
@@ -366,6 +366,13 @@ namespace ts.NavigationBar {
}
}
// We want to merge own children like `I` in in `module A { interface I {} } module A { interface I {} }`
// We don't want to merge unrelated children like `m` in `const o = { a: { m() {} }, b: { m() {} } };`
function isOwnChild(n: Node, parent: NavigationBarNode): boolean {
const par = isModuleBlock(n.parent) ? n.parent.parent : n.parent;
return par === parent.node || contains(parent.additionalNodes, par);
}
// We use 1 NavNode to represent 'A.B.C', but there are multiple source nodes.
// Only merge module nodes that have the same chain. Don't merge 'A.B.C' with 'A'!
function areSameModule(a: ModuleDeclaration, b: ModuleDeclaration): boolean {
@@ -383,7 +390,7 @@ namespace ts.NavigationBar {
target.children = concatenate(target.children, source.children);
if (target.children) {
mergeChildren(target.children);
mergeChildren(target.children, target);
sortChildren(target.children);
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ namespace ts {
describe("convertToBase64", () => {
function runTest(input: string): void {
const actual = convertToBase64(input);
const expected = (Buffer.from ? Buffer.from(input) : new Buffer(input)).toString("base64");
const expected = sys.base64encode!(input);
assert.equal(actual, expected, "Encoded string using convertToBase64 does not match buffer.toString('base64')");
}
+1
View File
@@ -21,6 +21,7 @@ namespace ts {
const func = createFunctionExpression(/*modifiers*/ undefined, /*asteriskToken*/ undefined, "fn", /*typeParameters*/ undefined, /*parameters*/ undefined, /*type*/ undefined, createBlock([]));
checkExpression(func);
checkExpression(createCall(func, /*typeArguments*/ undefined, /*argumentsArray*/ undefined));
checkExpression(createTaggedTemplate(func, createNoSubstitutionTemplateLiteral("")));
checkExpression(createBinary(createLiteral("a"), SyntaxKind.CommaToken, createLiteral("b")));
checkExpression(createCommaList([createLiteral("a"), createLiteral("b")]));
+33 -1
View File
@@ -233,6 +233,38 @@ namespace ts {
assert.isBelow(fs.statSync("/src/core/index.js").mtimeMs, time(), "Upstream JS file should not have been rebuilt");
});
});
describe("tsbuild - with resolveJsonModule option", () => {
const projFs = loadProjectFromDisk("tests/projects/resolveJsonModuleAndComposite");
const allExpectedOutputs = ["/src/tests/dist/src/index.js", "/src/tests/dist/src/index.d.ts", "/src/tests/dist/src/hello.json"];
function verifyProjectWithResolveJsonModule(configFile: string, ...expectedDiagnosticMessages: DiagnosticMessage[]) {
const fs = projFs.shadow();
const host = new fakes.CompilerHost(fs);
const builder = createSolutionBuilder(host, buildHost, [configFile], { dry: false, force: false, verbose: false });
clearDiagnostics();
builder.buildAllProjects();
assertDiagnosticMessages(...expectedDiagnosticMessages);
if (!expectedDiagnosticMessages.length) {
// Check for outputs. Not an exhaustive list
for (const output of allExpectedOutputs) {
assert(fs.existsSync(output), `Expect file ${output} to exist`);
}
}
}
it("with resolveJsonModule and include only", () => {
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withInclude.json", Diagnostics.File_0_is_not_in_project_file_list_Projects_must_list_all_files_or_use_an_include_pattern);
});
it("with resolveJsonModule and files containing json file", () => {
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withFiles.json");
});
it("with resolveJsonModule and include and files", () => {
verifyProjectWithResolveJsonModule("/src/tests/tsconfig_withIncludeAndFiles.json");
});
});
}
export namespace OutFile {
@@ -427,4 +459,4 @@ namespace ts {
fs.makeReadonly();
return fs;
}
}
}
+55 -21
View File
@@ -2315,63 +2315,97 @@ declare module "fs" {
describe("tsc-watch console clearing", () => {
const currentDirectoryLog = "Current directory: / CaseSensitiveFileNames: false\n";
const fileWatcherAddedLog = [
"FileWatcher:: Added:: WatchInfo: f.ts 250 Source file\n",
"FileWatcher:: Added:: WatchInfo: /f.ts 250 Source file\n",
"FileWatcher:: Added:: WatchInfo: /a/lib/lib.d.ts 250 Source file\n"
];
const file: File = {
path: "/f.ts",
content: ""
};
function getProgramSynchronizingLog(options: CompilerOptions) {
return [
"Synchronizing program\n",
"CreatingProgramWith::\n",
" roots: [\"f.ts\"]\n",
" roots: [\"/f.ts\"]\n",
` options: ${JSON.stringify(options)}\n`
];
}
function checkConsoleClearing(options: CompilerOptions = {}) {
const file = {
path: "f.ts",
content: ""
};
const files = [file, libFile];
const disableConsoleClear = options.diagnostics || options.extendedDiagnostics || options.preserveWatchOutput;
function isConsoleClearDisabled(options: CompilerOptions) {
return options.diagnostics || options.extendedDiagnostics || options.preserveWatchOutput;
}
function verifyCompilation(host: WatchedSystem, options: CompilerOptions, initialDisableOptions?: CompilerOptions) {
const disableConsoleClear = isConsoleClearDisabled(options);
const hasLog = options.extendedDiagnostics || options.diagnostics;
const host = createWatchedSystem(files);
createWatchOfFilesAndCompilerOptions([file.path], host, options);
checkOutputErrorsInitial(host, emptyArray, disableConsoleClear, hasLog ? [
checkOutputErrorsInitial(host, emptyArray, initialDisableOptions ? isConsoleClearDisabled(initialDisableOptions) : disableConsoleClear, hasLog ? [
currentDirectoryLog,
...getProgramSynchronizingLog(options),
...(options.extendedDiagnostics ? fileWatcherAddedLog : emptyArray)
] : undefined);
file.content = "//";
host.reloadFS(files);
host.modifyFile(file.path, "//");
host.runQueuedTimeoutCallbacks();
checkOutputErrorsIncremental(host, emptyArray, disableConsoleClear, hasLog ? [
"FileWatcher:: Triggered with /f.ts1:: WatchInfo: f.ts 250 Source file\n",
"FileWatcher:: Triggered with /f.ts 1:: WatchInfo: /f.ts 250 Source file\n",
"Scheduling update\n",
"Elapsed:: 0ms FileWatcher:: Triggered with /f.ts1:: WatchInfo: f.ts 250 Source file\n"
"Elapsed:: 0ms FileWatcher:: Triggered with /f.ts 1:: WatchInfo: /f.ts 250 Source file\n"
] : undefined, hasLog ? getProgramSynchronizingLog(options) : undefined);
}
function checkConsoleClearingUsingCommandLineOptions(options: CompilerOptions = {}) {
const files = [file, libFile];
const host = createWatchedSystem(files);
createWatchOfFilesAndCompilerOptions([file.path], host, options);
verifyCompilation(host, options);
}
it("without --diagnostics or --extendedDiagnostics", () => {
checkConsoleClearing();
checkConsoleClearingUsingCommandLineOptions();
});
it("with --diagnostics", () => {
checkConsoleClearing({
checkConsoleClearingUsingCommandLineOptions({
diagnostics: true,
});
});
it("with --extendedDiagnostics", () => {
checkConsoleClearing({
checkConsoleClearingUsingCommandLineOptions({
extendedDiagnostics: true,
});
});
it("with --preserveWatchOutput", () => {
checkConsoleClearing({
checkConsoleClearingUsingCommandLineOptions({
preserveWatchOutput: true,
});
});
describe("when preserveWatchOutput is true in config file", () => {
const compilerOptions: CompilerOptions = {
preserveWatchOutput: true
};
const configFile: File = {
path: "/tsconfig.json",
content: JSON.stringify({ compilerOptions })
};
const files = [file, configFile, libFile];
it("using createWatchOfConfigFile ", () => {
const host = createWatchedSystem(files);
createWatchOfConfigFile(configFile.path, host);
// Initially console is cleared if --preserveOutput is not provided since the config file is yet to be parsed
verifyCompilation(host, compilerOptions, {});
});
it("when createWatchProgram is invoked with configFileParseResult on WatchCompilerHostOfConfigFile", () => {
const host = createWatchedSystem(files);
const reportDiagnostic = createDiagnosticReporter(host);
const optionsToExtend: CompilerOptions = {};
const configParseResult = parseConfigFileWithSystem(configFile.path, optionsToExtend, host, reportDiagnostic)!;
const watchCompilerHost = createWatchCompilerHostOfConfigFile(configParseResult.options.configFilePath!, optionsToExtend, host, /*createProgram*/ undefined, reportDiagnostic, createWatchStatusReporter(host));
watchCompilerHost.configFileParsingResult = configParseResult;
createWatchProgram(watchCompilerHost);
verifyCompilation(host, compilerOptions);
});
});
});
describe("tsc-watch with different polling/non polling options", () => {
+2 -2
View File
@@ -199,7 +199,7 @@ namespace ts.server {
private write(s: string) {
if (this.fd >= 0) {
const buf = Buffer.from ? Buffer.from(s) : new Buffer(s);
const buf = sys.bufferFrom!(s);
// tslint:disable-next-line no-null-keyword
fs.writeSync(this.fd, buf, 0, buf.length, /*position*/ null!); // TODO: GH#18217
}
@@ -869,7 +869,7 @@ namespace ts.server {
}
// Override sys.write because fs.writeSync is not reliable on Node 4
sys.write = (s: string) => writeMessage(Buffer.from ? Buffer.from(s, "utf8") : new Buffer(s, "utf8"));
sys.write = (s: string) => writeMessage(sys.bufferFrom!(s, "utf8"));
sys.watchFile = (fileName, callback) => {
const watchedFile = pollingWatchedFileSet.addFile(fileName, callback);
return {