mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into release-3.0
This commit is contained in:
+26
-30
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -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
|
||||
},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
@@ -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") {
|
||||
|
||||
@@ -488,6 +488,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (watch) {
|
||||
builder.buildAllProjects();
|
||||
builder.startWatching();
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
Vendored
+4
-4
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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')");
|
||||
}
|
||||
|
||||
|
||||
@@ -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")]));
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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", () => {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user