Skip to content

Commit 64baa80

Browse files
committed
Merge branch 'master' of https://github.com/Microsoft/TypeScript into feature/eslint
2 parents ccba537 + 303297a commit 64baa80

161 files changed

Lines changed: 6340 additions & 1087 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/compiler/builder.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,8 @@ namespace ts {
612612
*/
613613
function getProgramBuildInfo(state: Readonly<ReusableBuilderProgramState>, getCanonicalFileName: GetCanonicalFileName): ProgramBuildInfo | undefined {
614614
if (state.compilerOptions.outFile || state.compilerOptions.out) return undefined;
615-
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getOutputPathForBuildInfo(state.compilerOptions)!, Debug.assertDefined(state.program).getCurrentDirectory()));
615+
const currentDirectory = Debug.assertDefined(state.program).getCurrentDirectory();
616+
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getOutputPathForBuildInfo(state.compilerOptions)!, currentDirectory));
616617
const fileInfos: MapLike<BuilderState.FileInfo> = {};
617618
state.fileInfos.forEach((value, key) => {
618619
const signature = state.currentAffectedFilesSignatures && state.currentAffectedFilesSignatures.get(key);
@@ -621,7 +622,7 @@ namespace ts {
621622

622623
const result: ProgramBuildInfo = {
623624
fileInfos,
624-
options: convertToReusableCompilerOptions(state.compilerOptions, relativeToBuildInfo)
625+
options: convertToReusableCompilerOptions(state.compilerOptions, relativeToBuildInfoEnsuringAbsolutePath)
625626
};
626627
if (state.referencedMap) {
627628
const referencedMap: MapLike<string[]> = {};
@@ -661,6 +662,10 @@ namespace ts {
661662

662663
return result;
663664

665+
function relativeToBuildInfoEnsuringAbsolutePath(path: string) {
666+
return relativeToBuildInfo(getNormalizedAbsolutePath(path, currentDirectory));
667+
}
668+
664669
function relativeToBuildInfo(path: string) {
665670
return ensurePathIsNonModuleName(getRelativePathFromDirectory(buildInfoDirectory, path, getCanonicalFileName));
666671
}

src/compiler/checker.ts

Lines changed: 76 additions & 42 deletions
Large diffs are not rendered by default.

src/compiler/diagnosticMessages.json

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,10 +2076,6 @@
20762076
"category": "Error",
20772077
"code": 2569
20782078
},
2079-
"Property '{0}' does not exist on type '{1}'. Did you forget to use 'await'?": {
2080-
"category": "Error",
2081-
"code": 2570
2082-
},
20832079
"Object is of type 'unknown'.": {
20842080
"category": "Error",
20852081
"code": 2571
@@ -4639,6 +4635,11 @@
46394635
"category": "Suggestion",
46404636
"code": 80006
46414637
},
4638+
"'await' has no effect on the type of this expression.": {
4639+
"category": "Suggestion",
4640+
"code": 80007
4641+
},
4642+
46424643
"Add missing 'super()' call": {
46434644
"category": "Message",
46444645
"code": 90001
@@ -5079,14 +5080,39 @@
50795080
"category": "Message",
50805081
"code": 95080
50815082
},
5083+
"Add 'const' to unresolved variable": {
5084+
"category": "Message",
5085+
"code": 95081
5086+
},
5087+
"Add 'const' to all unresolved variables": {
5088+
"category": "Message",
5089+
"code": 95082
5090+
},
5091+
"Add 'await'": {
5092+
"category": "Message",
5093+
"code": 95083
5094+
},
5095+
"Add 'await' to initializer for '{0}'": {
5096+
"category": "Message",
5097+
"code": 95084
5098+
},
5099+
"Fix all expressions possibly missing 'await'": {
5100+
"category": "Message",
5101+
"code": 95085
5102+
},
5103+
"Remove unnecessary 'await'": {
5104+
"category": "Message",
5105+
"code": 95086
5106+
},
5107+
"Remove all unnecessary uses of 'await'": {
5108+
"category": "Message",
5109+
"code": 95087
5110+
},
5111+
50825112
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
50835113
"category": "Error",
50845114
"code": 18004
50855115
},
5086-
"Quoted constructors have previously been interpreted as methods, which is incorrect. In TypeScript 3.6, they will be correctly parsed as constructors. In the meantime, consider using 'constructor()' to write a constructor, or '[\"constructor\"]()' to write a method.": {
5087-
"category": "Error",
5088-
"code": 18005
5089-
},
50905116
"Classes may not have a field named 'constructor'.": {
50915117
"category": "Error",
50925118
"code": 18006

src/compiler/parser.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5654,12 +5654,27 @@ namespace ts {
56545654
return finishNode(node);
56555655
}
56565656

5657-
function parseConstructorDeclaration(node: ConstructorDeclaration): ConstructorDeclaration {
5658-
node.kind = SyntaxKind.Constructor;
5659-
parseExpected(SyntaxKind.ConstructorKeyword);
5660-
fillSignature(SyntaxKind.ColonToken, SignatureFlags.None, node);
5661-
node.body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected);
5662-
return finishNode(node);
5657+
function parseConstructorName() {
5658+
if (token() === SyntaxKind.ConstructorKeyword) {
5659+
return parseExpected(SyntaxKind.ConstructorKeyword);
5660+
}
5661+
if (token() === SyntaxKind.StringLiteral && lookAhead(nextToken) === SyntaxKind.OpenParenToken) {
5662+
return tryParse(() => {
5663+
const literalNode = parseLiteralNode();
5664+
return literalNode.text === "constructor" ? literalNode : undefined;
5665+
});
5666+
}
5667+
}
5668+
5669+
function tryParseConstructorDeclaration(node: ConstructorDeclaration): ConstructorDeclaration | undefined {
5670+
return tryParse(() => {
5671+
if (parseConstructorName()) {
5672+
node.kind = SyntaxKind.Constructor;
5673+
fillSignature(SyntaxKind.ColonToken, SignatureFlags.None, node);
5674+
node.body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected);
5675+
return finishNode(node);
5676+
}
5677+
});
56635678
}
56645679

56655680
function parseMethodDeclaration(node: MethodDeclaration, asteriskToken: AsteriskToken, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
@@ -5865,8 +5880,11 @@ namespace ts {
58655880
return parseAccessorDeclaration(<AccessorDeclaration>node, SyntaxKind.SetAccessor);
58665881
}
58675882

5868-
if (token() === SyntaxKind.ConstructorKeyword) {
5869-
return parseConstructorDeclaration(<ConstructorDeclaration>node);
5883+
if (token() === SyntaxKind.ConstructorKeyword || token() === SyntaxKind.StringLiteral) {
5884+
const constructorDeclaration = tryParseConstructorDeclaration(<ConstructorDeclaration>node);
5885+
if (constructorDeclaration) {
5886+
return constructorDeclaration;
5887+
}
58705888
}
58715889

58725890
if (isIndexSignature()) {

src/compiler/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1883,6 +1883,7 @@ namespace ts {
18831883
}
18841884

18851885
export interface JsxAttributes extends ObjectLiteralExpressionBase<JsxAttributeLike> {
1886+
kind: SyntaxKind.JsxAttributes;
18861887
parent: JsxOpeningLikeElement;
18871888
}
18881889

src/compiler/utilities.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3155,6 +3155,23 @@ namespace ts {
31553155
return s.replace(escapedCharsRegExp, getReplacement);
31563156
}
31573157

3158+
/**
3159+
* Strip off existed single quotes or double quotes from a given string
3160+
*
3161+
* @return non-quoted string
3162+
*/
3163+
export function stripQuotes(name: string) {
3164+
const length = name.length;
3165+
if (length >= 2 && name.charCodeAt(0) === name.charCodeAt(length - 1) && startsWithQuote(name)) {
3166+
return name.substring(1, length - 1);
3167+
}
3168+
return name;
3169+
}
3170+
3171+
export function startsWithQuote(name: string): boolean {
3172+
return isSingleOrDoubleQuote(name.charCodeAt(0));
3173+
}
3174+
31583175
function getReplacement(c: string, offset: number, input: string) {
31593176
if (c.charCodeAt(0) === CharacterCodes.nullCharacter) {
31603177
const lookAhead = input.charCodeAt(offset + c.length);
@@ -7477,7 +7494,7 @@ namespace ts {
74777494
export function getDirectoryPath(path: Path): Path;
74787495
/**
74797496
* Returns the path except for its basename. Semantics align with NodeJS's `path.dirname`
7480-
* except that we support URL's as well.
7497+
* except that we support URLs as well.
74817498
*
74827499
* ```ts
74837500
* getDirectoryPath("/path/to/file.ext") === "/path/to"

src/harness/fourslash.ts

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ namespace FourSlash {
798798
const name = typeof include === "string" ? include : include.name;
799799
const found = nameToEntries.get(name);
800800
if (!found) throw this.raiseError(`No completion ${name} found`);
801-
assert(found.length === 1); // Must use 'exact' for multiple completions with same name
801+
assert(found.length === 1, `Must use 'exact' for multiple completions with same name: '${name}'`);
802802
this.verifyCompletionEntry(ts.first(found), include);
803803
}
804804
}
@@ -2828,11 +2828,28 @@ Actual: ${stringify(fullActual)}`);
28282828
}
28292829
}
28302830

2831-
public verifyCodeFixAvailable(negative: boolean, expected: FourSlashInterface.VerifyCodeFixAvailableOptions[] | undefined): void {
2832-
assert(!negative || !expected);
2831+
public verifyCodeFixAvailable(negative: boolean, expected: FourSlashInterface.VerifyCodeFixAvailableOptions[] | string | undefined): void {
28332832
const codeFixes = this.getCodeFixes(this.activeFile.fileName);
2834-
const actuals = codeFixes.map((fix): FourSlashInterface.VerifyCodeFixAvailableOptions => ({ description: fix.description, commands: fix.commands }));
2835-
this.assertObjectsEqual(actuals, negative ? ts.emptyArray : expected);
2833+
if (negative) {
2834+
if (typeof expected === "undefined") {
2835+
this.assertObjectsEqual(codeFixes, ts.emptyArray);
2836+
}
2837+
else if (typeof expected === "string") {
2838+
if (codeFixes.some(fix => fix.fixName === expected)) {
2839+
this.raiseError(`Expected not to find a fix with the name '${expected}', but one exists.`);
2840+
}
2841+
}
2842+
else {
2843+
assert(typeof expected === "undefined" || typeof expected === "string", "With a negated assertion, 'expected' must be undefined or a string value of a codefix name.");
2844+
}
2845+
}
2846+
else if (typeof expected === "string") {
2847+
this.assertObjectsEqual(codeFixes.map(fix => fix.fixName), [expected]);
2848+
}
2849+
else {
2850+
const actuals = codeFixes.map((fix): FourSlashInterface.VerifyCodeFixAvailableOptions => ({ description: fix.description, commands: fix.commands }));
2851+
this.assertObjectsEqual(actuals, negative ? ts.emptyArray : expected);
2852+
}
28362853
}
28372854

28382855
public verifyApplicableRefactorAvailableAtMarker(negative: boolean, markerName: string) {

0 commit comments

Comments
 (0)