fix(codegen): fix some typescript codegen problems (#989)

This commit is contained in:
Boshen 2023-10-13 16:23:48 +08:00 committed by GitHub
parent b9d0d57fa2
commit f32bf27106
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 47 additions and 147 deletions

View file

@ -1049,7 +1049,7 @@ pub enum Declaration<'a> {
impl<'a> Declaration<'a> {
pub fn is_typescript_syntax(&self) -> bool {
match self {
Self::VariableDeclaration(_) => false,
Self::VariableDeclaration(decl) => decl.is_typescript_syntax(),
Self::FunctionDeclaration(func) => func.is_typescript_syntax(),
Self::ClassDeclaration(class) => class.is_declare(),
_ => true,
@ -1069,6 +1069,12 @@ pub struct VariableDeclaration<'a> {
pub modifiers: Modifiers<'a>,
}
impl<'a> VariableDeclaration<'a> {
pub fn is_typescript_syntax(&self) -> bool {
self.modifiers.contains(ModifierKind::Declare)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "lowercase"))]
pub enum VariableDeclarationKind {

View file

@ -10,7 +10,7 @@ use oxc_span::SourceType;
// 2. run `cargo run -p oxc_codegen --example codegen` or `just example codegen`
fn main() {
let name = env::args().nth(1).unwrap_or_else(|| "test.ts".to_string());
let name = env::args().nth(1).unwrap_or_else(|| "test.tsx".to_string());
let path = Path::new(&name);
let source_text = std::fs::read_to_string(path).unwrap_or_else(|_| panic!("{name} not found"));
let source_type = SourceType::from_path(path).unwrap();
@ -25,11 +25,16 @@ fn main() {
return;
}
println!("Original:");
println!("{source_text}");
let codegen_options = CodegenOptions;
let printed = Codegen::<false>::new(source_text.len(), codegen_options).build(&ret.program);
let printed = Codegen::<true>::new(source_text.len(), codegen_options).build(&ret.program);
println!("Printed:");
println!("{printed}");
let ret = Parser::new(&allocator, &printed, source_type).parse();
let printed = Codegen::<false>::new(source_text.len(), codegen_options).build(&ret.program);
println!("{printed}");
let minified = Codegen::<true>::new(source_text.len(), codegen_options).build(&ret.program);
println!("Minified:");
println!("{minified}");
}

View file

@ -65,9 +65,6 @@ fn print_directives_and_statements<const MINIFY: bool>(
p.print_semicolon_if_needed();
stmt.gen(p, ctx);
}
if !MINIFY && !statements.is_empty() {
p.print_semicolon_if_needed();
}
}
impl<const MINIFY: bool> Gen<MINIFY> for Hashbang {
@ -80,9 +77,9 @@ impl<const MINIFY: bool> Gen<MINIFY> for Hashbang {
impl<const MINIFY: bool> Gen<MINIFY> for Directive {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.print_indent();
p.print(b'"');
p.print(b'\'');
p.print_str(self.directive.as_bytes());
p.print(b'"');
p.print(b'\'');
p.print_semicolon();
}
}
@ -114,15 +111,6 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for Statement<'a> {
}
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for Option<Statement<'a>> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
match self {
Some(stmt) => stmt.gen(p, ctx),
None => p.print(b';'),
}
}
}
impl<'a, const MINIFY: bool> Gen<MINIFY> for ExpressionStatement<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.print_indent();
@ -494,7 +482,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ModuleDeclaration<'a> {
Self::ExportAllDeclaration(decl) => decl.gen(p, ctx),
Self::ExportDefaultDeclaration(decl) => decl.gen(p, ctx),
Self::ExportNamedDeclaration(decl) => decl.gen(p, ctx),
_ => {}
_ => p.needs_semicolon = false,
}
}
}
@ -502,19 +490,23 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ModuleDeclaration<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for Declaration<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
match self {
Self::VariableDeclaration(stmt) => {
p.print_indent();
stmt.gen(p, ctx);
p.print_semicolon_after_statement();
Self::VariableDeclaration(decl) => {
if !decl.is_typescript_syntax() {
p.print_indent();
decl.gen(p, ctx);
p.print_semicolon_after_statement();
}
}
Self::FunctionDeclaration(stmt) => {
p.print_indent();
p.print_space_before_identifier();
stmt.gen(p, ctx);
Self::FunctionDeclaration(decl) => {
if !decl.is_typescript_syntax() {
p.print_indent();
p.print_space_before_identifier();
decl.gen(p, ctx);
}
}
Self::ClassDeclaration(declaration) => {
Self::ClassDeclaration(decl) => {
p.print_space_before_identifier();
declaration.gen(p, ctx);
decl.gen(p, ctx);
}
Self::UsingDeclaration(declaration) => {
p.print_space_before_identifier();
@ -738,7 +730,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for ExportNamedDeclaration<'a> {
p.print_str(b"from");
source.gen(p, ctx);
}
p.print_semicolon_after_statement();
p.needs_semicolon = true;
}
}
}
@ -1747,8 +1739,8 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXAttributeName<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXAttribute<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) {
self.name.gen(p, ctx);
p.print(b'=');
if let Some(value) = &self.value {
p.print(b'=');
value.gen(p, ctx);
}
}
@ -1788,7 +1780,9 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXAttributeValue<'a> {
impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXSpreadAttribute<'a> {
fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) {
p.print_str(b"{...");
self.argument.gen_expr(p, Precedence::lowest(), Context::default());
p.print(b'}');
}
}
@ -1806,6 +1800,7 @@ impl<'a, const MINIFY: bool> Gen<MINIFY> for JSXOpeningElement<'a> {
p.print_str(b"<");
self.name.gen(p, ctx);
for attr in &self.attributes {
p.print_hard_space();
attr.gen(p, ctx);
}
if self.self_closing {

View file

@ -88,7 +88,7 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
}
}
// pub fn with_mangler(&mut self, mangler: Mangler) {
// fn with_mangler(&mut self, mangler: Mangler) {
// self.mangler = Some(mangler);
// }
@ -97,7 +97,7 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
self.into_code()
}
fn into_code(self) -> String {
pub fn into_code(self) -> String {
unsafe { String::from_utf8_unchecked(self.code) }
}
@ -129,8 +129,7 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
self.print(b' ');
}
#[inline]
pub fn print_soft_newline(&mut self) {
fn print_soft_newline(&mut self) {
if !MINIFY {
self.print(b'\n');
}
@ -157,21 +156,19 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
unsafe { from_utf8_unchecked(self.code()) }.chars().nth_back(n)
}
#[inline]
pub fn indent(&mut self) {
fn indent(&mut self) {
if !MINIFY {
self.indentation += 1;
}
}
#[inline]
pub fn dedent(&mut self) {
fn dedent(&mut self) {
if !MINIFY {
self.indentation -= 1;
}
}
pub fn print_indent(&mut self) {
fn print_indent(&mut self) {
if !MINIFY {
for _ in 0..self.indentation {
self.print(b'\t');
@ -219,14 +216,12 @@ impl<const MINIFY: bool> Codegen<MINIFY> {
}
}
#[inline]
fn print_block_start(&mut self) {
self.print(b'{');
self.print_soft_newline();
self.indent();
}
#[inline]
fn print_block_end(&mut self) {
self.dedent();
self.print_indent();

View file

@ -1,22 +1,14 @@
codegen_typescript Summary:
AST Parsed : 5063/5063 (100.00%)
Positive Passed: 4867/5063 (96.13%)
Positive Passed: 4968/5063 (98.12%)
Expect to Parse: "compiler/binopAssignmentShouldHaveType.ts"
Expect to Parse: "compiler/callOfConditionalTypeWithConcreteBranches.ts"
Expect to Parse: "compiler/callsOnComplexSignatures.tsx"
Expect to Parse: "compiler/castExpressionParentheses.ts"
Expect to Parse: "compiler/collisionExportsRequireAndInternalModuleAliasInGlobalFile.ts"
Expect to Parse: "compiler/collisionRestParameterFunctionExpressions.ts"
Expect to Parse: "compiler/collisionThisExpressionAndAliasInGlobal.ts"
Expect to Parse: "compiler/commentEmitAtEndOfFile1.ts"
Expect to Parse: "compiler/computedPropertyNameAndTypeParameterConflict.ts"
Expect to Parse: "compiler/conditionalEqualityTestingNullability.ts"
Expect to Parse: "compiler/conditionallyDuplicateOverloadsCausedByOverloadResolution.ts"
Expect to Parse: "compiler/constDeclarations-ambient.ts"
Expect to Parse: "compiler/contextualTypingOfOptionalMembers.tsx"
Expect to Parse: "compiler/commentsemitComments.ts"
Expect to Parse: "compiler/contextualTypingOfTooShortOverloads.ts"
Expect to Parse: "compiler/contextuallyTypedJsxAttribute.ts"
Expect to Parse: "compiler/contextuallyTypedJsxChildren.tsx"
Expect to Parse: "compiler/declarationEmitDestructuringObjectLiteralPattern2.ts"
Expect to Parse: "compiler/declarationEmitNonExportedBindingPattern.ts"
Expect to Parse: "compiler/declarationEmitRetainsJsdocyComments.ts"
@ -24,7 +16,7 @@ Expect to Parse: "compiler/declarationMaps.ts"
Expect to Parse: "compiler/declarationTypecheckNoUseBeforeReferenceCheck.ts"
Expect to Parse: "compiler/declareFileExportAssignment.ts"
Expect to Parse: "compiler/declareFileExportAssignmentWithVarFromVariableStatement.ts"
Expect to Parse: "compiler/discriminatedUnionJsxElement.tsx"
Expect to Parse: "compiler/doNotEmitPinnedCommentOnNotEmittedNode.ts"
Expect to Parse: "compiler/dottedModuleName2.ts"
Expect to Parse: "compiler/downlevelLetConst13.ts"
Expect to Parse: "compiler/duplicateVarAndImport.ts"
@ -42,73 +34,38 @@ Expect to Parse: "compiler/exportAsNamespace.d.ts"
Expect to Parse: "compiler/exportAssignValueAndType.ts"
Expect to Parse: "compiler/exportAssignmentWithPrivacyError.ts"
Expect to Parse: "compiler/exportAssignmentWithoutIdentifier1.ts"
Expect to Parse: "compiler/exportDefaultVariable.ts"
Expect to Parse: "compiler/exportEqualNamespaces.ts"
Expect to Parse: "compiler/functionReturnTypeQuery.ts"
Expect to Parse: "compiler/genericInferenceDefaultTypeParameterJsxReact.tsx"
Expect to Parse: "compiler/genericOverloadSignatures.ts"
Expect to Parse: "compiler/identityRelationNeverTypes.ts"
Expect to Parse: "compiler/indexingTypesWithNever.ts"
Expect to Parse: "compiler/inferenceErasedSignatures.ts"
Expect to Parse: "compiler/innerOverloads.ts"
Expect to Parse: "compiler/interfaceWithCommaSeparators.ts"
Expect to Parse: "compiler/jsxCallbackWithDestructuring.tsx"
Expect to Parse: "compiler/jsxComplexSignatureHasApplicabilityError.tsx"
Expect to Parse: "compiler/jsxElementClassTooManyParams.tsx"
Expect to Parse: "compiler/jsxEmitAttributeWithPreserve.tsx"
Expect to Parse: "compiler/jsxFragmentFactoryNoUnusedLocals.tsx"
Expect to Parse: "compiler/jsxGenericComponentWithSpreadingResultOfGenericFunction.tsx"
Expect to Parse: "compiler/jsxHasLiteralType.tsx"
Expect to Parse: "compiler/jsxInferenceProducesLiteralAsExpected.tsx"
Expect to Parse: "compiler/jsxIntrinsicElementsCompatability.tsx"
Expect to Parse: "compiler/jsxIntrinsicUnions.tsx"
Expect to Parse: "compiler/jsxLibraryManagedAttributesUnusedGeneric.tsx"
Expect to Parse: "compiler/jsxMultilineAttributeStringValues.tsx"
Expect to Parse: "compiler/jsxMultilineAttributeValuesReact.tsx"
Expect to Parse: "compiler/jsxNamespacedNameNotComparedToNonMatchingIndexSignature.tsx"
Expect to Parse: "compiler/jsxPartialSpread.tsx"
Expect to Parse: "compiler/jsxPropsAsIdentifierNames.tsx"
Expect to Parse: "compiler/jsxSpreadFirstUnionNoErrors.tsx"
Expect to Parse: "compiler/jsxSpreadTag.ts"
Expect to Parse: "compiler/keyofObjectWithGlobalSymbolIncluded.ts"
Expect to Parse: "compiler/keywordInJsxIdentifier.tsx"
Expect to Parse: "compiler/localClassesInLoop.ts"
Expect to Parse: "compiler/localClassesInLoop_ES6.ts"
Expect to Parse: "compiler/moduleVariables.ts"
Expect to Parse: "compiler/module_augmentUninstantiatedModule2.ts"
Expect to Parse: "compiler/numericIndexerConstraint3.ts"
Expect to Parse: "compiler/objectAssignLikeNonUnionResult.ts"
Expect to Parse: "compiler/overloadCallTest.ts"
Expect to Parse: "compiler/parseJsxExtends1.ts"
Expect to Parse: "compiler/privacyCheckAnonymousFunctionParameter.ts"
Expect to Parse: "compiler/privacyCheckAnonymousFunctionParameter2.ts"
Expect to Parse: "compiler/privacyCheckExportAssignmentOnExportedGenericInterface1.ts"
Expect to Parse: "compiler/privacyImport.ts"
Expect to Parse: "compiler/reactHOCSpreadprops.tsx"
Expect to Parse: "compiler/reactNamespaceJSXEmit.tsx"
Expect to Parse: "compiler/reactReadonlyHOCAssignabilityReal.tsx"
Expect to Parse: "compiler/reactTagNameComponentWithPropsNoOOM.tsx"
Expect to Parse: "compiler/reactTagNameComponentWithPropsNoOOM2.tsx"
Expect to Parse: "compiler/reducibleIndexedAccessTypes.ts"
Expect to Parse: "compiler/staticAnonymousTypeNotReferencingTypeParameter.ts"
Expect to Parse: "compiler/styledComponentsInstantiaionLimitNotReached.ts"
Expect to Parse: "compiler/templateLiteralIntersection.ts"
Expect to Parse: "compiler/tsxAttributeQuickinfoTypesSameAsObjectLiteral.tsx"
Expect to Parse: "compiler/tsxDiscriminantPropertyInference.tsx"
Expect to Parse: "compiler/tsxInferenceShouldNotYieldAnyOnUnions.tsx"
Expect to Parse: "compiler/tsxSpreadDoesNotReportExcessProps.tsx"
Expect to Parse: "compiler/tsxUnionMemberChecksFilterDataProps.tsx"
Expect to Parse: "compiler/typeAliasDeclarationEmit3.ts"
Expect to Parse: "compiler/typeInferenceWithExcessPropertiesJsx.tsx"
Expect to Parse: "conformance/ambient/ambientDeclarations.ts"
Expect to Parse: "conformance/ambient/ambientInsideNonAmbientExternalModule.ts"
Expect to Parse: "conformance/classes/classExpression.ts"
Expect to Parse: "conformance/classes/propertyMemberDeclarations/staticPropertyNameConflicts.ts"
Expect to Parse: "conformance/constEnums/constEnum4.ts"
Expect to Parse: "conformance/decorators/legacyDecorators-contextualTypes.ts"
Expect to Parse: "conformance/es6/Symbols/symbolProperty55.ts"
Expect to Parse: "conformance/es6/Symbols/symbolProperty56.ts"
Expect to Parse: "conformance/es6/Symbols/symbolProperty60.ts"
Expect to Parse: "conformance/es6/yieldExpressions/generatorTypeCheck59.ts"
Expect to Parse: "conformance/es6/yieldExpressions/generatorTypeCheck61.ts"
Expect to Parse: "conformance/esDecorators/esDecorators-contextualTypes.ts"
@ -126,65 +83,10 @@ Expect to Parse: "conformance/interfaces/declarationMerging/twoMergedInterfacesW
Expect to Parse: "conformance/interfaces/interfaceDeclarations/asiPreventsParsingAsInterface03.ts"
Expect to Parse: "conformance/internalModules/moduleDeclarations/asiPreventsParsingAsNamespace03.ts"
Expect to Parse: "conformance/internalModules/moduleDeclarations/nonInstantiatedModule.ts"
Expect to Parse: "conformance/jsx/checkJsxChildrenProperty1.tsx"
Expect to Parse: "conformance/jsx/checkJsxChildrenProperty12.tsx"
Expect to Parse: "conformance/jsx/checkJsxChildrenProperty16.tsx"
Expect to Parse: "conformance/jsx/checkJsxChildrenProperty6.tsx"
Expect to Parse: "conformance/jsx/checkJsxChildrenProperty8.tsx"
Expect to Parse: "conformance/jsx/checkJsxIntersectionElementPropsType.tsx"
Expect to Parse: "conformance/jsx/checkJsxSubtleSkipContextSensitiveBug.tsx"
Expect to Parse: "conformance/jsx/checkJsxUnionSFXContextualTypeInferredCorrectly.tsx"
Expect to Parse: "conformance/jsx/jsxReactTestSuite.tsx"
Expect to Parse: "conformance/jsx/jsxs/jsxJsxsCjsTransformKeyProp.tsx"
Expect to Parse: "conformance/jsx/jsxs/jsxJsxsCjsTransformNestedSelfClosingChild.tsx"
Expect to Parse: "conformance/jsx/tsxAttributeResolution16.tsx"
Expect to Parse: "conformance/jsx/tsxDefaultAttributesResolution1.tsx"
Expect to Parse: "conformance/jsx/tsxDefaultAttributesResolution2.tsx"
Expect to Parse: "conformance/jsx/tsxElementResolution.tsx"
Expect to Parse: "conformance/jsx/tsxElementResolution13.tsx"
Expect to Parse: "conformance/jsx/tsxElementResolution14.tsx"
Expect to Parse: "conformance/jsx/tsxElementResolution5.tsx"
Expect to Parse: "conformance/jsx/tsxEmit1.tsx"
Expect to Parse: "conformance/jsx/tsxEmit2.tsx"
Expect to Parse: "conformance/jsx/tsxEmitSpreadAttribute.ts"
Expect to Parse: "conformance/jsx/tsxGenericAttributesType1.tsx"
Expect to Parse: "conformance/jsx/tsxGenericAttributesType2.tsx"
Expect to Parse: "conformance/jsx/tsxGenericAttributesType3.tsx"
Expect to Parse: "conformance/jsx/tsxGenericAttributesType4.tsx"
Expect to Parse: "conformance/jsx/tsxGenericAttributesType5.tsx"
Expect to Parse: "conformance/jsx/tsxGenericAttributesType6.tsx"
Expect to Parse: "conformance/jsx/tsxGenericAttributesType7.tsx"
Expect to Parse: "conformance/jsx/tsxGenericAttributesType9.tsx"
Expect to Parse: "conformance/jsx/tsxInArrowFunction.tsx"
Expect to Parse: "conformance/jsx/tsxNamespacedAttributeName1.tsx"
Expect to Parse: "conformance/jsx/tsxNamespacedAttributeName2.tsx"
Expect to Parse: "conformance/jsx/tsxReactComponentWithDefaultTypeParameter1.tsx"
Expect to Parse: "conformance/jsx/tsxReactComponentWithDefaultTypeParameter2.tsx"
Expect to Parse: "conformance/jsx/tsxReactEmit1.tsx"
Expect to Parse: "conformance/jsx/tsxReactEmit2.tsx"
Expect to Parse: "conformance/jsx/tsxReactEmit8.tsx"
Expect to Parse: "conformance/jsx/tsxReactEmitEntities.tsx"
Expect to Parse: "conformance/jsx/tsxReactEmitNesting.tsx"
Expect to Parse: "conformance/jsx/tsxReactEmitSpreadAttribute.ts"
Expect to Parse: "conformance/jsx/tsxSpreadAttributesResolution11.tsx"
Expect to Parse: "conformance/jsx/tsxSpreadAttributesResolution13.tsx"
Expect to Parse: "conformance/jsx/tsxSpreadAttributesResolution15.tsx"
Expect to Parse: "conformance/jsx/tsxSpreadAttributesResolution3.tsx"
Expect to Parse: "conformance/jsx/tsxSpreadAttributesResolution8.tsx"
Expect to Parse: "conformance/jsx/tsxSpreadAttributesResolution9.tsx"
Expect to Parse: "conformance/jsx/tsxSpreadChildren.tsx"
Expect to Parse: "conformance/jsx/tsxSpreadChildrenInvalidType.tsx"
Expect to Parse: "conformance/jsx/tsxStatelessFunctionComponentOverload2.tsx"
Expect to Parse: "conformance/jsx/tsxStatelessFunctionComponentOverload3.tsx"
Expect to Parse: "conformance/jsx/tsxStatelessFunctionComponentOverload6.tsx"
Expect to Parse: "conformance/jsx/tsxStatelessFunctionComponentWithDefaultTypeParameter1.tsx"
Expect to Parse: "conformance/jsx/tsxStatelessFunctionComponentsWithTypeArguments1.tsx"
Expect to Parse: "conformance/jsx/tsxStatelessFunctionComponentsWithTypeArguments3.tsx"
Expect to Parse: "conformance/jsx/tsxStatelessFunctionComponentsWithTypeArguments5.tsx"
Expect to Parse: "conformance/jsx/tsxTypeErrors.tsx"
Expect to Parse: "conformance/jsx/tsxUnionElementType5.tsx"
Expect to Parse: "conformance/jsx/tsxUnionTypeComponent1.tsx"
Expect to Parse: "conformance/jsx/unicodeEscapesInJsxtags.tsx"
Expect to Parse: "conformance/types/namedTypes/optionalMethods.ts"
Expect to Parse: "conformance/types/rest/genericRestParameters2.ts"
Expect to Parse: "conformance/types/stringLiteral/stringLiteralTypesOverloads01.ts"
@ -193,7 +95,4 @@ Expect to Parse: "conformance/types/thisType/inferThisType.ts"
Expect to Parse: "conformance/types/thisType/thisTypeInFunctions4.ts"
Expect to Parse: "conformance/types/typeAliases/asiPreventsParsingAsTypeAlias02.ts"
Expect to Parse: "conformance/types/typeAliases/circularTypeAliasForUnionWithInterface.ts"
Expect to Parse: "conformance/types/typeRelationships/recursiveTypes/recursiveTypesUsedAsFunctionParameters.ts"
Expect to Parse: "conformance/types/typeRelationships/subtypesAndSuperTypes/subtypingWithObjectMembersOptionality.ts"
Expect to Parse: "conformance/types/typeRelationships/typeAndMemberIdentity/typeParametersAreIdenticalToThemselves.ts"
Expect to Parse: "conformance/types/typeRelationships/typeInference/intraExpressionInferencesJsx.tsx"