Skip to content

TSC in isolated declaration will still use the type checker to print types #129

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
25 changes: 2 additions & 23 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,6 @@ import {
isAssignmentTarget,
isAutoAccessorPropertyDeclaration,
isAwaitExpression,
isBigIntLiteral,
isBinaryExpression,
isBindableObjectDefinePropertyCall,
isBindableStaticElementAccessExpression,
Expand Down Expand Up @@ -678,6 +677,7 @@ import {
isPartOfTypeQuery,
isPlainJsFile,
isPrefixUnaryExpression,
isPrimitiveLiteralValue,
isPrivateIdentifier,
isPrivateIdentifierClassElementDeclaration,
isPrivateIdentifierPropertyAccessExpression,
Expand Down Expand Up @@ -721,7 +721,6 @@ import {
isSuperCall,
isSuperProperty,
isTaggedTemplateExpression,
isTemplateExpression,
isTemplateSpan,
isThisContainerOrFunctionBlock,
isThisIdentifier,
Expand Down Expand Up @@ -47885,26 +47884,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
return undefined;
}

function isPrimitiveLiteralValue(node: Expression): boolean {
if (isNumericLiteral(node) || isBigIntLiteral(node) || isStringLiteralLike(node)) return true;

if (node.kind === SyntaxKind.TrueKeyword || node.kind === SyntaxKind.FalseKeyword) return true;

if (isPrefixUnaryExpression(node)) {
const operand = node.operand;
if (node.operator === SyntaxKind.MinusToken) {
return isNumericLiteral(operand) || isBigIntLiteral(operand);
}
if (node.operator === SyntaxKind.PlusToken) {
return isNumericLiteral(operand);
}
}
if (isTemplateExpression(node)) {
return node.templateSpans.every(t => isPrimitiveLiteralValue(t.expression));
}
return false;
}

function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean {
if (isDeclarationReadonly(node) || (isVariableDeclaration(node) && isVarConstLike(node)) || isEnumMember(node)) {
if (compilerOptions.isolatedDeclarations) {
Expand All @@ -47916,7 +47895,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function isLiteralComputedName(node: ComputedPropertyName) {
const expression = node.expression;
if (isPrimitiveLiteralValue(expression)) {
if (isPrimitiveLiteralValue(expression, /*includeBigInt*/ false)) {
return true;
}
const type = getTypeOfExpression(expression);
Expand Down
78 changes: 57 additions & 21 deletions src/compiler/transformers/declarations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ const declarationEmitNodeBuilderFlags = NodeBuilderFlags.MultilineObjectLiterals
*
* @internal
*/
export function transformDeclarations(context: TransformationContext) {
export function transformDeclarations(context: TransformationContext, _useTscEmit = true) {
const throwDiagnostic = () => Debug.fail("Diagnostic emitted without context");
let getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic = throwDiagnostic;
let needsDeclare = true;
Expand All @@ -318,20 +318,30 @@ export function transformDeclarations(context: TransformationContext) {
let refs: Map<NodeId, SourceFile>;
let libs: Map<string, boolean>;
let emittedImports: readonly AnyImportSyntax[] | undefined; // must be declared in container so it can be `undefined` while transformer's first pass
const { localInferenceResolver, isolatedDeclarations, host, resolver, symbolTracker, ensureNoInitializer } = createTransformerServices();
const { localInferenceResolver, isolatedDeclarations, host, resolver, symbolTracker, ensureNoInitializer, useTscEmit } = createTransformerServices();
const options = context.getCompilerOptions();
const { noResolve, stripInternal } = options;
return transformRoot;

function createTransformerServices(): {
isolatedDeclarations: true;
useTscEmit: false;
resolver: IsolatedEmitResolver;
localInferenceResolver: LocalInferenceResolver;
host: undefined;
symbolTracker: undefined;
ensureNoInitializer: (node: CanHaveLiteralInitializer) => Expression | undefined;
} | {
isolatedDeclarations: true;
useTscEmit: true;
resolver: EmitResolver;
localInferenceResolver: LocalInferenceResolver;
host: EmitHost;
symbolTracker: SymbolTracker;
ensureNoInitializer: (node: CanHaveLiteralInitializer) => Expression | undefined;
} | {
isolatedDeclarations: false;
useTscEmit: false;
resolver: EmitResolver;
localInferenceResolver: undefined;
host: EmitHost;
Expand All @@ -353,30 +363,53 @@ export function transformDeclarations(context: TransformationContext) {
});

if (isolatedDeclarations) {
const resolver: IsolatedEmitResolver = context.getEmitResolver();
// Ideally nothing should require the symbol tracker in isolated declarations mode.
// createLiteralConstValue is teh one exception
const emptySymbolTracker = {};
return {
isolatedDeclarations,
resolver,
localInferenceResolver,
symbolTracker: undefined,
host: undefined,
ensureNoInitializer: (node: CanHaveLiteralInitializer) => {
if (shouldPrintWithInitializer(node)) {
return resolver.createLiteralConstValue(getParseTreeNode(node) as CanHaveLiteralInitializer, emptySymbolTracker); // TODO: Make safe
}
return undefined;
},
};
if (!_useTscEmit) {
const resolver: IsolatedEmitResolver = context.getEmitResolver();
// Ideally nothing should require the symbol tracker in isolated declarations mode.
// createLiteralConstValue is the one exception
const emptySymbolTracker = {};
return {
isolatedDeclarations,
useTscEmit: false,
resolver,
localInferenceResolver,
symbolTracker: undefined,
host: undefined,
ensureNoInitializer: (node: CanHaveLiteralInitializer) => {
if (shouldPrintWithInitializer(node)) {
return resolver.createLiteralConstValue(getParseTreeNode(node) as CanHaveLiteralInitializer, emptySymbolTracker); // TODO: Make safe
}
return undefined;
},
};
}
else {
const host = context.getEmitHost();
const resolver: EmitResolver = context.getEmitResolver();
const symbolTracker = createSymbolTracker(resolver, host);
return {
isolatedDeclarations,
useTscEmit: true,
resolver,
localInferenceResolver,
symbolTracker,
host,
ensureNoInitializer: (node: CanHaveLiteralInitializer) => {
if (shouldPrintWithInitializer(node)) {
return resolver.createLiteralConstValue(getParseTreeNode(node) as CanHaveLiteralInitializer, symbolTracker); // TODO: Make safe
}
return undefined;
},
};
}
}
else {
const host = context.getEmitHost();
const resolver = context.getEmitResolver();
const symbolTracker: SymbolTracker = createSymbolTracker(resolver, host);
return {
isolatedDeclarations,
useTscEmit: false,
localInferenceResolver,
resolver,
symbolTracker,
Expand Down Expand Up @@ -918,7 +951,10 @@ export function transformDeclarations(context: TransformationContext) {
return;
}
if (isolatedDeclarations) {
return localInferenceResolver.fromInitializer(node, type, currentSourceFile);
const { typeNode, isInvalid } = localInferenceResolver.fromInitializer(node, type, currentSourceFile);
if (!useTscEmit || isInvalid) {
return typeNode;
}
}
const shouldUseResolverType = node.kind === SyntaxKind.Parameter &&
(resolver.isRequiredInitializedParameter(node) ||
Expand Down Expand Up @@ -1571,7 +1607,7 @@ export function transformDeclarations(context: TransformationContext) {
});
errorFallbackNode = input;
const type = isolatedDeclarations ?
localInferenceResolver.fromInitializer(input, /*type*/ undefined, currentSourceFile) :
localInferenceResolver.fromInitializer(input, /*type*/ undefined, currentSourceFile).typeNode :
resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker);
const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, type, /*initializer*/ undefined);
errorFallbackNode = undefined;
Expand Down
Loading