Skip to content

Merge master 5/22 #24329

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 33 commits into from
May 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
acee628
Fix discriminant checking in contextual types to avoid infinite recur…
ahejlsberg Apr 30, 2018
0ab3c1f
Normalize this.currentDirectory
minestarks May 15, 2018
dff5809
Accept new baseline
minestarks May 16, 2018
d558371
Update version
mhegazy May 16, 2018
3a00ac1
Merge branch 'master' into updateVersion
mhegazy May 16, 2018
6f041e9
Accept baselines
mhegazy May 16, 2018
59d1925
Add test to verify the document is released from source file when inf…
sheetalkamat May 15, 2018
81ca650
Cache the latest source file from document registry so we can keep it…
sheetalkamat May 16, 2018
e4c380a
Merge branch 'master' into documentRegistery
sheetalkamat May 21, 2018
f1acbc9
Add noGetErrOnBackgroundUpdate session option to not queue diagnostic…
sheetalkamat May 21, 2018
c8ac085
Infer non-widening literal types when type parameter constraint inclu…
ahejlsberg May 21, 2018
8528dbe
Handle union types in getRegularTypeOfLiteralType
ahejlsberg May 21, 2018
5bbadb6
Accept new baselines
ahejlsberg May 21, 2018
9d4096f
Add tests
ahejlsberg May 21, 2018
b31c414
Accept new baselines
ahejlsberg May 21, 2018
edd31a1
Preserver jsx imports even when the compiler option is not set
amcasey May 21, 2018
a9e89ce
Merge pull request #24180 from Microsoft/updateVersion
mhegazy May 22, 2018
4b47c0c
fix wrong formatting with multiline type literals with IntersectionTy…
Kingwl May 22, 2018
f52c4af
Merge pull request #24310 from Microsoft/nonWideningLiteralInferences
ahejlsberg May 22, 2018
982c8d0
Add suggestion diagnostics for unused label and unreachable code (#24…
May 22, 2018
5e5c5a7
Merge pull request #24139 from minestarks/dynamicprojectassert
minestarks May 22, 2018
a8715d0
Update user baselines (#24289)
May 22, 2018
9d57903
Merge pull request #24312 from Kingwl/multiline-type-literal-formatter
mhegazy May 22, 2018
a5029e3
Merge pull request #23794 from Microsoft/fixDiscriminatedContextualType
ahejlsberg May 22, 2018
2e0cc63
Check TransformFlags.ContainsJsx, rather than LanguageVariant.JSX
amcasey May 22, 2018
7fb3123
Merge pull request #24298 from Microsoft/noErrOnBackgroundUpdate
mhegazy May 22, 2018
7106a58
Add type for diagnostics where location is defined (#23686)
May 22, 2018
66590a9
Verify ref counts are set correctly when reusing the source file from…
sheetalkamat May 22, 2018
bedc110
Merge pull request #24311 from amcasey/GH23287
amcasey May 22, 2018
e8a0e56
Add a test when orphan file changes before it gets added back to project
sheetalkamat May 22, 2018
f44dd6f
Merge pull request #24206 from Microsoft/documentRegistery
sheetalkamat May 22, 2018
1318c93
Merge branch 'master' into MergeMaster5-22-2
mhegazy May 22, 2018
4f25e83
Update baselines
mhegazy May 22, 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
55 changes: 33 additions & 22 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ namespace ts {
* If so, the node _must_ be in the current file (as that's the only way anything could have traversed to it to yield it as the error node)
* This version of `createDiagnosticForNode` uses the binder's context to account for this, and always yields correct diagnostics even in these situations.
*/
function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): Diagnostic {
function createDiagnosticForNode(node: Node, message: DiagnosticMessage, arg0?: string | number, arg1?: string | number, arg2?: string | number): DiagnosticWithLocation {
return createDiagnosticForNodeInSourceFile(getSourceFileOfNode(node) || file, node, message, arg0, arg1, arg2);
}

Expand Down Expand Up @@ -1208,7 +1208,7 @@ namespace ts {
bind(node.statement);
popActiveLabel();
if (!activeLabel.referenced && !options.allowUnusedLabels) {
file.bindDiagnostics.push(createDiagnosticForNode(node.label, Diagnostics.Unused_label));
errorOrSuggestionOnFirstToken(unusedLabelIsError(options), node, Diagnostics.Unused_label);
}
if (!node.statement || node.statement.kind !== SyntaxKind.DoStatement) {
// do statement sets current flow inside bindDoStatement
Expand Down Expand Up @@ -1914,6 +1914,17 @@ namespace ts {
file.bindDiagnostics.push(createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2));
}

function errorOrSuggestionOnFirstToken(isError: boolean, node: Node, message: DiagnosticMessage, arg0?: any, arg1?: any, arg2?: any) {
const span = getSpanOfTokenAtPosition(file, node.pos);
const diag = createFileDiagnostic(file, span.start, span.length, message, arg0, arg1, arg2);
if (isError) {
file.bindDiagnostics.push(diag);
}
else {
file.bindSuggestionDiagnostics = append(file.bindSuggestionDiagnostics, { ...diag, category: DiagnosticCategory.Suggestion });
}
}

function bind(node: Node): void {
if (!node) {
return;
Expand Down Expand Up @@ -2730,26 +2741,26 @@ namespace ts {
if (reportError) {
currentFlow = reportedUnreachableFlow;

// unreachable code is reported if
// - user has explicitly asked about it AND
// - statement is in not ambient context (statements in ambient context is already an error
// so we should not report extras) AND
// - node is not variable statement OR
// - node is block scoped variable statement OR
// - node is not block scoped variable statement and at least one variable declaration has initializer
// Rationale: we don't want to report errors on non-initialized var's since they are hoisted
// On the other side we do want to report errors on non-initialized 'lets' because of TDZ
const reportUnreachableCode =
!options.allowUnreachableCode &&
!(node.flags & NodeFlags.Ambient) &&
(
node.kind !== SyntaxKind.VariableStatement ||
getCombinedNodeFlags((<VariableStatement>node).declarationList) & NodeFlags.BlockScoped ||
forEach((<VariableStatement>node).declarationList.declarations, d => d.initializer)
);

if (reportUnreachableCode) {
errorOnFirstToken(node, Diagnostics.Unreachable_code_detected);
if (!options.allowUnreachableCode) {
// unreachable code is reported if
// - user has explicitly asked about it AND
// - statement is in not ambient context (statements in ambient context is already an error
// so we should not report extras) AND
// - node is not variable statement OR
// - node is block scoped variable statement OR
// - node is not block scoped variable statement and at least one variable declaration has initializer
// Rationale: we don't want to report errors on non-initialized var's since they are hoisted
// On the other side we do want to report errors on non-initialized 'lets' because of TDZ
const isError =
unreachableCodeIsError(options) &&
!(node.flags & NodeFlags.Ambient) &&
(
!isVariableStatement(node) ||
!!(getCombinedNodeFlags(node.declarationList) & NodeFlags.BlockScoped) ||
node.declarationList.declarations.some(d => !!d.initializer)
);

errorOrSuggestionOnFirstToken(isError, node, Diagnostics.Unreachable_code_detected);
}
}
}
Expand Down
48 changes: 36 additions & 12 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,11 +313,11 @@ namespace ts {

getSuggestionDiagnostics: file => {
return (suggestionDiagnostics.get(file.fileName) || emptyArray).concat(getUnusedDiagnostics());
function getUnusedDiagnostics(): ReadonlyArray<Diagnostic> {
function getUnusedDiagnostics(): ReadonlyArray<DiagnosticWithLocation> {
if (file.isDeclarationFile) return emptyArray;

checkSourceFile(file);
const diagnostics: Diagnostic[] = [];
const diagnostics: DiagnosticWithLocation[] = [];
Debug.assert(!!(getNodeLinks(file).flags & NodeCheckFlags.TypeChecked));
checkUnusedIdentifiers(getPotentiallyUnusedIdentifiers(file), (kind, diag) => {
if (!unusedIsError(kind)) {
Expand Down Expand Up @@ -481,7 +481,7 @@ namespace ts {

const diagnostics = createDiagnosticCollection();
// Suggestion diagnostics must have a file. Keyed by source file name.
const suggestionDiagnostics = createMultiMap<Diagnostic>();
const suggestionDiagnostics = createMultiMap<DiagnosticWithLocation>();

const enum TypeFacts {
None = 0,
Expand Down Expand Up @@ -628,7 +628,7 @@ namespace ts {
Local,
Parameter,
}
type AddUnusedDiagnostic = (type: UnusedKind, diagnostic: Diagnostic) => void;
type AddUnusedDiagnostic = (type: UnusedKind, diagnostic: DiagnosticWithLocation) => void;

const builtinGlobals = createSymbolTable();
builtinGlobals.set(undefinedSymbol.escapedName, undefinedSymbol);
Expand Down Expand Up @@ -824,7 +824,7 @@ namespace ts {
diagnostics.add(diagnostic);
}

function addErrorOrSuggestion(isError: boolean, diagnostic: Diagnostic) {
function addErrorOrSuggestion(isError: boolean, diagnostic: DiagnosticWithLocation) {
if (isError) {
diagnostics.add(diagnostic);
}
Expand Down Expand Up @@ -9286,8 +9286,10 @@ namespace ts {
return type;
}

function getRegularTypeOfLiteralType(type: Type) {
return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (<LiteralType>type).regularType : type;
function getRegularTypeOfLiteralType(type: Type): Type {
return type.flags & TypeFlags.StringOrNumberLiteral && type.flags & TypeFlags.FreshLiteral ? (<LiteralType>type).regularType :
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getRegularTypeOfLiteralType)) :
type;
}

function getLiteralType(value: string | number, enumId?: number, symbol?: Symbol) {
Expand Down Expand Up @@ -12774,10 +12776,12 @@ namespace ts {
// all inferences were made to top-level occurrences of the type parameter, and
// the type parameter has no constraint or its constraint includes no primitive or literal types, and
// the type parameter was fixed during inference or does not occur at top-level in the return type.
const widenLiteralTypes = inference.topLevel &&
!hasPrimitiveConstraint(inference.typeParameter) &&
const primitiveConstraint = hasPrimitiveConstraint(inference.typeParameter);
const widenLiteralTypes = !primitiveConstraint && inference.topLevel &&
(inference.isFixed || !isTypeParameterAtTopLevel(getReturnTypeOfSignature(signature), inference.typeParameter));
const baseCandidates = widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) : candidates;
const baseCandidates = primitiveConstraint ? sameMap(candidates, getRegularTypeOfLiteralType) :
widenLiteralTypes ? sameMap(candidates, getWidenedLiteralType) :
candidates;
// If all inferences were made from contravariant positions, infer a common subtype. Otherwise, if
// union types were requested or if all inferences were made from the return type position, infer a
// union type. Otherwise, infer a common supertype.
Expand Down Expand Up @@ -15303,6 +15307,26 @@ namespace ts {
}
}

// Return true if the given expression is possibly a discriminant value. We limit the kinds of
// expressions we check to those that don't depend on their contextual type in order not to cause
// recursive (and possibly infinite) invocations of getContextualType.
function isPossiblyDiscriminantValue(node: Expression): boolean {
switch (node.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
case SyntaxKind.NullKeyword:
case SyntaxKind.Identifier:
return true;
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ParenthesizedExpression:
return isPossiblyDiscriminantValue((<PropertyAccessExpression | ParenthesizedExpression>node).expression);
}
return false;
}

// Return the contextual type for a given expression node. During overload resolution, a contextual type may temporarily
// be "pushed" onto a node using the contextualType property.
function getApparentTypeOfContextualType(node: Expression): Type {
Expand All @@ -15316,8 +15340,8 @@ namespace ts {
propLoop: for (const prop of node.properties) {
if (!prop.symbol) continue;
if (prop.kind !== SyntaxKind.PropertyAssignment) continue;
if (isDiscriminantProperty(contextualType, prop.symbol.escapedName)) {
const discriminatingType = getTypeOfNode(prop.initializer);
if (isPossiblyDiscriminantValue(prop.initializer) && isDiscriminantProperty(contextualType, prop.symbol.escapedName)) {
const discriminatingType = checkExpression(prop.initializer);
for (const type of (contextualType as UnionType).types) {
const targetType = getTypeOfPropertyOfType(type, prop.symbol.escapedName);
if (targetType && checkTypeAssignableTo(discriminatingType, targetType, /*errorNode*/ undefined)) {
Expand Down
16 changes: 12 additions & 4 deletions src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ namespace ts {
return pathIsRelative(moduleName) || isRootedDiskPath(moduleName);
}

export function sortAndDeduplicateDiagnostics(diagnostics: ReadonlyArray<Diagnostic>): Diagnostic[] {
return sortAndDeduplicate(diagnostics, compareDiagnostics);
export function sortAndDeduplicateDiagnostics<T extends Diagnostic>(diagnostics: ReadonlyArray<T>): T[] {
return sortAndDeduplicate<T>(diagnostics, compareDiagnostics);
}
}

Expand Down Expand Up @@ -1619,8 +1619,8 @@ namespace ts {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
}

export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number)[]): Diagnostic;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): Diagnostic {
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number)[]): DiagnosticWithLocation;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): DiagnosticWithLocation {
Debug.assertGreaterThanOrEqual(start, 0);
Debug.assertGreaterThanOrEqual(length, 0);

Expand Down Expand Up @@ -1991,6 +1991,14 @@ namespace ts {
return moduleResolution;
}

export function unreachableCodeIsError(options: CompilerOptions): boolean {
return options.allowUnreachableCode === false;
}

export function unusedLabelIsError(options: CompilerOptions): boolean {
return options.allowUnusedLabels === false;
}

export function getAreDeclarationMapsEnabled(options: CompilerOptions) {
return !!(options.declaration && options.declarationMap);
}
Expand Down
6 changes: 4 additions & 2 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -2238,7 +2238,8 @@
},
"Left side of comma operator is unused and has no side effects.": {
"category": "Error",
"code": 2695
"code": 2695,
"reportsUnnecessary": true
},
"The 'Object' type is assignable to very few other types. Did you mean to use the 'any' type instead?": {
"category": "Error",
Expand Down Expand Up @@ -3673,7 +3674,8 @@
},
"Unreachable code detected.": {
"category": "Error",
"code": 7027
"code": 7027,
"reportsUnnecessary": true
},
"Unused label.": {
"category": "Error",
Expand Down
1 change: 1 addition & 0 deletions src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2463,6 +2463,7 @@ namespace ts {
if (node.symbolCount !== undefined) updated.symbolCount = node.symbolCount;
if (node.parseDiagnostics !== undefined) updated.parseDiagnostics = node.parseDiagnostics;
if (node.bindDiagnostics !== undefined) updated.bindDiagnostics = node.bindDiagnostics;
if (node.bindSuggestionDiagnostics !== undefined) updated.bindSuggestionDiagnostics = node.bindSuggestionDiagnostics;
if (node.lineMap !== undefined) updated.lineMap = node.lineMap;
if (node.classifiableNames !== undefined) updated.classifiableNames = node.classifiableNames;
if (node.resolvedModules !== undefined) updated.resolvedModules = node.resolvedModules;
Expand Down
3 changes: 2 additions & 1 deletion src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ namespace ts {
// tslint:enable variable-name

let sourceFile: SourceFile;
let parseDiagnostics: Diagnostic[];
let parseDiagnostics: DiagnosticWithLocation[];
let syntaxCursor: IncrementalParser.SyntaxCursor;

let currentToken: SyntaxKind;
Expand Down Expand Up @@ -912,6 +912,7 @@ namespace ts {

sourceFile.text = sourceText;
sourceFile.bindDiagnostics = [];
sourceFile.bindSuggestionDiagnostics = undefined;
sourceFile.languageVersion = languageVersion;
sourceFile.fileName = normalizePath(fileName);
sourceFile.languageVariant = getLanguageVariant(scriptKind);
Expand Down
Loading