Skip to content

Commit

Permalink
Merge branch 'master' of github.com:Microsoft/TypeScript into nojvek-…
Browse files Browse the repository at this point in the history
…jsx-fragment-factory
  • Loading branch information
Noj committed Jun 16, 2020
2 parents 4eaec97 + 4bda7ce commit 2d7372a
Show file tree
Hide file tree
Showing 930 changed files with 47,757 additions and 15,793 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/Bug_report.md
Expand Up @@ -7,7 +7,7 @@ assignees: ''

---

<!-- 🚨 STOP 🚨 𝗦𝗧𝗢𝗣 🚨 𝑺𝑻𝑶𝑷 🚨
<!-- 🚨 STOP 🚨 STOP 🚨 STOP 🚨
Half of all issues filed here are duplicates, answered in the FAQ, or not appropriate for the bug tracker. Even if you think you've found a *bug*, please read the FAQ first, especially the Common "Bugs" That Aren't Bugs section!
Expand Down
Empty file removed .gitmodules
Empty file.
2 changes: 1 addition & 1 deletion scripts/request-pr-review.ts
Expand Up @@ -42,7 +42,7 @@ main().catch(console.error);

async function main() {
const gh = new Octokit({ auth: options.token });
const response = await gh.pulls.createReviewRequest({
const response = await gh.pulls.requestReviewers({
owner: options.owner,
repo: options.repo,
pull_number,
Expand Down
37 changes: 30 additions & 7 deletions src/compiler/binder.ts
Expand Up @@ -905,6 +905,9 @@ namespace ts {
function isNarrowingBinaryExpression(expr: BinaryExpression) {
switch (expr.operatorToken.kind) {
case SyntaxKind.EqualsToken:
case SyntaxKind.BarBarEqualsToken:
case SyntaxKind.AmpersandAmpersandEqualsToken:
case SyntaxKind.QuestionQuestionEqualsToken:
return containsNarrowableReference(expr.left);
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
Expand Down Expand Up @@ -1041,12 +1044,18 @@ namespace ts {
}
}

function isLogicalAssignmentExpression(node: Node) {
node = skipParentheses(node);
return isBinaryExpression(node) && isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind);
}

function isTopLevelLogicalExpression(node: Node): boolean {
while (isParenthesizedExpression(node.parent) ||
isPrefixUnaryExpression(node.parent) && node.parent.operator === SyntaxKind.ExclamationToken) {
node = node.parent;
}
return !isStatementCondition(node) &&
!isLogicalAssignmentExpression(node.parent) &&
!isLogicalExpression(node.parent) &&
!(isOptionalChain(node.parent) && node.parent.expression === node);
}
Expand All @@ -1063,7 +1072,7 @@ namespace ts {

function bindCondition(node: Expression | undefined, trueTarget: FlowLabel, falseTarget: FlowLabel) {
doWithConditionalBranches(bind, node, trueTarget, falseTarget);
if (!node || !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) {
if (!node || !isLogicalAssignmentExpression(node) && !isLogicalExpression(node) && !(isOptionalChain(node) && isOutermostOptionalChain(node))) {
addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
}
Expand Down Expand Up @@ -1404,17 +1413,27 @@ namespace ts {
}
}

function bindLogicalExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
function bindLogicalLikeExpression(node: BinaryExpression, trueTarget: FlowLabel, falseTarget: FlowLabel) {
const preRightLabel = createBranchLabel();
if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
if (node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || node.operatorToken.kind === SyntaxKind.AmpersandAmpersandEqualsToken) {
bindCondition(node.left, preRightLabel, falseTarget);
}
else {
bindCondition(node.left, trueTarget, preRightLabel);
}
currentFlow = finishFlowLabel(preRightLabel);
bind(node.operatorToken);
bindCondition(node.right, trueTarget, falseTarget);

if (isLogicalOrCoalescingAssignmentOperator(node.operatorToken.kind)) {
doWithConditionalBranches(bind, node.right, trueTarget, falseTarget);
bindAssignmentTargetFlow(node.left);

addAntecedent(trueTarget, createFlowCondition(FlowFlags.TrueCondition, currentFlow, node));
addAntecedent(falseTarget, createFlowCondition(FlowFlags.FalseCondition, currentFlow, node));
}
else {
bindCondition(node.right, trueTarget, falseTarget);
}
}

function bindPrefixUnaryExpressionFlow(node: PrefixUnaryExpression) {
Expand Down Expand Up @@ -1500,14 +1519,15 @@ namespace ts {
// TODO: bindLogicalExpression is recursive - if we want to handle deeply nested `&&` expressions
// we'll need to handle the `bindLogicalExpression` scenarios in this state machine, too
// For now, though, since the common cases are chained `+`, leaving it recursive is fine
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken ||
isLogicalOrCoalescingAssignmentOperator(operator)) {
if (isTopLevelLogicalExpression(node)) {
const postExpressionLabel = createBranchLabel();
bindLogicalExpression(node, postExpressionLabel, postExpressionLabel);
bindLogicalLikeExpression(node, postExpressionLabel, postExpressionLabel);
currentFlow = finishFlowLabel(postExpressionLabel);
}
else {
bindLogicalExpression(node, currentTrueTarget!, currentFalseTarget!);
bindLogicalLikeExpression(node, currentTrueTarget!, currentFalseTarget!);
}
completeNode();
}
Expand Down Expand Up @@ -3607,6 +3627,9 @@ namespace ts {
if (operatorTokenKind === SyntaxKind.QuestionQuestionToken) {
transformFlags |= TransformFlags.AssertES2020;
}
else if (isLogicalOrCoalescingAssignmentOperator(operatorTokenKind)) {
transformFlags |= TransformFlags.AssertESNext;
}
else if (operatorTokenKind === SyntaxKind.EqualsToken && leftKind === SyntaxKind.ObjectLiteralExpression) {
// Destructuring object assignments with are ES2015 syntax
// and possibly ES2018 if they contain rest
Expand Down
55 changes: 42 additions & 13 deletions src/compiler/builder.ts
Expand Up @@ -148,7 +148,7 @@ namespace ts {
/**
* true if build info is emitted
*/
emittedBuildInfo?: boolean;
buildInfoEmitPending: boolean;
/**
* Already seen emitted files
*/
Expand All @@ -173,7 +173,7 @@ namespace ts {
const compilerOptions = newProgram.getCompilerOptions();
state.compilerOptions = compilerOptions;
// With --out or --outFile, any change affects all semantic diagnostics so no need to cache them
if (!compilerOptions.outFile && !compilerOptions.out) {
if (!outFile(compilerOptions)) {
state.semanticDiagnosticsPerFile = createMap<readonly Diagnostic[]>();
}
state.changedFilesSet = createMap<true>();
Expand All @@ -197,7 +197,7 @@ namespace ts {
if (changedFilesSet) {
copyEntries(changedFilesSet, state.changedFilesSet);
}
if (!compilerOptions.outFile && !compilerOptions.out && oldState!.affectedFilesPendingEmit) {
if (!outFile(compilerOptions) && oldState!.affectedFilesPendingEmit) {
state.affectedFilesPendingEmit = oldState!.affectedFilesPendingEmit.slice();
state.affectedFilesPendingEmitKind = cloneMapOrUndefined(oldState!.affectedFilesPendingEmitKind);
state.affectedFilesPendingEmitIndex = oldState!.affectedFilesPendingEmitIndex;
Expand Down Expand Up @@ -250,14 +250,14 @@ namespace ts {
BuilderState.getAllFilesExcludingDefaultLibraryFile(state, newProgram, /*firstSourceFile*/ undefined)
.forEach(file => state.changedFilesSet.set(file.resolvedPath, true));
}
else if (oldCompilerOptions && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
else if (oldCompilerOptions && !outFile(compilerOptions) && compilerOptionsAffectEmit(compilerOptions, oldCompilerOptions)) {
// Add all files to affectedFilesPendingEmit since emit changed
newProgram.getSourceFiles().forEach(f => addToAffectedFilesPendingEmit(state, f.resolvedPath, BuilderFileEmit.Full));
Debug.assert(!state.seenAffectedFiles || !state.seenAffectedFiles.size);
state.seenAffectedFiles = state.seenAffectedFiles || createMap<true>();
}

state.emittedBuildInfo = !state.changedFilesSet.size && !state.affectedFilesPendingEmit;
state.buildInfoEmitPending = !!state.changedFilesSet.size;
return state;
}

Expand Down Expand Up @@ -374,7 +374,7 @@ namespace ts {
// so operations are performed directly on program, return program
const program = Debug.checkDefined(state.program);
const compilerOptions = program.getCompilerOptions();
if (compilerOptions.outFile || compilerOptions.out) {
if (outFile(compilerOptions)) {
Debug.assert(!state.semanticDiagnosticsPerFile);
return program;
}
Expand Down Expand Up @@ -611,7 +611,7 @@ namespace ts {
isBuildInfoEmit?: boolean
) {
if (isBuildInfoEmit) {
state.emittedBuildInfo = true;
state.buildInfoEmitPending = false;
}
else if (affected === state.program) {
state.changedFilesSet.clear();
Expand All @@ -624,6 +624,7 @@ namespace ts {
}
if (isPendingEmit) {
state.affectedFilesPendingEmitIndex!++;
state.buildInfoEmitPending = true;
}
else {
state.affectedFilesIndex!++;
Expand Down Expand Up @@ -688,19 +689,21 @@ namespace ts {
}

export type ProgramBuildInfoDiagnostic = string | [string, readonly ReusableDiagnostic[]];
export type ProgramBuilderInfoFilePendingEmit = [string, BuilderFileEmit];
export interface ProgramBuildInfo {
fileInfos: MapLike<BuilderState.FileInfo>;
options: CompilerOptions;
referencedMap?: MapLike<string[]>;
exportedModulesMap?: MapLike<string[]>;
semanticDiagnosticsPerFile?: ProgramBuildInfoDiagnostic[];
affectedFilesPendingEmit?: ProgramBuilderInfoFilePendingEmit[];
}

/**
* Gets the program information to be emitted in buildInfo so that we can use it to create new program
*/
function getProgramBuildInfo(state: Readonly<ReusableBuilderProgramState>, getCanonicalFileName: GetCanonicalFileName): ProgramBuildInfo | undefined {
if (state.compilerOptions.outFile || state.compilerOptions.out) return undefined;
if (outFile(state.compilerOptions)) return undefined;
const currentDirectory = Debug.checkDefined(state.program).getCurrentDirectory();
const buildInfoDirectory = getDirectoryPath(getNormalizedAbsolutePath(getTsBuildInfoEmitOutputFilePath(state.compilerOptions)!, currentDirectory));
const fileInfos: MapLike<BuilderState.FileInfo> = {};
Expand Down Expand Up @@ -751,6 +754,17 @@ namespace ts {
result.semanticDiagnosticsPerFile = semanticDiagnosticsPerFile;
}

if (state.affectedFilesPendingEmit) {
const affectedFilesPendingEmit: ProgramBuilderInfoFilePendingEmit[] = [];
const seenFiles = createMap<true>();
for (const path of state.affectedFilesPendingEmit.slice(state.affectedFilesPendingEmitIndex).sort(compareStringsCaseSensitive)) {
if (addToSeen(seenFiles, path)) {
affectedFilesPendingEmit.push([relativeToBuildInfo(path), state.affectedFilesPendingEmitKind!.get(path)!]);
}
}
result.affectedFilesPendingEmit = affectedFilesPendingEmit;
}

return result;

function relativeToBuildInfoEnsuringAbsolutePath(path: string) {
Expand Down Expand Up @@ -916,13 +930,23 @@ namespace ts {
else if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
(builderProgram as EmitAndSemanticDiagnosticsBuilderProgram).getSemanticDiagnosticsOfNextAffectedFile = getSemanticDiagnosticsOfNextAffectedFile;
(builderProgram as EmitAndSemanticDiagnosticsBuilderProgram).emitNextAffectedFile = emitNextAffectedFile;
builderProgram.emitBuildInfo = emitBuildInfo;
}
else {
notImplemented();
}

return builderProgram;

function emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult {
if (state.buildInfoEmitPending) {
const result = Debug.checkDefined(state.program).emitBuildInfo(writeFile || maybeBind(host, host.writeFile), cancellationToken);
state.buildInfoEmitPending = false;
return result;
}
return emitSkippedWithNoDiagnostics;
}

/**
* Emits the next affected file's emit result (EmitResult and sourceFiles emitted) or returns undefined if iteration is complete
* The first of writeFile if provided, writeFile of BuilderProgramHost if provided, writeFile of compiler host
Expand All @@ -933,10 +957,10 @@ namespace ts {
let emitKind = BuilderFileEmit.Full;
let isPendingEmitFile = false;
if (!affected) {
if (!state.compilerOptions.out && !state.compilerOptions.outFile) {
if (!outFile(state.compilerOptions)) {
const pendingAffectedFile = getNextAffectedFilePendingEmit(state);
if (!pendingAffectedFile) {
if (state.emittedBuildInfo) {
if (!state.buildInfoEmitPending) {
return undefined;
}

Expand Down Expand Up @@ -993,7 +1017,7 @@ namespace ts {
function emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
if (kind === BuilderProgramKind.EmitAndSemanticDiagnosticsBuilderProgram) {
assertSourceFileOkWithoutNextAffectedCall(state, targetSourceFile);
const result = handleNoEmitOptions(builderProgram, targetSourceFile, cancellationToken);
const result = handleNoEmitOptions(builderProgram, targetSourceFile, writeFile, cancellationToken);
if (result) return result;
if (!targetSourceFile) {
// Emit and report any errors we ran into.
Expand Down Expand Up @@ -1071,7 +1095,7 @@ namespace ts {
function getSemanticDiagnostics(sourceFile?: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] {
assertSourceFileOkWithoutNextAffectedCall(state, sourceFile);
const compilerOptions = Debug.checkDefined(state.program).getCompilerOptions();
if (compilerOptions.outFile || compilerOptions.out) {
if (outFile(compilerOptions)) {
Debug.assert(!state.semanticDiagnosticsPerFile);
// We dont need to cache the diagnostics just return them from program
return Debug.checkDefined(state.program).getSemanticDiagnostics(sourceFile, cancellationToken);
Expand Down Expand Up @@ -1142,7 +1166,10 @@ namespace ts {
referencedMap: getMapOfReferencedSet(program.referencedMap, toPath),
exportedModulesMap: getMapOfReferencedSet(program.exportedModulesMap, toPath),
semanticDiagnosticsPerFile: program.semanticDiagnosticsPerFile && arrayToMap(program.semanticDiagnosticsPerFile, value => toPath(isString(value) ? value : value[0]), value => isString(value) ? emptyArray : value[1]),
hasReusableDiagnostic: true
hasReusableDiagnostic: true,
affectedFilesPendingEmit: map(program.affectedFilesPendingEmit, value => toPath(value[0])),
affectedFilesPendingEmitKind: program.affectedFilesPendingEmit && arrayToMap(program.affectedFilesPendingEmit, value => toPath(value[0]), value => value[1]),
affectedFilesPendingEmitIndex: program.affectedFilesPendingEmit && 0,
};
return {
getState: () => state,
Expand All @@ -1165,6 +1192,7 @@ namespace ts {
getCurrentDirectory: notImplemented,
emitNextAffectedFile: notImplemented,
getSemanticDiagnosticsOfNextAffectedFile: notImplemented,
emitBuildInfo: notImplemented,
close: noop,
};

Expand Down Expand Up @@ -1195,6 +1223,7 @@ namespace ts {
getDeclarationDiagnostics: (sourceFile, cancellationToken) => getProgram().getDeclarationDiagnostics(sourceFile, cancellationToken),
getSemanticDiagnostics: (sourceFile, cancellationToken) => getProgram().getSemanticDiagnostics(sourceFile, cancellationToken),
emit: (sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers) => getProgram().emit(sourceFile, writeFile, cancellationToken, emitOnlyDts, customTransformers),
emitBuildInfo: (writeFile, cancellationToken) => getProgram().emitBuildInfo(writeFile, cancellationToken),
getAllDependencies: notImplemented,
getCurrentDirectory: () => getProgram().getCurrentDirectory(),
close: noop,
Expand Down
2 changes: 2 additions & 0 deletions src/compiler/builderPublic.ts
Expand Up @@ -99,6 +99,8 @@ namespace ts {
* in that order would be used to write the files
*/
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
/*@internal*/
emitBuildInfo(writeFile?: WriteFileCallback, cancellationToken?: CancellationToken): EmitResult;
/**
* Get the current directory of the program
*/
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/builderState.ts
Expand Up @@ -403,7 +403,7 @@ namespace ts {
export function getAllDependencies(state: BuilderState, programOfThisState: Program, sourceFile: SourceFile): readonly string[] {
const compilerOptions = programOfThisState.getCompilerOptions();
// With --out or --outFile all outputs go into single file, all files depend on each other
if (compilerOptions.outFile || compilerOptions.out) {
if (outFile(compilerOptions)) {
return getAllFileNames(state, programOfThisState);
}

Expand Down Expand Up @@ -519,7 +519,7 @@ namespace ts {
const compilerOptions = programOfThisState.getCompilerOptions();
// If `--out` or `--outFile` is specified, any new emit will result in re-emitting the entire project,
// so returning the file itself is good enough.
if (compilerOptions && (compilerOptions.out || compilerOptions.outFile)) {
if (compilerOptions && outFile(compilerOptions)) {
return [sourceFileWithUpdatedShape];
}
return getAllFilesExcludingDefaultLibraryFile(state, programOfThisState, sourceFileWithUpdatedShape);
Expand All @@ -534,7 +534,7 @@ namespace ts {
}

const compilerOptions = programOfThisState.getCompilerOptions();
if (compilerOptions && (compilerOptions.isolatedModules || compilerOptions.out || compilerOptions.outFile)) {
if (compilerOptions && (compilerOptions.isolatedModules || outFile(compilerOptions))) {
return [sourceFileWithUpdatedShape];
}

Expand Down

0 comments on commit 2d7372a

Please sign in to comment.