Skip to content

Commit 1b4dfbc

Browse files
committed
Merge branch 'master' of https://github.com/Microsoft/TypeScript into feature/eslint
2 parents 11ec611 + 3d09010 commit 1b4dfbc

File tree

65 files changed

+2541
-874
lines changed

Some content is hidden

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

65 files changed

+2541
-874
lines changed

src/compiler/binder.ts

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ namespace ts {
120120
let thisParentContainer: Node; // Container one level up
121121
let blockScopeContainer: Node;
122122
let lastContainer: Node;
123-
let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag)[];
123+
let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag)[];
124124
let seenThisKeyword: boolean;
125125

126126
// state used by control flow analysis
@@ -732,7 +732,8 @@ namespace ts {
732732
break;
733733
case SyntaxKind.JSDocTypedefTag:
734734
case SyntaxKind.JSDocCallbackTag:
735-
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag);
735+
case SyntaxKind.JSDocEnumTag:
736+
bindJSDocTypeAlias(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
736737
break;
737738
// In source files and blocks, bind functions first to match hoisting that occurs at runtime
738739
case SyntaxKind.SourceFile: {
@@ -1436,9 +1437,9 @@ namespace ts {
14361437
}
14371438
}
14381439

1439-
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag) {
1440+
function bindJSDocTypeAlias(node: JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag) {
14401441
node.tagName.parent = node;
1441-
if (node.fullName) {
1442+
if (node.kind !== SyntaxKind.JSDocEnumTag && node.fullName) {
14421443
setParentPointers(node, node.fullName);
14431444
}
14441445
}
@@ -1805,7 +1806,7 @@ namespace ts {
18051806
currentFlow = { flags: FlowFlags.Start };
18061807
parent = typeAlias;
18071808
bind(typeAlias.typeExpression);
1808-
if (!typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) {
1809+
if (isJSDocEnumTag(typeAlias) || !typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) {
18091810
parent = typeAlias.parent;
18101811
bindBlockScopedDeclaration(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
18111812
}
@@ -2319,7 +2320,8 @@ namespace ts {
23192320
return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes);
23202321
case SyntaxKind.JSDocTypedefTag:
23212322
case SyntaxKind.JSDocCallbackTag:
2322-
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag);
2323+
case SyntaxKind.JSDocEnumTag:
2324+
return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag);
23232325
}
23242326
}
23252327

@@ -2766,11 +2768,8 @@ namespace ts {
27662768
}
27672769

27682770
if (!isBindingPattern(node.name)) {
2769-
const isEnum = isInJSFile(node) && !!getJSDocEnumTag(node);
2770-
const enumFlags = (isEnum ? SymbolFlags.RegularEnum : SymbolFlags.None);
2771-
const enumExcludes = (isEnum ? SymbolFlags.RegularEnumExcludes : SymbolFlags.None);
27722771
if (isBlockOrCatchScoped(node)) {
2773-
bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable | enumFlags, SymbolFlags.BlockScopedVariableExcludes | enumExcludes);
2772+
bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes);
27742773
}
27752774
else if (isParameterDeclaration(node)) {
27762775
// It is safe to walk up parent chain to find whether the node is a destructuring parameter declaration
@@ -2785,7 +2784,7 @@ namespace ts {
27852784
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.ParameterExcludes);
27862785
}
27872786
else {
2788-
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable | enumFlags, SymbolFlags.FunctionScopedVariableExcludes | enumExcludes);
2787+
declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes);
27892788
}
27902789
}
27912790
}

src/compiler/checker.ts

Lines changed: 169 additions & 96 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2467,7 +2467,8 @@ namespace ts {
24672467
kind: SyntaxKind.JSDocClassTag;
24682468
}
24692469

2470-
export interface JSDocEnumTag extends JSDocTag {
2470+
export interface JSDocEnumTag extends JSDocTag, Declaration {
2471+
parent: JSDoc;
24712472
kind: SyntaxKind.JSDocEnumTag;
24722473
typeExpression?: JSDocTypeExpression;
24732474
}

src/compiler/utilities.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2150,11 +2150,11 @@ namespace ts {
21502150
return !!name && name.escapedText === "new";
21512151
}
21522152

2153-
export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag {
2154-
return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag;
2153+
export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag {
2154+
return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag || node.kind === SyntaxKind.JSDocEnumTag;
21552155
}
21562156

2157-
export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | TypeAliasDeclaration {
2157+
export function isTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag | TypeAliasDeclaration {
21582158
return isJSDocTypeAlias(node) || isTypeAliasDeclaration(node);
21592159
}
21602160

@@ -5098,7 +5098,7 @@ namespace ts {
50985098
* attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol
50995099
* will be merged with)
51005100
*/
5101-
function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag): Identifier | undefined {
5101+
function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag | JSDocEnumTag): Identifier | undefined {
51025102
const hostNode = declaration.parent.parent;
51035103
if (!hostNode) {
51045104
return undefined;
@@ -5184,6 +5184,8 @@ namespace ts {
51845184
}
51855185
case SyntaxKind.JSDocTypedefTag:
51865186
return getNameOfJSDocTypedef(declaration as JSDocTypedefTag);
5187+
case SyntaxKind.JSDocEnumTag:
5188+
return nameForNamelessJSDocTypedef(declaration as JSDocEnumTag);
51875189
case SyntaxKind.ExportAssignment: {
51885190
const { expression } = declaration as ExportAssignment;
51895191
return isIdentifier(expression) ? expression : undefined;

src/harness/typeWriter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ class TypeWriterWalker {
9797
if (!isSymbolWalk) {
9898
// Don't try to get the type of something that's already a type.
9999
// Exception for `T` in `type T = something` because that may evaluate to some interesting type.
100-
if (ts.isPartOfTypeNode(node) || ts.isIdentifier(node) && !(ts.getMeaningFromDeclaration(node.parent) & ts.SemanticMeaning.Value) && !(ts.isTypeAlias(node.parent) && node.parent.name === node)) {
100+
if (ts.isPartOfTypeNode(node) || ts.isIdentifier(node) && !(ts.getMeaningFromDeclaration(node.parent) & ts.SemanticMeaning.Value) && !(ts.isTypeAliasDeclaration(node.parent) && node.parent.name === node)) {
101101
return undefined;
102102
}
103103

src/server/editorServices.ts

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,10 @@ namespace ts.server {
284284
configFileErrors?: ReadonlyArray<Diagnostic>;
285285
}
286286

287+
interface AssignProjectResult extends OpenConfiguredProjectResult {
288+
defaultConfigProject: ConfiguredProject | undefined;
289+
}
290+
287291
interface FilePropertyReader<T> {
288292
getFileName(f: T): string;
289293
getScriptKind(f: T, extraFileExtensions?: FileExtensionInfo[]): ScriptKind;
@@ -2634,10 +2638,11 @@ namespace ts.server {
26342638
return info;
26352639
}
26362640

2637-
private assignProjectToOpenedScriptInfo(info: ScriptInfo): OpenConfiguredProjectResult {
2641+
private assignProjectToOpenedScriptInfo(info: ScriptInfo): AssignProjectResult {
26382642
let configFileName: NormalizedPath | undefined;
26392643
let configFileErrors: ReadonlyArray<Diagnostic> | undefined;
26402644
let project: ConfiguredProject | ExternalProject | undefined = this.findExternalProjectContainingOpenScriptInfo(info);
2645+
let defaultConfigProject: ConfiguredProject | undefined;
26412646
if (!project && !this.syntaxOnly) { // Checking syntaxOnly is an optimization
26422647
configFileName = this.getConfigFileNameForFile(info);
26432648
if (configFileName) {
@@ -2658,6 +2663,7 @@ namespace ts.server {
26582663
// Ensure project is ready to check if it contains opened script info
26592664
updateProjectIfDirty(project);
26602665
}
2666+
defaultConfigProject = project;
26612667
}
26622668
}
26632669

@@ -2677,13 +2683,13 @@ namespace ts.server {
26772683
this.assignOrphanScriptInfoToInferredProject(info, this.openFiles.get(info.path));
26782684
}
26792685
Debug.assert(!info.isOrphan());
2680-
return { configFileName, configFileErrors };
2686+
return { configFileName, configFileErrors, defaultConfigProject };
26812687
}
26822688

2683-
private cleanupAfterOpeningFile() {
2689+
private cleanupAfterOpeningFile(toRetainConfigProjects: ConfiguredProject[] | ConfiguredProject | undefined) {
26842690
// This was postponed from closeOpenFile to after opening next file,
26852691
// so that we can reuse the project if we need to right away
2686-
this.removeOrphanConfiguredProjects();
2692+
this.removeOrphanConfiguredProjects(toRetainConfigProjects);
26872693

26882694
// Remove orphan inferred projects now that we have reused projects
26892695
// We need to create a duplicate because we cant guarantee order after removal
@@ -2704,22 +2710,30 @@ namespace ts.server {
27042710

27052711
openClientFileWithNormalizedPath(fileName: NormalizedPath, fileContent?: string, scriptKind?: ScriptKind, hasMixedContent?: boolean, projectRootPath?: NormalizedPath): OpenConfiguredProjectResult {
27062712
const info = this.getOrCreateOpenScriptInfo(fileName, fileContent, scriptKind, hasMixedContent, projectRootPath);
2707-
const result = this.assignProjectToOpenedScriptInfo(info);
2708-
this.cleanupAfterOpeningFile();
2713+
const { defaultConfigProject, ...result } = this.assignProjectToOpenedScriptInfo(info);
2714+
this.cleanupAfterOpeningFile(defaultConfigProject);
27092715
this.telemetryOnOpenFile(info);
27102716
return result;
27112717
}
27122718

2713-
private removeOrphanConfiguredProjects() {
2719+
private removeOrphanConfiguredProjects(toRetainConfiguredProjects: ConfiguredProject[] | ConfiguredProject | undefined) {
27142720
const toRemoveConfiguredProjects = cloneMap(this.configuredProjects);
2721+
if (toRetainConfiguredProjects) {
2722+
if (isArray(toRetainConfiguredProjects)) {
2723+
toRetainConfiguredProjects.forEach(retainConfiguredProject);
2724+
}
2725+
else {
2726+
retainConfiguredProject(toRetainConfiguredProjects);
2727+
}
2728+
}
27152729

27162730
// Do not remove configured projects that are used as original projects of other
27172731
this.inferredProjects.forEach(markOriginalProjectsAsUsed);
27182732
this.externalProjects.forEach(markOriginalProjectsAsUsed);
27192733
this.configuredProjects.forEach(project => {
27202734
// If project has open ref (there are more than zero references from external project/open file), keep it alive as well as any project it references
27212735
if (project.hasOpenRef()) {
2722-
toRemoveConfiguredProjects.delete(project.canonicalConfigFilePath);
2736+
retainConfiguredProject(project);
27232737
markOriginalProjectsAsUsed(project);
27242738
}
27252739
else {
@@ -2728,7 +2742,7 @@ namespace ts.server {
27282742
if (ref) {
27292743
const refProject = this.configuredProjects.get(ref.sourceFile.path);
27302744
if (refProject && refProject.hasOpenRef()) {
2731-
toRemoveConfiguredProjects.delete(project.canonicalConfigFilePath);
2745+
retainConfiguredProject(project);
27322746
}
27332747
}
27342748
});
@@ -2743,6 +2757,10 @@ namespace ts.server {
27432757
project.originalConfiguredProjects.forEach((_value, configuredProjectPath) => toRemoveConfiguredProjects.delete(configuredProjectPath));
27442758
}
27452759
}
2760+
2761+
function retainConfiguredProject(project: ConfiguredProject) {
2762+
toRemoveConfiguredProjects.delete(project.canonicalConfigFilePath);
2763+
}
27462764
}
27472765

27482766
private removeOrphanScriptInfos() {
@@ -2885,8 +2903,9 @@ namespace ts.server {
28852903
}
28862904

28872905
// All the script infos now exist, so ok to go update projects for open files
2906+
let defaultConfigProjects: ConfiguredProject[] | undefined;
28882907
if (openScriptInfos) {
2889-
openScriptInfos.forEach(info => this.assignProjectToOpenedScriptInfo(info));
2908+
defaultConfigProjects = mapDefined(openScriptInfos, info => this.assignProjectToOpenedScriptInfo(info).defaultConfigProject);
28902909
}
28912910

28922911
// While closing files there could be open files that needed assigning new inferred projects, do it now
@@ -2895,7 +2914,7 @@ namespace ts.server {
28952914
}
28962915

28972916
// Cleanup projects
2898-
this.cleanupAfterOpeningFile();
2917+
this.cleanupAfterOpeningFile(defaultConfigProjects);
28992918

29002919
// Telemetry
29012920
forEach(openScriptInfos, info => this.telemetryOnOpenFile(info));

src/services/codefixes/importFixes.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -445,9 +445,12 @@ namespace ts.codefix {
445445
const aliased = checker.getImmediateAliasedSymbol(defaultExport);
446446
return aliased && getDefaultExportInfoWorker(aliased, Debug.assertDefined(aliased.parent), checker, compilerOptions);
447447
}
448-
else {
449-
return { symbolForMeaning: defaultExport, name: moduleSymbolToValidIdentifier(moduleSymbol, compilerOptions.target!) };
448+
449+
if (defaultExport.escapedName !== InternalSymbolName.Default &&
450+
defaultExport.escapedName !== InternalSymbolName.ExportEquals) {
451+
return { symbolForMeaning: defaultExport, name: defaultExport.getName() };
450452
}
453+
return { symbolForMeaning: defaultExport, name: moduleSymbolToValidIdentifier(moduleSymbol, compilerOptions.target!) };
451454
}
452455

453456
function getNameForExportDefault(symbol: Symbol): string | undefined {

src/services/outliningElementsCollector.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,8 @@ namespace ts.OutliningElementsCollector {
7171
function addRegionOutliningSpans(sourceFile: SourceFile, out: Push<OutliningSpan>): void {
7272
const regions: OutliningSpan[] = [];
7373
const lineStarts = sourceFile.getLineStarts();
74-
for (let i = 0; i < lineStarts.length; i++) {
75-
const currentLineStart = lineStarts[i];
76-
const lineEnd = i + 1 === lineStarts.length ? sourceFile.getEnd() : lineStarts[i + 1] - 1;
74+
for (const currentLineStart of lineStarts) {
75+
const lineEnd = sourceFile.getLineEndOfPosition(currentLineStart);
7776
const lineText = sourceFile.text.substring(currentLineStart, lineEnd);
7877
const result = isRegionDelimiter(lineText);
7978
if (!result || isInComment(sourceFile, currentLineStart)) {

src/services/smartSelection.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,13 @@ namespace ts.SmartSelectionRange {
6464
parentNode = node;
6565
break;
6666
}
67+
68+
// If we made it to the end of the for loop, we’re done.
69+
// In practice, I’ve only seen this happen at the very end
70+
// of a SourceFile.
71+
if (i === children.length - 1) {
72+
break outer;
73+
}
6774
}
6875
}
6976

src/testRunner/externalCompileRunner.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,22 +185,26 @@ function stripRushStageNumbers(result: string): string {
185185
* so we purge as much of the gulp output as we can
186186
*/
187187
function sanitizeUnimportantGulpOutput(result: string): string {
188-
return result.replace(/^.*(\] (Starting)|(Finished)).*$/gm, "") // task start/end messages (nondeterministic order)
188+
return result.replace(/^.*(\] (Starting)|(Finished)).*$/gm, "") // "gulp" task start/end messages (nondeterministic order)
189+
.replace(/^.*(\] . (finished)|(started)).*$/gm, "") // "just" task start/end messages (nondeterministic order)
189190
.replace(/^.*\] Respawned to PID: \d+.*$/gm, "") // PID of child is OS and system-load dependent (likely stableish in a container but still dangerous)
190191
.replace(/\n+/g, "\n");
191192
}
192193

193194
function sanitizeTimestamps(result: string): string {
194195
return result.replace(/\[\d?\d:\d\d:\d\d (A|P)M\]/g, "[XX:XX:XX XM]")
195196
.replace(/\[\d?\d:\d\d:\d\d\]/g, "[XX:XX:XX]")
197+
.replace(/\/\d+-\d+-[\d_TZ]+-debug.log/g, "\/XXXX-XX-XXXXXXXXX-debug.log")
196198
.replace(/\d+(\.\d+)? sec(onds?)?/g, "? seconds")
197199
.replace(/\d+(\.\d+)? min(utes?)?/g, "")
198-
.replace(/\d+(\.\d+)?( m)?s/g, "?s");
200+
.replace(/\d+(\.\d+)? ?m?s/g, "?s")
201+
.replace(/ \(\?s\)/g, "");
199202
}
200203

201204
function sanitizeVersionSpecifiers(result: string): string {
202205
return result
203206
.replace(/\d+.\d+.\d+-insiders.\d\d\d\d\d\d\d\d/g, "X.X.X-insiders.xxxxxxxx")
207+
.replace(/Rush Multi-Project Build Tool (\d+)\.\d+\.\d+/g, "Rush Multi-Project Build Tool $1.X.X")
204208
.replace(/([@v\()])\d+\.\d+\.\d+/g, "$1X.X.X");
205209
}
206210

0 commit comments

Comments
 (0)