From 66dacb331aae8468f0f2864184cd6f240e813895 Mon Sep 17 00:00:00 2001 From: "Marc J. Schmidt" Date: Fri, 27 May 2022 02:05:02 +0200 Subject: [PATCH] use smart pointer in node struct, start with parser --- src/CMakeLists.txt | 2 +- src/core.h | 27 ++ src/node_test.h | 872 +++++++++++++++++---------------- src/parser2.h | 642 ++++++++++++------------- src/path.h | 39 ++ src/tests/test_core.cpp | 312 +++++++----- src/types.cpp | 16 +- src/types.h | 1012 ++++++++++++++++++++------------------- src/utilities.h | 232 +++++---- 9 files changed, 1690 insertions(+), 1464 deletions(-) create mode 100644 src/path.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cd0b5f1..4f8f55c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -6,5 +6,5 @@ add_definitions(-DTRACY_ENABLE) add_subdirectory(tests) #add_library(typescript parser.cpp scanner.cpp utf.cpp syntax_cursor.cpp syntax_cursor.h ast.h parser2.h) -add_library(typescript scanner.cpp utf.cpp syntax_cursor.cpp syntax_cursor.h ast.h parser2.h types.cpp factory.h node_test.h) +add_library(typescript scanner.cpp utf.cpp syntax_cursor.cpp syntax_cursor.h ast.h parser2.h types.cpp factory.h node_test.h path.h) #add_library(typescript scanner.cpp utf.cpp syntax_cursor.cpp syntax_cursor.h ast.h) \ No newline at end of file diff --git a/src/core.h b/src/core.h index 2718097..67e18e0 100644 --- a/src/core.h +++ b/src/core.h @@ -10,6 +10,33 @@ namespace ts { using namespace std; + unsigned constexpr const_hash(char const *input) { + return *input ? + static_cast(*input) + 33 * const_hash(input + 1) : + 5381; + } + + unsigned constexpr const_hash(const string &input) { + return const_hash(input.c_str()); + } + + constexpr unsigned operator "" _hash(const char *s, size_t) { + return const_hash(s); + } + + /** + * shared_ptr has optional semantic already built-in, so we use it instead of std::optional, + * but instead of using shared_ptr directly, we use opt to make it clear that it can be empty. + */ + template + using sharedOpt = shared_ptr; + + /** + * Because shared_ptr is ugly. + */ + template + using shared = shared_ptr; + // // template // using Optional = optional>; diff --git a/src/node_test.h b/src/node_test.h index 87c5270..e53f3aa 100644 --- a/src/node_test.h +++ b/src/node_test.h @@ -5,765 +5,761 @@ namespace ts { // Literals - bool isNumericLiteral(Node &node) { - return node.kind == SyntaxKind::NumericLiteral; + bool isNumericLiteral(const shared &node) { + return node->kind == SyntaxKind::NumericLiteral; } - bool isBigIntLiteral(Node &node) { - return node.kind == SyntaxKind::BigIntLiteral; + bool isBigIntLiteral(const shared &node) { + return node->kind == SyntaxKind::BigIntLiteral; } - bool isStringLiteral(Node &node) { - return node.kind == SyntaxKind::StringLiteral; + bool isStringLiteral(const shared &node) { + return node->kind == SyntaxKind::StringLiteral; } - bool isJsxText(Node &node) { - return node.kind == SyntaxKind::JsxText; + bool isJsxText(const shared &node) { + return node->kind == SyntaxKind::JsxText; } - bool isRegularExpressionLiteral(Node &node) { - return node.kind == SyntaxKind::RegularExpressionLiteral; + bool isRegularExpressionLiteral(const shared &node) { + return node->kind == SyntaxKind::RegularExpressionLiteral; } - bool isNoSubstitutionTemplateLiteral(Node &node) { - return node.kind == SyntaxKind::NoSubstitutionTemplateLiteral; + bool isNoSubstitutionTemplateLiteral(const shared &node) { + return node->kind == SyntaxKind::NoSubstitutionTemplateLiteral; } // Pseudo-literals - bool isTemplateHead(Node &node) { - return node.kind == SyntaxKind::TemplateHead; + bool isTemplateHead(const shared &node) { + return node->kind == SyntaxKind::TemplateHead; } - bool isTemplateMiddle(Node &node) { - return node.kind == SyntaxKind::TemplateMiddle; + bool isTemplateMiddle(const shared &node) { + return node->kind == SyntaxKind::TemplateMiddle; } - bool isTemplateTail(Node &node) { - return node.kind == SyntaxKind::TemplateTail; + bool isTemplateTail(const shared &node) { + return node->kind == SyntaxKind::TemplateTail; } // Punctuation - bool isDotDotDotToken(Node &node) { - return node.kind == SyntaxKind::DotDotDotToken; + bool isDotDotDotToken(const shared &node) { + return node->kind == SyntaxKind::DotDotDotToken; } /*@internal*/ - bool isCommaToken(Node &node) { - return node.kind == SyntaxKind::CommaToken; + bool isCommaToken(const shared &node) { + return node->kind == SyntaxKind::CommaToken; } - bool isPlusToken(Node &node) { - return node.kind == SyntaxKind::PlusToken; + bool isPlusToken(const shared &node) { + return node->kind == SyntaxKind::PlusToken; } - bool isMinusToken(Node &node) { - return node.kind == SyntaxKind::MinusToken; + bool isMinusToken(const shared &node) { + return node->kind == SyntaxKind::MinusToken; } - bool isAsteriskToken(Node &node) { - return node.kind == SyntaxKind::AsteriskToken; + bool isAsteriskToken(const shared &node) { + return node->kind == SyntaxKind::AsteriskToken; } /*@internal*/ - bool isExclamationToken(Node &node) { - return node.kind == SyntaxKind::ExclamationToken; + bool isExclamationToken(const shared &node) { + return node->kind == SyntaxKind::ExclamationToken; } /*@internal*/ - bool isQuestionToken(Node &node) { - return node.kind == SyntaxKind::QuestionToken; + bool isQuestionToken(const shared &node) { + return node->kind == SyntaxKind::QuestionToken; } /*@internal*/ - bool isColonToken(Node &node) { - return node.kind == SyntaxKind::ColonToken; + bool isColonToken(const shared &node) { + return node->kind == SyntaxKind::ColonToken; } /*@internal*/ - bool isQuestionDotToken(Node &node) { - return node.kind == SyntaxKind::QuestionDotToken; + bool isQuestionDotToken(const shared &node) { + return node->kind == SyntaxKind::QuestionDotToken; } /*@internal*/ - bool isEqualsGreaterThanToken(Node &node) { - return node.kind == SyntaxKind::EqualsGreaterThanToken; + bool isEqualsGreaterThanToken(const shared &node) { + return node->kind == SyntaxKind::EqualsGreaterThanToken; } // Identifiers - bool isIdentifier(Node &node) { - return node.kind == SyntaxKind::Identifier; + bool isIdentifier(const shared &node) { + return node->kind == SyntaxKind::Identifier; } - bool isPrivateIdentifier(Node &node) { - return node.kind == SyntaxKind::PrivateIdentifier; + bool isPrivateIdentifier(const shared &node) { + return node->kind == SyntaxKind::PrivateIdentifier; } // Reserved Words /* @internal */ - bool isExportModifier(Node &node) { - return node.kind == SyntaxKind::ExportKeyword; + bool isExportModifier(const shared &node) { + return node->kind == SyntaxKind::ExportKeyword; } /* @internal */ - bool isAsyncModifier(Node &node) { - return node.kind == SyntaxKind::AsyncKeyword; + bool isAsyncModifier(const shared &node) { + return node->kind == SyntaxKind::AsyncKeyword; } /* @internal */ - bool isAssertsKeyword(Node &node) { - return node.kind == SyntaxKind::AssertsKeyword; + bool isAssertsKeyword(const shared &node) { + return node->kind == SyntaxKind::AssertsKeyword; } /* @internal */ - bool isAwaitKeyword(Node &node) { - return node.kind == SyntaxKind::AwaitKeyword; + bool isAwaitKeyword(const shared &node) { + return node->kind == SyntaxKind::AwaitKeyword; } /* @internal */ - bool isReadonlyKeyword(Node &node) { - return node.kind == SyntaxKind::ReadonlyKeyword; + bool isReadonlyKeyword(const shared &node) { + return node->kind == SyntaxKind::ReadonlyKeyword; } /* @internal */ - bool isStaticModifier(Node &node) { - return node.kind == SyntaxKind::StaticKeyword; + bool isStaticModifier(const shared &node) { + return node->kind == SyntaxKind::StaticKeyword; } /* @internal */ - bool isAbstractModifier(Node &node) { - return node.kind == SyntaxKind::AbstractKeyword; + bool isAbstractModifier(const shared &node) { + return node->kind == SyntaxKind::AbstractKeyword; } /*@internal*/ - bool isSuperKeyword(Node &node) { - return node.kind == SyntaxKind::SuperKeyword; + bool isSuperKeyword(const shared &node) { + return node->kind == SyntaxKind::SuperKeyword; } /*@internal*/ - bool isImportKeyword(Node &node) { - return node.kind == SyntaxKind::ImportKeyword; + bool isImportKeyword(const shared &node) { + return node->kind == SyntaxKind::ImportKeyword; } // Names - bool isQualifiedName(Node &node) { - return node.kind == SyntaxKind::QualifiedName; + bool isQualifiedName(const shared &node) { + return node->kind == SyntaxKind::QualifiedName; } - bool isComputedPropertyName(Node &node) { - return node.kind == SyntaxKind::ComputedPropertyName; + bool isComputedPropertyName(const shared &node) { + return node->kind == SyntaxKind::ComputedPropertyName; } // Signature elements - bool isTypeParameterDeclaration(Node &node) { - return node.kind == SyntaxKind::TypeParameter; + bool isTypeParameterDeclaration(const shared &node) { + return node->kind == SyntaxKind::TypeParameter; } // TODO(rbuckton): Rename to 'isParameterDeclaration' - bool isParameter(Node &node) { - return node.kind == SyntaxKind::Parameter; + bool isParameter(const shared &node) { + return node->kind == SyntaxKind::Parameter; } - bool isDecorator(Node &node) { - return node.kind == SyntaxKind::Decorator; + bool isDecorator(const shared &node) { + return node->kind == SyntaxKind::Decorator; } // TypeMember - bool isPropertySignature(Node &node) { - return node.kind == SyntaxKind::PropertySignature; + bool isPropertySignature(const shared &node) { + return node->kind == SyntaxKind::PropertySignature; } - bool isPropertyDeclaration(Node &node) { - return node.kind == SyntaxKind::PropertyDeclaration; + bool isPropertyDeclaration(const shared &node) { + return node->kind == SyntaxKind::PropertyDeclaration; } - bool isMethodSignature(Node &node) { - return node.kind == SyntaxKind::MethodSignature; + bool isMethodSignature(const shared &node) { + return node->kind == SyntaxKind::MethodSignature; } - bool isMethodDeclaration(Node &node) { - return node.kind == SyntaxKind::MethodDeclaration; + bool isMethodDeclaration(const shared &node) { + return node->kind == SyntaxKind::MethodDeclaration; } - bool isClassStaticBlockDeclaration(Node &node) { - return node.kind == SyntaxKind::ClassStaticBlockDeclaration; + bool isClassStaticBlockDeclaration(const shared &node) { + return node->kind == SyntaxKind::ClassStaticBlockDeclaration; } - bool isConstructorDeclaration(Node &node) { - return node.kind == SyntaxKind::Constructor; + bool isConstructorDeclaration(const shared &node) { + return node->kind == SyntaxKind::Constructor; } - bool isGetAccessorDeclaration(Node &node) { - return node.kind == SyntaxKind::GetAccessor; + bool isGetAccessorDeclaration(const shared &node) { + return node->kind == SyntaxKind::GetAccessor; } - bool isSetAccessorDeclaration(Node &node) { - return node.kind == SyntaxKind::SetAccessor; + bool isSetAccessorDeclaration(const shared &node) { + return node->kind == SyntaxKind::SetAccessor; } - bool isCallSignatureDeclaration(Node &node) { - return node.kind == SyntaxKind::CallSignature; + bool isCallSignatureDeclaration(const shared &node) { + return node->kind == SyntaxKind::CallSignature; } - bool isConstructSignatureDeclaration(Node &node) { - return node.kind == SyntaxKind::ConstructSignature; + bool isConstructSignatureDeclaration(const shared &node) { + return node->kind == SyntaxKind::ConstructSignature; } - bool isIndexSignatureDeclaration(Node &node) { - return node.kind == SyntaxKind::IndexSignature; + bool isIndexSignatureDeclaration(const shared &node) { + return node->kind == SyntaxKind::IndexSignature; } // Type - bool isTypePredicateNode(Node &node) { - return node.kind == SyntaxKind::TypePredicate; + bool isTypePredicateNode(const shared &node) { + return node->kind == SyntaxKind::TypePredicate; } - bool isTypeReferenceNode(Node &node) { - return node.kind == SyntaxKind::TypeReference; + bool isTypeReferenceNode(const shared &node) { + return node->kind == SyntaxKind::TypeReference; } - bool isFunctionTypeNode(Node &node) { - return node.kind == SyntaxKind::FunctionType; + bool isFunctionTypeNode(const shared &node) { + return node->kind == SyntaxKind::FunctionType; } - bool isConstructorTypeNode(Node &node) { - return node.kind == SyntaxKind::ConstructorType; + bool isConstructorTypeNode(const shared &node) { + return node->kind == SyntaxKind::ConstructorType; } - bool isTypeQueryNode(Node &node) { - return node.kind == SyntaxKind::TypeQuery; + bool isTypeQueryNode(const shared &node) { + return node->kind == SyntaxKind::TypeQuery; } - bool isTypeLiteralNode(Node &node) { - return node.kind == SyntaxKind::TypeLiteral; + bool isTypeLiteralNode(const shared &node) { + return node->kind == SyntaxKind::TypeLiteral; } - bool isArrayTypeNode(Node &node) { - return node.kind == SyntaxKind::ArrayType; + bool isArrayTypeNode(const shared &node) { + return node->kind == SyntaxKind::ArrayType; } - bool isTupleTypeNode(Node &node) { - return node.kind == SyntaxKind::TupleType; + bool isTupleTypeNode(const shared &node) { + return node->kind == SyntaxKind::TupleType; } - bool isNamedTupleMember(Node &node) { - return node.kind == SyntaxKind::NamedTupleMember; + bool isNamedTupleMember(const shared &node) { + return node->kind == SyntaxKind::NamedTupleMember; } - bool isOptionalTypeNode(Node &node) { - return node.kind == SyntaxKind::OptionalType; + bool isOptionalTypeNode(const shared &node) { + return node->kind == SyntaxKind::OptionalType; } - bool isRestTypeNode(Node &node) { - return node.kind == SyntaxKind::RestType; + bool isRestTypeNode(const shared &node) { + return node->kind == SyntaxKind::RestType; } - bool isUnionTypeNode(Node &node) { - return node.kind == SyntaxKind::UnionType; + bool isUnionTypeNode(const shared &node) { + return node->kind == SyntaxKind::UnionType; } - bool isIntersectionTypeNode(Node &node) { - return node.kind == SyntaxKind::IntersectionType; + bool isIntersectionTypeNode(const shared &node) { + return node->kind == SyntaxKind::IntersectionType; } - bool isConditionalTypeNode(Node &node) { - return node.kind == SyntaxKind::ConditionalType; + bool isConditionalTypeNode(const shared &node) { + return node->kind == SyntaxKind::ConditionalType; } - bool isInferTypeNode(Node &node) { - return node.kind == SyntaxKind::InferType; + bool isInferTypeNode(const shared &node) { + return node->kind == SyntaxKind::InferType; } - bool isParenthesizedTypeNode(Node &node) { - return node.kind == SyntaxKind::ParenthesizedType; + bool isParenthesizedTypeNode(const shared &node) { + return node->kind == SyntaxKind::ParenthesizedType; } - bool isThisTypeNode(Node &node) { - return node.kind == SyntaxKind::ThisType; + bool isThisTypeNode(const shared &node) { + return node->kind == SyntaxKind::ThisType; } - bool isTypeOperatorNode(Node &node) { - return node.kind == SyntaxKind::TypeOperator; + bool isTypeOperatorNode(const shared &node) { + return node->kind == SyntaxKind::TypeOperator; } - bool isIndexedAccessTypeNode(Node &node) { - return node.kind == SyntaxKind::IndexedAccessType; + bool isIndexedAccessTypeNode(const shared &node) { + return node->kind == SyntaxKind::IndexedAccessType; } - bool isMappedTypeNode(Node &node) { - return node.kind == SyntaxKind::MappedType; + bool isMappedTypeNode(const shared &node) { + return node->kind == SyntaxKind::MappedType; } - bool isLiteralTypeNode(Node &node) { - return node.kind == SyntaxKind::LiteralType; + bool isLiteralTypeNode(const shared &node) { + return node->kind == SyntaxKind::LiteralType; } - bool isImportTypeNode(Node &node) { - return node.kind == SyntaxKind::ImportType; + bool isImportTypeNode(const shared &node) { + return node->kind == SyntaxKind::ImportType; } - bool isTemplateLiteralTypeSpan(Node &node) { - return node.kind == SyntaxKind::TemplateLiteralTypeSpan; + bool isTemplateLiteralTypeSpan(const shared &node) { + return node->kind == SyntaxKind::TemplateLiteralTypeSpan; } - bool isTemplateLiteralTypeNode(Node &node) { - return node.kind == SyntaxKind::TemplateLiteralType; + bool isTemplateLiteralTypeNode(const shared &node) { + return node->kind == SyntaxKind::TemplateLiteralType; } // Binding patterns - bool isObjectBindingPattern(Node &node) { - return node.kind == SyntaxKind::ObjectBindingPattern; + bool isObjectBindingPattern(const shared &node) { + return node->kind == SyntaxKind::ObjectBindingPattern; } - bool isArrayBindingPattern(Node &node) { - return node.kind == SyntaxKind::ArrayBindingPattern; + bool isArrayBindingPattern(const shared &node) { + return node->kind == SyntaxKind::ArrayBindingPattern; } - bool isBindingElement(Node &node) { - return node.kind == SyntaxKind::BindingElement; + bool isBindingElement(const shared &node) { + return node->kind == SyntaxKind::BindingElement; } // Expression - bool isArrayLiteralExpression(Node &node) { - return node.kind == SyntaxKind::ArrayLiteralExpression; + bool isArrayLiteralExpression(const shared &node) { + return node->kind == SyntaxKind::ArrayLiteralExpression; } - bool isObjectLiteralExpression(Node &node) { - return node.kind == SyntaxKind::ObjectLiteralExpression; + bool isObjectLiteralExpression(const shared &node) { + return node->kind == SyntaxKind::ObjectLiteralExpression; } - bool isPropertyAccessExpression(Node &node) { - return node.kind == SyntaxKind::PropertyAccessExpression; + bool isPropertyAccessExpression(const shared &node) { + return node->kind == SyntaxKind::PropertyAccessExpression; } - bool isElementAccessExpression(Node &node) { - return node.kind == SyntaxKind::ElementAccessExpression; + bool isElementAccessExpression(const shared &node) { + return node->kind == SyntaxKind::ElementAccessExpression; } - bool isCallExpression(Node &node) { - return node.kind == SyntaxKind::CallExpression; + bool isCallExpression(const shared &node) { + return node->kind == SyntaxKind::CallExpression; } - bool isNewExpression(Node &node) { - return node.kind == SyntaxKind::NewExpression; + bool isNewExpression(const shared &node) { + return node->kind == SyntaxKind::NewExpression; } - bool isTaggedTemplateExpression(Node &node) { - return node.kind == SyntaxKind::TaggedTemplateExpression; + bool isTaggedTemplateExpression(const shared &node) { + return node->kind == SyntaxKind::TaggedTemplateExpression; } - bool isTypeAssertionExpression(Node &node) { - return node.kind == SyntaxKind::TypeAssertionExpression; + bool isTypeAssertionExpression(const shared &node) { + return node->kind == SyntaxKind::TypeAssertionExpression; } - bool isParenthesizedExpression(Node &node) { - return node.kind == SyntaxKind::ParenthesizedExpression; + bool isParenthesizedExpression(const shared &node) { + return node->kind == SyntaxKind::ParenthesizedExpression; } - bool isFunctionExpression(Node &node) { - return node.kind == SyntaxKind::FunctionExpression; + bool isFunctionExpression(const shared &node) { + return node->kind == SyntaxKind::FunctionExpression; } - bool isArrowFunction(Node &node) { - return node.kind == SyntaxKind::ArrowFunction; + bool isArrowFunction(const shared &node) { + return node->kind == SyntaxKind::ArrowFunction; } - bool isDeleteExpression(Node &node) { - return node.kind == SyntaxKind::DeleteExpression; + bool isDeleteExpression(const shared &node) { + return node->kind == SyntaxKind::DeleteExpression; } - bool isTypeOfExpression(Node &node) { - return node.kind == SyntaxKind::TypeOfExpression; + bool isTypeOfExpression(const shared &node) { + return node->kind == SyntaxKind::TypeOfExpression; } - bool isVoidExpression(Node &node) { - return node.kind == SyntaxKind::VoidExpression; + bool isVoidExpression(const shared &node) { + return node->kind == SyntaxKind::VoidExpression; } - bool isAwaitExpression(Node &node) { - return node.kind == SyntaxKind::AwaitExpression; + bool isAwaitExpression(const shared &node) { + return node->kind == SyntaxKind::AwaitExpression; } - bool isPrefixUnaryExpression(Node &node) { - return node.kind == SyntaxKind::PrefixUnaryExpression; + bool isPrefixUnaryExpression(const shared &node) { + return node->kind == SyntaxKind::PrefixUnaryExpression; } - bool isPostfixUnaryExpression(Node &node) { - return node.kind == SyntaxKind::PostfixUnaryExpression; + bool isPostfixUnaryExpression(const shared &node) { + return node->kind == SyntaxKind::PostfixUnaryExpression; } - bool isBinaryExpression(Node &node) { - return node.kind == SyntaxKind::BinaryExpression; + bool isBinaryExpression(const shared &node) { + return node->kind == SyntaxKind::BinaryExpression; } - bool isConditionalExpression(Node &node) { - return node.kind == SyntaxKind::ConditionalExpression; + bool isConditionalExpression(const shared &node) { + return node->kind == SyntaxKind::ConditionalExpression; } - bool isTemplateExpression(Node &node) { - return node.kind == SyntaxKind::TemplateExpression; + bool isTemplateExpression(const shared &node) { + return node->kind == SyntaxKind::TemplateExpression; } - bool isYieldExpression(Node &node) { - return node.kind == SyntaxKind::YieldExpression; + bool isYieldExpression(const shared &node) { + return node->kind == SyntaxKind::YieldExpression; } - bool isSpreadElement(Node &node) { - return node.kind == SyntaxKind::SpreadElement; + bool isSpreadElement(const shared &node) { + return node->kind == SyntaxKind::SpreadElement; } - bool isClassExpression(Node &node) { - return node.kind == SyntaxKind::ClassExpression; + bool isClassExpression(const shared &node) { + return node->kind == SyntaxKind::ClassExpression; } - bool isOmittedExpression(Node &node) { - return node.kind == SyntaxKind::OmittedExpression; + bool isOmittedExpression(const shared &node) { + return node->kind == SyntaxKind::OmittedExpression; } - bool isExpressionWithTypeArguments(Node &node) { - return node.kind == SyntaxKind::ExpressionWithTypeArguments; + bool isExpressionWithTypeArguments(const shared &node) { + return node->kind == SyntaxKind::ExpressionWithTypeArguments; } - bool isAsExpression(Node &node) { - return node.kind == SyntaxKind::AsExpression; + bool isAsExpression(const shared &node) { + return node->kind == SyntaxKind::AsExpression; } - bool isNonNullExpression(Node &node) { - return node.kind == SyntaxKind::NonNullExpression; + bool isNonNullExpression(const shared &node) { + return node->kind == SyntaxKind::NonNullExpression; } - bool isMetaProperty(Node &node) { - return node.kind == SyntaxKind::MetaProperty; + bool isMetaProperty(const shared &node) { + return node->kind == SyntaxKind::MetaProperty; } - bool isSyntheticExpression(Node &node) { - return node.kind == SyntaxKind::SyntheticExpression; + bool isSyntheticExpression(const shared &node) { + return node->kind == SyntaxKind::SyntheticExpression; } - bool isPartiallyEmittedExpression(Node &node) { - return node.kind == SyntaxKind::PartiallyEmittedExpression; + bool isPartiallyEmittedExpression(const shared &node) { + return node->kind == SyntaxKind::PartiallyEmittedExpression; } - bool isCommaListExpression(Node &node) { - return node.kind == SyntaxKind::CommaListExpression; + bool isCommaListExpression(const shared &node) { + return node->kind == SyntaxKind::CommaListExpression; } // Misc - bool isTemplateSpan(Node &node) { - return node.kind == SyntaxKind::TemplateSpan; + bool isTemplateSpan(const shared &node) { + return node->kind == SyntaxKind::TemplateSpan; } - bool isSemicolonClassElement(Node &node) { - return node.kind == SyntaxKind::SemicolonClassElement; + bool isSemicolonClassElement(const shared &node) { + return node->kind == SyntaxKind::SemicolonClassElement; } // Elements - bool isBlock(Node &node) { - return node.kind == SyntaxKind::Block; + bool isBlock(const shared &node) { + return node->kind == SyntaxKind::Block; } - bool isVariableStatement(Node &node) { - return node.kind == SyntaxKind::VariableStatement; + bool isVariableStatement(const shared &node) { + return node->kind == SyntaxKind::VariableStatement; } - bool isEmptyStatement(Node &node) { - return node.kind == SyntaxKind::EmptyStatement; + bool isEmptyStatement(const shared &node) { + return node->kind == SyntaxKind::EmptyStatement; } - bool isExpressionStatement(Node &node) { - return node.kind == SyntaxKind::ExpressionStatement; + bool isExpressionStatement(const shared &node) { + return node->kind == SyntaxKind::ExpressionStatement; } - bool isIfStatement(Node &node) { - return node.kind == SyntaxKind::IfStatement; + bool isIfStatement(const shared &node) { + return node->kind == SyntaxKind::IfStatement; } - bool isDoStatement(Node &node) { - return node.kind == SyntaxKind::DoStatement; + bool isDoStatement(const shared &node) { + return node->kind == SyntaxKind::DoStatement; } - bool isWhileStatement(Node &node) { - return node.kind == SyntaxKind::WhileStatement; + bool isWhileStatement(const shared &node) { + return node->kind == SyntaxKind::WhileStatement; } - bool isForStatement(Node &node) { - return node.kind == SyntaxKind::ForStatement; + bool isForStatement(const shared &node) { + return node->kind == SyntaxKind::ForStatement; } - bool isForInStatement(Node &node) { - return node.kind == SyntaxKind::ForInStatement; + bool isForInStatement(const shared &node) { + return node->kind == SyntaxKind::ForInStatement; } - bool isForOfStatement(Node &node) { - return node.kind == SyntaxKind::ForOfStatement; + bool isForOfStatement(const shared &node) { + return node->kind == SyntaxKind::ForOfStatement; } - bool isContinueStatement(Node &node) { - return node.kind == SyntaxKind::ContinueStatement; + bool isContinueStatement(const shared &node) { + return node->kind == SyntaxKind::ContinueStatement; } - bool isBreakStatement(Node &node) { - return node.kind == SyntaxKind::BreakStatement; + bool isBreakStatement(const shared &node) { + return node->kind == SyntaxKind::BreakStatement; } - bool isReturnStatement(Node &node) { - return node.kind == SyntaxKind::ReturnStatement; + bool isReturnStatement(const shared &node) { + return node->kind == SyntaxKind::ReturnStatement; } - bool isWithStatement(Node &node) { - return node.kind == SyntaxKind::WithStatement; + bool isWithStatement(const shared &node) { + return node->kind == SyntaxKind::WithStatement; } - bool isSwitchStatement(Node &node) { - return node.kind == SyntaxKind::SwitchStatement; + bool isSwitchStatement(const shared &node) { + return node->kind == SyntaxKind::SwitchStatement; } - bool isLabeledStatement(Node &node) { - return node.kind == SyntaxKind::LabeledStatement; + bool isLabeledStatement(const shared &node) { + return node->kind == SyntaxKind::LabeledStatement; } - bool isThrowStatement(Node &node) { - return node.kind == SyntaxKind::ThrowStatement; + bool isThrowStatement(const shared &node) { + return node->kind == SyntaxKind::ThrowStatement; } - bool isTryStatement(Node &node) { - return node.kind == SyntaxKind::TryStatement; + bool isTryStatement(const shared &node) { + return node->kind == SyntaxKind::TryStatement; } - bool isDebuggerStatement(Node &node) { - return node.kind == SyntaxKind::DebuggerStatement; + bool isDebuggerStatement(const shared &node) { + return node->kind == SyntaxKind::DebuggerStatement; } - bool isVariableDeclaration(Node &node) { - return node.kind == SyntaxKind::VariableDeclaration; + bool isVariableDeclaration(const shared &node) { + return node->kind == SyntaxKind::VariableDeclaration; } - bool isVariableDeclarationList(Node &node) { - return node.kind == SyntaxKind::VariableDeclarationList; + bool isVariableDeclarationList(const shared &node) { + return node->kind == SyntaxKind::VariableDeclarationList; } - bool isFunctionDeclaration(Node &node) { - return node.kind == SyntaxKind::FunctionDeclaration; + bool isFunctionDeclaration(const shared &node) { + return node->kind == SyntaxKind::FunctionDeclaration; } - bool isClassDeclaration(Node &node) { - return node.kind == SyntaxKind::ClassDeclaration; + bool isClassDeclaration(const shared &node) { + return node->kind == SyntaxKind::ClassDeclaration; } - bool isInterfaceDeclaration(Node &node) { - return node.kind == SyntaxKind::InterfaceDeclaration; + bool isInterfaceDeclaration(const shared &node) { + return node->kind == SyntaxKind::InterfaceDeclaration; } - bool isTypeAliasDeclaration(Node &node) { - return node.kind == SyntaxKind::TypeAliasDeclaration; + bool isTypeAliasDeclaration(const shared &node) { + return node->kind == SyntaxKind::TypeAliasDeclaration; } - bool isEnumDeclaration(Node &node) { - return node.kind == SyntaxKind::EnumDeclaration; + bool isEnumDeclaration(const shared &node) { + return node->kind == SyntaxKind::EnumDeclaration; } - bool isModuleDeclaration(Node &node) { - return node.kind == SyntaxKind::ModuleDeclaration; + bool isModuleDeclaration(const shared &node) { + return node->kind == SyntaxKind::ModuleDeclaration; } - bool isModuleBlock(Node &node) { - return node.kind == SyntaxKind::ModuleBlock; + bool isModuleBlock(const shared &node) { + return node->kind == SyntaxKind::ModuleBlock; } - bool isCaseBlock(Node &node) { - return node.kind == SyntaxKind::CaseBlock; + bool isCaseBlock(const shared &node) { + return node->kind == SyntaxKind::CaseBlock; } - bool isNamespaceExportDeclaration(Node &node) { - return node.kind == SyntaxKind::NamespaceExportDeclaration; + bool isNamespaceExportDeclaration(const shared &node) { + return node->kind == SyntaxKind::NamespaceExportDeclaration; } - bool isImportEqualsDeclaration(Node &node) { - return node.kind == SyntaxKind::ImportEqualsDeclaration; + bool isImportEqualsDeclaration(const shared &node) { + return node->kind == SyntaxKind::ImportEqualsDeclaration; } - bool isImportDeclaration(Node &node) { - return node.kind == SyntaxKind::ImportDeclaration; + bool isImportDeclaration(const shared &node) { + return node->kind == SyntaxKind::ImportDeclaration; } - bool isImportClause(Node &node) { - return node.kind == SyntaxKind::ImportClause; + bool isImportClause(const shared &node) { + return node->kind == SyntaxKind::ImportClause; } - bool isAssertClause(Node &node) { - return node.kind == SyntaxKind::AssertClause; + bool isAssertClause(const shared &node) { + return node->kind == SyntaxKind::AssertClause; } - bool isAssertEntry(Node &node) { - return node.kind == SyntaxKind::AssertEntry; + bool isAssertEntry(const shared &node) { + return node->kind == SyntaxKind::AssertEntry; } - bool isNamespaceImport(Node &node) { - return node.kind == SyntaxKind::NamespaceImport; + bool isNamespaceImport(const shared &node) { + return node->kind == SyntaxKind::NamespaceImport; } - bool isNamespaceExport(Node &node) { - return node.kind == SyntaxKind::NamespaceExport; + bool isNamespaceExport(const shared &node) { + return node->kind == SyntaxKind::NamespaceExport; } - bool isNamedImports(Node &node) { - return node.kind == SyntaxKind::NamedImports; + bool isNamedImports(const shared &node) { + return node->kind == SyntaxKind::NamedImports; } - bool isImportSpecifier(Node &node) { - return node.kind == SyntaxKind::ImportSpecifier; + bool isImportSpecifier(const shared &node) { + return node->kind == SyntaxKind::ImportSpecifier; } - bool isExportAssignment(Node &node) { - return node.kind == SyntaxKind::ExportAssignment; + bool isExportAssignment(const shared &node) { + return node->kind == SyntaxKind::ExportAssignment; } - bool isExportDeclaration(Node &node) { - return node.kind == SyntaxKind::ExportDeclaration; + bool isExportDeclaration(const shared &node) { + return node->kind == SyntaxKind::ExportDeclaration; } - bool isNamedExports(Node &node) { - return node.kind == SyntaxKind::NamedExports; + bool isNamedExports(const shared &node) { + return node->kind == SyntaxKind::NamedExports; } - bool isExportSpecifier(Node &node) { - return node.kind == SyntaxKind::ExportSpecifier; + bool isExportSpecifier(const shared &node) { + return node->kind == SyntaxKind::ExportSpecifier; } - bool isMissingDeclaration(Node &node) { - return node.kind == SyntaxKind::MissingDeclaration; + bool isMissingDeclaration(const shared &node) { + return node->kind == SyntaxKind::MissingDeclaration; } - bool isNotEmittedStatement(Node &node) { - return node.kind == SyntaxKind::NotEmittedStatement; + bool isNotEmittedStatement(const shared &node) { + return node->kind == SyntaxKind::NotEmittedStatement; } /* @internal */ - bool isSyntheticReference(Node &node) { - return node.kind == SyntaxKind::SyntheticReferenceExpression; + bool isSyntheticReference(const shared &node) { + return node->kind == SyntaxKind::SyntheticReferenceExpression; } /* @internal */ - bool isMergeDeclarationMarker(Node &node) { - return node.kind == SyntaxKind::MergeDeclarationMarker; + bool isMergeDeclarationMarker(const shared &node) { + return node->kind == SyntaxKind::MergeDeclarationMarker; } /* @internal */ - bool isEndOfDeclarationMarker(Node &node) { - return node.kind == SyntaxKind::EndOfDeclarationMarker; + bool isEndOfDeclarationMarker(const shared &node) { + return node->kind == SyntaxKind::EndOfDeclarationMarker; } // Module References - bool isExternalModuleReference(Node &node) { - return node.kind == SyntaxKind::ExternalModuleReference; - } - - bool isExternalModuleReference(BaseUnion &node) { - return node.kind() == SyntaxKind::ExternalModuleReference; + bool isExternalModuleReference(const shared &node) { + return node->kind == SyntaxKind::ExternalModuleReference; } // JSX - bool isJsxElement(Node &node) { - return node.kind == SyntaxKind::JsxElement; + bool isJsxElement(const shared &node) { + return node->kind == SyntaxKind::JsxElement; } - bool isJsxSelfClosingElement(Node &node) { - return node.kind == SyntaxKind::JsxSelfClosingElement; + bool isJsxSelfClosingElement(const shared &node) { + return node->kind == SyntaxKind::JsxSelfClosingElement; } - bool isJsxOpeningElement(Node &node) { - return node.kind == SyntaxKind::JsxOpeningElement; + bool isJsxOpeningElement(const shared &node) { + return node->kind == SyntaxKind::JsxOpeningElement; } - bool isJsxClosingElement(Node &node) { - return node.kind == SyntaxKind::JsxClosingElement; + bool isJsxClosingElement(const shared &node) { + return node->kind == SyntaxKind::JsxClosingElement; } - bool isJsxFragment(Node &node) { - return node.kind == SyntaxKind::JsxFragment; + bool isJsxFragment(const shared &node) { + return node->kind == SyntaxKind::JsxFragment; } - bool isJsxOpeningFragment(Node &node) { - return node.kind == SyntaxKind::JsxOpeningFragment; + bool isJsxOpeningFragment(const shared &node) { + return node->kind == SyntaxKind::JsxOpeningFragment; } - bool isJsxClosingFragment(Node &node) { - return node.kind == SyntaxKind::JsxClosingFragment; + bool isJsxClosingFragment(const shared &node) { + return node->kind == SyntaxKind::JsxClosingFragment; } - bool isJsxAttribute(Node &node) { - return node.kind == SyntaxKind::JsxAttribute; + bool isJsxAttribute(const shared &node) { + return node->kind == SyntaxKind::JsxAttribute; } - bool isJsxAttributes(Node &node) { - return node.kind == SyntaxKind::JsxAttributes; + bool isJsxAttributes(const shared &node) { + return node->kind == SyntaxKind::JsxAttributes; } - bool isJsxSpreadAttribute(Node &node) { - return node.kind == SyntaxKind::JsxSpreadAttribute; + bool isJsxSpreadAttribute(const shared &node) { + return node->kind == SyntaxKind::JsxSpreadAttribute; } - bool isJsxExpression(Node &node) { - return node.kind == SyntaxKind::JsxExpression; + bool isJsxExpression(const shared &node) { + return node->kind == SyntaxKind::JsxExpression; } // Clauses - bool isCaseClause(Node &node) { - return node.kind == SyntaxKind::CaseClause; + bool isCaseClause(const shared &node) { + return node->kind == SyntaxKind::CaseClause; } - bool isDefaultClause(Node &node) { - return node.kind == SyntaxKind::DefaultClause; + bool isDefaultClause(const shared &node) { + return node->kind == SyntaxKind::DefaultClause; } - bool isHeritageClause(Node &node) { - return node.kind == SyntaxKind::HeritageClause; + bool isHeritageClause(const shared &node) { + return node->kind == SyntaxKind::HeritageClause; } - bool isCatchClause(Node &node) { - return node.kind == SyntaxKind::CatchClause; + bool isCatchClause(const shared &node) { + return node->kind == SyntaxKind::CatchClause; } // Property assignments - bool isPropertyAssignment(Node &node) { - return node.kind == SyntaxKind::PropertyAssignment; + bool isPropertyAssignment(const shared &node) { + return node->kind == SyntaxKind::PropertyAssignment; } - bool isShorthandPropertyAssignment(Node &node) { - return node.kind == SyntaxKind::ShorthandPropertyAssignment; + bool isShorthandPropertyAssignment(const shared &node) { + return node->kind == SyntaxKind::ShorthandPropertyAssignment; } - bool isSpreadAssignment(Node &node) { - return node.kind == SyntaxKind::SpreadAssignment; + bool isSpreadAssignment(const shared &node) { + return node->kind == SyntaxKind::SpreadAssignment; } // Enum - bool isEnumMember(Node &node) { - return node.kind == SyntaxKind::EnumMember; + bool isEnumMember(const shared &node) { + return node->kind == SyntaxKind::EnumMember; } // Unparsed // TODO(rbuckton): isUnparsedPrologue - bool isUnparsedPrepend(Node &node) { - return node.kind == SyntaxKind::UnparsedPrepend; + bool isUnparsedPrepend(const shared &node) { + return node->kind == SyntaxKind::UnparsedPrepend; } // TODO(rbuckton): isUnparsedText @@ -771,180 +767,180 @@ namespace ts { // TODO(rbuckton): isUnparsedSyntheticReference // Top-level nodes - bool isSourceFile(Node &node) { - return node.kind == SyntaxKind::SourceFile; + bool isSourceFile(const shared &node) { + return node->kind == SyntaxKind::SourceFile; } - bool isBundle(Node &node) { - return node.kind == SyntaxKind::Bundle; + bool isBundle(const shared &node) { + return node->kind == SyntaxKind::Bundle; } - bool isUnparsedSource(Node &node) { - return node.kind == SyntaxKind::UnparsedSource; + bool isUnparsedSource(const shared &node) { + return node->kind == SyntaxKind::UnparsedSource; } // TODO(rbuckton): isInputFiles // JSDoc Elements - bool isJSDocTypeExpression(Node &node) { - return node.kind == SyntaxKind::JSDocTypeExpression; + bool isJSDocTypeExpression(const shared &node) { + return node->kind == SyntaxKind::JSDocTypeExpression; } - bool isJSDocNameReference(Node &node) { - return node.kind == SyntaxKind::JSDocNameReference; + bool isJSDocNameReference(const shared &node) { + return node->kind == SyntaxKind::JSDocNameReference; } - bool isJSDocMemberName(Node &node) { - return node.kind == SyntaxKind::JSDocMemberName; + bool isJSDocMemberName(const shared &node) { + return node->kind == SyntaxKind::JSDocMemberName; } - bool isJSDocLink(Node &node) { - return node.kind == SyntaxKind::JSDocLink; + bool isJSDocLink(const shared &node) { + return node->kind == SyntaxKind::JSDocLink; } - bool isJSDocLinkCode(Node &node) { - return node.kind == SyntaxKind::JSDocLinkCode; + bool isJSDocLinkCode(const shared &node) { + return node->kind == SyntaxKind::JSDocLinkCode; } - bool isJSDocLinkPlain(Node &node) { - return node.kind == SyntaxKind::JSDocLinkPlain; + bool isJSDocLinkPlain(const shared &node) { + return node->kind == SyntaxKind::JSDocLinkPlain; } - bool isJSDocAllType(Node &node) { - return node.kind == SyntaxKind::JSDocAllType; + bool isJSDocAllType(const shared &node) { + return node->kind == SyntaxKind::JSDocAllType; } - bool isJSDocUnknownType(Node &node) { - return node.kind == SyntaxKind::JSDocUnknownType; + bool isJSDocUnknownType(const shared &node) { + return node->kind == SyntaxKind::JSDocUnknownType; } - bool isJSDocNullableType(Node &node) { - return node.kind == SyntaxKind::JSDocNullableType; + bool isJSDocNullableType(const shared &node) { + return node->kind == SyntaxKind::JSDocNullableType; } - bool isJSDocNonNullableType(Node &node) { - return node.kind == SyntaxKind::JSDocNonNullableType; + bool isJSDocNonNullableType(const shared &node) { + return node->kind == SyntaxKind::JSDocNonNullableType; } - bool isJSDocOptionalType(Node &node) { - return node.kind == SyntaxKind::JSDocOptionalType; + bool isJSDocOptionalType(const shared &node) { + return node->kind == SyntaxKind::JSDocOptionalType; } - bool isJSDocFunctionType(Node &node) { - return node.kind == SyntaxKind::JSDocFunctionType; + bool isJSDocFunctionType(const shared &node) { + return node->kind == SyntaxKind::JSDocFunctionType; } - bool isJSDocVariadicType(Node &node) { - return node.kind == SyntaxKind::JSDocVariadicType; + bool isJSDocVariadicType(const shared &node) { + return node->kind == SyntaxKind::JSDocVariadicType; } - bool isJSDocNamepathType(Node &node) { - return node.kind == SyntaxKind::JSDocNamepathType; + bool isJSDocNamepathType(const shared &node) { + return node->kind == SyntaxKind::JSDocNamepathType; } - bool isJSDoc(Node &node) { - return node.kind == SyntaxKind::JSDoc; + bool isJSDoc(const shared &node) { + return node->kind == SyntaxKind::JSDoc; } - bool isJSDocTypeLiteral(Node &node) { - return node.kind == SyntaxKind::JSDocTypeLiteral; + bool isJSDocTypeLiteral(const shared &node) { + return node->kind == SyntaxKind::JSDocTypeLiteral; } - bool isJSDocSignature(Node &node) { - return node.kind == SyntaxKind::JSDocSignature; + bool isJSDocSignature(const shared &node) { + return node->kind == SyntaxKind::JSDocSignature; } // JSDoc Tags - bool isJSDocAugmentsTag(Node &node) { - return node.kind == SyntaxKind::JSDocAugmentsTag; + bool isJSDocAugmentsTag(const shared &node) { + return node->kind == SyntaxKind::JSDocAugmentsTag; } - bool isJSDocAuthorTag(Node &node) { - return node.kind == SyntaxKind::JSDocAuthorTag; + bool isJSDocAuthorTag(const shared &node) { + return node->kind == SyntaxKind::JSDocAuthorTag; } - bool isJSDocClassTag(Node &node) { - return node.kind == SyntaxKind::JSDocClassTag; + bool isJSDocClassTag(const shared &node) { + return node->kind == SyntaxKind::JSDocClassTag; } - bool isJSDocCallbackTag(Node &node) { - return node.kind == SyntaxKind::JSDocCallbackTag; + bool isJSDocCallbackTag(const shared &node) { + return node->kind == SyntaxKind::JSDocCallbackTag; } - bool isJSDocPublicTag(Node &node) { - return node.kind == SyntaxKind::JSDocPublicTag; + bool isJSDocPublicTag(const shared &node) { + return node->kind == SyntaxKind::JSDocPublicTag; } - bool isJSDocPrivateTag(Node &node) { - return node.kind == SyntaxKind::JSDocPrivateTag; + bool isJSDocPrivateTag(const shared &node) { + return node->kind == SyntaxKind::JSDocPrivateTag; } - bool isJSDocProtectedTag(Node &node) { - return node.kind == SyntaxKind::JSDocProtectedTag; + bool isJSDocProtectedTag(const shared &node) { + return node->kind == SyntaxKind::JSDocProtectedTag; } - bool isJSDocReadonlyTag(Node &node) { - return node.kind == SyntaxKind::JSDocReadonlyTag; + bool isJSDocReadonlyTag(const shared &node) { + return node->kind == SyntaxKind::JSDocReadonlyTag; } - bool isJSDocOverrideTag(Node &node) { - return node.kind == SyntaxKind::JSDocOverrideTag; + bool isJSDocOverrideTag(const shared &node) { + return node->kind == SyntaxKind::JSDocOverrideTag; } - bool isJSDocDeprecatedTag(Node &node) { - return node.kind == SyntaxKind::JSDocDeprecatedTag; + bool isJSDocDeprecatedTag(const shared &node) { + return node->kind == SyntaxKind::JSDocDeprecatedTag; } - bool isJSDocSeeTag(Node &node) { - return node.kind == SyntaxKind::JSDocSeeTag; + bool isJSDocSeeTag(const shared &node) { + return node->kind == SyntaxKind::JSDocSeeTag; } - bool isJSDocEnumTag(Node &node) { - return node.kind == SyntaxKind::JSDocEnumTag; + bool isJSDocEnumTag(const shared &node) { + return node->kind == SyntaxKind::JSDocEnumTag; } - bool isJSDocParameterTag(Node &node) { - return node.kind == SyntaxKind::JSDocParameterTag; + bool isJSDocParameterTag(const shared &node) { + return node->kind == SyntaxKind::JSDocParameterTag; } - bool isJSDocReturnTag(Node &node) { - return node.kind == SyntaxKind::JSDocReturnTag; + bool isJSDocReturnTag(const shared &node) { + return node->kind == SyntaxKind::JSDocReturnTag; } - bool isJSDocThisTag(Node &node) { - return node.kind == SyntaxKind::JSDocThisTag; + bool isJSDocThisTag(const shared &node) { + return node->kind == SyntaxKind::JSDocThisTag; } - bool isJSDocTypeTag(Node &node) { - return node.kind == SyntaxKind::JSDocTypeTag; + bool isJSDocTypeTag(const shared &node) { + return node->kind == SyntaxKind::JSDocTypeTag; } - bool isJSDocTemplateTag(Node &node) { - return node.kind == SyntaxKind::JSDocTemplateTag; + bool isJSDocTemplateTag(const shared &node) { + return node->kind == SyntaxKind::JSDocTemplateTag; } - bool isJSDocTypedefTag(Node &node) { - return node.kind == SyntaxKind::JSDocTypedefTag; + bool isJSDocTypedefTag(const shared &node) { + return node->kind == SyntaxKind::JSDocTypedefTag; } - bool isJSDocUnknownTag(Node &node) { - return node.kind == SyntaxKind::JSDocTag; + bool isJSDocUnknownTag(const shared &node) { + return node->kind == SyntaxKind::JSDocTag; } - bool isJSDocPropertyTag(Node &node) { - return node.kind == SyntaxKind::JSDocPropertyTag; + bool isJSDocPropertyTag(const shared &node) { + return node->kind == SyntaxKind::JSDocPropertyTag; } - bool isJSDocImplementsTag(Node &node) { - return node.kind == SyntaxKind::JSDocImplementsTag; + bool isJSDocImplementsTag(const shared &node) { + return node->kind == SyntaxKind::JSDocImplementsTag; } // Synthesized list /* @internal */ - bool isSyntaxList(Node &node){ - return node.kind == SyntaxKind::SyntaxList; + bool isSyntaxList(const shared &node){ + return node->kind == SyntaxKind::SyntaxList; } } diff --git a/src/parser2.h b/src/parser2.h index a850a95..8fb56aa 100644 --- a/src/parser2.h +++ b/src/parser2.h @@ -1,22 +1,23 @@ #pragma once #include -#include #include +#include #include #include #include "types.h" #include "core.h" #include "node_test.h" #include "factory.h" +#include "utilities.h" using namespace ts::types; namespace ts { using std::string; using std::vector; - using std::optional; using std::function; + using std::optional; using std::variant; enum class SignatureFlags { @@ -55,19 +56,18 @@ namespace ts { //// /* @internal */ //// export const parseNodeFactory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules, parseBaseNodeFactory); - LogicalOrReturnLast> visitNode(function(Node &)> cbNode, OptionalNode node) { - if (!empty(node)) LogicalOrReturnLast(cbNode(resolve(node))); - return LogicalOrReturnLast>(nullopt); -// return LogicalOrReturnLast(node ? cbNode(*node) : nullptr); + sharedOpt visitNode(function(shared)> cbNode, sharedOpt node) { + if (node) cbNode(node); + return nullptr; } // Node *visitNode(function cbNode, Node &node) { // return cbNode(node); // } - LogicalOrReturnLast> visitNodes( - function(Node &)> cbNode, - optional(BaseNodeArray)>> cbNodes, + sharedOpt visitNodes( + function(shared)> cbNode, + optional(BaseNodeArray)>> cbNodes, optional nodes ) { if (nodes) { @@ -81,7 +81,7 @@ namespace ts { } } } - return LogicalOrReturnLast>(nullopt); + return nullptr; } /** @@ -89,7 +89,7 @@ namespace ts { * returns a truthy value, then returns that value. * If no such value is found, the callback is applied to each element of array and undefined is returned. */ - optional forEach(optional array, function(Node &element, int index)> callback) { + sharedOpt forEach(optional array, function(shared element, int index)> callback) { if (array) { for (int i = 0; i < array->list.size(); i ++) { auto result = callback((*array).list[i], i); @@ -98,10 +98,10 @@ namespace ts { } } } - return nullopt; + return nullptr; } - bool some(optional array, optional> predicate) { + bool some(optional array, optional value)>> predicate) { if (array) { if (predicate) { for (auto &v: array->list) { @@ -109,54 +109,54 @@ namespace ts { return true; } } - } - else { + } else { return array->list.size() > 0; } } return false; } - optional forEachChild(Node &node, function(Node &)> cbNode, optional(BaseNodeArray)>> cbNodes = nullopt); + sharedOpt forEachChild(const shared &node, function(shared)> cbNode, optional(BaseNodeArray)>> cbNodes = nullopt); /** Do not use hasModifier inside the parser; it relies on parent pointers. Use this instead. */ - bool hasModifierOfKind(Node &node, SyntaxKind kind) { - return some(node.modifiers, [kind](auto m) { return m.kind == kind; }); + bool hasModifierOfKind(shared node, SyntaxKind kind) { + return some(node->modifiers, [kind](auto m) { return m->kind == kind; }); } - optional isAnExternalModuleIndicatorNode(Node &node, int) { + sharedOpt isAnExternalModuleIndicatorNode(shared node, int) { if (hasModifierOfKind(node, SyntaxKind::ExportKeyword) - || (node.is() && isExternalModuleReference(node.to().moduleReference)) - || isImportDeclaration(node) - || isExportAssignment(node) - || isExportDeclaration(node)) return node; - return nullopt; + || (node->is() && isExternalModuleReference(node->to().moduleReference)) + || isImportDeclaration(node) + || isExportAssignment(node) + || isExportDeclaration(node)) + return node; + return nullptr; } - bool isImportMeta(Node &node) { + bool isImportMeta(const shared &node) { if (isMetaProperty(node)) { - MetaProperty &meta = node.to(); - return meta.keywordToken == SyntaxKind::ImportKeyword && meta.name.to().escapedText == "meta"; + auto meta = node->to(); + return meta.keywordToken == SyntaxKind::ImportKeyword && meta.name->to().escapedText == "meta"; } return false; } - optional walkTreeForImportMeta(Node &node) { + sharedOpt walkTreeForImportMeta(const shared &node) { if (isImportMeta(node)) return node; return forEachChild(node, walkTreeForImportMeta, nullopt); } - optional getImportMetaIfNecessary(SourceFile &sourceFile) { - return sourceFile.to().flags & (int) NodeFlags::PossiblyContainsImportMeta ? + sharedOpt getImportMetaIfNecessary(const shared &sourceFile) { + return sourceFile->flags & (int) NodeFlags::PossiblyContainsImportMeta ? walkTreeForImportMeta(sourceFile) : - nullopt; + nullptr; } /*@internal*/ - OptionalNode isFileProbablyExternalModule(SourceFile &sourceFile) { + sharedOpt isFileProbablyExternalModule(const shared &sourceFile) { // Try to use the first top-level import/export when available, then // fall back to looking for an 'import.meta' somewhere in the tree if necessary. - auto r = forEach(sourceFile.statements, isAnExternalModuleIndicatorNode); + auto r = forEach(sourceFile->statements, isAnExternalModuleIndicatorNode); if (r) return r; return getImportMetaIfNecessary(sourceFile); @@ -175,9 +175,9 @@ namespace ts { * @remarks `forEachChild` must visit the children of a node in the order * that they appear in the source code. The language service depends on this property to locate nodes by position. */ - optional forEachChild(Node &node, function(Node &)> cbNode, optional(BaseNodeArray)>> cbNodes) { + sharedOpt forEachChild(Node &node, function(shared)> cbNode, optional(BaseNodeArray)>> cbNodes) { if (node.kind <= SyntaxKind::LastToken) { - return nullopt; + return nullptr; } switch (node.kind) { case SyntaxKind::QualifiedName: @@ -262,6 +262,8 @@ namespace ts { case SyntaxKind::FunctionExpression: case SyntaxKind::FunctionDeclaration: case SyntaxKind::ArrowFunction: { + if (auto b = visitNodes(cbNode, cbNodes, node.decorators)) return b; + return visitNodes(cbNode, cbNodes, node.decorators) || visitNodes(cbNode, cbNodes, node.modifiers) || visitNode(cbNode, node.cast().asteriskToken) || @@ -271,7 +273,7 @@ namespace ts { visitNodes(cbNode, cbNodes, node.cast().typeParameters) || visitNodes(cbNode, cbNodes, node.cast().parameters) || visitNode(cbNode, node.cast().type) || - (node.kind == SyntaxKind::ArrowFunction ? visitNode(cbNode, node.to().equalsGreaterThanToken) : LogicalOrReturnLast>(nullopt)) || + (node.kind == SyntaxKind::ArrowFunction ? visitNode(cbNode, node.to().equalsGreaterThanToken) : shared(nullptr)) || visitNode(cbNode, node.cast().body); } case SyntaxKind::ClassStaticBlockDeclaration: @@ -696,7 +698,7 @@ namespace ts { * `getSetExternalModuleIndicator` on a valid `CompilerOptions` object. If not present, the default * check specified by `isFileProbablyExternalModule` will be used to set the field. */ - optional> setExternalModuleIndicator; + optional)>> setExternalModuleIndicator; }; // @@ -704,19 +706,19 @@ namespace ts { // sourceFile.externalModuleIndicator = isFileProbablyExternalModule(sourceFile); // } - void setExternalModuleIndicator(SourceFile &sourceFile) { - sourceFile.externalModuleIndicator = isFileProbablyExternalModule(sourceFile); + void setExternalModuleIndicator(shared sourceFile) { + sourceFile->externalModuleIndicator = isFileProbablyExternalModule(sourceFile); } namespace Parser { -// parseSourceFile + shared parseSourceFile(string fileName, string sourceText, ScriptTarget languageVersion, bool setParentNodes = false, optional scriptKind = {}, optional)>> setExternalModuleIndicatorOverride = {}); }; - SourceFile createSourceFile(string fileName, string sourceText, variant languageVersionOrOptions, bool setParentNodes = false, optional scriptKind = {}) { + shared createSourceFile(string fileName, string sourceText, variant languageVersionOrOptions, bool setParentNodes = false, optional scriptKind = {}) { // tracing?.push(tracing.Phase.Parse, "createSourceFile", { path: fileName }, /*separateBeginAndEnd*/ true); // performance.mark("beforeParse"); - SourceFile result = createBaseNode(); - optional> overrideSetExternalModuleIndicator; + shared_ptr result = make_shared(); + optional)>> overrideSetExternalModuleIndicator; optional format; // perfLogger.logStartParseSourceFile(fileName); @@ -731,17 +733,17 @@ namespace ts { } if (languageVersion == ScriptTarget::JSON) { - result = Parser::parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ {}, setParentNodes, ScriptKind::JSON); + result = Parser::parseSourceFile(fileName, sourceText, languageVersion, setParentNodes, ScriptKind::JSON); } else { - optional> setIndicator = ! format.has_value() ? overrideSetExternalModuleIndicator : [format, overrideSetExternalModuleIndicator](SourceFile file) { - file.impliedNodeFormat = format; + optional)>> setIndicator = ! format.has_value() ? overrideSetExternalModuleIndicator : [format, overrideSetExternalModuleIndicator](shared file) { + file->impliedNodeFormat = format; if (overrideSetExternalModuleIndicator) { (*overrideSetExternalModuleIndicator)(file); } else { setExternalModuleIndicator(file); } }; - result = Parser::parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ {}, setParentNodes, scriptKind, setIndicator); + result = Parser::parseSourceFile(fileName, sourceText, languageVersion, setParentNodes, scriptKind, setIndicator); } // perfLogger.logStopParseSourceFile(); // @@ -840,255 +842,128 @@ namespace ts { // // const factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, baseNodeFactory); // -// let fileName: string; -// let sourceFlags: NodeFlags; -// let sourceText: string; -// let languageVersion: ScriptTarget; -// let scriptKind: ScriptKind; -// let languageVariant: LanguageVariant; -// let parseDiagnostics: DiagnosticWithDetachedLocation[]; -// let jsDocDiagnostics: DiagnosticWithDetachedLocation[]; + string fileName = ""; + /*NodeFlags*/ int sourceFlags = 0; + string sourceText = ""; + ScriptTarget languageVersion; + ScriptKind scriptKind; + LanguageVariant languageVariant; + vector parseDiagnostics; + vector jsDocDiagnostics; // let syntaxCursor: IncrementalParser.SyntaxCursor | undefined; -// -// let currentToken: SyntaxKind; -// let nodeCount: number; + + SyntaxKind currentToken; + int nodeCount = 0; // let identifiers: ESMap; // let privateIdentifiers: ESMap; -// let identifierCount: number; -// -// let parsingContext: ParsingContext; -// + int identifierCount = 0; + + /*ParsingContext*/ int parsingContext = 0; + // let notParenthesizedArrow: Set | undefined; -// -// // Flags that dictate what parsing context we're in. For example: -// // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is -// // that some tokens that would be considered identifiers may be considered keywords. -// // -// // When adding more parser context flags, consider which is the more common case that the -// // flag will be in. This should be the 'false' state for that flag. The reason for this is -// // that we don't store data in our nodes unless the value is in the *non-default* state. So, -// // for example, more often than code 'allows-in' (or doesn't 'disallow-in'). We opt for -// // 'disallow-in' set to 'false'. Otherwise, if we had 'allowsIn' set to 'true', then almost -// // all nodes would need extra state on them to store this info. -// // -// // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6 -// // grammar specification. -// // -// // An important thing about these context concepts. By default they are effectively inherited -// // while parsing through every grammar production. i.e. if you don't change them, then when -// // you parse a sub-production, it will have the same context values as the parent production. -// // This is great most of the time. After all, consider all the 'expression' grammar productions -// // and how nearly all of them pass along the 'in' and 'yield' context values: -// // -// // EqualityExpression[In, Yield] : -// // RelationalExpression[?In, ?Yield] -// // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] -// // EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield] -// // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] -// // EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield] -// // -// // Where you have to be careful is then understanding what the points are in the grammar -// // where the values are *not* passed along. For example: -// // -// // SingleNameBinding[Yield,GeneratorParameter] -// // [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt -// // [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt -// // -// // Here this is saying that if the GeneratorParameter context flag is set, that we should -// // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier -// // and we should explicitly unset the 'yield' context flag before calling into the Initializer. -// // production. Conversely, if the GeneratorParameter context flag is not set, then we -// // should leave the 'yield' context flag alone. -// // -// // Getting this all correct is tricky and requires careful reading of the grammar to -// // understand when these values should be changed versus when they should be inherited. -// // -// // Note: it should not be necessary to save/restore these flags during speculative/lookahead -// // parsing. These context flags are naturally stored and restored through normal recursive -// // descent parsing and unwinding. -// let contextFlags: NodeFlags; -// -// // Indicates whether we are currently parsing top-level statements. -// let topLevel = true; -// -// // Whether or not we've had a parse error since creating the last AST node. If we have -// // encountered an error, it will be stored on the next AST node we create. Parse errors -// // can be broken down into three categories: -// // -// // 1) An error that occurred during scanning. For example, an unterminated literal, or a -// // character that was completely not understood. -// // -// // 2) A token was expected, but was not present. This type of error is commonly produced -// // by the 'parseExpected' function. -// // -// // 3) A token was present that no parsing function was able to consume. This type of error -// // only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser -// // decides to skip the token. -// // -// // In all of these cases, we want to mark the next node as having had an error before it. -// // With this mark, we can know in incremental settings if this node can be reused, or if -// // we have to reparse it. If we don't keep this information around, we may just reuse the -// // node. in that event we would then not produce the same errors as we did before, causing -// // significant confusion problems. -// // -// // Note: it is necessary that this value be saved/restored during speculative/lookahead -// // parsing. During lookahead parsing, we will often create a node. That node will have -// // this value attached, and then this value will be set back to 'false'. If we decide to -// // rewind, we must get back to the same value we had prior to the lookahead. -// // -// // Note: any errors at the end of the file that do not precede a regular node, should get -// // attached to the EOF token. -// let parseErrorBeforeNextFinishedNode = false; - SourceFile parseSourceFileWorker(ScriptTarget languageVersion, bool setParentNodes, ScriptKind scriptKind, function setExternalModuleIndicator); + // Flags that dictate what parsing context we're in. For example: + // Whether or not we are in strict parsing mode. All that changes in strict parsing mode is + // that some tokens that would be considered identifiers may be considered keywords. + // + // When adding more parser context flags, consider which is the more common case that the + // flag will be in. This should be the 'false' state for that flag. The reason for this is + // that we don't store data in our nodes unless the value is in the *non-default* state. So, + // for example, more often than code 'allows-in' (or doesn't 'disallow-in'). We opt for + // 'disallow-in' set to 'false'. Otherwise, if we had 'allowsIn' set to 'true', then almost + // all nodes would need extra state on them to store this info. + // + // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6 + // grammar specification. + // + // An important thing about these context concepts. By default they are effectively inherited + // while parsing through every grammar production. i.e. if you don't change them, then when + // you parse a sub-production, it will have the same context values as the parent production. + // This is great most of the time. After all, consider all the 'expression' grammar productions + // and how nearly all of them pass along the 'in' and 'yield' context values: + // + // EqualityExpression[In, Yield] : + // RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield] + // EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield] + // + // Where you have to be careful is then understanding what the points are in the grammar + // where the values are *not* passed along. For example: + // + // SingleNameBinding[Yield,GeneratorParameter] + // [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt + // [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt + // + // Here this is saying that if the GeneratorParameter context flag is set, that we should + // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier + // and we should explicitly unset the 'yield' context flag before calling into the Initializer. + // production. Conversely, if the GeneratorParameter context flag is not set, then we + // should leave the 'yield' context flag alone. + // + // Getting this all correct is tricky and requires careful reading of the grammar to + // understand when these values should be changed versus when they should be inherited. + // + // Note: it should not be necessary to save/restore these flags during speculative/lookahead + // parsing. These context flags are naturally stored and restored through normal recursive + // descent parsing and unwinding. + /*NodeFlags*/ int contextFlags = 0; - SourceFile parseSourceFile(string fileName, string sourceText, ScriptTarget languageVersion, bool setParentNodes = false, optional scriptKind = {}, optional> setExternalModuleIndicatorOverride = {}) { - scriptKind = ensureScriptKind(fileName, scriptKind); -// -// if (scriptKind == ScriptKind.JSON) { -// const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes); -// convertToObjectWorker(result, result.statements[0]?.expression, result.parseDiagnostics, /*returnValue*/ false, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); -// result.referencedFiles = emptyArray; -// result.typeReferenceDirectives = emptyArray; -// result.libReferenceDirectives = emptyArray; -// result.amdDependencies = emptyArray; -// result.hasNoDefaultLib = false; -// result.pragmas = emptyMap as ReadonlyPragmaMap; -// return result; -// } -// -// initializeState(fileName, sourceText, languageVersion, syntaxCursor, scriptKind); -// - auto result = parseSourceFileWorker(languageVersion, setParentNodes, scriptKind, setExternalModuleIndicatorOverride ? *setExternalModuleIndicatorOverride : setExternalModuleIndicator); -// -// clearState(); + // Indicates whether we are currently parsing top-level statements. + bool topLevel = true; - return result; - } -// -// export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName | undefined { -// // Choice of `isDeclarationFile` should be arbitrary -// initializeState("", content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS); -// // Prime the scanner. -// nextToken(); -// const entityName = parseEntityName(/*allowReservedWords*/ true); -// const isInvalid = token() == SyntaxKind::EndOfFileToken && !parseDiagnostics.length; -// clearState(); -// return isInvalid ? entityName : undefined; -// } -// -// export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): JsonSourceFile { -// initializeState(fileName, sourceText, languageVersion, syntaxCursor, ScriptKind.JSON); -// sourceFlags = contextFlags; -// -// // Prime the scanner. -// nextToken(); -// const pos = getNodePos(); -// let statements, endOfFileToken; -// if (token() == SyntaxKind::EndOfFileToken) { -// statements = createNodeArray([], pos, pos); -// endOfFileToken = parseTokenNode(); -// } -// else { -// // Loop and synthesize an ArrayLiteralExpression if there are more than -// // one top-level expressions to ensure all input text is consumed. -// let expressions: Expression[] | Expression | undefined; -// while (token() !== SyntaxKind::EndOfFileToken) { -// let expression; -// switch (token()) { -// case SyntaxKind::OpenBracketToken: -// expression = parseArrayLiteralExpression(); -// break; -// case SyntaxKind::TrueKeyword: -// case SyntaxKind::FalseKeyword: -// case SyntaxKind::NullKeyword: -// expression = parseTokenNode(); -// break; -// case SyntaxKind::MinusToken: -// if (lookAhead(() => nextToken() == SyntaxKind::NumericLiteral && nextToken() !== SyntaxKind::ColonToken)) { -// expression = parsePrefixUnaryExpression() as JsonMinusNumericLiteral; -// } -// else { -// expression = parseObjectLiteralExpression(); -// } -// break; -// case SyntaxKind::NumericLiteral: -// case SyntaxKind::StringLiteral: -// if (lookAhead(() => nextToken() !== SyntaxKind::ColonToken)) { -// expression = parseLiteralNode() as StringLiteral | NumericLiteral; -// break; -// } -// // falls through -// default: -// expression = parseObjectLiteralExpression(); -// break; -// } -// -// // Error recovery: collect multiple top-level expressions -// if (expressions && isArray(expressions)) { -// expressions.push(expression); -// } -// else if (expressions) { -// expressions = [expressions, expression]; -// } -// else { -// expressions = expression; -// if (token() !== SyntaxKind::EndOfFileToken) { -// parseErrorAtCurrentToken(Diagnostics.Unexpected_token); -// } -// } -// } -// -// const expression = isArray(expressions) ? finishNode(factory.createArrayLiteralExpression(expressions), pos) : Debug.checkDefined(expressions); -// const statement = factory.createExpressionStatement(expression) as JsonObjectExpressionStatement; -// finishNode(statement, pos); -// statements = createNodeArray([statement], pos); -// endOfFileToken = parseExpectedToken(SyntaxKind::EndOfFileToken, Diagnostics.Unexpected_token); -// } -// -// // Set source file so that errors will be reported with this file name -// const sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false, statements, endOfFileToken, sourceFlags, noop); -// -// if (setParentNodes) { -// fixupParentReferences(sourceFile); -// } -// -// sourceFile.nodeCount = nodeCount; -// sourceFile.identifierCount = identifierCount; -// sourceFile.identifiers = identifiers; -// sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); -// if (jsDocDiagnostics) { -// sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); -// } -// -// const result = sourceFile as JsonSourceFile; -// clearState(); -// return result; -// } -// -// function initializeState(_fileName: string, _sourceText: string, _languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, _scriptKind: ScriptKind) { + // Whether or not we've had a parse error since creating the last AST node. If we have + // encountered an error, it will be stored on the next AST node we create. Parse errors + // can be broken down into three categories: + // + // 1) An error that occurred during scanning. For example, an unterminated literal, or a + // character that was completely not understood. + // + // 2) A token was expected, but was not present. This type of error is commonly produced + // by the 'parseExpected' function. + // + // 3) A token was present that no parsing function was able to consume. This type of error + // only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser + // decides to skip the token. + // + // In all of these cases, we want to mark the next node as having had an error before it. + // With this mark, we can know in incremental settings if this node can be reused, or if + // we have to reparse it. If we don't keep this information around, we may just reuse the + // node. in that event we would then not produce the same errors as we did before, causing + // significant confusion problems. + // + // Note: it is necessary that this value be saved/restored during speculative/lookahead + // parsing. During lookahead parsing, we will often create a node. That node will have + // this value attached, and then this value will be set back to 'false'. If we decide to + // rewind, we must get back to the same value we had prior to the lookahead. + // + // Note: any errors at the end of the file that do not precede a regular node, should get + // attached to the EOF token. + bool parseErrorBeforeNextFinishedNode = false; + + void initializeState(string _fileName, string _sourceText, ScriptTarget _languageVersion, ScriptKind _scriptKind) { // NodeConstructor = objectAllocator.getNodeConstructor(); // TokenConstructor = objectAllocator.getTokenConstructor(); // IdentifierConstructor = objectAllocator.getIdentifierConstructor(); // PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor(); // SourceFileConstructor = objectAllocator.getSourceFileConstructor(); // -// fileName = normalizePath(_fileName); -// sourceText = _sourceText; -// languageVersion = _languageVersion; -// syntaxCursor = _syntaxCursor; -// scriptKind = _scriptKind; -// languageVariant = getLanguageVariant(_scriptKind); -// -// parseDiagnostics = []; -// parsingContext = 0; + fileName = normalizePath(_fileName); + sourceText = _sourceText; + languageVersion = _languageVersion; + scriptKind = _scriptKind; + languageVariant = getLanguageVariant(_scriptKind); + + parseDiagnostics.clear(); + parsingContext = 0; // identifiers = new Map(); // privateIdentifiers = new Map(); -// identifierCount = 0; -// nodeCount = 0; -// sourceFlags = 0; -// topLevel = true; -// + identifierCount = 0; + nodeCount = 0; + sourceFlags = 0; + topLevel = true; + // switch (scriptKind) { // case ScriptKind.JS: // case ScriptKind.JSX: @@ -1131,7 +1006,7 @@ namespace ts { // topLevel = true; // } // - SourceFile parseSourceFileWorker(ScriptTarget languageVersion, bool setParentNodes, ScriptKind scriptKind, function setExternalModuleIndicator) { + shared parseSourceFileWorker(ScriptTarget languageVersion, bool setParentNodes, ScriptKind scriptKind, function)> setExternalModuleIndicator) { // const isDeclarationFile = isDeclarationFileName(fileName); // if (isDeclarationFile) { // contextFlags |= NodeFlags::Ambient; @@ -1170,7 +1045,7 @@ namespace ts { // function reportPragmaDiagnostic(pos: number, end: number, diagnostic: DiagnosticMessage) { // parseDiagnostics.push(createDetachedDiagnostic(fileName, pos, end, diagnostic)); // } - } + } // // function withJSDoc(node: T, hasJSDoc: boolean): T { // return hasJSDoc ? addJSDocComment(node) : node; @@ -7711,41 +7586,41 @@ namespace ts { // const node = factory.createExportAssignment(decorators, modifiers, isExportEquals, expression); // return withJSDoc(finishNode(node, pos), hasJSDoc); // } -// -// const enum ParsingContext { -// SourceElements, // Elements in source file -// BlockStatements, // Statements in block -// SwitchClauses, // Clauses in switch statement -// SwitchClauseStatements, // Statements in switch clause -// TypeMembers, // Members in interface or type literal -// ClassMembers, // Members in class declaration -// EnumMembers, // Members in enum declaration -// HeritageClauseElement, // Elements in a heritage clause -// VariableDeclarations, // Variable declarations in variable statement -// ObjectBindingElements, // Binding elements in object binding list -// ArrayBindingElements, // Binding elements in array binding list -// ArgumentExpressions, // Expressions in argument list -// ObjectLiteralMembers, // Members in object literal -// JsxAttributes, // Attributes in jsx element -// JsxChildren, // Things between opening and closing JSX tags -// ArrayLiteralMembers, // Members in array literal -// Parameters, // Parameters in parameter list -// JSDocParameters, // JSDoc parameters in parameter list of JSDoc function type -// RestProperties, // Property names in a rest type list -// TypeParameters, // Type parameters in type parameter list -// TypeArguments, // Type arguments in type argument list -// TupleElementTypes, // Element types in tuple element type list -// HeritageClauses, // Heritage clauses for a class or interface declaration. -// ImportOrExportSpecifiers, // Named import clause's import specifier list, -// AssertEntries, // Import entries list. -// Count // Number of parsing contexts -// } -// -// const enum Tristate { -// False, -// True, -// Unknown -// } + + enum class ParsingContext { + SourceElements, // Elements in source file + BlockStatements, // Statements in block + SwitchClauses, // Clauses in switch statement + SwitchClauseStatements, // Statements in switch clause + TypeMembers, // Members in interface or type literal + ClassMembers, // Members in class declaration + EnumMembers, // Members in enum declaration + HeritageClauseElement, // Elements in a heritage clause + VariableDeclarations, // Variable declarations in variable statement + ObjectBindingElements, // Binding elements in object binding list + ArrayBindingElements, // Binding elements in array binding list + ArgumentExpressions, // Expressions in argument list + ObjectLiteralMembers, // Members in object literal + JsxAttributes, // Attributes in jsx element + JsxChildren, // Things between opening and closing JSX tags + ArrayLiteralMembers, // Members in array literal + Parameters, // Parameters in parameter list + JSDocParameters, // JSDoc parameters in parameter list of JSDoc function type + RestProperties, // Property names in a rest type list + TypeParameters, // Type parameters in type parameter list + TypeArguments, // Type arguments in type argument list + TupleElementTypes, // Element types in tuple element type list + HeritageClauses, // Heritage clauses for a class or interface declaration. + ImportOrExportSpecifiers, // Named import clause's import specifier list, + AssertEntries, // Import entries list. + Count // Number of parsing contexts + }; + + enum class Tristate { + False, + True, + Unknown + }; // // export namespace JSDocParser { // export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined { @@ -8782,7 +8657,134 @@ namespace ts { // } // } // } - } + } + + shared parseSourceFileWorker(ScriptTarget languageVersion, bool setParentNodes, ScriptKind scriptKind, function)> setExternalModuleIndicator); + + shared parseSourceFile(string fileName, string sourceText, ScriptTarget languageVersion, bool setParentNodes, optional scriptKind, optional)>> setExternalModuleIndicatorOverride) { + scriptKind = ensureScriptKind(fileName, scriptKind); +// +// if (scriptKind == ScriptKind.JSON) { +// const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes); +// convertToObjectWorker(result, result.statements[0]?.expression, result.parseDiagnostics, /*returnValue*/ false, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined); +// result.referencedFiles = emptyArray; +// result.typeReferenceDirectives = emptyArray; +// result.libReferenceDirectives = emptyArray; +// result.amdDependencies = emptyArray; +// result.hasNoDefaultLib = false; +// result.pragmas = emptyMap as ReadonlyPragmaMap; +// return result; +// } +// + initializeState(fileName, sourceText, languageVersion, scriptKind); + + auto result = parseSourceFileWorker(languageVersion, setParentNodes, *scriptKind, setExternalModuleIndicatorOverride ? *setExternalModuleIndicatorOverride : setExternalModuleIndicator); +// +// clearState(); + + return result; + } +// +// export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName | undefined { +// // Choice of `isDeclarationFile` should be arbitrary +// initializeState("", content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS); +// // Prime the scanner. +// nextToken(); +// const entityName = parseEntityName(/*allowReservedWords*/ true); +// const isInvalid = token() == SyntaxKind::EndOfFileToken && !parseDiagnostics.length; +// clearState(); +// return isInvalid ? entityName : undefined; +// } +// +// export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): JsonSourceFile { +// initializeState(fileName, sourceText, languageVersion, syntaxCursor, ScriptKind.JSON); +// sourceFlags = contextFlags; +// +// // Prime the scanner. +// nextToken(); +// const pos = getNodePos(); +// let statements, endOfFileToken; +// if (token() == SyntaxKind::EndOfFileToken) { +// statements = createNodeArray([], pos, pos); +// endOfFileToken = parseTokenNode(); +// } +// else { +// // Loop and synthesize an ArrayLiteralExpression if there are more than +// // one top-level expressions to ensure all input text is consumed. +// let expressions: Expression[] | Expression | undefined; +// while (token() !== SyntaxKind::EndOfFileToken) { +// let expression; +// switch (token()) { +// case SyntaxKind::OpenBracketToken: +// expression = parseArrayLiteralExpression(); +// break; +// case SyntaxKind::TrueKeyword: +// case SyntaxKind::FalseKeyword: +// case SyntaxKind::NullKeyword: +// expression = parseTokenNode(); +// break; +// case SyntaxKind::MinusToken: +// if (lookAhead(() => nextToken() == SyntaxKind::NumericLiteral && nextToken() !== SyntaxKind::ColonToken)) { +// expression = parsePrefixUnaryExpression() as JsonMinusNumericLiteral; +// } +// else { +// expression = parseObjectLiteralExpression(); +// } +// break; +// case SyntaxKind::NumericLiteral: +// case SyntaxKind::StringLiteral: +// if (lookAhead(() => nextToken() !== SyntaxKind::ColonToken)) { +// expression = parseLiteralNode() as StringLiteral | NumericLiteral; +// break; +// } +// // falls through +// default: +// expression = parseObjectLiteralExpression(); +// break; +// } +// +// // Error recovery: collect multiple top-level expressions +// if (expressions && isArray(expressions)) { +// expressions.push(expression); +// } +// else if (expressions) { +// expressions = [expressions, expression]; +// } +// else { +// expressions = expression; +// if (token() !== SyntaxKind::EndOfFileToken) { +// parseErrorAtCurrentToken(Diagnostics.Unexpected_token); +// } +// } +// } +// +// const expression = isArray(expressions) ? finishNode(factory.createArrayLiteralExpression(expressions), pos) : Debug.checkDefined(expressions); +// const statement = factory.createExpressionStatement(expression) as JsonObjectExpressionStatement; +// finishNode(statement, pos); +// statements = createNodeArray([statement], pos); +// endOfFileToken = parseExpectedToken(SyntaxKind::EndOfFileToken, Diagnostics.Unexpected_token); +// } +// +// // Set source file so that errors will be reported with this file name +// const sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false, statements, endOfFileToken, sourceFlags, noop); +// +// if (setParentNodes) { +// fixupParentReferences(sourceFile); +// } +// +// sourceFile.nodeCount = nodeCount; +// sourceFile.identifierCount = identifierCount; +// sourceFile.identifiers = identifiers; +// sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); +// if (jsDocDiagnostics) { +// sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); +// } +// +// const result = sourceFile as JsonSourceFile; +// clearState(); +// return result; +// } +// // // namespace IncrementalParser { // export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile { @@ -9670,4 +9672,4 @@ namespace ts { // return (lhs as PropertyAccessExpression).name.escapedText == (rhs as PropertyAccessExpression).name.escapedText && // tagNamesAreEquivalent((lhs as PropertyAccessExpression).expression as JsxTagNameExpression, (rhs as PropertyAccessExpression).expression as JsxTagNameExpression); // } -} + } diff --git a/src/path.h b/src/path.h new file mode 100644 index 0000000..b5daa77 --- /dev/null +++ b/src/path.h @@ -0,0 +1,39 @@ +#pragma once + +#include ; + +namespace ts { + + using std::string; + + /** + * Normalize path separators, converting `\` into `/`. + */ + string normalizeSlashes(const string &path) { + const index = path.indexOf("\\"); + if (index === -1) { + return path; + } + backslashRegExp.lastIndex = index; // prime regex with known position + return path.replace(backslashRegExp, directorySeparator); + } + + string normalizePath(const string &path) { + path = normalizeSlashes(path); + // Most paths don't require normalization + if (!relativePathSegmentRegExp.test(path)) { + return path; + } + // Some paths only require cleanup of `/./` or leading `./` + const simplified = path.replace(/\/\.\//g, "/").replace(/^\.\//, ""); + if (simplified !== path) { + path = simplified; + if (!relativePathSegmentRegExp.test(path)) { + return path; + } + } + // Other paths require full normalization + const normalized = getPathFromPathComponents(reducePathComponents(getPathComponents(path))); + return normalized && hasTrailingDirectorySeparator(path) ? ensureTrailingDirectorySeparator(normalized) : normalized; + } +} diff --git a/src/tests/test_core.cpp b/src/tests/test_core.cpp index 9c6b2b1..4fc890d 100644 --- a/src/tests/test_core.cpp +++ b/src/tests/test_core.cpp @@ -59,14 +59,14 @@ struct OptionalRef: public optional { //}; TEST(core, optionalNode) { - optional i; - EXPECT_EQ(i.has_value(), false); + sharedOpt i; + EXPECT_EQ(!!i, false); - i.emplace(Identifier()); - EXPECT_EQ(i.has_value(), true); + i = make_shared(); + EXPECT_EQ(!!i, true); - auto fn = [](OptionalNode node) { - resolve(node).to().escapedText = "changed"; + auto fn = [](sharedOpt node) { + node->to().escapedText = "changed"; }; fn(i); @@ -75,31 +75,192 @@ TEST(core, optionalNode) { EXPECT_EQ(i->escapedText, "changed"); } -SyntaxKind takeUnion(BaseUnion &node) { - return node.kind(); +struct TestEnum { + constexpr static auto a = "a", b = "b", c = "c"; +}; + +TEST(core, constHash) { + int i = 0; + + auto b = "b"; + + switch (const_hash(b)) { + case const_hash(TestEnum::a): + i = 1; + break; + case const_hash(TestEnum::b): + i = 2; + break; + case const_hash(TestEnum::c): + i = 3; + break; + } + + EXPECT_EQ(i, 2); +} + +TEST(core, switchString) { + int i = 0; + + auto b = "b"; + + switch (const_hash(b)) { + case "a"_hash: + i = 1; + break; + case "b"_hash: + i = 2; + break; + case "c"_hash: + i = 3; + break; + } + + EXPECT_EQ(i, 2); +} + +shared visitNode(const function(shared)> &cbNode, sharedOpt node) { + if (! node) return nullptr; + return cbNode(node); +} + +TEST(core, nodeVisitAlternative) { + shared_ptr empty; + shared_ptr a = make_shared(); + shared_ptr s = make_shared(); + + EXPECT_EQ(a->kind, SyntaxKind::Identifier); + + a = make_shared(); + a = s; + + visitNode([&a](auto n) { + EXPECT_EQ(&(*n), &(*a)) << "Same reference is passed"; + return nullptr; + }, a); } -SyntaxKind takeNode(const Node &node) { - return node.kind; +//variant>, optional> operator || (bool a, optional &b) { +// if (!a) return b; +// return nullopt; +//}; + +void acceptShared(shared node) { + if (node->is()) { + node->to().escapedText = "changed"; + } } -SyntaxKind takeOptionalNode(OptionalNode node) { - return resolve(node).kind; +//TEST(core, passNodeUnionToSharedNode) { +// { +// NodeUnion entity; +// EXPECT_EQ(entity.is(), true); +// acceptShared(entity); +// } +// +//// { +//// NodeUnion entity{Identifier()}; +//// acceptShared(entity); +//// } +//} + +TEST(core, passNodeToShared) { + { + Identifier node; + acceptShared(make_shared(node)); + EXPECT_EQ(node.escapedText, ""); + } + + { + auto node = make_shared(); + acceptShared(node); + EXPECT_EQ(node->escapedText, "changed"); + } +} + +TEST(core, logicalOrOverload) { + sharedOpt empty; + sharedOpt a = make_shared(); + sharedOpt b = make_shared(); + sharedOpt c = make_shared(); + + EXPECT_EQ(a.get(), a.get()); + EXPECT_EQ(a.get(), (a || b).get()); + EXPECT_EQ(a.get(), (a || empty).get()); + EXPECT_EQ(a.get(), (empty || a).get()); + EXPECT_EQ(empty.get(), (empty || empty).get()); + + EXPECT_EQ(b.get(), (empty || b || a).get()); + + EXPECT_EQ(a.get(), (a || b || c).get()); + EXPECT_EQ(b.get(), (empty || b || c).get()); + EXPECT_EQ(c.get(), (empty || empty || c).get()); +} + +//TEST(core, assignUnionKeepsRef) { +// //this is important so that moving around NodeUnion (even accidentally via by-value) doesn't mean we lose the reference +// //since NodeUnion should act as regular {} in JS. +// NodeUnion i1; +// EXPECT_EQ(i1.kind(), SyntaxKind::Identifier); +// i1.to(); +// EXPECT_EQ(i1.kind(), SyntaxKind::SourceFile); +// +// NodeUnion i2 = i1; +// EXPECT_EQ(i2.kind(), SyntaxKind::SourceFile); +// EXPECT_EQ(&(*i1.node), &(*i2.node)); +//} + + +//NodeUnion has no type related semantics, just meta-data +SyntaxKind takeUnion(shared node) { + return node->kind; +} + +SyntaxKind takeNode(shared node) { + return node->kind; +} + +SyntaxKind takeOptionalNode(sharedOpt node) { + if (node) return node->kind; + return SyntaxKind::Unknown; +} + +SyntaxKind takeOptionalNodeUnion(sharedOpt node) { + if (node) return node->kind; + return SyntaxKind::Unknown; +} + +TEST(core, ParameterDeclaration) { + auto p = make_shared(); + + EXPECT_EQ(takeUnion(p->name), SyntaxKind::Identifier); + EXPECT_EQ(takeNode(p->name), SyntaxKind::Identifier); + EXPECT_EQ(takeOptionalNode(p->name), SyntaxKind::Identifier); + EXPECT_EQ(takeOptionalNodeUnion(p->name), SyntaxKind::Identifier); } TEST(core, nodeUnion) { - NodeUnion i1; + shared i1 = make_shared(); EXPECT_EQ(takeUnion(i1), SyntaxKind::Identifier); EXPECT_EQ(takeNode(i1), SyntaxKind::Identifier); + EXPECT_EQ(takeOptionalNode(i1), SyntaxKind::Identifier); + EXPECT_EQ(takeOptionalNodeUnion(i1), SyntaxKind::Identifier); - NodeUnion i2{SourceFile()}; + shared i2(new SourceFile); EXPECT_EQ(takeUnion(i2), SyntaxKind::SourceFile); EXPECT_EQ(takeNode(i2), SyntaxKind::SourceFile); + EXPECT_EQ(takeOptionalNode(i2), SyntaxKind::SourceFile); + EXPECT_EQ(takeOptionalNodeUnion(i2), SyntaxKind::SourceFile); - EXPECT_EQ(takeOptionalNode(i1), SyntaxKind::Identifier); - optional> o1; - o1.emplace(Identifier()); + sharedOpt o1(new Identifier); + EXPECT_EQ(takeUnion(o1), SyntaxKind::Identifier); + EXPECT_EQ(takeNode(o1), SyntaxKind::Identifier); EXPECT_EQ(takeOptionalNode(o1), SyntaxKind::Identifier); + EXPECT_EQ(takeOptionalNodeUnion(o1), SyntaxKind::Identifier); + + sharedOpt o2; + EXPECT_EQ(takeOptionalNode(o2), SyntaxKind::Unknown); + EXPECT_EQ(takeOptionalNodeUnion(o2), SyntaxKind::Unknown); } TEST(core, node2) { @@ -128,100 +289,6 @@ TEST(core, node) { EXPECT_EQ(node.to().escapedText, "id"); } -//TEST(core, nodeUnion) { -// NodeType node; -// -// EXPECT_EQ(node.kinds()[0], SyntaxKind::Identifier); -// EXPECT_EQ(node.kinds()[1], SyntaxKind::QualifiedName); -// -// EXPECT_EQ(node.contains(SyntaxKind::Identifier), true); -// EXPECT_EQ(node.contains(SyntaxKind::QualifiedName), true); -// EXPECT_EQ(node.contains(SyntaxKind::TypeParameter), false); -// -//// using MyIds = variant; -////// struct MyIds: NodeType{}; -//// -//// auto id = createBaseNode(); -//// id.to().escapedText = "id"; -//// -//// auto id2 = id.toUnion(); -//} - -struct A { - constexpr static auto kind = types::SyntaxKind::TypeParameter; -}; - -#include - -struct B { -// using kind = types::SyntaxKind::Identifier; - constexpr static auto kind = types::SyntaxKind::Identifier; -}; - -//template