Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
96de93c
Added command line option and errors
dragomirtitian Apr 15, 2024
94e1f5b
Added isolated declaration errors.
dragomirtitian Apr 15, 2024
5ed6046
Addressed code review.
dragomirtitian Apr 16, 2024
2160065
Improved expando function handling.
dragomirtitian Apr 16, 2024
461669d
Change how isolated declaration checks are called.
dragomirtitian Apr 17, 2024
987a476
Improve error for variables initialized with class expression
dragomirtitian Apr 17, 2024
5cb9fad
Forbid allowJS with isolated declarations and changed description of …
dragomirtitian Apr 18, 2024
652d1dc
Merge remote-tracking branch 'remotes/origin/main' into isolated-decl…
dragomirtitian Apr 18, 2024
186a8b8
Remove visitor cache workaround.
dragomirtitian Apr 18, 2024
d5a298d
Removed restriction on isolatedDeclaration running with out and outFile.
dragomirtitian Apr 18, 2024
75a43c4
Removed errors for enum members where there is no tantalizer emitted …
dragomirtitian Apr 18, 2024
5d747bb
Moved isolated declaration diagnostics to diagnostics.ts
dragomirtitian Apr 18, 2024
a831ae4
Changed diagnostic message texts.
dragomirtitian Apr 18, 2024
0b83d8a
Changed import to use ts namespace instead of the file.
dragomirtitian Apr 18, 2024
7ac2788
Renamed expressionOrTypeToTypeNode
dragomirtitian Apr 18, 2024
7c893ca
Fixed typo in diagnostic.
dragomirtitian Apr 19, 2024
b0ad92c
Forbid isolated declarations without declaration option.
dragomirtitian Apr 19, 2024
108fe87
Call expressionOrTypeToTypeNodeHelper instead expressionOrTypeToTypeNode
dragomirtitian Apr 19, 2024
27e1b8a
Removed drive by fix to shouldPrintWithInitializer
dragomirtitian Apr 19, 2024
53cb0ac
Use getEmitDeclarations instead of declaration
dragomirtitian Apr 19, 2024
5f3721c
Update src/compiler/program.ts
dragomirtitian Apr 19, 2024
bdd411a
Move methods off of context, fix context bug
jakebailey Apr 19, 2024
b761b3f
Merge pull request #144 from jakebailey/bloomberg-isolated-declaratio…
dragomirtitian Apr 19, 2024
4c9318c
Fix unused code lints
jakebailey Apr 19, 2024
102ebf7
Merge pull request #145 from jakebailey/bloomberg-isolated-declaratio…
dragomirtitian Apr 19, 2024
9a073be
Make isEntityNameVisible have the same parameter order
jakebailey Apr 19, 2024
ee7a872
Merge pull request #146 from jakebailey/bloomberg-isolated-declaratio…
dragomirtitian Apr 19, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 92 additions & 11 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,7 @@ import {
hasExtension,
HasIllegalDecorators,
HasIllegalModifiers,
hasInferredType,
HasInitializer,
hasInitializer,
hasJSDocNodes,
Expand Down Expand Up @@ -682,6 +683,7 @@ import {
isPartOfTypeQuery,
isPlainJsFile,
isPrefixUnaryExpression,
isPrimitiveLiteralValue,
isPrivateIdentifier,
isPrivateIdentifierClassElementDeclaration,
isPrivateIdentifierPropertyAccessExpression,
Expand Down Expand Up @@ -1005,6 +1007,7 @@ import {
SymbolTable,
SymbolTracker,
SymbolVisibilityResult,
SyntacticTypeNodeBuilderContext,
SyntaxKind,
SyntheticDefaultModuleType,
SyntheticExpression,
Expand Down Expand Up @@ -1100,6 +1103,7 @@ import {
} from "./_namespaces/ts";
import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers";
import * as performance from "./_namespaces/ts.performance";
import { createSyntacticTypeNodeBuilder } from "./expressionToTypeNode";
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated

const ambientModuleSymbolRegex = /^".+"$/;
const anon = "(anonymous)" as __String & string;
Expand Down Expand Up @@ -1481,6 +1485,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
var checkBinaryExpression = createCheckBinaryExpression();
var emitResolver = createResolver();
var nodeBuilder = createNodeBuilder();
var syntacticNodeBuilder = createSyntacticTypeNodeBuilder(compilerOptions);
var evaluate = createEvaluator({
evaluateElementAccessExpression,
evaluateEntityNameExpression,
Expand Down Expand Up @@ -5862,7 +5867,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return meaning;
}

function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult {
function isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node, shouldComputeAliasToMakeVisible = true): SymbolVisibilityResult {
const meaning = getMeaningOfEntityNameReference(entityName);
const firstIdentifier = getFirstIdentifier(entityName);
const symbol = resolveName(enclosingDeclaration, firstIdentifier.escapedText, meaning, /*nameNotFoundMessage*/ undefined, /*isUse*/ false);
Expand All @@ -5874,7 +5879,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

// Verify if the symbol is accessible
return (symbol && hasVisibleDeclarations(symbol, /*shouldComputeAliasToMakeVisible*/ true)) || {
return (symbol && hasVisibleDeclarations(symbol, shouldComputeAliasToMakeVisible)) || {
accessibility: SymbolAccessibility.NotAccessible,
errorSymbolName: getTextOfNode(firstIdentifier),
errorNode: firstIdentifier,
Expand Down Expand Up @@ -5980,9 +5985,27 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return {
typeToTypeNode: (type: Type, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typeToTypeNodeHelper(type, context)),
typePredicateToTypePredicateNode: (typePredicate: TypePredicate, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => typePredicateToTypePredicateNodeHelper(typePredicate, context)),
expressionOrTypeToTypeNode: (expr: Expression | JsxAttributeValue | undefined, type: Type, addUndefined?: boolean, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => expressionOrTypeToTypeNode(context, expr, type, addUndefined)),
serializeTypeForDeclaration: (declaration: Declaration, type: Type, symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => serializeTypeForDeclaration(context, declaration, type, symbol)),
serializeReturnTypeForSignature: (signature: Signature, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => serializeReturnTypeForSignature(context, signature)),
expressionOrTypeToTypeNode: (expr: Expression | JsxAttributeValue | undefined, type: Type, addUndefined?: boolean, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
withContext(enclosingDeclaration, flags, tracker, context => {
if (expr) {
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
syntacticNodeBuilder.serializeTypeOfExpression(expr, context, addUndefined);
}
return expressionOrTypeToTypeNode(context, expr, type, addUndefined);
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
}),
serializeTypeForDeclaration: (declaration: Declaration, type: Type, symbol: Symbol, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
withContext(enclosingDeclaration, flags, tracker, context => {
if (declaration && hasInferredType(declaration)) {
syntacticNodeBuilder.serializeTypeOfDeclaration(declaration, context);
}
return serializeTypeForDeclaration(context, declaration, type, symbol);
}),
serializeReturnTypeForSignature: (signature: Signature, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) =>
withContext(enclosingDeclaration, flags, tracker, context => {
if (signature.declaration) {
syntacticNodeBuilder.serializeReturnTypeForSignature(signature.declaration, context);
}
return serializeReturnTypeForSignature(context, signature);
}),
indexInfoToIndexSignatureDeclaration: (indexInfo: IndexInfo, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => indexInfoToIndexSignatureDeclarationHelper(indexInfo, context, /*typeNode*/ undefined)),
signatureToSignatureDeclaration: (signature: Signature, kind: SignatureDeclaration["kind"], enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => signatureToSignatureDeclarationHelper(signature, kind, context)),
symbolToEntityName: (symbol: Symbol, meaning: SymbolFlags, enclosingDeclaration?: Node, flags?: NodeBuilderFlags, tracker?: SymbolTracker) => withContext(enclosingDeclaration, flags, tracker, context => symbolToName(symbol, context, meaning, /*expectsIdentifier*/ false)),
Expand Down Expand Up @@ -6112,6 +6135,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
approximateLength: 0,
trackedSymbols: undefined,
bundled: !!compilerOptions.outFile && !!enclosingDeclaration && isExternalOrCommonJsModule(getSourceFileOfNode(enclosingDeclaration)),
isEntityNameVisible: (entityName, shouldComputeAliasToMakeVisible) => isEntityNameVisible(entityName, context.enclosingDeclaration!, shouldComputeAliasToMakeVisible),
isExpandoFunctionDeclaration,
isOptionalParameter,
Comment thread
jakebailey marked this conversation as resolved.
Outdated
isLiteralComputedName,
trackComputedName(accessExpression) {
trackComputedName(accessExpression, context.enclosingDeclaration, context);
},
getAllAccessorDeclarations: getAllAccessorDeclarationsForDeclaration,
requiresAddingImplicitUndefined,
isUndefinedIdentifier(node: Identifier) {
return getResolvedSymbol(node) === undefinedSymbol;
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
},
};
context.tracker = new SymbolTrackerImpl(context, tracker, moduleResolverHost);
const resultingNode = cb(context);
Expand Down Expand Up @@ -45593,9 +45628,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
result.value,
/*isSyntacticallyString*/ false,
/*resolvedOtherFiles*/ true,
/*hasExternalReferences*/ true,
);
}
return result;
return evaluatorResult(result.value, result.isSyntacticallyString, result.resolvedOtherFiles, /*hasExternalReferences*/ true);
}
}
return evaluatorResult(/*value*/ undefined);
Expand Down Expand Up @@ -45627,7 +45663,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
error(expr, Diagnostics.A_member_initializer_in_a_enum_declaration_cannot_reference_members_declared_after_it_including_members_defined_in_other_enums);
return evaluatorResult(/*value*/ 0);
}
return getEnumMemberValue(declaration as EnumMember);
const value = getEnumMemberValue(declaration as EnumMember);
if (location.parent !== declaration.parent) {
return evaluatorResult(value.value, value.isSyntacticallyString, value.resolvedOtherFiles, /*hasExternalReferences*/ true);
}
return value;
}

function checkEnumDeclaration(node: EnumDeclaration) {
Expand Down Expand Up @@ -48243,12 +48283,24 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}

function isExpandoFunctionDeclaration(node: Declaration): boolean {
const declaration = getParseTreeNode(node, isFunctionDeclaration);
const declaration = getParseTreeNode(node, (n): n is FunctionDeclaration | VariableDeclaration => isFunctionDeclaration(n) || isVariableDeclaration(n));
if (!declaration) {
return false;
}
const symbol = getSymbolOfDeclaration(declaration);
if (!symbol || !(symbol.flags & SymbolFlags.Function)) {
let symbol: Symbol;
Comment thread
jakebailey marked this conversation as resolved.
Outdated
if (isVariableDeclaration(declaration)) {
if (declaration.type || !isVarConstLike(declaration)) {
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
return false;
}
if (!(declaration.initializer && isFunctionExpressionOrArrowFunction(declaration.initializer))) {
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
return false;
}
symbol = getSymbolOfDeclaration(declaration.initializer);
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
}
else {
symbol = getSymbolOfDeclaration(declaration);
}
if (!symbol || !(symbol.flags & SymbolFlags.Function | SymbolFlags.Variable)) {
return false;
}
return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && isExpandoPropertyDeclaration(p.valueDeclaration));
Expand Down Expand Up @@ -48585,6 +48637,28 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
return false;
}
function isLiteralComputedName(node: ComputedPropertyName) {
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
const expression = node.expression;
if (isPrimitiveLiteralValue(expression, /*includeBigInt*/ false)) {
return true;
}
const type = getTypeOfExpression(expression);
if (!isTypeUsableAsPropertyName(type)) {
return false;
}

// Only identifiers of the for A.B.C can be used
if (!isEntityNameExpression(expression)) {
return false;
}
const symbol = getSymbolAtLocation(expression);
if (!symbol) {
return false;
}
// Ensure not type narrowing
const declaredType = getTypeOfSymbol(symbol);
return declaredType === type;
}

function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression {
const enumResult = type.flags & TypeFlags.EnumLike ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, tracker)
Expand Down Expand Up @@ -48710,6 +48784,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return node && getExternalModuleFileFromDeclaration(node);
},
isLiteralConstDeclaration,
isLiteralComputedName,
isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => {
const node = getParseTreeNode(nodeIn, isDeclaration);
const symbol = node && getSymbolOfDeclaration(node);
Expand Down Expand Up @@ -51022,7 +51097,7 @@ function createBasicNodeBuilderModuleSpecifierResolutionHost(host: TypeCheckerHo
};
}

interface NodeBuilderContext {
interface NodeBuilderContext extends SyntacticTypeNodeBuilderContext {
enclosingDeclaration: Node | undefined;
/**
* `enclosingFile` is generated from the initial `enclosingDeclaration` and
Expand Down Expand Up @@ -51146,4 +51221,10 @@ class SymbolTrackerImpl implements SymbolTracker {
private onDiagnosticReported() {
this.context.reportedDiagnostic = true;
}

reportInferenceFallback(node: Node): void {
if (this.inner?.reportInferenceFallback) {
this.inner.reportInferenceFallback(node);
}
}
}
9 changes: 9 additions & 0 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,15 @@ const commandOptionsWithoutBuild: CommandLineOption[] = [
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,
defaultValueDescription: false,
},
{
name: "isolatedDeclarations",
type: "boolean",
category: Diagnostics.Interop_Constraints,
description: Diagnostics.Ensure_that_each_file_can_have_declaration_emit_generated_without_type_information,
defaultValueDescription: false,
affectsBuildInfo: true,
affectsEmit: true,
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
},

// Strict Type Checks
{
Expand Down
125 changes: 125 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -6227,6 +6227,11 @@
"category": "Message",
"code": 6718
},
"Ensure that each file can have declaration emit generated without type information": {
Comment thread
dragomirtitian marked this conversation as resolved.
Outdated
"category": "Message",
"code": 6719
},

"Default catch clause variables as 'unknown' instead of 'any'.": {
"category": "Message",
"code": 6803
Expand Down Expand Up @@ -6741,6 +6746,126 @@
"category": "Error",
"code": 9006
},
"Function must have an explicit return type annotation with --isolatedDeclarations.": {
"category": "Error",
"code": 9007
},
"Method must have an explicit return type annotation with --isolatedDeclarations.": {
"category": "Error",
"code": 9008
},
"At least one accessor must have an explicit return type annotation with --isolatedDeclarations.": {
"category": "Error",
"code": 9009
},
"Variable must have an explicit type annotation with --isolatedDeclarations.": {
"category": "Error",
"code": 9010
},
"Parameter must have an explicit type annotation with --isolatedDeclarations.": {
"category": "Error",
"code": 9011
},
"Property must have an explicit type annotation with --isolatedDeclarations.": {
"category": "Error",
"code": 9012
},
"Expression type can't be inferred with --isolatedDeclarations.": {
"category": "Error",
"code": 9013
},
"Computed properties must be number or string literals, variables or dotted expressions with --isolatedDeclarations.": {
"category": "Error",
"code": 9014
},
"Objects that contain spread assignments can't be inferred with --isolatedDeclarations.": {
"category": "Error",
"code": 9015
},
"Objects that contain shorthand properties can't be inferred with --isolatedDeclarations.": {
"category": "Error",
"code": 9016
},
"Only const arrays can be inferred with --isolatedDeclarations.": {
"category": "Error",
"code": 9017
},
"Arrays with spread elements can't inferred with --isolatedDeclarations.": {
"category": "Error",
"code": 9018
},
"Binding elements can't be exported directly with --isolatedDeclarations.": {
"category": "Error",
"code": 9019
},
"Enum member initializers must be computable without references to external symbols with --isolatedDeclarations.": {
"category": "Error",
"code": 9020
},
"Extends clause can't contain an expression with --isolatedDeclarations.": {
"category": "Error",
"code": 9021
},
"Inference from class expressions is not supported with --isolatedDeclarations.": {
"category": "Error",
"code": 9022
},
"Assigning properties to functions without declaring them is not supported with --isolatedDeclarations. Add an explicit declaration for the properties assigned to this function.": {
"category": "Error",
"code": 9023
},
"Declaration emit for this parameter requires implicitly adding undefined to it's type. This is not supported with --isolatedDeclarations.": {
"category": "Error",
"code": 9025
},
"Declaration emit for this file requires preserving this import for augmentations. This is not supported with --isolatedDeclarations.": {
"category": "Error",
"code": 9026
},
"Add a type annotation to the variable {0}.": {
"category": "Error",
"code": 9027
},
"Add a type annotation to the parameter {0}.": {
"category": "Error",
"code": 9028
},
"Add a type annotation to the property {0}.": {
"category": "Error",
"code": 9029
},
"Add a return type to the function expression.": {
"category": "Error",
"code": 9030
},
"Add a return type to the function declaration.": {
"category": "Error",
"code": 9031
},
"Add a return type to the get accessor declaration.": {
"category": "Error",
"code": 9032
},
"Add a type to parameter of the set accessor declaration.": {
"category": "Error",
"code": 9033
},
"Add a return type to the method": {
"category": "Error",
"code": 9034
},
"Add a type assertion to this expression to make type type explicit.": {
"category": "Error",
"code": 9035
},
"Move the expression in default export to a variable and add a type annotation to it.": {
"category": "Error",
"code": 9036
},
"Default exports can't be inferred with --isolatedDeclarations.": {
"category": "Error",
"code": 9037
},
"JSX attributes must only be assigned a non-empty 'expression'.": {
"category": "Error",
"code": 17000
Expand Down
1 change: 1 addition & 0 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,7 @@ export const notImplementedResolver: EmitResolver = {
isArgumentsLocalBinding: notImplemented,
getExternalModuleFileFromDeclaration: notImplemented,
isLiteralConstDeclaration: notImplemented,
isLiteralComputedName: notImplemented,
getJsxFactoryEntity: notImplemented,
getJsxFragmentFactoryEntity: notImplemented,
isBindingCapturedByNode: notImplemented,
Expand Down
Loading