Skip to content

Commit e62418e

Browse files
dragomirtitiansheetalkamatjakebailey
authored
Isolated declarations errors (#58201)
Co-authored-by: Sheetal Nandi <[email protected]> Co-authored-by: Jake Bailey <[email protected]>
1 parent e8f2225 commit e62418e

File tree

121 files changed

+13230
-35
lines changed

Some content is hidden

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

121 files changed

+13230
-35
lines changed

src/compiler/_namespaces/ts.ts

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export * from "../watchPublic";
7272
export * from "../tsbuild";
7373
export * from "../tsbuildPublic";
7474
export * from "../executeCommandLine";
75+
export * from "../expressionToTypeNode";
7576
import * as moduleSpecifiers from "./ts.moduleSpecifiers";
7677
export { moduleSpecifiers };
7778
import * as performance from "./ts.performance";

src/compiler/checker.ts

+85-7
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ import {
124124
createPrinterWithRemoveCommentsOmitTrailingSemicolon,
125125
createPropertyNameNodeForIdentifierOrLiteral,
126126
createSymbolTable,
127+
createSyntacticTypeNodeBuilder,
127128
createTextWriter,
128129
Debug,
129130
Declaration,
@@ -387,6 +388,7 @@ import {
387388
hasExtension,
388389
HasIllegalDecorators,
389390
HasIllegalModifiers,
391+
hasInferredType,
390392
HasInitializer,
391393
hasInitializer,
392394
hasJSDocNodes,
@@ -1481,6 +1483,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
14811483
var checkBinaryExpression = createCheckBinaryExpression();
14821484
var emitResolver = createResolver();
14831485
var nodeBuilder = createNodeBuilder();
1486+
var syntacticNodeBuilder = createSyntacticTypeNodeBuilder(compilerOptions, {
1487+
isEntityNameVisible,
1488+
isExpandoFunctionDeclaration,
1489+
isNonNarrowedBindableName,
1490+
getAllAccessorDeclarations: getAllAccessorDeclarationsForDeclaration,
1491+
requiresAddingImplicitUndefined,
1492+
isUndefinedIdentifierExpression(node: Identifier) {
1493+
Debug.assert(isExpressionNode(node));
1494+
return getSymbolAtLocation(node) === undefinedSymbol;
1495+
},
1496+
});
14841497
var evaluate = createEvaluator({
14851498
evaluateElementAccessExpression,
14861499
evaluateEntityNameExpression,
@@ -5864,7 +5877,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
58645877
return meaning;
58655878
}
58665879

5867-
function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult {
5880+
function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node, shouldComputeAliasToMakeVisible = true): SymbolVisibilityResult {
58685881
const meaning = getMeaningOfEntityNameReference(entityName);
58695882
const firstIdentifier = getFirstIdentifier(entityName);
58705883
const symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, /*nameNotFoundMessage*/ undefined, /*isUse*/ false);
@@ -5876,7 +5889,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
58765889
}
58775890

58785891
// Verify if the symbol is accessible
5879-
return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || {
5892+
return (symbol && hasVisibleDeclarations(symbol, shouldComputeAliasToMakeVisible)) || {
58805893
accessibility: SymbolAccessibility.NotAccessible,
58815894
errorSymbolName: getTextOfNode(firstIdentifier),
58825895
errorNode: firstIdentifier,
@@ -6018,7 +6031,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
60186031
return setTextRangeWorker(setOriginalNode(range, location), location);
60196032
}
60206033

6034+
/**
6035+
* Same as expressionOrTypeToTypeNodeHelper, but also checks if the expression can be syntactically typed.
6036+
*/
60216037
function expressionOrTypeToTypeNode(context: NodeBuilderContext, expr: Expression | JsxAttributeValue | undefined, type: Type, addUndefined?: boolean) {
6038+
const oldFlags = context.flags;
6039+
if (expr && !(context.flags & NodeBuilderFlags.NoSyntacticPrinter)) {
6040+
syntacticNodeBuilder.serializeTypeOfExpression(expr, context, addUndefined);
6041+
}
6042+
context.flags |= NodeBuilderFlags.NoSyntacticPrinter;
6043+
const result = expressionOrTypeToTypeNodeHelper(context, expr, type, addUndefined);
6044+
context.flags = oldFlags;
6045+
return result;
6046+
}
6047+
function expressionOrTypeToTypeNodeHelper(context: NodeBuilderContext, expr: Expression | JsxAttributeValue | undefined, type: Type, addUndefined?: boolean) {
60226048
if (expr) {
60236049
const typeNode = isAssertionExpression(expr) ? expr.type
60246050
: isJSDocTypeAssertion(expr) ? getJSDocTypeAssertionType(expr)
@@ -8155,6 +8181,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
81558181
const decl = declaration ?? symbol.valueDeclaration ?? symbol.declarations?.[0];
81568182
const expr = decl && isDeclarationWithPossibleInnerTypeNodeReuse(decl) ? getPossibleTypeNodeReuseExpression(decl) : undefined;
81578183

8184+
if (decl && hasInferredType(decl) && !(context.flags & NodeBuilderFlags.NoSyntacticPrinter)) {
8185+
syntacticNodeBuilder.serializeTypeOfDeclaration(decl, context);
8186+
}
8187+
context.flags |= NodeBuilderFlags.NoSyntacticPrinter;
81588188
const result = expressionOrTypeToTypeNode(context, expr, type, addUndefined);
81598189
context.flags = oldFlags;
81608190
return result;
@@ -8177,6 +8207,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
81778207
let returnTypeNode: TypeNode | undefined;
81788208
const returnType = getReturnTypeOfSignature(signature);
81798209
if (returnType && !(suppressAny && isTypeAny(returnType))) {
8210+
if (signature.declaration && !(context.flags & NodeBuilderFlags.NoSyntacticPrinter)) {
8211+
syntacticNodeBuilder.serializeReturnTypeForSignature(signature.declaration, context);
8212+
}
8213+
context.flags |= NodeBuilderFlags.NoSyntacticPrinter;
81808214
returnTypeNode = serializeReturnTypeForSignatureWorker(context, signature);
81818215
}
81828216
else if (!suppressAny) {
@@ -45633,9 +45667,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4563345667
result.value,
4563445668
/*isSyntacticallyString*/ false,
4563545669
/*resolvedOtherFiles*/ true,
45670+
/*hasExternalReferences*/ true,
4563645671
);
4563745672
}
45638-
return result;
45673+
return evaluatorResult(result.value, result.isSyntacticallyString, result.resolvedOtherFiles, /*hasExternalReferences*/ true);
4563945674
}
4564045675
}
4564145676
return evaluatorResult(/*value*/ undefined);
@@ -45667,7 +45702,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4566745702
error(expr, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums);
4566845703
return evaluatorResult(/*value*/ 0);
4566945704
}
45670-
return getEnumMemberValue(declaration as EnumMember);
45705+
const value = getEnumMemberValue(declaration as EnumMember);
45706+
if (location.parent !== declaration.parent) {
45707+
return evaluatorResult(value.value, value.isSyntacticallyString, value.resolvedOtherFiles, /*hasExternalReferences*/ true);
45708+
}
45709+
return value;
4567145710
}
4567245711

4567345712
function checkEnumDeclaration(node: EnumDeclaration) {
@@ -48283,12 +48322,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4828348322
}
4828448323

4828548324
function isExpandoFunctionDeclaration(node: Declaration): boolean {
48286-
const declaration = getParseTreeNode(node, isFunctionDeclaration);
48325+
const declaration = getParseTreeNode(node, (n): n is FunctionDeclaration | VariableDeclaration => isFunctionDeclaration(n) || isVariableDeclaration(n));
4828748326
if (!declaration) {
4828848327
return false;
4828948328
}
48290-
const symbol = getSymbolOfDeclaration(declaration);
48291-
if (!symbol || !(symbol.flags & SymbolFlags.Function)) {
48329+
let symbol: Symbol | undefined;
48330+
if (isVariableDeclaration(declaration)) {
48331+
if (declaration.type || (!isInJSFile(declaration) && !isVarConstLike(declaration))) {
48332+
return false;
48333+
}
48334+
const initializer = getDeclaredExpandoInitializer(declaration);
48335+
if (!initializer || !canHaveSymbol(initializer)) {
48336+
return false;
48337+
}
48338+
symbol = getSymbolOfDeclaration(initializer);
48339+
}
48340+
else {
48341+
symbol = getSymbolOfDeclaration(declaration);
48342+
}
48343+
if (!symbol || !(symbol.flags & SymbolFlags.Function | SymbolFlags.Variable)) {
4829248344
return false;
4829348345
}
4829448346
return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && isExpandoPropertyDeclaration(p.valueDeclaration));
@@ -48625,6 +48677,25 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4862548677
}
4862648678
return false;
4862748679
}
48680+
function isNonNarrowedBindableName(node: ComputedPropertyName) {
48681+
if (!hasBindableName(node.parent)) {
48682+
return false;
48683+
}
48684+
48685+
const expression = node.expression;
48686+
if (!isEntityNameExpression(expression)) {
48687+
return true;
48688+
}
48689+
48690+
const type = getTypeOfExpression(expression);
48691+
const symbol = getSymbolAtLocation(expression);
48692+
if (!symbol) {
48693+
return false;
48694+
}
48695+
// Ensure not type narrowing
48696+
const declaredType = getTypeOfSymbol(symbol);
48697+
return declaredType === type;
48698+
}
4862848699

4862948700
function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression {
4863048701
const enumResult = type.flags & TypeFlags.EnumLike ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker)
@@ -48750,6 +48821,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4875048821
return node && getExternalModuleFileFromDeclaration(node);
4875148822
},
4875248823
isLiteralConstDeclaration,
48824+
isNonNarrowedBindableName,
4875348825
isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => {
4875448826
const node = getParseTreeNode(nodeIn, isDeclaration);
4875548827
const symbol = node && getSymbolOfDeclaration(node);
@@ -51186,4 +51258,10 @@ class SymbolTrackerImpl implements SymbolTracker {
5118651258
private onDiagnosticReported() {
5118751259
this.context.reportedDiagnostic = true;
5118851260
}
51261+
51262+
reportInferenceFallback(node: Node): void {
51263+
if (this.inner?.reportInferenceFallback) {
51264+
this.inner.reportInferenceFallback(node);
51265+
}
51266+
}
5118951267
}

src/compiler/commandLineParser.ts

+9
Original file line numberDiff line numberDiff line change
@@ -831,6 +831,15 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
831831
description: Diagnostics.Do_not_transform_or_elide_any_imports_or_exports_not_marked_as_type_only_ensuring_they_are_written_in_the_output_file_s_format_based_on_the_module_setting,
832832
defaultValueDescription: false,
833833
},
834+
{
835+
name: "isolatedDeclarations",
836+
type: "boolean",
837+
category: Diagnostics.Interop_Constraints,
838+
description: Diagnostics.Require_sufficient_annotation_on_exports_so_other_tools_can_trivially_generate_declaration_files,
839+
defaultValueDescription: false,
840+
affectsBuildInfo: true,
841+
affectsSemanticDiagnostics: true,
842+
},
834843

835844
// Strict Type Checks
836845
{

src/compiler/diagnosticMessages.json

+125
Original file line numberDiff line numberDiff line change
@@ -6227,6 +6227,11 @@
62276227
"category": "Message",
62286228
"code": 6718
62296229
},
6230+
"Require sufficient annotation on exports so other tools can trivially generate declaration files.": {
6231+
"category": "Message",
6232+
"code": 6719
6233+
},
6234+
62306235
"Default catch clause variables as 'unknown' instead of 'any'.": {
62316236
"category": "Message",
62326237
"code": 6803
@@ -6741,6 +6746,126 @@
67416746
"category": "Error",
67426747
"code": 9006
67436748
},
6749+
"Function must have an explicit return type annotation with --isolatedDeclarations.": {
6750+
"category": "Error",
6751+
"code": 9007
6752+
},
6753+
"Method must have an explicit return type annotation with --isolatedDeclarations.": {
6754+
"category": "Error",
6755+
"code": 9008
6756+
},
6757+
"At least one accessor must have an explicit return type annotation with --isolatedDeclarations.": {
6758+
"category": "Error",
6759+
"code": 9009
6760+
},
6761+
"Variable must have an explicit type annotation with --isolatedDeclarations.": {
6762+
"category": "Error",
6763+
"code": 9010
6764+
},
6765+
"Parameter must have an explicit type annotation with --isolatedDeclarations.": {
6766+
"category": "Error",
6767+
"code": 9011
6768+
},
6769+
"Property must have an explicit type annotation with --isolatedDeclarations.": {
6770+
"category": "Error",
6771+
"code": 9012
6772+
},
6773+
"Expression type can't be inferred with --isolatedDeclarations.": {
6774+
"category": "Error",
6775+
"code": 9013
6776+
},
6777+
"Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.": {
6778+
"category": "Error",
6779+
"code": 9014
6780+
},
6781+
"Objects that contain spread assignments can't be inferred with --isolatedDeclarations.": {
6782+
"category": "Error",
6783+
"code": 9015
6784+
},
6785+
"Objects that contain shorthand properties can't be inferred with --isolatedDeclarations.": {
6786+
"category": "Error",
6787+
"code": 9016
6788+
},
6789+
"Only const arrays can be inferred with --isolatedDeclarations.": {
6790+
"category": "Error",
6791+
"code": 9017
6792+
},
6793+
"Arrays with spread elements can't inferred with --isolatedDeclarations.": {
6794+
"category": "Error",
6795+
"code": 9018
6796+
},
6797+
"Binding elements can't be exported directly with --isolatedDeclarations.": {
6798+
"category": "Error",
6799+
"code": 9019
6800+
},
6801+
"Enum member initializers must be computable without references to external symbols with --isolatedDeclarations.": {
6802+
"category": "Error",
6803+
"code": 9020
6804+
},
6805+
"Extends clause can't contain an expression with --isolatedDeclarations.": {
6806+
"category": "Error",
6807+
"code": 9021
6808+
},
6809+
"Inference from class expressions is not supported with --isolatedDeclarations.": {
6810+
"category": "Error",
6811+
"code": 9022
6812+
},
6813+
"Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.": {
6814+
"category": "Error",
6815+
"code": 9023
6816+
},
6817+
"Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations.": {
6818+
"category": "Error",
6819+
"code": 9025
6820+
},
6821+
"Declaration emit for this file requires preserving this import for augmentations. This is not supported with --isolatedDeclarations.": {
6822+
"category": "Error",
6823+
"code": 9026
6824+
},
6825+
"Add a type annotation to the variable {0}.": {
6826+
"category": "Error",
6827+
"code": 9027
6828+
},
6829+
"Add a type annotation to the parameter {0}.": {
6830+
"category": "Error",
6831+
"code": 9028
6832+
},
6833+
"Add a type annotation to the property {0}.": {
6834+
"category": "Error",
6835+
"code": 9029
6836+
},
6837+
"Add a return type to the function expression.": {
6838+
"category": "Error",
6839+
"code": 9030
6840+
},
6841+
"Add a return type to the function declaration.": {
6842+
"category": "Error",
6843+
"code": 9031
6844+
},
6845+
"Add a return type to the get accessor declaration.": {
6846+
"category": "Error",
6847+
"code": 9032
6848+
},
6849+
"Add a type to parameter of the set accessor declaration.": {
6850+
"category": "Error",
6851+
"code": 9033
6852+
},
6853+
"Add a return type to the method": {
6854+
"category": "Error",
6855+
"code": 9034
6856+
},
6857+
"Add satisfies and a type assertion to this expression (satisfies T as T) to make the type explicit.": {
6858+
"category": "Error",
6859+
"code": 9035
6860+
},
6861+
"Move the expression in default export to a variable and add a type annotation to it.": {
6862+
"category": "Error",
6863+
"code": 9036
6864+
},
6865+
"Default exports can't be inferred with --isolatedDeclarations.": {
6866+
"category": "Error",
6867+
"code": 9037
6868+
},
67446869
"JSX attributes must only be assigned a non-empty 'expression'.": {
67456870
"category": "Error",
67466871
"code": 17000

src/compiler/emitter.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,7 @@ export const notImplementedResolver: EmitResolver = {
11141114
isArgumentsLocalBinding: notImplemented,
11151115
getExternalModuleFileFromDeclaration: notImplemented,
11161116
isLiteralConstDeclaration: notImplemented,
1117+
isNonNarrowedBindableName: notImplemented,
11171118
getJsxFactoryEntity: notImplemented,
11181119
getJsxFragmentFactoryEntity: notImplemented,
11191120
isBindingCapturedByNode: notImplemented,

0 commit comments

Comments
 (0)