Skip to content

Commit b8142f9

Browse files
committed
Merge branch 'master' into deprecated_support
2 parents 2d189dc + b977f86 commit b8142f9

File tree

122 files changed

+8289
-909
lines changed

Some content is hidden

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

122 files changed

+8289
-909
lines changed

Diff for: package.json

+1
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
"chalk": "latest",
6666
"convert-source-map": "latest",
6767
"del": "5.1.0",
68+
"diff": "^4.0.2",
6869
"eslint": "6.8.0",
6970
"eslint-formatter-autolinkable-stylish": "1.1.2",
7071
"eslint-plugin-import": "2.20.2",

Diff for: src/compiler/builder.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ namespace ts {
66
reportDeprecated?: {}
77
source?: string;
88
relatedInformation?: ReusableDiagnosticRelatedInformation[];
9+
skippedOn?: keyof CompilerOptions;
910
}
1011

1112
export interface ReusableDiagnosticRelatedInformation {
@@ -270,6 +271,7 @@ namespace ts {
270271
result.reportsUnnecessary = diagnostic.reportsUnnecessary;
271272
result.reportsDeprecated = diagnostic.reportDeprecated;
272273
result.source = diagnostic.source;
274+
result.skippedOn = diagnostic.skippedOn;
273275
const { relatedInformation } = diagnostic;
274276
result.relatedInformation = relatedInformation ?
275277
relatedInformation.length ?
@@ -678,7 +680,7 @@ namespace ts {
678680
const cachedDiagnostics = state.semanticDiagnosticsPerFile.get(path);
679681
// Report the bind and check diagnostics from the cache if we already have those diagnostics present
680682
if (cachedDiagnostics) {
681-
return cachedDiagnostics;
683+
return filterSemanticDiagnotics(cachedDiagnostics, state.compilerOptions);
682684
}
683685
}
684686

@@ -687,7 +689,7 @@ namespace ts {
687689
if (state.semanticDiagnosticsPerFile) {
688690
state.semanticDiagnosticsPerFile.set(path, diagnostics);
689691
}
690-
return diagnostics;
692+
return filterSemanticDiagnotics(diagnostics, state.compilerOptions);
691693
}
692694

693695
export type ProgramBuildInfoDiagnostic = string | [string, readonly ReusableDiagnostic[]];
@@ -819,6 +821,7 @@ namespace ts {
819821
result.reportsUnnecessary = diagnostic.reportsUnnecessary;
820822
result.reportDeprecated = diagnostic.reportsDeprecated;
821823
result.source = diagnostic.source;
824+
result.skippedOn = diagnostic.skippedOn;
822825
const { relatedInformation } = diagnostic;
823826
result.relatedInformation = relatedInformation ?
824827
relatedInformation.length ?

Diff for: src/compiler/checker.ts

+99-35
Large diffs are not rendered by default.

Diff for: src/compiler/commandLineParser.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,6 @@ namespace ts {
462462
{
463463
name: "noEmit",
464464
type: "boolean",
465-
affectsEmit: true,
466465
showInSimplifiedHelpView: true,
467466
category: Diagnostics.Basic_Options,
468467
description: Diagnostics.Do_not_emit_outputs,
@@ -766,6 +765,12 @@ namespace ts {
766765
category: Diagnostics.Advanced_Options,
767766
description: Diagnostics.Specify_the_JSX_factory_function_to_use_when_targeting_react_JSX_emit_e_g_React_createElement_or_h
768767
},
768+
{
769+
name: "jsxFragmentFactory",
770+
type: "string",
771+
category: Diagnostics.Advanced_Options,
772+
description: Diagnostics.Specify_the_JSX_fragment_factory_function_to_use_when_targeting_react_JSX_emit_with_jsxFactory_compiler_option_is_specified_e_g_Fragment
773+
},
769774
{
770775
name: "resolveJsonModule",
771776
type: "boolean",

Diff for: src/compiler/diagnosticMessages.json

+14-2
Original file line numberDiff line numberDiff line change
@@ -4458,6 +4458,10 @@
44584458
"category": "Error",
44594459
"code": 6309
44604460
},
4461+
"Referenced project '{0}' may not disable emit.": {
4462+
"category": "Error",
4463+
"code": 6310
4464+
},
44614465
"Project '{0}' is out of date because oldest output '{1}' is older than newest input '{2}'": {
44624466
"category": "Message",
44634467
"code": 6350
@@ -5032,11 +5036,11 @@
50325036
"category": "Error",
50335037
"code": 17015
50345038
},
5035-
"JSX fragment is not supported when using --jsxFactory": {
5039+
"The 'jsxFragmentFactory' compiler option must be provided to use JSX fragments with the 'jsxFactory' compiler option.": {
50365040
"category": "Error",
50375041
"code": 17016
50385042
},
5039-
"JSX fragment is not supported when using an inline JSX factory pragma": {
5043+
"An @jsxFrag pragma is required when using an @jsx pragma with JSX fragments.": {
50405044
"category": "Error",
50415045
"code": 17017
50425046
},
@@ -5842,5 +5846,13 @@
58425846
"Only numeric enums can have computed members, but this expression has type '{0}'. If you do not need exhaustiveness checks, consider using an object literal instead.": {
58435847
"category": "Error",
58445848
"code": 18033
5849+
},
5850+
"Specify the JSX fragment factory function to use when targeting 'react' JSX emit with 'jsxFactory' compiler option is specified, e.g. 'Fragment'.": {
5851+
"category": "Message",
5852+
"code": 18034
5853+
},
5854+
"Invalid value for 'jsxFragmentFactory'. '{0}' is not a valid identifier or qualified-name.": {
5855+
"category": "Error",
5856+
"code": 18035
58455857
}
58465858
}

Diff for: src/compiler/emitter.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ namespace ts {
333333
// Write build information if applicable
334334
if (!buildInfoPath || targetSourceFile || emitSkipped) return;
335335
const program = host.getProgramBuildInfo();
336-
if (host.isEmitBlocked(buildInfoPath) || compilerOptions.noEmit) {
336+
if (host.isEmitBlocked(buildInfoPath)) {
337337
emitSkipped = true;
338338
return;
339339
}
@@ -660,6 +660,7 @@ namespace ts {
660660
getTypeReferenceDirectivesForSymbol: notImplemented,
661661
isLiteralConstDeclaration: notImplemented,
662662
getJsxFactoryEntity: notImplemented,
663+
getJsxFragmentFactoryEntity: notImplemented,
663664
getAllAccessorDeclarations: notImplemented,
664665
getSymbolOfExternalModuleSpecifier: notImplemented,
665666
isBindingCapturedByNode: notImplemented,

Diff for: src/compiler/factory/utilities.ts

+13-9
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ namespace ts {
5555
);
5656
}
5757

58+
function createJsxFragmentFactoryExpression(factory: NodeFactory, jsxFragmentFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression {
59+
return jsxFragmentFactoryEntity ?
60+
createJsxFactoryExpressionFromEntityName(factory, jsxFragmentFactoryEntity, parent) :
61+
factory.createPropertyAccessExpression(
62+
createReactNamespace(reactNamespace, parent),
63+
"Fragment"
64+
);
65+
}
66+
5867
export function createExpressionForJsxElement(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, tagName: Expression, props: Expression | undefined, children: readonly Expression[] | undefined, parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression {
5968
const argumentsList = [tagName];
6069
if (props) {
@@ -87,14 +96,9 @@ namespace ts {
8796
);
8897
}
8998

90-
export function createExpressionForJsxFragment(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, children: readonly Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression {
91-
const tagName = factory.createPropertyAccessExpression(
92-
createReactNamespace(reactNamespace, parentElement),
93-
"Fragment"
94-
);
95-
96-
const argumentsList = [<Expression>tagName];
97-
argumentsList.push(factory.createNull());
99+
export function createExpressionForJsxFragment(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, jsxFragmentFactoryEntity: EntityName | undefined, reactNamespace: string, children: readonly Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression {
100+
const tagName = createJsxFragmentFactoryExpression(factory, jsxFragmentFactoryEntity, reactNamespace, parentElement);
101+
const argumentsList = [tagName, factory.createNull()];
98102

99103
if (children && children.length > 0) {
100104
if (children.length > 1) {
@@ -820,4 +824,4 @@ namespace ts {
820824
export function isStaticModifier(node: Modifier): node is StaticKeyword {
821825
return node.kind === SyntaxKind.StaticKeyword;
822826
}
823-
}
827+
}

Diff for: src/compiler/parser.ts

+5-3
Original file line numberDiff line numberDiff line change
@@ -3120,7 +3120,7 @@ namespace ts {
31203120
return finishNode(factory.createRestTypeNode(parseType()), pos);
31213121
}
31223122
const type = parseType();
3123-
if (!(contextFlags & NodeFlags.JSDoc) && isJSDocNullableType(type) && type.pos === type.type.pos) {
3123+
if (isJSDocNullableType(type) && type.pos === type.type.pos) {
31243124
const node = factory.createOptionalTypeNode(type.type);
31253125
setTextRange(node, type);
31263126
(node as Mutable<Node>).flags = type.flags;
@@ -3361,7 +3361,7 @@ namespace ts {
33613361
break;
33623362
case SyntaxKind.QuestionToken:
33633363
// If not in JSDoc and next token is start of a type we have a conditional type
3364-
if (!(contextFlags & NodeFlags.JSDoc) && lookAhead(nextTokenIsStartOfType)) {
3364+
if (lookAhead(nextTokenIsStartOfType)) {
33653365
return type;
33663366
}
33673367
nextToken();
@@ -8577,7 +8577,9 @@ namespace ts {
85778577
});
85788578
break;
85798579
}
8580-
case "jsx": return; // Accessed directly
8580+
case "jsx":
8581+
case "jsxfrag":
8582+
return; // Accessed directly
85818583
default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future?
85828584
}
85838585
});

Diff for: src/compiler/program.ts

+27-10
Original file line numberDiff line numberDiff line change
@@ -1530,7 +1530,7 @@ namespace ts {
15301530
function getPrependNodes() {
15311531
return createPrependNodes(
15321532
projectReferences,
1533-
(_ref, index) => resolvedProjectReferences![index]!.commandLine,
1533+
(_ref, index) => resolvedProjectReferences![index]?.commandLine,
15341534
fileName => {
15351535
const path = toPath(fileName);
15361536
const sourceFile = getSourceFileByPath(path);
@@ -1719,7 +1719,7 @@ namespace ts {
17191719

17201720
function getSemanticDiagnosticsForFile(sourceFile: SourceFile, cancellationToken: CancellationToken | undefined): readonly Diagnostic[] {
17211721
return concatenate(
1722-
getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken),
1722+
filterSemanticDiagnotics(getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken), options),
17231723
getProgramDiagnostics(sourceFile)
17241724
);
17251725
}
@@ -3011,10 +3011,6 @@ namespace ts {
30113011
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_incremental_can_only_be_specified_using_tsconfig_emitting_to_single_file_or_when_option_tsBuildInfoFile_is_specified));
30123012
}
30133013

3014-
if (!options.listFilesOnly && options.noEmit && isIncrementalCompilation(options)) {
3015-
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_with_option_1, "noEmit", options.incremental ? "incremental" : "composite");
3016-
}
3017-
30183014
verifyProjectReferences();
30193015

30203016
// List of collected files is complete; validate exhautiveness if this is a project with a file list
@@ -3196,6 +3192,15 @@ namespace ts {
31963192
createOptionValueDiagnostic("reactNamespace", Diagnostics.Invalid_value_for_reactNamespace_0_is_not_a_valid_identifier, options.reactNamespace);
31973193
}
31983194

3195+
if (options.jsxFragmentFactory) {
3196+
if (!options.jsxFactory) {
3197+
createDiagnosticForOptionName(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "jsxFragmentFactory", "jsxFactory");
3198+
}
3199+
if (!parseIsolatedEntityName(options.jsxFragmentFactory, languageVersion)) {
3200+
createOptionValueDiagnostic("jsxFragmentFactory", Diagnostics.Invalid_value_for_jsxFragmentFactory_0_is_not_a_valid_identifier_or_qualified_name, options.jsxFragmentFactory);
3201+
}
3202+
}
3203+
31993204
// If the emit is enabled make sure that every output file is unique and not overwriting any of the input files
32003205
if (!options.noEmit && !options.suppressOutputPathCheck) {
32013206
const emitHost = getEmitHost();
@@ -3269,7 +3274,7 @@ namespace ts {
32693274
}
32703275

32713276
function verifyProjectReferences() {
3272-
const buildInfoPath = !options.noEmit && !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined;
3277+
const buildInfoPath = !options.suppressOutputPathCheck ? getTsBuildInfoEmitOutputFilePath(options) : undefined;
32733278
forEachProjectReference(projectReferences, resolvedProjectReferences, (resolvedRef, index, parent) => {
32743279
const ref = (parent ? parent.commandLine.projectReferences : projectReferences)![index];
32753280
const parentFile = parent && parent.sourceFile as JsonSourceFile;
@@ -3278,11 +3283,12 @@ namespace ts {
32783283
return;
32793284
}
32803285
const options = resolvedRef.commandLine.options;
3281-
if (!options.composite) {
3286+
if (!options.composite || options.noEmit) {
32823287
// ok to not have composite if the current program is container only
32833288
const inputs = parent ? parent.commandLine.fileNames : rootNames;
32843289
if (inputs.length) {
3285-
createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path);
3290+
if (!options.composite) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_must_have_setting_composite_Colon_true, ref.path);
3291+
if (options.noEmit) createDiagnosticForReference(parentFile, index, Diagnostics.Referenced_project_0_may_not_disable_emit, ref.path);
32863292
}
32873293
}
32883294
if (ref.prepend) {
@@ -3648,7 +3654,13 @@ namespace ts {
36483654
cancellationToken: CancellationToken | undefined
36493655
): EmitResult | undefined {
36503656
const options = program.getCompilerOptions();
3651-
if (options.noEmit) return emitSkippedWithNoDiagnostics;
3657+
if (options.noEmit) {
3658+
// Cache the semantic diagnostics
3659+
program.getSemanticDiagnostics(sourceFile, cancellationToken);
3660+
return sourceFile || outFile(options) ?
3661+
emitSkippedWithNoDiagnostics :
3662+
program.emitBuildInfo(writeFile, cancellationToken);
3663+
}
36523664

36533665
// If the noEmitOnError flag is set, then check if we have any errors so far. If so,
36543666
// immediately bail out. Note that we pass 'undefined' for 'sourceFile' so that we
@@ -3675,6 +3687,11 @@ namespace ts {
36753687
return { diagnostics, sourceMaps: undefined, emittedFiles, emitSkipped: true };
36763688
}
36773689

3690+
/*@internal*/
3691+
export function filterSemanticDiagnotics(diagnostic: readonly Diagnostic[], option: CompilerOptions): readonly Diagnostic[] {
3692+
return filter(diagnostic, d => !d.skippedOn || !option[d.skippedOn]);
3693+
}
3694+
36783695
/*@internal*/
36793696
interface CompilerHostLike {
36803697
useCaseSensitiveFileNames(): boolean;

Diff for: src/compiler/transformers/jsx.ts

+1
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ namespace ts {
142142
const element = createExpressionForJsxFragment(
143143
factory,
144144
context.getEmitResolver().getJsxFactoryEntity(currentSourceFile),
145+
context.getEmitResolver().getJsxFragmentFactoryEntity(currentSourceFile),
145146
compilerOptions.reactNamespace!, // TODO: GH#18217
146147
mapDefined(children, transformJsxChildToExpression),
147148
node,

Diff for: src/compiler/types.ts

+9
Original file line numberDiff line numberDiff line change
@@ -3462,7 +3462,9 @@ namespace ts {
34623462
/* @internal */ version: string;
34633463
/* @internal */ pragmas: ReadonlyPragmaMap;
34643464
/* @internal */ localJsxNamespace?: __String;
3465+
/* @internal */ localJsxFragmentNamespace?: __String;
34653466
/* @internal */ localJsxFactory?: EntityName;
3467+
/* @internal */ localJsxFragmentFactory?: EntityName;
34663468

34673469
/* @internal */ exportedModulesFromDeclarationEmit?: ExportedModulesFromDeclarationEmit;
34683470
}
@@ -4471,6 +4473,7 @@ namespace ts {
44714473
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[] | undefined;
44724474
isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean;
44734475
getJsxFactoryEntity(location?: Node): EntityName | undefined;
4476+
getJsxFragmentFactoryEntity(location?: Node): EntityName | undefined;
44744477
getAllAccessorDeclarations(declaration: AccessorDeclaration): AllAccessorDeclarations;
44754478
getSymbolOfExternalModuleSpecifier(node: StringLiteralLike): Symbol | undefined;
44764479
isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement): boolean;
@@ -5533,6 +5536,7 @@ namespace ts {
55335536
reportsDeprecated?: {}
55345537
source?: string;
55355538
relatedInformation?: DiagnosticRelatedInformation[];
5539+
/* @internal */ skippedOn?: keyof CompilerOptions;
55365540
}
55375541

55385542
export interface DiagnosticRelatedInformation {
@@ -5692,6 +5696,7 @@ namespace ts {
56925696
/* @internal */ pretty?: boolean;
56935697
reactNamespace?: string;
56945698
jsxFactory?: string;
5699+
jsxFragmentFactory?: string;
56955700
composite?: boolean;
56965701
incremental?: boolean;
56975702
tsBuildInfoFile?: string;
@@ -7941,6 +7946,10 @@ namespace ts {
79417946
args: [{ name: "factory" }],
79427947
kind: PragmaKindFlags.MultiLine
79437948
},
7949+
"jsxfrag": {
7950+
args: [{ name: "factory" }],
7951+
kind: PragmaKindFlags.MultiLine
7952+
},
79447953
} as const;
79457954

79467955
/* @internal */

Diff for: src/harness/harnessIO.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -1293,6 +1293,7 @@ namespace Harness {
12931293
export interface BaselineOptions {
12941294
Subfolder?: string;
12951295
Baselinefolder?: string;
1296+
PrintDiff?: true;
12961297
}
12971298

12981299
export function localPath(fileName: string, baselineFolder?: string, subfolder?: string) {
@@ -1347,7 +1348,7 @@ namespace Harness {
13471348
return { expected, actual };
13481349
}
13491350

1350-
function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string) {
1351+
function writeComparison(expected: string, actual: string, relativeFileName: string, actualFileName: string, opts?: BaselineOptions) {
13511352
// For now this is written using TypeScript, because sys is not available when running old test cases.
13521353
// But we need to move to sys once we have
13531354
// Creates the directory including its parent if not already present
@@ -1381,7 +1382,14 @@ namespace Harness {
13811382
else {
13821383
IO.writeFile(actualFileName, encodedActual);
13831384
}
1384-
throw new Error(`The baseline file ${relativeFileName} has changed.`);
1385+
if (require && opts && opts.PrintDiff) {
1386+
const Diff = require("diff");
1387+
const patch = Diff.createTwoFilesPatch("Expected", "Actual", expected, actual, "The current baseline", "The new version");
1388+
throw new Error(`The baseline file ${relativeFileName} has changed.${ts.ForegroundColorEscapeSequences.Grey}\n\n${patch}`);
1389+
}
1390+
else {
1391+
throw new Error(`The baseline file ${relativeFileName} has changed.`);
1392+
}
13851393
}
13861394
}
13871395

@@ -1391,7 +1399,7 @@ namespace Harness {
13911399
throw new Error("The generated content was \"undefined\". Return \"null\" if no baselining is required.\"");
13921400
}
13931401
const comparison = compareToBaseline(actual, relativeFileName, opts);
1394-
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName);
1402+
writeComparison(comparison.expected, comparison.actual, relativeFileName, actualFileName, opts);
13951403
}
13961404

13971405
export function runMultifileBaseline(relativeFileBase: string, extension: string, generateContent: () => IterableIterator<[string, string, number]> | IterableIterator<[string, string]> | null, opts?: BaselineOptions, referencedExtensions?: string[]): void {

0 commit comments

Comments
 (0)