diff --git a/.github/workflows/new-release-branch.yaml b/.github/workflows/new-release-branch.yaml index 1e145a0932f79..8cb80522ae283 100644 --- a/.github/workflows/new-release-branch.yaml +++ b/.github/workflows/new-release-branch.yaml @@ -23,7 +23,7 @@ jobs: sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "${{ github.event.client_payload.core_major_minor }}"/g' tests/baselines/reference/api/typescript.d.ts sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "${{ github.event.client_payload.core_major_minor }}"/g' tests/baselines/reference/api/tsserverlibrary.d.ts sed -i -e 's/const version = `${versionMajorMinor}.0-.*`/const version = `${versionMajorMinor}.0-${{ github.event.client_payload.core_tag || 'dev' }}`/g' src/compiler/corePublic.ts - npm install + npm ci gulp LKG npm test git diff @@ -32,7 +32,7 @@ jobs: git add tests/baselines/reference/api/typescript.d.ts git add tests/baselines/reference/api/tsserverlibrary.d.ts git add ./lib - git config user.email "ts_bot@rcavanaugh.com" + git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" git commit -m 'Bump version to ${{ github.event.client_payload.package_version }} and LKG' git push --set-upstream origin ${{ github.event.client_payload.branch_name }} diff --git a/.github/workflows/release-branch-artifact.yaml b/.github/workflows/release-branch-artifact.yaml index ed50cfeb6464c..7683b7623acee 100644 --- a/.github/workflows/release-branch-artifact.yaml +++ b/.github/workflows/release-branch-artifact.yaml @@ -21,8 +21,7 @@ jobs: npm uninstall tslint --no-save - name: npm install and test run: | - npm install - npm update + npm ci npm test env: CI: true @@ -41,4 +40,3 @@ jobs: with: name: tgz path: typescript.tgz - \ No newline at end of file diff --git a/.github/workflows/set-version.yaml b/.github/workflows/set-version.yaml index a31d849cb4131..f337d5b58f472 100644 --- a/.github/workflows/set-version.yaml +++ b/.github/workflows/set-version.yaml @@ -29,7 +29,7 @@ jobs: sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "${{ github.event.client_payload.core_major_minor }}"/g' tests/baselines/reference/api/typescript.d.ts sed -i -e 's/const versionMajorMinor = ".*"/const versionMajorMinor = "${{ github.event.client_payload.core_major_minor }}"/g' tests/baselines/reference/api/tsserverlibrary.d.ts sed -i -e 's/const version = .*;/const version = "${{ github.event.client_payload.package_version }}" as string;/g' src/compiler/corePublic.ts - npm install + npm ci gulp LKG npm test git diff @@ -38,7 +38,7 @@ jobs: git add tests/baselines/reference/api/typescript.d.ts git add tests/baselines/reference/api/tsserverlibrary.d.ts git add ./lib - git config user.email "ts_bot@rcavanaugh.com" + git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" git commit -m 'Bump version to ${{ github.event.client_payload.package_version }} and LKG' git push diff --git a/.github/workflows/sync-branch.yaml b/.github/workflows/sync-branch.yaml index 642a353aa3c69..7c1e6b3667696 100644 --- a/.github/workflows/sync-branch.yaml +++ b/.github/workflows/sync-branch.yaml @@ -20,10 +20,10 @@ jobs: # required client_payload members: # branch_name - the target branch - run: | - git config user.email "ts_bot@rcavanaugh.com" + git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" git fetch origin master git merge master --no-ff - npm install + npm ci npm test git push diff --git a/.github/workflows/update-lkg.yml b/.github/workflows/update-lkg.yml index 8864d1316c0be..cf81cc97db9fb 100644 --- a/.github/workflows/update-lkg.yml +++ b/.github/workflows/update-lkg.yml @@ -17,9 +17,9 @@ jobs: - name: Configure Git and Update LKG run: | - git config user.email "ts_bot@rcavanaugh.com" + git config user.email "typescriptbot@microsoft.com" git config user.name "TypeScript Bot" - npm install + npm ci gulp LKG npm test git diff diff --git a/Dockerfile b/Dockerfile index 8898a69af6d38..5606df961119b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,6 @@ FROM node:current COPY . /typescript WORKDIR /typescript -RUN npm install +RUN npm ci RUN npm i -g gulp-cli RUN gulp configure-insiders && gulp LKG && gulp clean && npm pack . \ No newline at end of file diff --git a/README.md b/README.md index 848f1f4dd8c4b..723522332a738 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,7 @@ Install [Gulp](https://gulpjs.com/) tools and dev dependencies: ```bash npm install -g gulp -npm install +npm ci ``` Use one of the following to build and test: diff --git a/lib/protocol.d.ts b/lib/protocol.d.ts index ba7347422ec82..3c963c19f17ba 100644 --- a/lib/protocol.d.ts +++ b/lib/protocol.d.ts @@ -452,6 +452,11 @@ declare namespace ts.server.protocol { * so this description should make sense by itself if the parent is inlineable=true */ description: string; + /** + * A message to show to the user if the refactoring cannot be applied in + * the current context. + */ + notApplicableReason?: string; } interface GetEditsForRefactorRequest extends Request { command: CommandTypes.GetEditsForRefactor; @@ -2473,6 +2478,7 @@ declare namespace ts.server.protocol { readonly allowTextChangesInNewFiles?: boolean; readonly lazyConfiguredProjectsFromExternalProject?: boolean; readonly providePrefixAndSuffixTextForRename?: boolean; + readonly provideRefactorNotApplicableReason?: boolean; readonly allowRenameOfImportPath?: boolean; readonly includePackageJsonAutoImports?: "auto" | "on" | "off"; } diff --git a/lib/tsc.js b/lib/tsc.js index 94ebc43d97e95..d30565165b537 100644 --- a/lib/tsc.js +++ b/lib/tsc.js @@ -67,7 +67,7 @@ var __generator = (this && this.__generator) || function (thisArg, body) { var ts; (function (ts) { ts.versionMajorMinor = "4.0"; - ts.version = "4.0.3"; + ts.version = "4.0.5"; var NativeCollections; (function (NativeCollections) { function tryGetNativeMap() { @@ -73480,6 +73480,8 @@ var ts; switch (node.kind) { case 213: return visitBinaryExpression(node); + case 332: + return visitCommaListExpression(node); case 214: return visitConditionalExpression(node); case 216: @@ -73671,20 +73673,6 @@ var ts; } return ts.visitEachChild(node, visitor, context); } - function visitLogicalBinaryExpression(node) { - var resultLabel = defineLabel(); - var resultLocal = declareLocal(); - emitAssignment(resultLocal, ts.visitNode(node.left, visitor, ts.isExpression), node.left); - if (node.operatorToken.kind === 55) { - emitBreakWhenFalse(resultLabel, resultLocal, node.left); - } - else { - emitBreakWhenTrue(resultLabel, resultLocal, node.left); - } - emitAssignment(resultLocal, ts.visitNode(node.right, visitor, ts.isExpression), node.right); - markLabel(resultLabel); - return resultLocal; - } function visitCommaExpression(node) { var pendingExpressions = []; visit(node.left); @@ -73704,6 +73692,37 @@ var ts; } } } + function visitCommaListExpression(node) { + var pendingExpressions = []; + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var elem = _a[_i]; + if (ts.isBinaryExpression(elem) && elem.operatorToken.kind === 27) { + pendingExpressions.push(visitCommaExpression(elem)); + } + else { + if (containsYield(elem) && pendingExpressions.length > 0) { + emitWorker(1, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(elem, visitor, ts.isExpression)); + } + } + return factory.inlineExpressions(pendingExpressions); + } + function visitLogicalBinaryExpression(node) { + var resultLabel = defineLabel(); + var resultLocal = declareLocal(); + emitAssignment(resultLocal, ts.visitNode(node.left, visitor, ts.isExpression), node.left); + if (node.operatorToken.kind === 55) { + emitBreakWhenFalse(resultLabel, resultLocal, node.left); + } + else { + emitBreakWhenTrue(resultLabel, resultLocal, node.left); + } + emitAssignment(resultLocal, ts.visitNode(node.right, visitor, ts.isExpression), node.right); + markLabel(resultLabel); + return resultLocal; + } function visitConditionalExpression(node) { if (containsYield(node.whenTrue) || containsYield(node.whenFalse)) { var whenFalseLabel = defineLabel(); @@ -84207,6 +84226,7 @@ var ts; getOptionsDiagnostics: getOptionsDiagnostics, getGlobalDiagnostics: getGlobalDiagnostics, getSemanticDiagnostics: getSemanticDiagnostics, + getCachedSemanticDiagnostics: getCachedSemanticDiagnostics, getSuggestionDiagnostics: getSuggestionDiagnostics, getDeclarationDiagnostics: getDeclarationDiagnostics, getBindAndCheckDiagnostics: getBindAndCheckDiagnostics, @@ -84721,6 +84741,11 @@ var ts; function getSemanticDiagnostics(sourceFile, cancellationToken) { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } + function getCachedSemanticDiagnostics(sourceFile) { + var _a; + return sourceFile + ? (_a = cachedBindAndCheckDiagnosticsForFile.perFile) === null || _a === void 0 ? void 0 : _a.get(sourceFile.path) : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; + } function getBindAndCheckDiagnostics(sourceFile, cancellationToken) { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } @@ -87315,30 +87340,49 @@ var ts; return toAffectedFileEmitResult(state, ts.Debug.checkDefined(state.program).emit(affected === state.program ? undefined : affected, writeFile || ts.maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles || emitKind === 0, customTransformers), affected, emitKind, isPendingEmitFile); } function emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { + var restorePendingEmitOnHandlingNoEmitSuccess = false; + var savedAffectedFilesPendingEmit; + var savedAffectedFilesPendingEmitKind; + var savedAffectedFilesPendingEmitIndex; + if (kind !== BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram && + !targetSourceFile && + !ts.outFile(state.compilerOptions) && + !state.compilerOptions.noEmit && + state.compilerOptions.noEmitOnError) { + restorePendingEmitOnHandlingNoEmitSuccess = true; + savedAffectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice(); + savedAffectedFilesPendingEmitKind = state.affectedFilesPendingEmitKind && new ts.Map(state.affectedFilesPendingEmitKind); + savedAffectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex; + } if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); - var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); - if (result) - return result; - if (!targetSourceFile) { - var sourceMaps = []; - var emitSkipped = false; - var diagnostics = void 0; - var emittedFiles = []; - var affectedEmitResult = void 0; - while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { - emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; - diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); - emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); - sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); - } - return { - emitSkipped: emitSkipped, - diagnostics: diagnostics || ts.emptyArray, - emittedFiles: emittedFiles, - sourceMaps: sourceMaps - }; + } + var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); + if (result) + return result; + if (restorePendingEmitOnHandlingNoEmitSuccess) { + state.affectedFilesPendingEmit = savedAffectedFilesPendingEmit; + state.affectedFilesPendingEmitKind = savedAffectedFilesPendingEmitKind; + state.affectedFilesPendingEmitIndex = savedAffectedFilesPendingEmitIndex; + } + if (!targetSourceFile && kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + var sourceMaps = []; + var emitSkipped = false; + var diagnostics = void 0; + var emittedFiles = []; + var affectedEmitResult = void 0; + while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { + emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; + diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); + emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); + sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); } + return { + emitSkipped: emitSkipped, + diagnostics: diagnostics || ts.emptyArray, + emittedFiles: emittedFiles, + sourceMaps: sourceMaps + }; } return ts.Debug.checkDefined(state.program).emit(targetSourceFile, writeFile || ts.maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers); } @@ -87351,7 +87395,7 @@ var ts; else if (affected === state.program) { return toAffectedFileResult(state, state.program.getSemanticDiagnostics(undefined, cancellationToken), affected); } - if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram || state.compilerOptions.noEmit || state.compilerOptions.noEmitOnError) { addToAffectedFilesPendingEmit(state, affected.resolvedPath, 1); } if (ignoreSourceFile && ignoreSourceFile(affected)) { diff --git a/lib/tsserver.js b/lib/tsserver.js index 4a3a80c72bbd3..132e7451182be 100644 --- a/lib/tsserver.js +++ b/lib/tsserver.js @@ -94,7 +94,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.3"; + ts.version = "4.0.5"; /* @internal */ var Comparison; (function (Comparison) { @@ -89418,6 +89418,8 @@ var ts; switch (node.kind) { case 213 /* BinaryExpression */: return visitBinaryExpression(node); + case 332 /* CommaListExpression */: + return visitCommaListExpression(node); case 214 /* ConditionalExpression */: return visitConditionalExpression(node); case 216 /* YieldExpression */: @@ -89712,6 +89714,61 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ + function visitCommaExpression(node) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); + var pendingExpressions = []; + visit(node.left); + visit(node.right); + return factory.inlineExpressions(pendingExpressions); + function visit(node) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { + visit(node.left); + visit(node.right); + } + else { + if (containsYield(node) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); + } + } + } + /** + * Visits a comma-list expression. + * + * @param node The node to visit. + */ + function visitCommaListExpression(node) { + // flattened version of `visitCommaExpression` + var pendingExpressions = []; + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var elem = _a[_i]; + if (ts.isBinaryExpression(elem) && elem.operatorToken.kind === 27 /* CommaToken */) { + pendingExpressions.push(visitCommaExpression(elem)); + } + else { + if (containsYield(elem) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(elem, visitor, ts.isExpression)); + } + } + return factory.inlineExpressions(pendingExpressions); + } /** * Visits a logical binary expression containing `yield`. * @@ -89761,38 +89818,6 @@ var ts; markLabel(resultLabel); return resultLocal; } - /** - * Visits a comma expression containing `yield`. - * - * @param node The node to visit. - */ - function visitCommaExpression(node) { - // [source] - // x = a(), yield, b(); - // - // [intermediate] - // a(); - // .yield resumeLabel - // .mark resumeLabel - // x = %sent%, b(); - var pendingExpressions = []; - visit(node.left); - visit(node.right); - return factory.inlineExpressions(pendingExpressions); - function visit(node) { - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { - visit(node.left); - visit(node.right); - } - else { - if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); - pendingExpressions = []; - } - pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); - } - } - } /** * Visits a conditional expression containing `yield`. * @@ -102854,6 +102879,7 @@ var ts; getOptionsDiagnostics: getOptionsDiagnostics, getGlobalDiagnostics: getGlobalDiagnostics, getSemanticDiagnostics: getSemanticDiagnostics, + getCachedSemanticDiagnostics: getCachedSemanticDiagnostics, getSuggestionDiagnostics: getSuggestionDiagnostics, getDeclarationDiagnostics: getDeclarationDiagnostics, getBindAndCheckDiagnostics: getBindAndCheckDiagnostics, @@ -103477,6 +103503,11 @@ var ts; function getSemanticDiagnostics(sourceFile, cancellationToken) { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } + function getCachedSemanticDiagnostics(sourceFile) { + var _a; + return sourceFile + ? (_a = cachedBindAndCheckDiagnosticsForFile.perFile) === null || _a === void 0 ? void 0 : _a.get(sourceFile.path) : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; + } function getBindAndCheckDiagnostics(sourceFile, cancellationToken) { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } @@ -106509,31 +106540,54 @@ var ts; * in that order would be used to write the files */ function emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { + var restorePendingEmitOnHandlingNoEmitSuccess = false; + var savedAffectedFilesPendingEmit; + var savedAffectedFilesPendingEmitKind; + var savedAffectedFilesPendingEmitIndex; + // Backup and restore affected pendings emit state for non emit Builder if noEmitOnError is enabled and emitBuildInfo could be written in case there are errors + // This ensures pending files to emit is updated in tsbuildinfo + // Note that when there are no errors, emit proceeds as if everything is emitted as it is callers reponsibility to write the files to disk if at all (because its builder that doesnt track files to emit) + if (kind !== BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram && + !targetSourceFile && + !ts.outFile(state.compilerOptions) && + !state.compilerOptions.noEmit && + state.compilerOptions.noEmitOnError) { + restorePendingEmitOnHandlingNoEmitSuccess = true; + savedAffectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice(); + savedAffectedFilesPendingEmitKind = state.affectedFilesPendingEmitKind && new ts.Map(state.affectedFilesPendingEmitKind); + savedAffectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex; + } if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); - var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); - if (result) - return result; - if (!targetSourceFile) { - // Emit and report any errors we ran into. - var sourceMaps = []; - var emitSkipped = false; - var diagnostics = void 0; - var emittedFiles = []; - var affectedEmitResult = void 0; - while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { - emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; - diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); - emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); - sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); - } - return { - emitSkipped: emitSkipped, - diagnostics: diagnostics || ts.emptyArray, - emittedFiles: emittedFiles, - sourceMaps: sourceMaps - }; + } + var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); + if (result) + return result; + if (restorePendingEmitOnHandlingNoEmitSuccess) { + state.affectedFilesPendingEmit = savedAffectedFilesPendingEmit; + state.affectedFilesPendingEmitKind = savedAffectedFilesPendingEmitKind; + state.affectedFilesPendingEmitIndex = savedAffectedFilesPendingEmitIndex; + } + // Emit only affected files if using builder for emit + if (!targetSourceFile && kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Emit and report any errors we ran into. + var sourceMaps = []; + var emitSkipped = false; + var diagnostics = void 0; + var emittedFiles = []; + var affectedEmitResult = void 0; + while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { + emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; + diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); + emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); + sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); } + return { + emitSkipped: emitSkipped, + diagnostics: diagnostics || ts.emptyArray, + emittedFiles: emittedFiles, + sourceMaps: sourceMaps + }; } return ts.Debug.checkDefined(state.program).emit(targetSourceFile, writeFile || ts.maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers); } @@ -106553,7 +106607,8 @@ var ts; return toAffectedFileResult(state, state.program.getSemanticDiagnostics(/*targetSourceFile*/ undefined, cancellationToken), affected); } // Add file to affected file pending emit to handle for later emit time - if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Apart for emit builder do this for tsbuildinfo, do this for non emit builder when noEmit is set as tsbuildinfo is written and reused between emitters + if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram || state.compilerOptions.noEmit || state.compilerOptions.noEmitOnError) { addToAffectedFilesPendingEmit(state, affected.resolvedPath, 1 /* Full */); } // Get diagnostics for the affected file if its not ignored diff --git a/lib/tsserverlibrary.d.ts b/lib/tsserverlibrary.d.ts index aad052326e024..42c28b30e33e0 100644 --- a/lib/tsserverlibrary.d.ts +++ b/lib/tsserverlibrary.d.ts @@ -6881,6 +6881,11 @@ declare namespace ts.server.protocol { * so this description should make sense by itself if the parent is inlineable=true */ description: string; + /** + * A message to show to the user if the refactoring cannot be applied in + * the current context. + */ + notApplicableReason?: string; } interface GetEditsForRefactorRequest extends Request { command: CommandTypes.GetEditsForRefactor; @@ -8902,6 +8907,7 @@ declare namespace ts.server.protocol { readonly allowTextChangesInNewFiles?: boolean; readonly lazyConfiguredProjectsFromExternalProject?: boolean; readonly providePrefixAndSuffixTextForRename?: boolean; + readonly provideRefactorNotApplicableReason?: boolean; readonly allowRenameOfImportPath?: boolean; readonly includePackageJsonAutoImports?: "auto" | "on" | "off"; } diff --git a/lib/tsserverlibrary.js b/lib/tsserverlibrary.js index 19d76c21007c7..14db40a451d70 100644 --- a/lib/tsserverlibrary.js +++ b/lib/tsserverlibrary.js @@ -288,7 +288,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.3"; + ts.version = "4.0.5"; /* @internal */ var Comparison; (function (Comparison) { @@ -89612,6 +89612,8 @@ var ts; switch (node.kind) { case 213 /* BinaryExpression */: return visitBinaryExpression(node); + case 332 /* CommaListExpression */: + return visitCommaListExpression(node); case 214 /* ConditionalExpression */: return visitConditionalExpression(node); case 216 /* YieldExpression */: @@ -89906,6 +89908,61 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ + function visitCommaExpression(node) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); + var pendingExpressions = []; + visit(node.left); + visit(node.right); + return factory.inlineExpressions(pendingExpressions); + function visit(node) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { + visit(node.left); + visit(node.right); + } + else { + if (containsYield(node) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); + } + } + } + /** + * Visits a comma-list expression. + * + * @param node The node to visit. + */ + function visitCommaListExpression(node) { + // flattened version of `visitCommaExpression` + var pendingExpressions = []; + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var elem = _a[_i]; + if (ts.isBinaryExpression(elem) && elem.operatorToken.kind === 27 /* CommaToken */) { + pendingExpressions.push(visitCommaExpression(elem)); + } + else { + if (containsYield(elem) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(elem, visitor, ts.isExpression)); + } + } + return factory.inlineExpressions(pendingExpressions); + } /** * Visits a logical binary expression containing `yield`. * @@ -89955,38 +90012,6 @@ var ts; markLabel(resultLabel); return resultLocal; } - /** - * Visits a comma expression containing `yield`. - * - * @param node The node to visit. - */ - function visitCommaExpression(node) { - // [source] - // x = a(), yield, b(); - // - // [intermediate] - // a(); - // .yield resumeLabel - // .mark resumeLabel - // x = %sent%, b(); - var pendingExpressions = []; - visit(node.left); - visit(node.right); - return factory.inlineExpressions(pendingExpressions); - function visit(node) { - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { - visit(node.left); - visit(node.right); - } - else { - if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); - pendingExpressions = []; - } - pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); - } - } - } /** * Visits a conditional expression containing `yield`. * @@ -103048,6 +103073,7 @@ var ts; getOptionsDiagnostics: getOptionsDiagnostics, getGlobalDiagnostics: getGlobalDiagnostics, getSemanticDiagnostics: getSemanticDiagnostics, + getCachedSemanticDiagnostics: getCachedSemanticDiagnostics, getSuggestionDiagnostics: getSuggestionDiagnostics, getDeclarationDiagnostics: getDeclarationDiagnostics, getBindAndCheckDiagnostics: getBindAndCheckDiagnostics, @@ -103671,6 +103697,11 @@ var ts; function getSemanticDiagnostics(sourceFile, cancellationToken) { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } + function getCachedSemanticDiagnostics(sourceFile) { + var _a; + return sourceFile + ? (_a = cachedBindAndCheckDiagnosticsForFile.perFile) === null || _a === void 0 ? void 0 : _a.get(sourceFile.path) : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; + } function getBindAndCheckDiagnostics(sourceFile, cancellationToken) { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } @@ -106703,31 +106734,54 @@ var ts; * in that order would be used to write the files */ function emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { + var restorePendingEmitOnHandlingNoEmitSuccess = false; + var savedAffectedFilesPendingEmit; + var savedAffectedFilesPendingEmitKind; + var savedAffectedFilesPendingEmitIndex; + // Backup and restore affected pendings emit state for non emit Builder if noEmitOnError is enabled and emitBuildInfo could be written in case there are errors + // This ensures pending files to emit is updated in tsbuildinfo + // Note that when there are no errors, emit proceeds as if everything is emitted as it is callers reponsibility to write the files to disk if at all (because its builder that doesnt track files to emit) + if (kind !== BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram && + !targetSourceFile && + !ts.outFile(state.compilerOptions) && + !state.compilerOptions.noEmit && + state.compilerOptions.noEmitOnError) { + restorePendingEmitOnHandlingNoEmitSuccess = true; + savedAffectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice(); + savedAffectedFilesPendingEmitKind = state.affectedFilesPendingEmitKind && new ts.Map(state.affectedFilesPendingEmitKind); + savedAffectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex; + } if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); - var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); - if (result) - return result; - if (!targetSourceFile) { - // Emit and report any errors we ran into. - var sourceMaps = []; - var emitSkipped = false; - var diagnostics = void 0; - var emittedFiles = []; - var affectedEmitResult = void 0; - while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { - emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; - diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); - emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); - sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); - } - return { - emitSkipped: emitSkipped, - diagnostics: diagnostics || ts.emptyArray, - emittedFiles: emittedFiles, - sourceMaps: sourceMaps - }; + } + var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); + if (result) + return result; + if (restorePendingEmitOnHandlingNoEmitSuccess) { + state.affectedFilesPendingEmit = savedAffectedFilesPendingEmit; + state.affectedFilesPendingEmitKind = savedAffectedFilesPendingEmitKind; + state.affectedFilesPendingEmitIndex = savedAffectedFilesPendingEmitIndex; + } + // Emit only affected files if using builder for emit + if (!targetSourceFile && kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Emit and report any errors we ran into. + var sourceMaps = []; + var emitSkipped = false; + var diagnostics = void 0; + var emittedFiles = []; + var affectedEmitResult = void 0; + while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { + emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; + diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); + emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); + sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); } + return { + emitSkipped: emitSkipped, + diagnostics: diagnostics || ts.emptyArray, + emittedFiles: emittedFiles, + sourceMaps: sourceMaps + }; } return ts.Debug.checkDefined(state.program).emit(targetSourceFile, writeFile || ts.maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers); } @@ -106747,7 +106801,8 @@ var ts; return toAffectedFileResult(state, state.program.getSemanticDiagnostics(/*targetSourceFile*/ undefined, cancellationToken), affected); } // Add file to affected file pending emit to handle for later emit time - if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Apart for emit builder do this for tsbuildinfo, do this for non emit builder when noEmit is set as tsbuildinfo is written and reused between emitters + if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram || state.compilerOptions.noEmit || state.compilerOptions.noEmitOnError) { addToAffectedFilesPendingEmit(state, affected.resolvedPath, 1 /* Full */); } // Get diagnostics for the affected file if its not ignored diff --git a/lib/typescript.js b/lib/typescript.js index 67d0024d107e6..902286ac2ed8b 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -288,7 +288,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.3"; + ts.version = "4.0.5"; /* @internal */ var Comparison; (function (Comparison) { @@ -89612,6 +89612,8 @@ var ts; switch (node.kind) { case 213 /* BinaryExpression */: return visitBinaryExpression(node); + case 332 /* CommaListExpression */: + return visitCommaListExpression(node); case 214 /* ConditionalExpression */: return visitConditionalExpression(node); case 216 /* YieldExpression */: @@ -89906,6 +89908,61 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ + function visitCommaExpression(node) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); + var pendingExpressions = []; + visit(node.left); + visit(node.right); + return factory.inlineExpressions(pendingExpressions); + function visit(node) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { + visit(node.left); + visit(node.right); + } + else { + if (containsYield(node) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); + } + } + } + /** + * Visits a comma-list expression. + * + * @param node The node to visit. + */ + function visitCommaListExpression(node) { + // flattened version of `visitCommaExpression` + var pendingExpressions = []; + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var elem = _a[_i]; + if (ts.isBinaryExpression(elem) && elem.operatorToken.kind === 27 /* CommaToken */) { + pendingExpressions.push(visitCommaExpression(elem)); + } + else { + if (containsYield(elem) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(elem, visitor, ts.isExpression)); + } + } + return factory.inlineExpressions(pendingExpressions); + } /** * Visits a logical binary expression containing `yield`. * @@ -89955,38 +90012,6 @@ var ts; markLabel(resultLabel); return resultLocal; } - /** - * Visits a comma expression containing `yield`. - * - * @param node The node to visit. - */ - function visitCommaExpression(node) { - // [source] - // x = a(), yield, b(); - // - // [intermediate] - // a(); - // .yield resumeLabel - // .mark resumeLabel - // x = %sent%, b(); - var pendingExpressions = []; - visit(node.left); - visit(node.right); - return factory.inlineExpressions(pendingExpressions); - function visit(node) { - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { - visit(node.left); - visit(node.right); - } - else { - if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); - pendingExpressions = []; - } - pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); - } - } - } /** * Visits a conditional expression containing `yield`. * @@ -103048,6 +103073,7 @@ var ts; getOptionsDiagnostics: getOptionsDiagnostics, getGlobalDiagnostics: getGlobalDiagnostics, getSemanticDiagnostics: getSemanticDiagnostics, + getCachedSemanticDiagnostics: getCachedSemanticDiagnostics, getSuggestionDiagnostics: getSuggestionDiagnostics, getDeclarationDiagnostics: getDeclarationDiagnostics, getBindAndCheckDiagnostics: getBindAndCheckDiagnostics, @@ -103671,6 +103697,11 @@ var ts; function getSemanticDiagnostics(sourceFile, cancellationToken) { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } + function getCachedSemanticDiagnostics(sourceFile) { + var _a; + return sourceFile + ? (_a = cachedBindAndCheckDiagnosticsForFile.perFile) === null || _a === void 0 ? void 0 : _a.get(sourceFile.path) : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; + } function getBindAndCheckDiagnostics(sourceFile, cancellationToken) { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } @@ -106703,31 +106734,54 @@ var ts; * in that order would be used to write the files */ function emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { + var restorePendingEmitOnHandlingNoEmitSuccess = false; + var savedAffectedFilesPendingEmit; + var savedAffectedFilesPendingEmitKind; + var savedAffectedFilesPendingEmitIndex; + // Backup and restore affected pendings emit state for non emit Builder if noEmitOnError is enabled and emitBuildInfo could be written in case there are errors + // This ensures pending files to emit is updated in tsbuildinfo + // Note that when there are no errors, emit proceeds as if everything is emitted as it is callers reponsibility to write the files to disk if at all (because its builder that doesnt track files to emit) + if (kind !== BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram && + !targetSourceFile && + !ts.outFile(state.compilerOptions) && + !state.compilerOptions.noEmit && + state.compilerOptions.noEmitOnError) { + restorePendingEmitOnHandlingNoEmitSuccess = true; + savedAffectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice(); + savedAffectedFilesPendingEmitKind = state.affectedFilesPendingEmitKind && new ts.Map(state.affectedFilesPendingEmitKind); + savedAffectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex; + } if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); - var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); - if (result) - return result; - if (!targetSourceFile) { - // Emit and report any errors we ran into. - var sourceMaps = []; - var emitSkipped = false; - var diagnostics = void 0; - var emittedFiles = []; - var affectedEmitResult = void 0; - while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { - emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; - diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); - emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); - sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); - } - return { - emitSkipped: emitSkipped, - diagnostics: diagnostics || ts.emptyArray, - emittedFiles: emittedFiles, - sourceMaps: sourceMaps - }; + } + var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); + if (result) + return result; + if (restorePendingEmitOnHandlingNoEmitSuccess) { + state.affectedFilesPendingEmit = savedAffectedFilesPendingEmit; + state.affectedFilesPendingEmitKind = savedAffectedFilesPendingEmitKind; + state.affectedFilesPendingEmitIndex = savedAffectedFilesPendingEmitIndex; + } + // Emit only affected files if using builder for emit + if (!targetSourceFile && kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Emit and report any errors we ran into. + var sourceMaps = []; + var emitSkipped = false; + var diagnostics = void 0; + var emittedFiles = []; + var affectedEmitResult = void 0; + while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { + emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; + diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); + emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); + sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); } + return { + emitSkipped: emitSkipped, + diagnostics: diagnostics || ts.emptyArray, + emittedFiles: emittedFiles, + sourceMaps: sourceMaps + }; } return ts.Debug.checkDefined(state.program).emit(targetSourceFile, writeFile || ts.maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers); } @@ -106747,7 +106801,8 @@ var ts; return toAffectedFileResult(state, state.program.getSemanticDiagnostics(/*targetSourceFile*/ undefined, cancellationToken), affected); } // Add file to affected file pending emit to handle for later emit time - if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Apart for emit builder do this for tsbuildinfo, do this for non emit builder when noEmit is set as tsbuildinfo is written and reused between emitters + if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram || state.compilerOptions.noEmit || state.compilerOptions.noEmitOnError) { addToAffectedFilesPendingEmit(state, affected.resolvedPath, 1 /* Full */); } // Get diagnostics for the affected file if its not ignored diff --git a/lib/typescriptServices.js b/lib/typescriptServices.js index 2852ef52b1d67..f5b4a76c03a59 100644 --- a/lib/typescriptServices.js +++ b/lib/typescriptServices.js @@ -288,7 +288,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.3"; + ts.version = "4.0.5"; /* @internal */ var Comparison; (function (Comparison) { @@ -89612,6 +89612,8 @@ var ts; switch (node.kind) { case 213 /* BinaryExpression */: return visitBinaryExpression(node); + case 332 /* CommaListExpression */: + return visitCommaListExpression(node); case 214 /* ConditionalExpression */: return visitConditionalExpression(node); case 216 /* YieldExpression */: @@ -89906,6 +89908,61 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ + function visitCommaExpression(node) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); + var pendingExpressions = []; + visit(node.left); + visit(node.right); + return factory.inlineExpressions(pendingExpressions); + function visit(node) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { + visit(node.left); + visit(node.right); + } + else { + if (containsYield(node) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); + } + } + } + /** + * Visits a comma-list expression. + * + * @param node The node to visit. + */ + function visitCommaListExpression(node) { + // flattened version of `visitCommaExpression` + var pendingExpressions = []; + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var elem = _a[_i]; + if (ts.isBinaryExpression(elem) && elem.operatorToken.kind === 27 /* CommaToken */) { + pendingExpressions.push(visitCommaExpression(elem)); + } + else { + if (containsYield(elem) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(elem, visitor, ts.isExpression)); + } + } + return factory.inlineExpressions(pendingExpressions); + } /** * Visits a logical binary expression containing `yield`. * @@ -89955,38 +90012,6 @@ var ts; markLabel(resultLabel); return resultLocal; } - /** - * Visits a comma expression containing `yield`. - * - * @param node The node to visit. - */ - function visitCommaExpression(node) { - // [source] - // x = a(), yield, b(); - // - // [intermediate] - // a(); - // .yield resumeLabel - // .mark resumeLabel - // x = %sent%, b(); - var pendingExpressions = []; - visit(node.left); - visit(node.right); - return factory.inlineExpressions(pendingExpressions); - function visit(node) { - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { - visit(node.left); - visit(node.right); - } - else { - if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); - pendingExpressions = []; - } - pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); - } - } - } /** * Visits a conditional expression containing `yield`. * @@ -103048,6 +103073,7 @@ var ts; getOptionsDiagnostics: getOptionsDiagnostics, getGlobalDiagnostics: getGlobalDiagnostics, getSemanticDiagnostics: getSemanticDiagnostics, + getCachedSemanticDiagnostics: getCachedSemanticDiagnostics, getSuggestionDiagnostics: getSuggestionDiagnostics, getDeclarationDiagnostics: getDeclarationDiagnostics, getBindAndCheckDiagnostics: getBindAndCheckDiagnostics, @@ -103671,6 +103697,11 @@ var ts; function getSemanticDiagnostics(sourceFile, cancellationToken) { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } + function getCachedSemanticDiagnostics(sourceFile) { + var _a; + return sourceFile + ? (_a = cachedBindAndCheckDiagnosticsForFile.perFile) === null || _a === void 0 ? void 0 : _a.get(sourceFile.path) : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; + } function getBindAndCheckDiagnostics(sourceFile, cancellationToken) { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } @@ -106703,31 +106734,54 @@ var ts; * in that order would be used to write the files */ function emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { + var restorePendingEmitOnHandlingNoEmitSuccess = false; + var savedAffectedFilesPendingEmit; + var savedAffectedFilesPendingEmitKind; + var savedAffectedFilesPendingEmitIndex; + // Backup and restore affected pendings emit state for non emit Builder if noEmitOnError is enabled and emitBuildInfo could be written in case there are errors + // This ensures pending files to emit is updated in tsbuildinfo + // Note that when there are no errors, emit proceeds as if everything is emitted as it is callers reponsibility to write the files to disk if at all (because its builder that doesnt track files to emit) + if (kind !== BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram && + !targetSourceFile && + !ts.outFile(state.compilerOptions) && + !state.compilerOptions.noEmit && + state.compilerOptions.noEmitOnError) { + restorePendingEmitOnHandlingNoEmitSuccess = true; + savedAffectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice(); + savedAffectedFilesPendingEmitKind = state.affectedFilesPendingEmitKind && new ts.Map(state.affectedFilesPendingEmitKind); + savedAffectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex; + } if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); - var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); - if (result) - return result; - if (!targetSourceFile) { - // Emit and report any errors we ran into. - var sourceMaps = []; - var emitSkipped = false; - var diagnostics = void 0; - var emittedFiles = []; - var affectedEmitResult = void 0; - while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { - emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; - diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); - emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); - sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); - } - return { - emitSkipped: emitSkipped, - diagnostics: diagnostics || ts.emptyArray, - emittedFiles: emittedFiles, - sourceMaps: sourceMaps - }; + } + var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); + if (result) + return result; + if (restorePendingEmitOnHandlingNoEmitSuccess) { + state.affectedFilesPendingEmit = savedAffectedFilesPendingEmit; + state.affectedFilesPendingEmitKind = savedAffectedFilesPendingEmitKind; + state.affectedFilesPendingEmitIndex = savedAffectedFilesPendingEmitIndex; + } + // Emit only affected files if using builder for emit + if (!targetSourceFile && kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Emit and report any errors we ran into. + var sourceMaps = []; + var emitSkipped = false; + var diagnostics = void 0; + var emittedFiles = []; + var affectedEmitResult = void 0; + while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { + emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; + diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); + emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); + sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); } + return { + emitSkipped: emitSkipped, + diagnostics: diagnostics || ts.emptyArray, + emittedFiles: emittedFiles, + sourceMaps: sourceMaps + }; } return ts.Debug.checkDefined(state.program).emit(targetSourceFile, writeFile || ts.maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers); } @@ -106747,7 +106801,8 @@ var ts; return toAffectedFileResult(state, state.program.getSemanticDiagnostics(/*targetSourceFile*/ undefined, cancellationToken), affected); } // Add file to affected file pending emit to handle for later emit time - if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Apart for emit builder do this for tsbuildinfo, do this for non emit builder when noEmit is set as tsbuildinfo is written and reused between emitters + if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram || state.compilerOptions.noEmit || state.compilerOptions.noEmitOnError) { addToAffectedFilesPendingEmit(state, affected.resolvedPath, 1 /* Full */); } // Get diagnostics for the affected file if its not ignored diff --git a/lib/typingsInstaller.js b/lib/typingsInstaller.js index d12214a7b1bb3..2c9fa35817330 100644 --- a/lib/typingsInstaller.js +++ b/lib/typingsInstaller.js @@ -83,7 +83,7 @@ var ts; // If changing the text in this section, be sure to test `configurePrerelease` too. ts.versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - ts.version = "4.0.3"; + ts.version = "4.0.5"; /* @internal */ var Comparison; (function (Comparison) { @@ -89407,6 +89407,8 @@ var ts; switch (node.kind) { case 213 /* BinaryExpression */: return visitBinaryExpression(node); + case 332 /* CommaListExpression */: + return visitCommaListExpression(node); case 214 /* ConditionalExpression */: return visitConditionalExpression(node); case 216 /* YieldExpression */: @@ -89701,6 +89703,61 @@ var ts; } return ts.visitEachChild(node, visitor, context); } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ + function visitCommaExpression(node) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); + var pendingExpressions = []; + visit(node.left); + visit(node.right); + return factory.inlineExpressions(pendingExpressions); + function visit(node) { + if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { + visit(node.left); + visit(node.right); + } + else { + if (containsYield(node) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); + } + } + } + /** + * Visits a comma-list expression. + * + * @param node The node to visit. + */ + function visitCommaListExpression(node) { + // flattened version of `visitCommaExpression` + var pendingExpressions = []; + for (var _i = 0, _a = node.elements; _i < _a.length; _i++) { + var elem = _a[_i]; + if (ts.isBinaryExpression(elem) && elem.operatorToken.kind === 27 /* CommaToken */) { + pendingExpressions.push(visitCommaExpression(elem)); + } + else { + if (containsYield(elem) && pendingExpressions.length > 0) { + emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(ts.visitNode(elem, visitor, ts.isExpression)); + } + } + return factory.inlineExpressions(pendingExpressions); + } /** * Visits a logical binary expression containing `yield`. * @@ -89750,38 +89807,6 @@ var ts; markLabel(resultLabel); return resultLocal; } - /** - * Visits a comma expression containing `yield`. - * - * @param node The node to visit. - */ - function visitCommaExpression(node) { - // [source] - // x = a(), yield, b(); - // - // [intermediate] - // a(); - // .yield resumeLabel - // .mark resumeLabel - // x = %sent%, b(); - var pendingExpressions = []; - visit(node.left); - visit(node.right); - return factory.inlineExpressions(pendingExpressions); - function visit(node) { - if (ts.isBinaryExpression(node) && node.operatorToken.kind === 27 /* CommaToken */) { - visit(node.left); - visit(node.right); - } - else { - if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(1 /* Statement */, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); - pendingExpressions = []; - } - pendingExpressions.push(ts.visitNode(node, visitor, ts.isExpression)); - } - } - } /** * Visits a conditional expression containing `yield`. * @@ -102843,6 +102868,7 @@ var ts; getOptionsDiagnostics: getOptionsDiagnostics, getGlobalDiagnostics: getGlobalDiagnostics, getSemanticDiagnostics: getSemanticDiagnostics, + getCachedSemanticDiagnostics: getCachedSemanticDiagnostics, getSuggestionDiagnostics: getSuggestionDiagnostics, getDeclarationDiagnostics: getDeclarationDiagnostics, getBindAndCheckDiagnostics: getBindAndCheckDiagnostics, @@ -103466,6 +103492,11 @@ var ts; function getSemanticDiagnostics(sourceFile, cancellationToken) { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } + function getCachedSemanticDiagnostics(sourceFile) { + var _a; + return sourceFile + ? (_a = cachedBindAndCheckDiagnosticsForFile.perFile) === null || _a === void 0 ? void 0 : _a.get(sourceFile.path) : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; + } function getBindAndCheckDiagnostics(sourceFile, cancellationToken) { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } @@ -106498,31 +106529,54 @@ var ts; * in that order would be used to write the files */ function emit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { + var restorePendingEmitOnHandlingNoEmitSuccess = false; + var savedAffectedFilesPendingEmit; + var savedAffectedFilesPendingEmitKind; + var savedAffectedFilesPendingEmitIndex; + // Backup and restore affected pendings emit state for non emit Builder if noEmitOnError is enabled and emitBuildInfo could be written in case there are errors + // This ensures pending files to emit is updated in tsbuildinfo + // Note that when there are no errors, emit proceeds as if everything is emitted as it is callers reponsibility to write the files to disk if at all (because its builder that doesnt track files to emit) + if (kind !== BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram && + !targetSourceFile && + !ts.outFile(state.compilerOptions) && + !state.compilerOptions.noEmit && + state.compilerOptions.noEmitOnError) { + restorePendingEmitOnHandlingNoEmitSuccess = true; + savedAffectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice(); + savedAffectedFilesPendingEmitKind = state.affectedFilesPendingEmitKind && new ts.Map(state.affectedFilesPendingEmitKind); + savedAffectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex; + } if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); - var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); - if (result) - return result; - if (!targetSourceFile) { - // Emit and report any errors we ran into. - var sourceMaps = []; - var emitSkipped = false; - var diagnostics = void 0; - var emittedFiles = []; - var affectedEmitResult = void 0; - while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { - emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; - diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); - emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); - sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); - } - return { - emitSkipped: emitSkipped, - diagnostics: diagnostics || ts.emptyArray, - emittedFiles: emittedFiles, - sourceMaps: sourceMaps - }; + } + var result = ts.handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); + if (result) + return result; + if (restorePendingEmitOnHandlingNoEmitSuccess) { + state.affectedFilesPendingEmit = savedAffectedFilesPendingEmit; + state.affectedFilesPendingEmitKind = savedAffectedFilesPendingEmitKind; + state.affectedFilesPendingEmitIndex = savedAffectedFilesPendingEmitIndex; + } + // Emit only affected files if using builder for emit + if (!targetSourceFile && kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Emit and report any errors we ran into. + var sourceMaps = []; + var emitSkipped = false; + var diagnostics = void 0; + var emittedFiles = []; + var affectedEmitResult = void 0; + while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { + emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; + diagnostics = ts.addRange(diagnostics, affectedEmitResult.result.diagnostics); + emittedFiles = ts.addRange(emittedFiles, affectedEmitResult.result.emittedFiles); + sourceMaps = ts.addRange(sourceMaps, affectedEmitResult.result.sourceMaps); } + return { + emitSkipped: emitSkipped, + diagnostics: diagnostics || ts.emptyArray, + emittedFiles: emittedFiles, + sourceMaps: sourceMaps + }; } return ts.Debug.checkDefined(state.program).emit(targetSourceFile, writeFile || ts.maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers); } @@ -106542,7 +106596,8 @@ var ts; return toAffectedFileResult(state, state.program.getSemanticDiagnostics(/*targetSourceFile*/ undefined, cancellationToken), affected); } // Add file to affected file pending emit to handle for later emit time - if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Apart for emit builder do this for tsbuildinfo, do this for non emit builder when noEmit is set as tsbuildinfo is written and reused between emitters + if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram || state.compilerOptions.noEmit || state.compilerOptions.noEmitOnError) { addToAffectedFilesPendingEmit(state, affected.resolvedPath, 1 /* Full */); } // Get diagnostics for the affected file if its not ignored diff --git a/package.json b/package.json index c929b609c604c..ab953b17d074a 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "typescript", "author": "Microsoft Corp.", "homepage": "https://www.typescriptlang.org/", - "version": "4.0.3", + "version": "4.0.5", "license": "Apache-2.0", "description": "TypeScript is a language for application scale JavaScript development", "keywords": [ diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 7765a75331281..6ef84502688a9 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -1019,31 +1019,57 @@ namespace ts { * in that order would be used to write the files */ function emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult { + let restorePendingEmitOnHandlingNoEmitSuccess = false; + let savedAffectedFilesPendingEmit; + let savedAffectedFilesPendingEmitKind; + let savedAffectedFilesPendingEmitIndex; + // Backup and restore affected pendings emit state for non emit Builder if noEmitOnError is enabled and emitBuildInfo could be written in case there are errors + // This ensures pending files to emit is updated in tsbuildinfo + // Note that when there are no errors, emit proceeds as if everything is emitted as it is callers reponsibility to write the files to disk if at all (because its builder that doesnt track files to emit) + if (kind !== BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram && + !targetSourceFile && + !outFile(state.compilerOptions) && + !state.compilerOptions.noEmit && + state.compilerOptions.noEmitOnError) { + restorePendingEmitOnHandlingNoEmitSuccess = true; + savedAffectedFilesPendingEmit = state.affectedFilesPendingEmit && state.affectedFilesPendingEmit.slice(); + savedAffectedFilesPendingEmitKind = state.affectedFilesPendingEmitKind && new Map(state.affectedFilesPendingEmitKind); + savedAffectedFilesPendingEmitIndex = state.affectedFilesPendingEmitIndex; + } + if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile); - const result = handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); - if (result) return result; - if (!targetSourceFile) { - // Emit and report any errors we ran into. - let sourceMaps: SourceMapEmitResult[] = []; - let emitSkipped = false; - let diagnostics: Diagnostic[] | undefined; - let emittedFiles: string[] = []; - - let affectedEmitResult: AffectedFileResult; - while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { - emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; - diagnostics = addRange(diagnostics, affectedEmitResult.result.diagnostics); - emittedFiles = addRange(emittedFiles, affectedEmitResult.result.emittedFiles); - sourceMaps = addRange(sourceMaps, affectedEmitResult.result.sourceMaps); - } - return { - emitSkipped, - diagnostics: diagnostics || emptyArray, - emittedFiles, - sourceMaps - }; + } + const result = handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken); + if (result) return result; + + if (restorePendingEmitOnHandlingNoEmitSuccess) { + state.affectedFilesPendingEmit = savedAffectedFilesPendingEmit; + state.affectedFilesPendingEmitKind = savedAffectedFilesPendingEmitKind; + state.affectedFilesPendingEmitIndex = savedAffectedFilesPendingEmitIndex; + } + + // Emit only affected files if using builder for emit + if (!targetSourceFile && kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Emit and report any errors we ran into. + let sourceMaps: SourceMapEmitResult[] = []; + let emitSkipped = false; + let diagnostics: Diagnostic[] | undefined; + let emittedFiles: string[] = []; + + let affectedEmitResult: AffectedFileResult; + while (affectedEmitResult = emitNextAffectedFile(writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers)) { + emitSkipped = emitSkipped || affectedEmitResult.result.emitSkipped; + diagnostics = addRange(diagnostics, affectedEmitResult.result.diagnostics); + emittedFiles = addRange(emittedFiles, affectedEmitResult.result.emittedFiles); + sourceMaps = addRange(sourceMaps, affectedEmitResult.result.sourceMaps); } + return { + emitSkipped, + diagnostics: diagnostics || emptyArray, + emittedFiles, + sourceMaps + }; } return Debug.checkDefined(state.program).emit(targetSourceFile, writeFile || maybeBind(host, host.writeFile), cancellationToken, emitOnlyDtsFiles, customTransformers); } @@ -1069,7 +1095,8 @@ namespace ts { } // Add file to affected file pending emit to handle for later emit time - if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) { + // Apart for emit builder do this for tsbuildinfo, do this for non emit builder when noEmit is set as tsbuildinfo is written and reused between emitters + if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram || state.compilerOptions.noEmit || state.compilerOptions.noEmitOnError) { addToAffectedFilesPendingEmit(state, (affected as SourceFile).resolvedPath, BuilderFileEmit.Full); } diff --git a/src/compiler/corePublic.ts b/src/compiler/corePublic.ts index acf2b33f88d6c..d06cc13e38e7b 100644 --- a/src/compiler/corePublic.ts +++ b/src/compiler/corePublic.ts @@ -3,7 +3,7 @@ namespace ts { // If changing the text in this section, be sure to test `configurePrerelease` too. export const versionMajorMinor = "4.0"; /** The version of the TypeScript compiler release */ - export const version = "4.0.3" as string; + export const version = "4.0.5" as string; /** * Type of objects whose values are all of the same type. diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 304f89f56c3ff..5a0300a53e53c 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -935,6 +935,7 @@ namespace ts { getOptionsDiagnostics, getGlobalDiagnostics, getSemanticDiagnostics, + getCachedSemanticDiagnostics, getSuggestionDiagnostics, getDeclarationDiagnostics, getBindAndCheckDiagnostics, @@ -1648,6 +1649,12 @@ namespace ts { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } + function getCachedSemanticDiagnostics(sourceFile?: SourceFile): readonly Diagnostic[] | undefined { + return sourceFile + ? cachedBindAndCheckDiagnosticsForFile.perFile?.get(sourceFile.path) + : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; + } + function getBindAndCheckDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index e988100903b0e..6ae08275e3a02 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -397,6 +397,8 @@ namespace ts { switch (node.kind) { case SyntaxKind.BinaryExpression: return visitBinaryExpression(node); + case SyntaxKind.CommaListExpression: + return visitCommaListExpression(node); case SyntaxKind.ConditionalExpression: return visitConditionalExpression(node); case SyntaxKind.YieldExpression: @@ -772,6 +774,65 @@ namespace ts { return visitEachChild(node, visitor, context); } + /** + * Visits a comma expression containing `yield`. + * + * @param node The node to visit. + */ + function visitCommaExpression(node: BinaryExpression) { + // [source] + // x = a(), yield, b(); + // + // [intermediate] + // a(); + // .yield resumeLabel + // .mark resumeLabel + // x = %sent%, b(); + + let pendingExpressions: Expression[] = []; + visit(node.left); + visit(node.right); + return factory.inlineExpressions(pendingExpressions); + + function visit(node: Expression) { + if (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.CommaToken) { + visit(node.left); + visit(node.right); + } + else { + if (containsYield(node) && pendingExpressions.length > 0) { + emitWorker(OpCode.Statement, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + + pendingExpressions.push(visitNode(node, visitor, isExpression)); + } + } + } + + /** + * Visits a comma-list expression. + * + * @param node The node to visit. + */ + function visitCommaListExpression(node: CommaListExpression) { + // flattened version of `visitCommaExpression` + let pendingExpressions: Expression[] = []; + for (const elem of node.elements) { + if (isBinaryExpression(elem) && elem.operatorToken.kind === SyntaxKind.CommaToken) { + pendingExpressions.push(visitCommaExpression(elem)); + } + else { + if (containsYield(elem) && pendingExpressions.length > 0) { + emitWorker(OpCode.Statement, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); + pendingExpressions = []; + } + pendingExpressions.push(visitNode(elem, visitor, isExpression)); + } + } + return factory.inlineExpressions(pendingExpressions); + } + /** * Visits a logical binary expression containing `yield`. * @@ -825,42 +886,6 @@ namespace ts { return resultLocal; } - /** - * Visits a comma expression containing `yield`. - * - * @param node The node to visit. - */ - function visitCommaExpression(node: BinaryExpression) { - // [source] - // x = a(), yield, b(); - // - // [intermediate] - // a(); - // .yield resumeLabel - // .mark resumeLabel - // x = %sent%, b(); - - let pendingExpressions: Expression[] = []; - visit(node.left); - visit(node.right); - return factory.inlineExpressions(pendingExpressions); - - function visit(node: Expression) { - if (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.CommaToken) { - visit(node.left); - visit(node.right); - } - else { - if (containsYield(node) && pendingExpressions.length > 0) { - emitWorker(OpCode.Statement, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]); - pendingExpressions = []; - } - - pendingExpressions.push(visitNode(node, visitor, isExpression)); - } - } - } - /** * Visits a conditional expression containing `yield`. * diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 959ac410d294e..aa25879ae1f38 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3727,6 +3727,8 @@ namespace ts { /* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker; /* @internal */ dropDiagnosticsProducingTypeChecker(): void; + /* @internal */ getCachedSemanticDiagnostics(sourceFile?: SourceFile): readonly Diagnostic[] | undefined; + /* @internal */ getClassifiableNames(): Set<__String>; getNodeCount(): number; diff --git a/src/server/protocol.ts b/src/server/protocol.ts index b288124049e67..4bb19652ad51b 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -617,6 +617,12 @@ namespace ts.server.protocol { * so this description should make sense by itself if the parent is inlineable=true */ description: string; + + /** + * A message to show to the user if the refactoring cannot be applied in + * the current context. + */ + notApplicableReason?: string; } export interface GetEditsForRefactorRequest extends Request { @@ -3217,6 +3223,7 @@ namespace ts.server.protocol { readonly allowTextChangesInNewFiles?: boolean; readonly lazyConfiguredProjectsFromExternalProject?: boolean; readonly providePrefixAndSuffixTextForRename?: boolean; + readonly provideRefactorNotApplicableReason?: boolean; readonly allowRenameOfImportPath?: boolean; readonly includePackageJsonAutoImports?: "auto" | "on" | "off"; } diff --git a/src/testRunner/unittests/tscWatch/watchApi.ts b/src/testRunner/unittests/tscWatch/watchApi.ts index 6dcf1b30f7b35..1265fac6ed234 100644 --- a/src/testRunner/unittests/tscWatch/watchApi.ts +++ b/src/testRunner/unittests/tscWatch/watchApi.ts @@ -123,4 +123,119 @@ namespace ts.tscWatch { checkProgramActualFiles(watch.getProgram().getProgram(), [mainFile.path, otherFile.path, libFile.path]); }); }); + + describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticDiagnosticsBuilderProgram", () => { + function getWatch(config: File, optionsToExtend: CompilerOptions | undefined, sys: System, createProgram: CreateProgram) { + const watchCompilerHost = createWatchCompilerHost(config.path, optionsToExtend, sys, createProgram); + return createWatchProgram(watchCompilerHost); + } + + function setup(createProgram: CreateProgram, configText: string) { + const config: File = { + path: `${projectRoot}/tsconfig.json`, + content: configText + }; + const mainFile: File = { + path: `${projectRoot}/main.ts`, + content: "export const x = 10;" + }; + const otherFile: File = { + path: `${projectRoot}/other.ts`, + content: "export const y = 10;" + }; + const sys = createWatchedSystem([config, mainFile, otherFile, libFile]); + const watch = getWatch(config, { noEmit: true }, sys, createProgram); + return { sys, watch, mainFile, otherFile, config }; + } + + function verifyOutputs(sys: System, emitSys: System) { + for (const output of [`${projectRoot}/main.js`, `${projectRoot}/main.d.ts`, `${projectRoot}/other.js`, `${projectRoot}/other.d.ts`, `${projectRoot}/tsconfig.tsbuildinfo`]) { + assert.strictEqual(sys.readFile(output), emitSys.readFile(output), `Output file text for ${output}`); + } + } + + function verifyBuilder(config: File, sys: System, emitSys: System, createProgram: CreateProgram, createEmitProgram: CreateProgram, optionsToExtend?: CompilerOptions) { + const watch = getWatch(config, /*optionsToExtend*/ optionsToExtend, sys, createProgram); + const emitWatch = getWatch(config, /*optionsToExtend*/ optionsToExtend, emitSys, createEmitProgram); + verifyOutputs(sys, emitSys); + watch.close(); + emitWatch.close(); + } + + it("verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram and typechecking happens only on affected files", () => { + const { sys, watch, mainFile, otherFile } = setup(createSemanticDiagnosticsBuilderProgram, "{}"); + checkProgramActualFiles(watch.getProgram().getProgram(), [mainFile.path, otherFile.path, libFile.path]); + sys.appendFile(mainFile.path, "\n// SomeComment"); + sys.runQueuedTimeoutCallbacks(); + const program = watch.getProgram().getProgram(); + assert.deepEqual(program.getCachedSemanticDiagnostics(program.getSourceFile(mainFile.path)), []); + // Should not retrieve diagnostics for other file thats not changed + assert.deepEqual(program.getCachedSemanticDiagnostics(program.getSourceFile(otherFile.path)), /*expected*/ undefined); + }); + + it("noEmit with composite writes the tsbuildinfo with pending affected files correctly", () => { + const configText = JSON.stringify({ compilerOptions: { composite: true } }); + const { sys, watch, config, mainFile } = setup(createSemanticDiagnosticsBuilderProgram, configText); + const { sys: emitSys, watch: emitWatch } = setup(createEmitAndSemanticDiagnosticsBuilderProgram, configText); + verifyOutputs(sys, emitSys); + + watch.close(); + emitWatch.close(); + + // Emit on both sys should result in same output + verifyBuilder(config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram); + + // Change file + sys.appendFile(mainFile.path, "\n// SomeComment"); + emitSys.appendFile(mainFile.path, "\n// SomeComment"); + + // Verify noEmit results in same output + verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmit: true }); + + // Emit on both sys should result in same output + verifyBuilder(config, sys, emitSys, createEmitAndSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram); + + // Change file + sys.appendFile(mainFile.path, "\n// SomeComment"); + emitSys.appendFile(mainFile.path, "\n// SomeComment"); + + // Emit on both the builders should result in same files + verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram); + }); + + it("noEmitOnError with composite writes the tsbuildinfo with pending affected files correctly", () => { + const config: File = { + path: `${projectRoot}/tsconfig.json`, + content: JSON.stringify({ compilerOptions: { composite: true } }) + }; + const mainFile: File = { + path: `${projectRoot}/main.ts`, + content: "export const x: string = 10;" + }; + const otherFile: File = { + path: `${projectRoot}/other.ts`, + content: "export const y = 10;" + }; + const sys = createWatchedSystem([config, mainFile, otherFile, libFile]); + const emitSys = createWatchedSystem([config, mainFile, otherFile, libFile]); + + // Verify noEmit results in same output + verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmitOnError: true }); + + // Change file + sys.appendFile(mainFile.path, "\n// SomeComment"); + emitSys.appendFile(mainFile.path, "\n// SomeComment"); + + // Verify noEmit results in same output + verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmitOnError: true }); + + // Fix error + const fixed = "export const x = 10;"; + sys.appendFile(mainFile.path, fixed); + emitSys.appendFile(mainFile.path, fixed); + + // Emit on both the builders should result in same files + verifyBuilder(config, sys, emitSys, createSemanticDiagnosticsBuilderProgram, createEmitAndSemanticDiagnosticsBuilderProgram, { noEmitOnError: true }); + }); + }); } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index aad052326e024..42c28b30e33e0 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -6881,6 +6881,11 @@ declare namespace ts.server.protocol { * so this description should make sense by itself if the parent is inlineable=true */ description: string; + /** + * A message to show to the user if the refactoring cannot be applied in + * the current context. + */ + notApplicableReason?: string; } interface GetEditsForRefactorRequest extends Request { command: CommandTypes.GetEditsForRefactor; @@ -8902,6 +8907,7 @@ declare namespace ts.server.protocol { readonly allowTextChangesInNewFiles?: boolean; readonly lazyConfiguredProjectsFromExternalProject?: boolean; readonly providePrefixAndSuffixTextForRename?: boolean; + readonly provideRefactorNotApplicableReason?: boolean; readonly allowRenameOfImportPath?: boolean; readonly includePackageJsonAutoImports?: "auto" | "on" | "off"; } diff --git a/tests/baselines/reference/es5-asyncFunctionLongObjectLiteral.js b/tests/baselines/reference/es5-asyncFunctionLongObjectLiteral.js new file mode 100644 index 0000000000000..06370f1a0d753 --- /dev/null +++ b/tests/baselines/reference/es5-asyncFunctionLongObjectLiteral.js @@ -0,0 +1,131 @@ +//// [es5-asyncFunctionLongObjectLiteral.ts] +// the generated code from both should be similar + +const fooShort = async () => { + return { + a: await Promise.resolve(0), + b: await Promise.resolve(1), + c: await Promise.resolve(2), + d: await Promise.resolve(3), + e: await Promise.resolve(4), + }; +} + +const fooLong = async () => { + return { + a: await Promise.resolve(0), + b: await Promise.resolve(1), + c: await Promise.resolve(2), + d: await Promise.resolve(3), + e: await Promise.resolve(4), + f: await Promise.resolve(5), + g: await Promise.resolve(6), + h: await Promise.resolve(7), + i: await Promise.resolve(8), + j: await Promise.resolve(9), + }; +} + + +//// [es5-asyncFunctionLongObjectLiteral.js] +// the generated code from both should be similar +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var _this = this; +var fooShort = function () { return __awaiter(_this, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = {}; + return [4 /*yield*/, Promise.resolve(0)]; + case 1: + _a.a = _b.sent(); + return [4 /*yield*/, Promise.resolve(1)]; + case 2: + _a.b = _b.sent(); + return [4 /*yield*/, Promise.resolve(2)]; + case 3: + _a.c = _b.sent(); + return [4 /*yield*/, Promise.resolve(3)]; + case 4: + _a.d = _b.sent(); + return [4 /*yield*/, Promise.resolve(4)]; + case 5: return [2 /*return*/, (_a.e = _b.sent(), + _a)]; + } + }); +}); }; +var fooLong = function () { return __awaiter(_this, void 0, void 0, function () { + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + _a = {}; + return [4 /*yield*/, Promise.resolve(0)]; + case 1: + _a.a = _b.sent(); + return [4 /*yield*/, Promise.resolve(1)]; + case 2: + _a.b = _b.sent(); + return [4 /*yield*/, Promise.resolve(2)]; + case 3: + _a.c = _b.sent(); + return [4 /*yield*/, Promise.resolve(3)]; + case 4: + _a.d = _b.sent(); + return [4 /*yield*/, Promise.resolve(4)]; + case 5: + _a.e = _b.sent(); + return [4 /*yield*/, Promise.resolve(5)]; + case 6: + _a.f = _b.sent(); + return [4 /*yield*/, Promise.resolve(6)]; + case 7: + _a.g = _b.sent(); + return [4 /*yield*/, Promise.resolve(7)]; + case 8: + _a.h = _b.sent(); + return [4 /*yield*/, Promise.resolve(8)]; + case 9: + _a.i = _b.sent(); + return [4 /*yield*/, Promise.resolve(9)]; + case 10: return [2 /*return*/, (_a.j = _b.sent(), + _a)]; + } + }); +}); }; diff --git a/tests/baselines/reference/es5-asyncFunctionLongObjectLiteral.symbols b/tests/baselines/reference/es5-asyncFunctionLongObjectLiteral.symbols new file mode 100644 index 0000000000000..3a1ba97483e66 --- /dev/null +++ b/tests/baselines/reference/es5-asyncFunctionLongObjectLiteral.symbols @@ -0,0 +1,107 @@ +=== tests/cases/compiler/es5-asyncFunctionLongObjectLiteral.ts === +// the generated code from both should be similar + +const fooShort = async () => { +>fooShort : Symbol(fooShort, Decl(es5-asyncFunctionLongObjectLiteral.ts, 2, 5)) + + return { + a: await Promise.resolve(0), +>a : Symbol(a, Decl(es5-asyncFunctionLongObjectLiteral.ts, 3, 12)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + b: await Promise.resolve(1), +>b : Symbol(b, Decl(es5-asyncFunctionLongObjectLiteral.ts, 4, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + c: await Promise.resolve(2), +>c : Symbol(c, Decl(es5-asyncFunctionLongObjectLiteral.ts, 5, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + d: await Promise.resolve(3), +>d : Symbol(d, Decl(es5-asyncFunctionLongObjectLiteral.ts, 6, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + e: await Promise.resolve(4), +>e : Symbol(e, Decl(es5-asyncFunctionLongObjectLiteral.ts, 7, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + }; +} + +const fooLong = async () => { +>fooLong : Symbol(fooLong, Decl(es5-asyncFunctionLongObjectLiteral.ts, 12, 5)) + + return { + a: await Promise.resolve(0), +>a : Symbol(a, Decl(es5-asyncFunctionLongObjectLiteral.ts, 13, 12)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + b: await Promise.resolve(1), +>b : Symbol(b, Decl(es5-asyncFunctionLongObjectLiteral.ts, 14, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + c: await Promise.resolve(2), +>c : Symbol(c, Decl(es5-asyncFunctionLongObjectLiteral.ts, 15, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + d: await Promise.resolve(3), +>d : Symbol(d, Decl(es5-asyncFunctionLongObjectLiteral.ts, 16, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + e: await Promise.resolve(4), +>e : Symbol(e, Decl(es5-asyncFunctionLongObjectLiteral.ts, 17, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + f: await Promise.resolve(5), +>f : Symbol(f, Decl(es5-asyncFunctionLongObjectLiteral.ts, 18, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + g: await Promise.resolve(6), +>g : Symbol(g, Decl(es5-asyncFunctionLongObjectLiteral.ts, 19, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + h: await Promise.resolve(7), +>h : Symbol(h, Decl(es5-asyncFunctionLongObjectLiteral.ts, 20, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + i: await Promise.resolve(8), +>i : Symbol(i, Decl(es5-asyncFunctionLongObjectLiteral.ts, 21, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + j: await Promise.resolve(9), +>j : Symbol(j, Decl(es5-asyncFunctionLongObjectLiteral.ts, 22, 36)) +>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) +>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --)) + + }; +} + diff --git a/tests/baselines/reference/es5-asyncFunctionLongObjectLiteral.types b/tests/baselines/reference/es5-asyncFunctionLongObjectLiteral.types new file mode 100644 index 0000000000000..a2f8c81ceb494 --- /dev/null +++ b/tests/baselines/reference/es5-asyncFunctionLongObjectLiteral.types @@ -0,0 +1,158 @@ +=== tests/cases/compiler/es5-asyncFunctionLongObjectLiteral.ts === +// the generated code from both should be similar + +const fooShort = async () => { +>fooShort : () => Promise<{ a: number; b: number; c: number; d: number; e: number; }> +>async () => { return { a: await Promise.resolve(0), b: await Promise.resolve(1), c: await Promise.resolve(2), d: await Promise.resolve(3), e: await Promise.resolve(4), };} : () => Promise<{ a: number; b: number; c: number; d: number; e: number; }> + + return { +>{ a: await Promise.resolve(0), b: await Promise.resolve(1), c: await Promise.resolve(2), d: await Promise.resolve(3), e: await Promise.resolve(4), } : { a: number; b: number; c: number; d: number; e: number; } + + a: await Promise.resolve(0), +>a : number +>await Promise.resolve(0) : number +>Promise.resolve(0) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>0 : 0 + + b: await Promise.resolve(1), +>b : number +>await Promise.resolve(1) : number +>Promise.resolve(1) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>1 : 1 + + c: await Promise.resolve(2), +>c : number +>await Promise.resolve(2) : number +>Promise.resolve(2) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>2 : 2 + + d: await Promise.resolve(3), +>d : number +>await Promise.resolve(3) : number +>Promise.resolve(3) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>3 : 3 + + e: await Promise.resolve(4), +>e : number +>await Promise.resolve(4) : number +>Promise.resolve(4) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>4 : 4 + + }; +} + +const fooLong = async () => { +>fooLong : () => Promise<{ a: number; b: number; c: number; d: number; e: number; f: number; g: number; h: number; i: number; j: number; }> +>async () => { return { a: await Promise.resolve(0), b: await Promise.resolve(1), c: await Promise.resolve(2), d: await Promise.resolve(3), e: await Promise.resolve(4), f: await Promise.resolve(5), g: await Promise.resolve(6), h: await Promise.resolve(7), i: await Promise.resolve(8), j: await Promise.resolve(9), };} : () => Promise<{ a: number; b: number; c: number; d: number; e: number; f: number; g: number; h: number; i: number; j: number; }> + + return { +>{ a: await Promise.resolve(0), b: await Promise.resolve(1), c: await Promise.resolve(2), d: await Promise.resolve(3), e: await Promise.resolve(4), f: await Promise.resolve(5), g: await Promise.resolve(6), h: await Promise.resolve(7), i: await Promise.resolve(8), j: await Promise.resolve(9), } : { a: number; b: number; c: number; d: number; e: number; f: number; g: number; h: number; i: number; j: number; } + + a: await Promise.resolve(0), +>a : number +>await Promise.resolve(0) : number +>Promise.resolve(0) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>0 : 0 + + b: await Promise.resolve(1), +>b : number +>await Promise.resolve(1) : number +>Promise.resolve(1) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>1 : 1 + + c: await Promise.resolve(2), +>c : number +>await Promise.resolve(2) : number +>Promise.resolve(2) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>2 : 2 + + d: await Promise.resolve(3), +>d : number +>await Promise.resolve(3) : number +>Promise.resolve(3) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>3 : 3 + + e: await Promise.resolve(4), +>e : number +>await Promise.resolve(4) : number +>Promise.resolve(4) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>4 : 4 + + f: await Promise.resolve(5), +>f : number +>await Promise.resolve(5) : number +>Promise.resolve(5) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>5 : 5 + + g: await Promise.resolve(6), +>g : number +>await Promise.resolve(6) : number +>Promise.resolve(6) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>6 : 6 + + h: await Promise.resolve(7), +>h : number +>await Promise.resolve(7) : number +>Promise.resolve(7) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>7 : 7 + + i: await Promise.resolve(8), +>i : number +>await Promise.resolve(8) : number +>Promise.resolve(8) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>8 : 8 + + j: await Promise.resolve(9), +>j : number +>await Promise.resolve(9) : number +>Promise.resolve(9) : Promise +>Promise.resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>Promise : PromiseConstructor +>resolve : { (value: T | PromiseLike): Promise; (): Promise; } +>9 : 9 + + }; +} + diff --git a/tests/cases/compiler/es5-asyncFunctionLongObjectLiteral.ts b/tests/cases/compiler/es5-asyncFunctionLongObjectLiteral.ts new file mode 100644 index 0000000000000..563f81a0b55a0 --- /dev/null +++ b/tests/cases/compiler/es5-asyncFunctionLongObjectLiteral.ts @@ -0,0 +1,29 @@ +// @lib: es5,es2015.promise +// @target: ES5 + +// the generated code from both should be similar + +const fooShort = async () => { + return { + a: await Promise.resolve(0), + b: await Promise.resolve(1), + c: await Promise.resolve(2), + d: await Promise.resolve(3), + e: await Promise.resolve(4), + }; +} + +const fooLong = async () => { + return { + a: await Promise.resolve(0), + b: await Promise.resolve(1), + c: await Promise.resolve(2), + d: await Promise.resolve(3), + e: await Promise.resolve(4), + f: await Promise.resolve(5), + g: await Promise.resolve(6), + h: await Promise.resolve(7), + i: await Promise.resolve(8), + j: await Promise.resolve(9), + }; +}