Skip to content

Merge master into release-3.0 #25702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 30 commits into from
Jul 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
165a87a
getLeftmostExpression: handle TaggedTemplateExpression
ajafff Jul 8, 2018
b8ca925
Place 'pop' first in 'Array'.
DanielRosenwasser Jul 10, 2018
f7f0c51
Accepted baselines.
DanielRosenwasser Jul 10, 2018
94ad71e
Added test.
DanielRosenwasser Jul 10, 2018
751bceb
Accepted baselines.
DanielRosenwasser Jul 10, 2018
08d7b8f
When running with -w, do an initial compilation
RyanCavanaugh Jul 12, 2018
6a2ffec
Merge pull request #25610 from RyanCavanaugh/buildOnWatchStartup
RyanCavanaugh Jul 12, 2018
f500289
Stricter test that JSDoc @type tag matches function signature (#25615)
Jul 12, 2018
32e60a9
Explicitly typed special assignments are context sensitive (#25619)
sandersn Jul 12, 2018
1fb050b
Don't report unused diagnostics when the unused node has a parse erro…
Jul 13, 2018
ca08380
Fix incorrect handling of preserveWatchOutput flag is in config file
sheetalkamat Jul 13, 2018
88c6ced
indentMultilineCommentOrJsxText: Fix bug when 'parts' is empty (#25645)
Jul 13, 2018
27da9ea
fixUnreachableCode: Don't delete whole block when non-first line is u…
Jul 13, 2018
3f4412b
getContainingList: Handle TypeAliasDeclaration (#25614)
Jul 13, 2018
47e513e
Merge pull request #25627 from Microsoft/preserveOutputInConfig
sheetalkamat Jul 13, 2018
49ac60f
Support resolveJsonModule option when files contain the json file
sheetalkamat Jul 13, 2018
4f411a8
Change jsDocTagNames to lower case.
j-oliveras Jul 13, 2018
7ad4fcf
Merge pull request #25649 from Microsoft/jsonFilesOnCommandLine
sheetalkamat Jul 13, 2018
e25a23b
Fix Buffer.from uses to handle node 5.4.1 bug (#25659)
Jul 14, 2018
60986ad
Merge pull request #25507 from ajafff/leftmost-expr-tagged-template
DanielRosenwasser Jul 14, 2018
5b21cbc
Explicitly typed prototype assignments are context sensitive (#25688)
sandersn Jul 16, 2018
8ef146e
Merge pull request #25656 from j-oliveras/Fix_25653
mhegazy Jul 16, 2018
afdd47c
Simplify rules for `isControlFlowEndingStatement` (#25693)
Jul 16, 2018
93ab352
Merge pull request #25565 from Microsoft/popFirst
DanielRosenwasser Jul 16, 2018
ff8c30d
Revert "Explicitly typed prototype assignments are context sensitive …
sandersn Jul 16, 2018
1038c76
navigationBar: Don't merge unrelated grandchildren
Jul 16, 2018
16676f2
Revert "Explicitly typed special assignments are context sensitive (#…
sandersn Jul 16, 2018
d690835
Merge pull request #25698 from Microsoft/navigationBarUnrelatedGrandc…
mhegazy Jul 16, 2018
75930f8
Merge pull request #25699 from Microsoft/revert-explicitly-typed-spec…
mhegazy Jul 16, 2018
39a7891
Merge branch 'master' into release-3.0
mhegazy Jul 16, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 26 additions & 30 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
}
});
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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];
Expand All @@ -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];
Expand Down Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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;
Expand All @@ -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)));
}
}
}
Expand Down Expand Up @@ -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 {
Expand All @@ -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));
}
Expand All @@ -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))));
}
}
});
Expand Down Expand Up @@ -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);
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
Expand Down
5 changes: 5 additions & 0 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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>();
Expand Down Expand Up @@ -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;
}
Expand Down
23 changes: 12 additions & 11 deletions src/compiler/sys.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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") {
Expand Down
1 change: 1 addition & 0 deletions src/compiler/tsbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,7 @@ namespace ts {
}

if (watch) {
builder.buildAllProjects();
builder.startWatching();
return undefined;
}
Expand Down
15 changes: 7 additions & 8 deletions src/compiler/watch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

Expand Down
2 changes: 1 addition & 1 deletion src/compiler/watchUtilities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/harness/documents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 1 addition & 4 deletions src/harness/harness.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
Loading