-
Notifications
You must be signed in to change notification settings - Fork 14
Improve declaration emit type safety. #124
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
Changes from 2 commits
211b056
97161e0
c45ffaf
a3a5049
202d522
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,11 +4,13 @@ import { | |
Bundle, | ||
chainBundle, | ||
CompilerOptions, | ||
CoreEmitResolver, | ||
createEmitHelperFactory, | ||
CustomTransformer, | ||
CustomTransformerFactory, | ||
CustomTransformers, | ||
Debug, | ||
Diagnostic, | ||
DiagnosticWithLocation, | ||
disposeEmitNodes, | ||
EmitFlags, | ||
|
@@ -30,6 +32,7 @@ import { | |
getUseDefineForClassFields, | ||
Identifier, | ||
isBundle, | ||
IsolatedTransformationContext, | ||
isSourceFile, | ||
LexicalEnvironmentFlags, | ||
map, | ||
|
@@ -40,6 +43,7 @@ import { | |
NodeFlags, | ||
noop, | ||
notImplemented, | ||
NullTransformationContext, | ||
returnUndefined, | ||
ScriptTarget, | ||
setEmitFlags, | ||
|
@@ -49,6 +53,7 @@ import { | |
SyntaxKind, | ||
tracing, | ||
TransformationContext, | ||
TransformationContextKind, | ||
TransformationResult, | ||
transformClassFields, | ||
transformDeclarations, | ||
|
@@ -267,6 +272,7 @@ export function transformNodes<T extends Node>(resolver: EmitResolver | undefine | |
// The transformation context is provided to each transformer as part of transformer | ||
// initialization. | ||
const context: TransformationContext = { | ||
kind: TransformationContextKind.FullContext, | ||
factory, | ||
getCompilerOptions: () => options, | ||
getEmitResolver: () => resolver!, // TODO: GH#18217 | ||
|
@@ -662,33 +668,51 @@ export function transformNodes<T extends Node>(resolver: EmitResolver | undefine | |
} | ||
} | ||
} | ||
|
||
/** @internal */ | ||
export const nullTransformationContext: TransformationContext = { | ||
factory: factory, // eslint-disable-line object-shorthand | ||
getCompilerOptions: () => ({}), | ||
getEmitResolver: notImplemented, | ||
getEmitHost: notImplemented, | ||
getEmitHelperFactory: notImplemented, | ||
startLexicalEnvironment: noop, | ||
resumeLexicalEnvironment: noop, | ||
suspendLexicalEnvironment: noop, | ||
endLexicalEnvironment: returnUndefined, | ||
setLexicalEnvironmentFlags: noop, | ||
getLexicalEnvironmentFlags: () => 0, | ||
hoistVariableDeclaration: noop, | ||
hoistFunctionDeclaration: noop, | ||
addInitializationStatement: noop, | ||
startBlockScope: noop, | ||
endBlockScope: returnUndefined, | ||
addBlockScopedVariable: noop, | ||
requestEmitHelper: noop, | ||
readEmitHelpers: notImplemented, | ||
enableSubstitution: noop, | ||
enableEmitNotification: noop, | ||
isSubstitutionEnabled: notImplemented, | ||
isEmitNotificationEnabled: notImplemented, | ||
onSubstituteNode: noEmitSubstitution, | ||
onEmitNode: noEmitNotification, | ||
addDiagnostic: noop, | ||
}; | ||
export function createTransformationContext(kind: TransformationContextKind.NullContext): NullTransformationContext; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The overload seems a bit overcomplicated since we'll only ever create one |
||
/** @internal */ | ||
export function createTransformationContext( | ||
kind: TransformationContextKind.IsolatedContext, | ||
options: CompilerOptions, | ||
diagnostics: Diagnostic[], | ||
resolver: CoreEmitResolver, | ||
): IsolatedTransformationContext; | ||
export function createTransformationContext( | ||
kind: TransformationContextKind.IsolatedContext | TransformationContextKind.NullContext, | ||
options: CompilerOptions = {}, | ||
diagnostics?: Diagnostic[], | ||
resolver?: EmitResolver | CoreEmitResolver, | ||
host?: EmitHost, | ||
): NullTransformationContext | IsolatedTransformationContext | TransformationContext { | ||
return { | ||
kind, | ||
factory: factory, // eslint-disable-line object-shorthand | ||
getCompilerOptions: () => options, | ||
getEmitResolver: !resolver ? notImplemented : () => resolver, | ||
getEmitHost: !host ? notImplemented : () => host, | ||
getEmitHelperFactory: notImplemented, | ||
startLexicalEnvironment: noop, | ||
resumeLexicalEnvironment: noop, | ||
suspendLexicalEnvironment: noop, | ||
endLexicalEnvironment: returnUndefined, | ||
setLexicalEnvironmentFlags: noop, | ||
getLexicalEnvironmentFlags: () => 0, | ||
hoistVariableDeclaration: noop, | ||
hoistFunctionDeclaration: noop, | ||
addInitializationStatement: noop, | ||
startBlockScope: noop, | ||
endBlockScope: returnUndefined, | ||
addBlockScopedVariable: noop, | ||
requestEmitHelper: noop, | ||
readEmitHelpers: notImplemented, | ||
enableSubstitution: noop, | ||
enableEmitNotification: noop, | ||
isSubstitutionEnabled: notImplemented, | ||
isEmitNotificationEnabled: notImplemented, | ||
onSubstituteNode: noEmitSubstitution, | ||
onEmitNode: noEmitNotification, | ||
addDiagnostic: !diagnostics ? noop : (diag: Diagnostic) => diagnostics.push(diag), | ||
}; | ||
} | ||
/** @internal */ | ||
export const nullTransformationContext: NullTransformationContext = createTransformationContext(TransformationContextKind.NullContext); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing these results in a different shape than a normal transformation context, which is observable to the runtime during normal compilation since the null context is used by the command line compiler. I'd prefer we keep these in for the null context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since some of the removed members throw an exception at runtime, I would not expose them on the
NullTransformationContext
type. If someone somewhere is actually using thenullTransformationContext
as a full transformation context I kept thenullTransformationContext
to have the same runtime members but hid it behind the more restrictiveNullTransformationContext
Or did you have in mind that the
NullTransformationContext
type is more similar to a fullTransformationContext
. I don't particularly like that idea since some of them throw runtime exceptions so ideally the type system should not let you access those members.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NullTransformationContext
has always just been a normalTransformationContext
with the features that depended on a type checker or program disabled. Having the shape remain stable avoids V8 recompiling large chunks of tsc.js because the checker sees one shape when it creates synthetic nodes when producing diagnostics viatypeToTypeNode
and another shape when it sees a full checker when doing emit.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we want the type to follow the shape but limit access, we could always define a
NullTransformationContext
type that makes the return types of those methodsnever
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rbuckton I changed
NullTransformationContext
to have the same shape asTransformationContext
(just the not implemented methods return never)