From 7f5391ede044d9c3b233c0a544db0738a88e9694 Mon Sep 17 00:00:00 2001 From: joshvera Date: Tue, 4 Jun 2019 17:51:08 -0400 Subject: [PATCH 1/8] ++haskell-tree-sitter for mapped types --- vendor/haskell-tree-sitter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/haskell-tree-sitter b/vendor/haskell-tree-sitter index cc1b4fd66..ee9760ae1 160000 --- a/vendor/haskell-tree-sitter +++ b/vendor/haskell-tree-sitter @@ -1 +1 @@ -Subproject commit cc1b4fd6673c4d749bbba7abe6232fa60f3921de +Subproject commit ee9760ae10477c60a04f7df4b1b0fade33af5548 From 6346865828df03cef130ee35f851e5efaf8b832e Mon Sep 17 00:00:00 2001 From: joshvera Date: Tue, 4 Jun 2019 18:48:28 -0400 Subject: [PATCH 2/8] bump-haskell-tree-sitter --- vendor/haskell-tree-sitter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vendor/haskell-tree-sitter b/vendor/haskell-tree-sitter index ee9760ae1..4d1b34fab 160000 --- a/vendor/haskell-tree-sitter +++ b/vendor/haskell-tree-sitter @@ -1 +1 @@ -Subproject commit ee9760ae10477c60a04f7df4b1b0fade33af5548 +Subproject commit 4d1b34fabe021ce5fc726c95ed8097de3773075d From 33e267151a3c69cc2c8f81557127885bca4e5a4a Mon Sep 17 00:00:00 2001 From: joshvera Date: Wed, 5 Jun 2019 14:17:12 -0400 Subject: [PATCH 3/8] WIP --- semantic.cabal | 1 + src/Data/Language.hs | 7 +- src/Language/TSX/Assignment.hs | 975 +++++++++++++++++++++++++++++++ src/Language/TSX/Resolution.hs | 128 ++++ src/Language/TSX/Syntax.hs | 7 + src/Language/TSX/Syntax/JSX.hs | 115 ++++ src/Language/TSX/Syntax/Types.hs | 143 +++++ src/Parsing/Parser.hs | 1 + src/Semantic/Api/Bridge.hs | 2 + src/Semantic/Api/Diffs.hs | 5 +- src/Semantic/Api/Terms.hs | 5 +- 11 files changed, 1383 insertions(+), 6 deletions(-) create mode 100644 src/Language/TSX/Assignment.hs create mode 100644 src/Language/TSX/Resolution.hs create mode 100644 src/Language/TSX/Syntax.hs create mode 100644 src/Language/TSX/Syntax/JSX.hs create mode 100644 src/Language/TSX/Syntax/Types.hs diff --git a/semantic.cabal b/semantic.cabal index 8ede2c97a..e573ed553 100644 --- a/semantic.cabal +++ b/semantic.cabal @@ -320,6 +320,7 @@ library , tree-sitter-python , tree-sitter-ruby , tree-sitter-typescript + , tree-sitter-tsx , tree-sitter-java ghc-options: -Wall -Wmissing-export-lists -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fno-warn-name-shadowing -j if flag(release) diff --git a/src/Data/Language.hs b/src/Data/Language.hs index 3b881c26d..d4ff8fe6f 100644 --- a/src/Data/Language.hs +++ b/src/Data/Language.hs @@ -36,6 +36,7 @@ data Language | Ruby | TypeScript | PHP + | TSX deriving (Eq, Generic, Ord, Read, Show, Bounded, Hashable, ToJSON, Named, Enum, MessageField, NFData) class SLanguage (lang :: Language) where @@ -129,7 +130,7 @@ languageForType mediaType = case mediaType of ".go" -> Go ".js" -> JavaScript ".ts" -> TypeScript - ".tsx" -> TypeScript + ".tsx" -> TSX ".jsx" -> JSX ".py" -> Python ".php" -> PHP @@ -144,7 +145,9 @@ extensionsForLanguage language = case language of PHP -> [".php"] Python -> [".py"] Ruby -> [".rb"] - TypeScript -> [".ts", ".tsx", ".d.tsx"] + TypeScript -> [".ts"] + TSX -> [".tsx", ".d.tsx"] + JSX -> [".jsx"] _ -> [] -- | Return a language based on a FilePath's extension, or Nothing if extension is not found or not supported. diff --git a/src/Language/TSX/Assignment.hs b/src/Language/TSX/Assignment.hs new file mode 100644 index 000000000..26967b955 --- /dev/null +++ b/src/Language/TSX/Assignment.hs @@ -0,0 +1,975 @@ +{-# LANGUAGE DataKinds, RankNTypes, TypeOperators #-} +{-# OPTIONS_GHC -fno-warn-orphans #-} -- FIXME +module Language.TSX.Assignment +( assignment +, Syntax +, Grammar +, Term +) where + +import Assigning.Assignment hiding (Assignment, Error) +import Data.Abstract.Name (name) +import qualified Data.Abstract.ScopeGraph as ScopeGraph (AccessControl(..)) +import qualified Assigning.Assignment as Assignment +import Data.Sum +import Data.Syntax + ( contextualize + , emptyTerm + , handleError + , infixContext + , makeTerm + , makeTerm' + , makeTerm'' + , makeTerm1 + , parseError + , postContextualize + ) +import qualified Data.Syntax as Syntax +import qualified Data.Syntax.Comment as Comment +import qualified Data.Syntax.Declaration as Declaration +import qualified Data.Syntax.Expression as Expression +import qualified Data.Syntax.Literal as Literal +import qualified Data.Syntax.Statement as Statement +import qualified Data.Syntax.Type as Type +import qualified Data.Term as Term +import qualified Language.TSX.Syntax as TSX.Syntax +import qualified Language.TypeScript.Resolution as TypeScript.Resolution +import Prologue +import TreeSitter.TSX as Grammar + +-- | The type of TSX syntax. +type Syntax = '[ + Comment.Comment + , Comment.HashBang + , Declaration.Class + , Declaration.Function + , Declaration.Method + , Declaration.MethodSignature + , Declaration.InterfaceDeclaration + , Declaration.PublicFieldDefinition + , Declaration.VariableDeclaration + , Declaration.TypeAlias + , Expression.Plus + , Expression.Minus + , Expression.Times + , Expression.DividedBy + , Expression.Modulo + , Expression.Power + , Expression.Negate + , Expression.FloorDivision + , Expression.BAnd + , Expression.BOr + , Expression.BXOr + , Expression.LShift + , Expression.RShift + , Expression.UnsignedRShift + , Expression.Complement + , Expression.And + , Expression.Not + , Expression.Or + , Expression.XOr + , Expression.Call + , Expression.Cast + , Expression.LessThan + , Expression.LessThanEqual + , Expression.GreaterThan + , Expression.GreaterThanEqual + , Expression.Equal + , Expression.StrictEqual + , Expression.Comparison + , Expression.Enumeration + , Expression.MemberAccess + , Expression.NonNullExpression + , Expression.ScopeResolution + , Expression.SequenceExpression + , Expression.Subscript + , Expression.Member + , Expression.Delete + , Expression.Void + , Expression.Typeof + , Expression.InstanceOf + , Expression.New + , Expression.Await + , Expression.This + , Literal.Array + , Literal.Boolean + , Literal.Float + , Literal.Hash + , Literal.Integer + , Literal.KeyValue + , Literal.Null + , Literal.String + , Literal.TextElement + , Literal.Regex + , Statement.Assignment + , Statement.Break + , Statement.Catch + , Statement.Continue + , Statement.DoWhile + , Statement.Else + , Statement.Finally + , Statement.For + , Statement.ForEach + , Statement.If + , Statement.Match + , Statement.Pattern + , Statement.Retry + , Statement.Return + , Statement.ScopeEntry + , Statement.ScopeExit + , Statement.Statements + , Statement.Throw + , Statement.Try + , Statement.While + , Statement.Yield + , Syntax.AccessibilityModifier + , Syntax.Empty + , Syntax.Error + , Syntax.Identifier + , Syntax.Context + , Type.Readonly + , Type.TypeParameters + , TSX.Syntax.TypeParameter + , TSX.Syntax.Constraint + , TSX.Syntax.ParenthesizedType + , TSX.Syntax.DefaultType + , TSX.Syntax.PredefinedType + , TSX.Syntax.TypeIdentifier + , TSX.Syntax.NestedIdentifier + , TSX.Syntax.NestedTypeIdentifier + , TSX.Syntax.GenericType + , TSX.Syntax.TypeArguments + , TSX.Syntax.TypePredicate + , TSX.Syntax.CallSignature + , TSX.Syntax.ConstructSignature + , TSX.Syntax.ArrayType + , TSX.Syntax.LookupType + , TSX.Syntax.FlowMaybeType + , TSX.Syntax.TypeQuery + , TSX.Syntax.IndexTypeQuery + , TSX.Syntax.ThisType + , TSX.Syntax.ExistentialType + , TSX.Syntax.AbstractMethodSignature + , TSX.Syntax.IndexSignature + , TSX.Syntax.ObjectType + , TSX.Syntax.LiteralType + , TSX.Syntax.Union + , TSX.Syntax.Intersection + , TSX.Syntax.Module + , TSX.Syntax.InternalModule + , TSX.Syntax.FunctionType + , TSX.Syntax.Tuple + , TSX.Syntax.Constructor + , TSX.Syntax.TypeAssertion + , TSX.Syntax.ImportAlias + , TSX.Syntax.Debugger + , TSX.Syntax.ShorthandPropertyIdentifier + , TSX.Syntax.Super + , TSX.Syntax.Undefined + , TSX.Syntax.ClassHeritage + , TSX.Syntax.AbstractClass + , TSX.Syntax.ImplementsClause + , TSX.Syntax.JsxElement + , TSX.Syntax.JsxSelfClosingElement + , TSX.Syntax.JsxOpeningElement + , TSX.Syntax.JsxText + , TSX.Syntax.JsxClosingElement + , TSX.Syntax.JsxExpression + , TSX.Syntax.JsxAttribute + , TSX.Syntax.JsxFragment + , TSX.Syntax.JsxNamespaceName + , TSX.Syntax.OptionalParameter + , TSX.Syntax.RequiredParameter + , TSX.Syntax.RestParameter + , TSX.Syntax.PropertySignature + , TSX.Syntax.AmbientDeclaration + , TSX.Syntax.EnumDeclaration + , TSX.Syntax.ExtendsClause + , TSX.Syntax.AmbientFunction + , TSX.Syntax.ImportRequireClause + , TSX.Syntax.ImportClause + , TSX.Syntax.LabeledStatement + , TSX.Syntax.Annotation + , TSX.Syntax.With + , TSX.Syntax.ForOf + , TSX.Syntax.Update + , TSX.Syntax.ComputedPropertyName + , TSX.Syntax.Decorator + , TSX.Syntax.Import + , TSX.Syntax.QualifiedAliasedImport + , TSX.Syntax.SideEffectImport + , TSX.Syntax.DefaultExport + , TSX.Syntax.QualifiedExport + , TSX.Syntax.QualifiedExportFrom + , TSX.Syntax.JavaScriptRequire + , [] + , Statement.StatementBlock + , TSX.Syntax.MetaProperty + , TSX.Syntax.AnnotatedExpression + ] + +type Term = Term.Term (Sum Syntax) Location +type Assignment = Assignment.Assignment [] Grammar + +-- | Assignment from AST in TSX’s grammar onto a program in TSX’s syntax. +assignment :: Assignment Term +assignment = handleError $ makeTerm <$> symbol Program <*> children (Statement.Statements <$> manyTerm statement) <|> parseError + +expression :: Assignment Term +expression = handleError everything + where + everything = choice [ + typeAssertion, + asExpression, + nonNullExpression', + importAlias', + internalModule, + super, + object, + array, + jsxElement', + jsxFragment, + class', + anonymousClass, + function, + arrowFunction, + assignmentExpression, + augmentedAssignmentExpression, + awaitExpression, + unaryExpression, + binaryExpression, + ternaryExpression, + updateExpression, + callExpression, + memberExpression, + newExpression, + parenthesizedExpression, + subscriptExpression, + yieldExpression, + this, + number, + string, + templateString, + regex, + true, + false, + null', + undefined', + identifier + ] + +undefined' :: Assignment Term +undefined' = makeTerm <$> symbol Grammar.Undefined <*> (TSX.Syntax.Undefined <$ rawSource) + +assignmentExpression :: Assignment Term +assignmentExpression = makeTerm <$> symbol AssignmentExpression <*> children (Statement.Assignment [] <$> term (memberExpression <|> subscriptExpression <|> identifier <|> destructuringPattern) <*> expression) + +augmentedAssignmentExpression :: Assignment Term +augmentedAssignmentExpression = makeTerm' <$> symbol AugmentedAssignmentExpression <*> children (infixTerm (memberExpression <|> subscriptExpression <|> identifier <|> destructuringPattern) (term expression) [ + assign Expression.Plus <$ symbol AnonPlusEqual + , assign Expression.Minus <$ symbol AnonMinusEqual + , assign Expression.Times <$ symbol AnonStarEqual + , assign Expression.DividedBy <$ symbol AnonSlashEqual + , assign Expression.Modulo <$ symbol AnonPercentEqual + , assign Expression.BXOr <$ symbol AnonCaretEqual + , assign Expression.BAnd <$ symbol AnonAmpersandEqual + , assign Expression.RShift <$ symbol AnonRAngleRAngleEqual + , assign Expression.LShift <$ symbol AnonLAngleLAngleEqual + , assign Expression.UnsignedRShift <$ symbol AnonRAngleRAngleRAngleEqual + , assign Expression.LShift <$ symbol AnonLAngleLAngleEqual + , assign Expression.BOr <$ symbol AnonPipeEqual ]) + where assign :: (f :< Syntax) => (Term -> Term -> f Term) -> Term -> Term -> Sum Syntax Term + assign c l r = inject (Statement.Assignment [] l (makeTerm1 (c l r))) + + +awaitExpression :: Assignment Term +awaitExpression = makeTerm <$> symbol Grammar.AwaitExpression <*> children (Expression.Await <$> term expression) + +unaryExpression :: Assignment Term +unaryExpression = symbol Grammar.UnaryExpression >>= \ loc -> + makeTerm loc . Expression.Not <$> children (symbol AnonBang *> term expression) + <|> makeTerm loc . Expression.Complement <$> children (symbol AnonTilde *> term expression) + <|> makeTerm loc . Expression.Negate <$> children ((symbol AnonMinus <|> symbol AnonPlus) *> term expression) + <|> makeTerm loc . Expression.Typeof <$> children (symbol AnonTypeof *> term expression) + <|> makeTerm loc . Expression.Void <$> children (symbol AnonVoid *> term expression) + <|> makeTerm loc . Expression.Delete <$> children (symbol AnonDelete *> term expression) + +ternaryExpression :: Assignment Term +ternaryExpression = makeTerm <$> symbol Grammar.TernaryExpression <*> children (Statement.If <$> term expression <*> term expression <*> term expression) + +memberExpression :: Assignment Term +memberExpression = makeTerm <$> (symbol Grammar.MemberExpression <|> symbol Grammar.MemberExpression') <*> children (Expression.MemberAccess <$> term expression <*> propertyIdentifier) + +newExpression :: Assignment Term +newExpression = makeTerm <$> symbol Grammar.NewExpression <*> children (Expression.New <$> term constructableExpression <*> (typeArguments' <|> emptyTerm) <*> (arguments <|> pure [])) + +constructableExpression :: Assignment Term +constructableExpression = choice [ + this + , identifier + , number + , string + , templateString + , regex + , true + , false + , null' + , undefined' + , object + , array + , function + , arrowFunction + , class' + , anonymousClass + , parenthesizedExpression + , subscriptExpression + , memberExpression + , metaProperty + , newExpression + ] + +metaProperty :: Assignment Term +metaProperty = makeTerm <$> symbol Grammar.MetaProperty <*> (TSX.Syntax.MetaProperty <$ rawSource) + +updateExpression :: Assignment Term +updateExpression = makeTerm <$> symbol Grammar.UpdateExpression <*> children (TSX.Syntax.Update <$> term expression) + +yieldExpression :: Assignment Term +yieldExpression = makeTerm <$> symbol Grammar.YieldExpression <*> children (Statement.Yield <$> term (expression <|> emptyTerm)) + +this :: Assignment Term +this = makeTerm <$> symbol Grammar.This <*> (Expression.This <$ rawSource) + +regex :: Assignment Term +regex = makeTerm <$> symbol Grammar.Regex <*> (Literal.Regex <$> source) + +null' :: Assignment Term +null' = makeTerm <$> symbol Null <*> (Literal.Null <$ rawSource) + +anonymousClass :: Assignment Term +anonymousClass = makeTerm <$> symbol Grammar.AnonymousClass <*> children (Declaration.Class [] <$> emptyTerm <*> (classHeritage' <|> pure []) <*> classBodyStatements) + +abstractClass :: Assignment Term +abstractClass = makeTerm <$> symbol Grammar.AbstractClass <*> children (TSX.Syntax.AbstractClass <$> term typeIdentifier <*> (term typeParameters <|> emptyTerm) <*> (classHeritage' <|> pure []) <*> classBodyStatements) + +abstractMethodSignature :: Assignment Term +abstractMethodSignature = makeSignature <$> symbol Grammar.AbstractMethodSignature <*> children ((,,) <$> accessibilityModifier' <*> term propertyName <*> callSignatureParts) + where makeSignature loc (modifier, propertyName, (typeParams, params, annotation)) = makeTerm loc (TSX.Syntax.AbstractMethodSignature [typeParams, annotation] propertyName params modifier) + +classHeritage' :: Assignment [Term] +classHeritage' = symbol Grammar.ClassHeritage *> children ((mappend `on` toList) <$> optional (term extendsClause) <*> optional (term implementsClause')) + +extendsClause :: Assignment Term +extendsClause = makeTerm <$> symbol Grammar.ExtendsClause <*> children (TSX.Syntax.ExtendsClause <$> manyTerm (typeReference <|> expression)) + +typeReference :: Assignment Term +typeReference = typeIdentifier <|> nestedTypeIdentifier <|> genericType + +implementsClause' :: Assignment Term +implementsClause' = makeTerm <$> symbol Grammar.ImplementsClause <*> children (TSX.Syntax.ImplementsClause <$> manyTerm ty) + +super :: Assignment Term +super = makeTerm <$> symbol Grammar.Super <*> (TSX.Syntax.Super <$ rawSource) + +typeAssertion :: Assignment Term +typeAssertion = makeTerm <$> symbol Grammar.TypeAssertion <*> children (TSX.Syntax.TypeAssertion <$> term typeArguments' <*> term expression) + +asExpression :: Assignment Term +asExpression = makeTerm <$> symbol AsExpression <*> children (Expression.Cast <$> term expression <*> term (ty <|> templateString)) + +templateString :: Assignment Term +templateString = makeTerm <$> symbol TemplateString <*> children (Literal.String <$> manyTerm templateSubstitution) + +templateSubstitution :: Assignment Term +templateSubstitution = symbol TemplateSubstitution *> children (term expressions) + +nonNullExpression' :: Assignment Term +nonNullExpression' = makeTerm <$> symbol Grammar.NonNullExpression <*> children (Expression.NonNullExpression <$> term expression) + +importAlias' :: Assignment Term +importAlias' = makeTerm <$> symbol Grammar.ImportAlias <*> children (TSX.Syntax.ImportAlias <$> term identifier <*> term (identifier <|> nestedIdentifier)) + +number :: Assignment Term +number = makeTerm <$> symbol Grammar.Number <*> (Literal.Float <$> source) + +string :: Assignment Term +string = makeTerm <$> symbol Grammar.String <*> (Literal.TextElement <$> source) + +true :: Assignment Term +true = makeTerm <$> symbol Grammar.True <*> (Literal.true <$ rawSource) + +false :: Assignment Term +false = makeTerm <$> symbol Grammar.False <*> (Literal.false <$ rawSource) + +identifier :: Assignment Term +identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') <*> (Syntax.Identifier . name <$> source) + +class' :: Assignment Term +class' = makeClass <$> symbol Class <*> children ((,,,,) <$> manyTerm decorator <*> term typeIdentifier <*> (symbol TypeParameters *> children (manyTerm typeParameter') <|> pure []) <*> (classHeritage' <|> pure []) <*> classBodyStatements) + where makeClass loc (decorators, expression, typeParams, classHeritage, statements) = makeTerm loc (Declaration.Class (decorators <> typeParams) expression classHeritage statements) + +object :: Assignment Term +object = makeTerm <$> (symbol Object <|> symbol ObjectPattern) <*> children (Literal.Hash <$> manyTerm (pair <|> spreadElement <|> methodDefinition <|> assignmentPattern <|> shorthandPropertyIdentifier)) + +array :: Assignment Term +array = makeTerm <$> (symbol Array <|> symbol ArrayPattern) <*> children (Literal.Array <$> manyTerm (expression <|> spreadElement)) + +jsxElement' :: Assignment Term +jsxElement' = choice [ jsxElement, jsxSelfClosingElement ] + +jsxElement :: Assignment Term +jsxElement = makeTerm <$> symbol Grammar.JsxElement <*> children (TSX.Syntax.JsxElement <$> term jsxOpeningElement' <*> manyTerm jsxChild <*> term jsxClosingElement') + +jsxFragment :: Assignment Term +jsxFragment = makeTerm <$> symbol Grammar.JsxFragment <*> children (TSX.Syntax.JsxFragment <$> manyTerm jsxChild) + +jsxChild :: Assignment Term +jsxChild = choice [ jsxElement', jsxExpression', jsxText ] + +jsxSelfClosingElement :: Assignment Term +jsxSelfClosingElement = makeTerm <$> symbol Grammar.JsxSelfClosingElement <*> children (TSX.Syntax.JsxSelfClosingElement <$> term jsxElementName <*> manyTerm jsxAttribute') + +jsxAttribute' :: Assignment Term +jsxAttribute' = jsxAttribute <|> jsxExpression' + +jsxOpeningElement' :: Assignment Term +jsxOpeningElement' = makeTerm <$> symbol Grammar.JsxOpeningElement <*> children (TSX.Syntax.JsxOpeningElement <$> term jsxElementName <*> manyTerm jsxAttribute') + +jsxElementName :: Assignment Term +jsxElementName = choice [ identifier, nestedIdentifier, jsxNamespaceName ] + +jsxNamespaceName :: Assignment Term +jsxNamespaceName = makeTerm <$> symbol Grammar.JsxNamespaceName <*> children (TSX.Syntax.JsxNamespaceName <$> identifier <*> identifier) + +jsxExpression' :: Assignment Term +jsxExpression' = makeTerm <$> symbol Grammar.JsxExpression <*> children (TSX.Syntax.JsxExpression <$> term (expressions <|> spreadElement <|> emptyTerm)) + +jsxText :: Assignment Term +jsxText = makeTerm <$> symbol Grammar.JsxText <*> (TSX.Syntax.JsxText <$> source) + +jsxClosingElement' :: Assignment Term +jsxClosingElement' = makeTerm <$> symbol Grammar.JsxClosingElement <*> children (TSX.Syntax.JsxClosingElement <$> term jsxElementName) + +jsxAttribute :: Assignment Term +jsxAttribute = makeTerm <$> symbol Grammar.JsxAttribute <*> children (TSX.Syntax.JsxAttribute <$> term (propertyIdentifier <|> jsxNamespaceName) <*> (term jsxAttributeValue <|> emptyTerm)) + where jsxAttributeValue = choice [ string, jsxExpression', jsxElement', jsxFragment ] + +propertyIdentifier :: Assignment Term +propertyIdentifier = makeTerm <$> symbol PropertyIdentifier <*> (Syntax.Identifier . name <$> source) + +sequenceExpression :: Assignment Term +sequenceExpression = makeTerm <$> symbol Grammar.SequenceExpression <*> children (Expression.SequenceExpression <$> term expression <*> term expressions) + +expressions :: Assignment Term +expressions = annotatedExpression <|> expression <|> sequenceExpression + +annotatedExpression :: Assignment Term +annotatedExpression = mkAnnotated <$> location <*> expression <*> typeAnnotation' + where mkAnnotated loc expr ann = makeTerm loc (TSX.Syntax.AnnotatedExpression expr ann) + +parameter :: Assignment Term +parameter = requiredParameter + <|> restParameter + <|> optionalParameter + +accessibilityModifier' :: Assignment ScopeGraph.AccessControl +accessibilityModifier' = (symbol AccessibilityModifier >> children (public <|> protected <|> private)) <|> default' + where public = symbol AnonPublic >> pure ScopeGraph.Public + protected = symbol AnonProtected >> pure ScopeGraph.Protected + private = symbol AnonPrivate >> pure ScopeGraph.Private + default' = pure ScopeGraph.Public + + +destructuringPattern :: Assignment Term +destructuringPattern = object <|> array + +spreadElement :: Assignment Term +spreadElement = symbol SpreadElement *> children (term expression) + +readonly' :: Assignment Term +readonly' = makeTerm <$> symbol Readonly <*> (Type.Readonly <$ rawSource) + +methodDefinition :: Assignment Term +methodDefinition = makeMethod <$> + symbol MethodDefinition + <*> children ((,,,,,) <$> accessibilityModifier' <*> (term readonly' <|> emptyTerm) <*> emptyTerm <*> term propertyName <*> callSignatureParts <*> term statementBlock) + where + makeMethod loc (modifier, readonly, receiver, propertyName', (typeParameters', params, ty'), statements) = makeTerm loc (Declaration.Method [readonly, typeParameters', ty'] receiver propertyName' params statements modifier) + +callSignatureParts :: Assignment (Term, [Term], Term) +callSignatureParts = contextualize' <$> Assignment.manyThrough comment (postContextualize' <$> callSignature' <*> many comment) + where + callSignature' = symbol Grammar.CallSignature *> children ((,,) <$> (term typeParameters <|> emptyTerm) <*> formalParameters <*> (term typeAnnotation' <|> emptyTerm)) + contextualize' (cs, (typeParams, formalParams, annotation)) = case nonEmpty cs of + Just cs -> (makeTerm1 (Syntax.Context cs typeParams), formalParams, annotation) + Nothing -> (typeParams, formalParams, annotation) + postContextualize' (typeParams, formalParams, annotation) cs = case nonEmpty cs of + Just cs -> (typeParams, formalParams, makeTerm1 (Syntax.Context cs annotation)) + Nothing -> (typeParams, formalParams, annotation) + +callSignature :: Assignment Term +callSignature = makeTerm <$> symbol Grammar.CallSignature <*> children (TSX.Syntax.CallSignature <$> (fromMaybe <$> emptyTerm <*> optional (term typeParameters)) <*> formalParameters <*> (fromMaybe <$> emptyTerm <*> optional (term typeAnnotation'))) + +constructSignature :: Assignment Term +constructSignature = makeTerm <$> symbol Grammar.ConstructSignature <*> children (TSX.Syntax.ConstructSignature <$> (fromMaybe <$> emptyTerm <*> optional (term typeParameters)) <*> formalParameters <*> (fromMaybe <$> emptyTerm <*> optional (term typeAnnotation'))) + +indexSignature :: Assignment Term +indexSignature = makeTerm <$> symbol Grammar.IndexSignature <*> children (TSX.Syntax.IndexSignature <$> term identifier <*> predefinedTy <*> term typeAnnotation') + +methodSignature :: Assignment Term +methodSignature = makeMethodSignature <$> symbol Grammar.MethodSignature <*> children ((,,,) <$> accessibilityModifier' <*> (term readonly' <|> emptyTerm) <*> term propertyName <*> callSignatureParts) + where makeMethodSignature loc (accessControl, readonly, propertyName, (typeParams, params, annotation)) = makeTerm loc (Declaration.MethodSignature [readonly, typeParams, annotation] propertyName params accessControl) + +formalParameters :: Assignment [Term] +formalParameters = symbol FormalParameters *> children (contextualize' <$> Assignment.manyThrough comment (postContextualize' <$> (concat <$> many ((\as b -> as <> [b]) <$> manyTerm decorator <*> term parameter)) <*> many comment)) + where + contextualize' (cs, formalParams) = case nonEmpty cs of + Just cs -> toList cs <> formalParams + Nothing -> formalParams + postContextualize' formalParams cs = case nonEmpty cs of + Just cs -> formalParams <> toList cs + Nothing -> formalParams + + +decorator :: Assignment Term +decorator = makeTerm <$> symbol Grammar.Decorator <*> children (TSX.Syntax.Decorator <$> term (identifier <|> memberExpression <|> callExpression)) + +typeParameters :: Assignment Term +typeParameters = makeTerm <$> symbol TypeParameters <*> children (Type.TypeParameters <$> manyTerm typeParameter') + +typeAnnotation' :: Assignment Term +typeAnnotation' = makeTerm <$> symbol TypeAnnotation <*> children (TSX.Syntax.Annotation <$> term ty) + +typeParameter' :: Assignment Term +typeParameter' = makeTerm <$> symbol Grammar.TypeParameter <*> children (TSX.Syntax.TypeParameter <$> term typeIdentifier <*> term (constraint <|> emptyTerm) <*> term (defaultType <|> emptyTerm)) + +defaultType :: Assignment Term +defaultType = makeTerm <$> symbol Grammar.DefaultType <*> children (TSX.Syntax.DefaultType <$> term ty) + +constraint :: Assignment Term +constraint = makeTerm <$> symbol Grammar.Constraint <*> children (TSX.Syntax.Constraint <$> term ty) + +function :: Assignment Term +function = makeFunction <$> (symbol Grammar.Function <|> symbol Grammar.GeneratorFunction) <*> children ((,,) <$> term (identifier <|> emptyTerm) <*> callSignatureParts <*> term statementBlock) + where makeFunction loc (id, (typeParams, params, annotation), statements) = makeTerm loc (Declaration.Function [typeParams, annotation] id params statements) + +-- TODO: FunctionSignatures can, but don't have to be ambient functions. +ambientFunction :: Assignment Term +ambientFunction = makeAmbientFunction <$> symbol Grammar.FunctionSignature <*> children ((,) <$> term identifier <*> callSignatureParts) + where makeAmbientFunction loc (id, (typeParams, params, annotation)) = makeTerm loc (TSX.Syntax.AmbientFunction [typeParams, annotation] id params) + +ty :: Assignment Term +ty = primaryType <|> unionType <|> intersectionType <|> functionTy <|> constructorTy + +primaryType :: Assignment Term +primaryType = arrayTy + <|> existentialType + <|> flowMaybeTy + <|> genericType + <|> indexTypeQuery + <|> literalType + <|> lookupType + <|> nestedTypeIdentifier + <|> objectType + <|> parenthesizedTy + <|> predefinedTy + <|> thisType + <|> tupleType + <|> typeIdentifier + <|> typePredicate + <|> typeQuery + +parenthesizedTy :: Assignment Term +parenthesizedTy = makeTerm <$> symbol Grammar.ParenthesizedType <*> children (TSX.Syntax.ParenthesizedType <$> term ty) + +predefinedTy :: Assignment Term +predefinedTy = makeTerm <$> symbol Grammar.PredefinedType <*> (TSX.Syntax.PredefinedType <$> source) + +typeIdentifier :: Assignment Term +typeIdentifier = makeTerm <$> symbol Grammar.TypeIdentifier <*> (TSX.Syntax.TypeIdentifier <$> source) + +nestedIdentifier :: Assignment Term +nestedIdentifier = makeTerm <$> symbol Grammar.NestedIdentifier <*> children (TSX.Syntax.NestedIdentifier <$> term (identifier <|> nestedIdentifier) <*> term identifier) + +nestedTypeIdentifier :: Assignment Term +nestedTypeIdentifier = makeTerm <$> symbol Grammar.NestedTypeIdentifier <*> children (TSX.Syntax.NestedTypeIdentifier <$> term (identifier <|> nestedIdentifier) <*> term typeIdentifier) + +genericType :: Assignment Term +genericType = makeTerm <$> symbol Grammar.GenericType <*> children (TSX.Syntax.GenericType <$> term (typeIdentifier <|> nestedTypeIdentifier) <*> term typeArguments') + +typeArguments' :: Assignment Term +typeArguments' = makeTerm <$> symbol Grammar.TypeArguments <*> children (TSX.Syntax.TypeArguments <$> some (term ty)) + +typePredicate :: Assignment Term +typePredicate = makeTerm <$> symbol Grammar.TypePredicate <*> children (TSX.Syntax.TypePredicate <$> term identifier <*> term ty) + +objectType :: Assignment Term +objectType = makeTerm <$> symbol Grammar.ObjectType <*> children (TSX.Syntax.ObjectType <$> manyTerm (exportStatement <|> propertySignature <|> callSignature <|> constructSignature <|> indexSignature <|> methodSignature)) + +arrayTy :: Assignment Term +arrayTy = makeTerm <$> symbol Grammar.ArrayType <*> children (TSX.Syntax.ArrayType <$> term ty) + +lookupType :: Assignment Term +lookupType = makeTerm <$> symbol Grammar.LookupType <*> children (TSX.Syntax.LookupType <$> term (typeIdentifier <|> nestedTypeIdentifier) <*> term ty) + +flowMaybeTy :: Assignment Term +flowMaybeTy = makeTerm <$> symbol Grammar.FlowMaybeType <*> children (TSX.Syntax.FlowMaybeType <$> term primaryType) + +typeQuery :: Assignment Term +typeQuery = makeTerm <$> symbol Grammar.TypeQuery <*> children (TSX.Syntax.TypeQuery <$> term (identifier <|> nestedIdentifier)) + +indexTypeQuery :: Assignment Term +indexTypeQuery = makeTerm <$> symbol Grammar.IndexTypeQuery <*> children (TSX.Syntax.IndexTypeQuery <$> term (typeIdentifier <|> nestedTypeIdentifier)) + +thisType :: Assignment Term +thisType = makeTerm <$> symbol Grammar.ThisType <*> (TSX.Syntax.ThisType <$> source) + +existentialType :: Assignment Term +existentialType = makeTerm <$> symbol Grammar.ExistentialType <*> (TSX.Syntax.ExistentialType <$> source) + +literalType :: Assignment Term +literalType = makeTerm <$> symbol Grammar.LiteralType <*> children (TSX.Syntax.LiteralType <$> term (number <|> string <|> true <|> false)) + +unionType :: Assignment Term +unionType = makeTerm <$> symbol UnionType <*> children (TSX.Syntax.Union <$> (term ty <|> emptyTerm) <*> term ty) + +intersectionType :: Assignment Term +intersectionType = makeTerm <$> symbol IntersectionType <*> children (TSX.Syntax.Intersection <$> term ty <*> term ty) + +functionTy :: Assignment Term +functionTy = makeTerm <$> symbol Grammar.FunctionType <*> children (TSX.Syntax.FunctionType <$> (fromMaybe <$> emptyTerm <*> optional (term typeParameters)) <*> formalParameters <*> term ty) + +tupleType :: Assignment Term +tupleType = makeTerm <$> symbol TupleType <*> children (TSX.Syntax.Tuple <$> manyTerm ty) + +constructorTy :: Assignment Term +constructorTy = makeTerm <$> symbol ConstructorType <*> children (TSX.Syntax.Constructor <$> (fromMaybe <$> emptyTerm <*> optional (term typeParameters)) <*> formalParameters <*> term ty) + +statementTerm :: Assignment Term +statementTerm = makeTerm <$> symbol StatementBlock <*> children (Statement.Statements <$> manyTerm statement) + +statementBlock :: Assignment Term +statementBlock = makeTerm <$> symbol StatementBlock <*> children (Statement.StatementBlock <$> manyTerm statement) + +classBodyStatements :: Assignment Term +classBodyStatements = makeTerm'' <$> symbol ClassBody <*> children (contextualize' <$> Assignment.manyThrough comment (postContextualize' <$> (concat <$> many ((\as b -> as <> [b]) <$> manyTerm decorator <*> term (methodDefinition <|> publicFieldDefinition <|> methodSignature <|> indexSignature <|> abstractMethodSignature))) <*> many comment)) + where + contextualize' (cs, formalParams) = case nonEmpty cs of + Just cs -> toList cs <> formalParams + Nothing -> formalParams + postContextualize' formalParams cs = case nonEmpty cs of + Just cs -> formalParams <> toList cs + Nothing -> formalParams + +publicFieldDefinition :: Assignment Term +publicFieldDefinition = makeField <$> symbol Grammar.PublicFieldDefinition <*> children ((,,,,) <$> accessibilityModifier' <*> (term readonly' <|> emptyTerm) <*> term propertyName <*> (term typeAnnotation' <|> emptyTerm) <*> (term expression <|> emptyTerm)) + where makeField loc (accessControl, readonly, propertyName, annotation, expression) = makeTerm loc (Declaration.PublicFieldDefinition [readonly, annotation] propertyName expression accessControl) + + +statement :: Assignment Term +statement = handleError everything + where + everything = choice [ + exportStatement + , importStatement + , debuggerStatement + , expressionStatement' + , declaration + , statementTerm + , ifStatement + , switchStatement + , forStatement + , forInStatement + , forOfStatement + , whileStatement + , doStatement + , tryStatement + , withStatement + , breakStatement + , continueStatement + , returnStatement + , throwStatement + , hashBang + , emptyStatement + , labeledStatement ] + +forOfStatement :: Assignment Term +forOfStatement = makeTerm <$> symbol ForOfStatement <*> children (TSX.Syntax.ForOf <$> term expression <*> term expressions <*> term statement) + +forInStatement :: Assignment Term +forInStatement = makeTerm <$> symbol ForInStatement <*> children (Statement.ForEach <$> term expression <*> term expression <*> term statement) + +doStatement :: Assignment Term +doStatement = makeTerm <$> symbol DoStatement <*> children (flip Statement.DoWhile <$> term statement <*> term parenthesizedExpression) + +continueStatement :: Assignment Term +continueStatement = makeTerm <$> symbol ContinueStatement <*> children (Statement.Continue <$> (statementIdentifier <|> term emptyTerm)) + +breakStatement :: Assignment Term +breakStatement = makeTerm <$> symbol BreakStatement <*> children (Statement.Break <$> (statementIdentifier <|> term emptyTerm)) + +withStatement :: Assignment Term +withStatement = makeTerm <$> symbol WithStatement <*> children (TSX.Syntax.With <$> term parenthesizedExpression <*> term statement) + +returnStatement :: Assignment Term +returnStatement = makeTerm <$> symbol ReturnStatement <*> children (Statement.Return <$> (term expressions <|> term emptyTerm)) + +throwStatement :: Assignment Term +throwStatement = makeTerm <$> symbol Grammar.ThrowStatement <*> children (Statement.Throw <$> term expressions) + +hashBang :: Assignment Term +hashBang = makeTerm <$> symbol HashBangLine <*> (Comment.HashBang <$> source) + +labeledStatement :: Assignment Term +labeledStatement = makeTerm <$> symbol Grammar.LabeledStatement <*> children (TSX.Syntax.LabeledStatement <$> statementIdentifier <*> term statement) + +statementIdentifier :: Assignment Term +statementIdentifier = makeTerm <$> symbol StatementIdentifier <*> (Syntax.Identifier . name <$> source) + +importStatement :: Assignment Term +importStatement = makeImportTerm <$> symbol Grammar.ImportStatement <*> children ((,) <$> importClause <*> fromClause) + <|> makeTerm' <$> symbol Grammar.ImportStatement <*> children (requireImport <|> sideEffectImport) + where + -- `import foo = require "./foo"` + requireImport = inject <$> (symbol Grammar.ImportRequireClause *> children (TSX.Syntax.QualifiedAliasedImport <$> term identifier <*> fromClause)) + -- `import "./foo"` + sideEffectImport = inject <$> (TSX.Syntax.SideEffectImport <$> fromClause) + -- `import { bar } from "./foo"` + namedImport = (,) Nothing <$> (symbol Grammar.NamedImports *> children (many importSymbol)) + -- `import defaultMember from "./foo"` + defaultImport = (,) Nothing <$> (pure <$> (makeNameAliasPair <$> rawIdentifier <*> pure Nothing)) + -- `import * as name from "./foo"` + namespaceImport = symbol Grammar.NamespaceImport *> children ((,) . Just <$> term identifier <*> pure []) + + -- Combinations of the above. + importClause = symbol Grammar.ImportClause *> + children ( + (pure <$> namedImport) + <|> (pure <$> namespaceImport) + <|> ((\a b -> [a, b]) <$> defaultImport <*> (namedImport <|> namespaceImport)) + <|> (pure <$> defaultImport)) + + makeImportTerm1 loc from (Just alias, _) = makeTerm loc (TSX.Syntax.QualifiedAliasedImport alias from) + makeImportTerm1 loc from (Nothing, symbols) = makeTerm loc (TSX.Syntax.Import (uncurry TSX.Syntax.Alias <$> symbols) from) + makeImportTerm loc ([x], from) = makeImportTerm1 loc from x + makeImportTerm loc (xs, from) = makeTerm loc $ fmap (makeImportTerm1 loc from) xs + importSymbol = symbol Grammar.ImportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> ((Just <$> rawIdentifier) <|> pure Nothing)) + rawIdentifier = (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> (name <$> source) + makeNameAliasPair from (Just alias) = (from, alias) + makeNameAliasPair from Nothing = (from, from) + + -- TODO: Need to validate that inline comments are still handled with this change in assigning to Path and not a Term. + fromClause = symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source) + +debuggerStatement :: Assignment Term +debuggerStatement = makeTerm <$> symbol Grammar.DebuggerStatement <*> (TSX.Syntax.Debugger <$ rawSource) + +expressionStatement' :: Assignment Term +expressionStatement' = symbol ExpressionStatement *> children (term expressions) + +declaration :: Assignment Term +declaration = everything + where + everything = choice [ + exportStatement, + importAlias', + function, + internalModule, + ambientFunction, + abstractClass, + class', + module', + variableDeclaration, + typeAliasDeclaration, + enumDeclaration, + interfaceDeclaration, + ambientDeclaration + ] + +typeAliasDeclaration :: Assignment Term +typeAliasDeclaration = makeTypeAliasDecl <$> symbol Grammar.TypeAliasDeclaration <*> children ((,,) <$> term typeIdentifier <*> (term typeParameters <|> emptyTerm) <*> term ty) + where makeTypeAliasDecl loc (identifier, typeParams, body) = makeTerm loc (Declaration.TypeAlias [typeParams] identifier body) + +enumDeclaration :: Assignment Term +enumDeclaration = makeTerm <$> symbol Grammar.EnumDeclaration <*> children (TSX.Syntax.EnumDeclaration <$> term identifier <*> (symbol EnumBody *> children (manyTerm (propertyName <|> enumAssignment)))) + +enumAssignment :: Assignment Term +enumAssignment = makeTerm <$> symbol Grammar.EnumAssignment <*> children (Statement.Assignment [] <$> term propertyName <*> term expression) + +interfaceDeclaration :: Assignment Term +interfaceDeclaration = makeInterfaceDecl <$> symbol Grammar.InterfaceDeclaration <*> children ((,,,) <$> term typeIdentifier <*> (term typeParameters <|> emptyTerm) <*> optional (term extendsClause) <*> term objectType) + where makeInterfaceDecl loc (identifier, typeParams, clause, objectType) = makeTerm loc (Declaration.InterfaceDeclaration [typeParams] identifier (toList clause) objectType) + +ambientDeclaration :: Assignment Term +ambientDeclaration = makeTerm <$> symbol Grammar.AmbientDeclaration <*> children (TSX.Syntax.AmbientDeclaration <$> term (choice [propertyIdentifier *> ty, declaration, statementBlock])) + +exportStatement :: Assignment Term +exportStatement = makeTerm <$> symbol Grammar.ExportStatement <*> children (flip TSX.Syntax.QualifiedExportFrom <$> exportClause <*> fromClause) + <|> makeTerm <$> symbol Grammar.ExportStatement <*> children (TSX.Syntax.QualifiedExport <$> exportClause) + <|> makeTerm <$> symbol Grammar.ExportStatement <*> children (TSX.Syntax.DefaultExport <$> contextualize decorator (term (declaration <|> expression <|> identifier <|> importAlias'))) + where + exportClause = symbol Grammar.ExportClause *> children (many exportSymbol) + exportSymbol = symbol Grammar.ExportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> (Just <$> rawIdentifier)) + <|> symbol Grammar.ExportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> pure Nothing) + makeNameAliasPair from (Just alias) = TSX.Syntax.Alias from alias + makeNameAliasPair from Nothing = TSX.Syntax.Alias from from + rawIdentifier = (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> (name <$> source) + -- TODO: Need to validate that inline comments are still handled with this change in assigning to Path and not a Term. + fromClause = symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source) + +propertySignature :: Assignment Term +propertySignature = makePropertySignature <$> symbol Grammar.PropertySignature <*> children ((,,,) <$> accessibilityModifier' <*> (term readonly' <|> emptyTerm) <*> term propertyName <*> (term typeAnnotation' <|> emptyTerm)) + where makePropertySignature loc (modifier, readonly, propertyName, annotation) = makeTerm loc (TSX.Syntax.PropertySignature [readonly, annotation] propertyName modifier) + +propertyName :: Assignment Term +propertyName = term (propertyIdentifier <|> string <|> number <|> computedPropertyName) + +computedPropertyName :: Assignment Term +computedPropertyName = makeTerm <$> symbol Grammar.ComputedPropertyName <*> children (TSX.Syntax.ComputedPropertyName <$> term expression) + +assignmentPattern :: Assignment Term +assignmentPattern = makeTerm <$> symbol AssignmentPattern <*> children (Statement.Assignment [] <$> term shorthandPropertyIdentifier <*> term expression) + +shorthandPropertyIdentifier :: Assignment Term +shorthandPropertyIdentifier = makeTerm <$> symbol Grammar.ShorthandPropertyIdentifier <*> (TSX.Syntax.ShorthandPropertyIdentifier <$> source) + +requiredParameter :: Assignment Term +requiredParameter = makeRequiredParameter + <$> symbol Grammar.RequiredParameter + <*> children ( (,,,,) + <$> accessibilityModifier' + <*> (term readonly' <|> emptyTerm) + <*> term (identifier <|> destructuringPattern <|> this) + <*> (term typeAnnotation' <|> emptyTerm) + <*> (term expression <|> emptyTerm)) + where + makeRequiredParameter loc (modifier, readonly, identifier, annotation, initializer) = makeTerm loc (TSX.Syntax.RequiredParameter [readonly, annotation] identifier initializer modifier) + +restParameter :: Assignment Term +restParameter = makeRestParameter <$> symbol Grammar.RestParameter <*> children ((,) <$> term identifier <*> (term typeAnnotation' <|> emptyTerm)) + where makeRestParameter loc (identifier, annotation) = makeTerm loc (TSX.Syntax.RestParameter [annotation] identifier) + +optionalParameter :: Assignment Term +optionalParameter = makeOptionalParam <$> symbol Grammar.OptionalParameter <*> children ((,,,,) <$> accessibilityModifier' <*> (term readonly' <|> emptyTerm) <*> (term identifier <|> destructuringPattern) <*> (term typeAnnotation' <|> emptyTerm) <*> (term expression <|> emptyTerm)) + where makeOptionalParam loc (modifier, readonly, subject, annotation, initializer) = makeTerm loc (TSX.Syntax.OptionalParameter [readonly, annotation] (makeTerm loc (Statement.Assignment [] subject initializer)) modifier) + +internalModule :: Assignment Term +internalModule = makeTerm <$> symbol Grammar.InternalModule <*> children (TSX.Syntax.InternalModule <$> term (string <|> identifier <|> nestedIdentifier) <*> statements) + +module' :: Assignment Term +module' = makeTerm <$> symbol Module <*> children (TSX.Syntax.Module <$> term (string <|> identifier <|> nestedIdentifier) <*> (statements <|> pure [])) + + +statements :: Assignment [Term] +statements = symbol StatementBlock *> children (manyTerm statement) + +arrowFunction :: Assignment Term +arrowFunction = makeArrowFun <$> symbol ArrowFunction <*> children ((,,) <$> emptyTerm <*> (((\a b c -> (a, [b], c)) <$> emptyTerm <*> term identifier <*> emptyTerm) <|> callSignatureParts) <*> term (expression <|> statementBlock)) + where makeArrowFun loc (identifier, (typeParams, params, returnTy), body) = makeTerm loc (Declaration.Function [ typeParams, returnTy ] identifier params body) + +comment :: Assignment Term +comment = makeTerm <$> symbol Comment <*> (Comment.Comment <$> source) + +ifStatement :: Assignment Term +ifStatement = makeTerm <$> symbol IfStatement <*> children (Statement.If <$> term parenthesizedExpression <*> term statement <*> (term statement <|> emptyTerm)) + +whileStatement :: Assignment Term +whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.While <$> term expression <*> term statement) + +forStatement :: Assignment Term +forStatement = makeTerm <$> symbol ForStatement <*> children (Statement.For <$> term (variableDeclaration <|> expressionStatement' <|> emptyStatement) <*> term (expressionStatement' <|> emptyStatement) <*> term (expressions <|> emptyTerm) <*> term statement) + +variableDeclaration :: Assignment Term +variableDeclaration = makeTerm <$> (symbol Grammar.VariableDeclaration <|> symbol Grammar.LexicalDeclaration) <*> children (Declaration.VariableDeclaration <$> manyTerm variableDeclarator) + +variableDeclarator :: Assignment Term +variableDeclarator = + makeTerm <$> symbol VariableDeclarator <*> children (TSX.Syntax.JavaScriptRequire <$> identifier <*> requireCall) + <|> makeVarDecl <$> symbol VariableDeclarator <*> children ((,,) <$> term (identifier <|> destructuringPattern) <*> (term typeAnnotation' <|> emptyTerm) <*> (term expression <|> emptyTerm)) + where + makeVarDecl loc (subject, annotations, value) = makeTerm loc (Statement.Assignment [annotations] subject value) + + requireCall = symbol CallExpression *> children ((symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> do + s <- source + guard (s == "require") + symbol Arguments *> children (symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source)) + ) + + +parenthesizedExpression :: Assignment Term +parenthesizedExpression = symbol ParenthesizedExpression *> children (term expressions) + +switchStatement :: Assignment Term +switchStatement = makeTerm <$> symbol SwitchStatement <*> children (Statement.Match <$> term parenthesizedExpression <*> term switchBody) + where + switchBody = symbol SwitchBody *> children (makeTerm <$> location <*> manyTerm switchCase) + switchCase = makeTerm <$> (symbol SwitchCase <|> symbol SwitchDefault) <*> children (Statement.Pattern <$> (term expressions <|> emptyTerm) <*> (makeTerm <$> location <*> manyTerm statement)) + +subscriptExpression :: Assignment Term +subscriptExpression = makeTerm <$> symbol SubscriptExpression <*> children (Expression.Subscript <$> term expression <*> (pure <$> term expressions)) + +pair :: Assignment Term +pair = makeTerm <$> symbol Pair <*> children (Literal.KeyValue <$> term propertyName <*> term expression) + +callExpression :: Assignment Term +callExpression = makeCall <$> (symbol CallExpression <|> symbol CallExpression') <*> children ((,,,) <$> term (expression <|> super <|> function) <*> (typeArguments <|> pure []) <*> (arguments <|> (pure <$> term templateString)) <*> emptyTerm) + where makeCall loc (subject, typeArgs, args, body) = makeTerm loc (Expression.Call typeArgs subject args body) + typeArguments = symbol Grammar.TypeArguments *> children (some (term ty)) + +arguments :: Assignment [Term] +arguments = symbol Arguments *> children (manyTerm (expression <|> spreadElement)) + +tryStatement :: Assignment Term +tryStatement = makeTry <$> symbol TryStatement <*> children ((,,) <$> term statementTerm <*> optional (term catchClause) <*> optional (term finallyClause)) + where + makeTry loc (statementBlock', catch, finally) = makeTerm loc (Statement.Try statementBlock' (catMaybes [catch, finally])) + catchClause = makeTerm <$> symbol CatchClause <*> children (Statement.Catch <$> (identifier <|> emptyTerm) <*> statementTerm) + finallyClause = makeTerm <$> symbol FinallyClause <*> children (Statement.Finally <$> statementTerm) + +binaryExpression :: Assignment Term +binaryExpression = makeTerm' <$> symbol BinaryExpression <*> children (infixTerm expression (term expression) + [ (inject .) . Expression.Plus <$ symbol AnonPlus + , (inject .) . Expression.Minus <$ symbol AnonMinus + , (inject .) . Expression.Times <$ symbol AnonStar + , (inject .) . Expression.DividedBy <$ symbol AnonSlash + , (inject .) . Expression.Modulo <$ symbol AnonPercent + , (inject .) . Expression.Member <$ symbol AnonIn + , (inject .) . Expression.And <$ symbol AnonAmpersandAmpersand + , (inject .) . Expression.BAnd <$ symbol AnonAmpersand + , (inject .) . Expression.Or <$ symbol AnonPipePipe + , (inject .) . Expression.BOr <$ symbol AnonPipe + , (inject .) . Expression.BXOr <$ symbol AnonCaret + , (inject .) . Expression.InstanceOf <$ symbol AnonInstanceof + , (inject .) . Expression.Equal <$ symbol AnonEqualEqual + , (inject .) . Expression.StrictEqual <$ symbol AnonEqualEqualEqual + , (inject .) . invert Expression.Equal <$ symbol AnonBangEqual + , (inject .) . invert Expression.StrictEqual <$ symbol AnonBangEqualEqual + , (inject .) . Expression.LShift <$ symbol AnonLAngleLAngle + , (inject .) . Expression.RShift <$ symbol AnonRAngleRAngle + , (inject .) . Expression.UnsignedRShift <$ symbol AnonRAngleRAngleRAngle + , (inject .) . Expression.LessThan <$ symbol AnonLAngle + , (inject .) . Expression.GreaterThan <$ symbol AnonRAngle + , (inject .) . Expression.LessThanEqual <$ symbol AnonLAngleEqual + , (inject .) . Expression.GreaterThanEqual <$ symbol AnonRAngleEqual + ]) + where invert cons a b = Expression.Not (makeTerm1 (cons a b)) + + +-- Helpers + +-- | Match a term optionally preceded by comment(s), or a sequence of comments if the term is not present. +manyTerm :: Assignment Term -> Assignment [Term] +manyTerm term = many (contextualize comment term <|> makeTerm1 <$> (Syntax.Context <$> some1 comment <*> emptyTerm)) + +term :: Assignment Term -> Assignment Term +term term = contextualize comment (postContextualize comment term) + +emptyStatement :: Assignment Term +emptyStatement = makeTerm <$> symbol EmptyStatement <*> (Syntax.Empty <$ rawSource <|> pure Syntax.Empty) + +-- | Match infix terms separated by any of a list of operators, assigning any comments following each operand. +infixTerm :: Assignment Term + -> Assignment Term + -> [Assignment (Term -> Term -> Sum Syntax Term)] + -> Assignment (Sum Syntax Term) +infixTerm = infixContext comment diff --git a/src/Language/TSX/Resolution.hs b/src/Language/TSX/Resolution.hs new file mode 100644 index 000000000..6fd40cfea --- /dev/null +++ b/src/Language/TSX/Resolution.hs @@ -0,0 +1,128 @@ +module Language.TypeScript.Resolution + ( ImportPath (..) + , IsRelative (..) + , importPath + , toName + , resolveWithNodejsStrategy + , resolveModule + , resolveNonRelativePath + , javascriptExtensions + , typescriptExtensions + ) where + +import qualified Data.Map as Map +import System.FilePath.Posix + +import Data.Abstract.BaseError +import Data.Abstract.Evaluatable +import qualified Data.Abstract.Module as M +import Data.Abstract.Package +import Data.Abstract.Path +import Data.ImportPath +import qualified Data.Language as Language + +-- Node.js resolution algorithm: https://nodejs.org/api/modules.html#modules_all_together +-- +-- NB: TypeScript has a couple of different strategies, but the main one (and the +-- only one we support) mimics Node.js. +resolveWithNodejsStrategy :: ( Member (Modules address value) sig + , Member (Reader M.ModuleInfo) sig + , Member (Reader PackageInfo) sig + , Member (Reader Span) sig + , Member (Resumable (BaseError ResolutionError)) sig + , Member Trace sig + , Carrier sig m + ) + => ImportPath + -> [String] + -> Evaluator term address value m M.ModulePath +resolveWithNodejsStrategy (ImportPath path NonRelative) exts = resolveNonRelativePath path exts +resolveWithNodejsStrategy (ImportPath path _) exts = resolveRelativePath path exts + +-- | Resolve a relative TypeScript import to a known 'ModuleName' or fail. +-- +-- import { b } from "./moduleB" in /root/src/moduleA.ts +-- +-- /root/src/moduleB.ts +-- /root/src/moduleB/package.json (if it specifies a "types" property) +-- /root/src/moduleB/index.ts +resolveRelativePath :: ( Member (Modules address value) sig + , Member (Reader M.ModuleInfo) sig + , Member (Reader PackageInfo) sig + , Member (Reader Span) sig + , Member (Resumable (BaseError ResolutionError)) sig + , Member Trace sig + , Carrier sig m + ) + => FilePath + -> [String] + -> Evaluator term address value m M.ModulePath +resolveRelativePath relImportPath exts = do + M.ModuleInfo{..} <- currentModule + let relRootDir = takeDirectory modulePath + let path = joinPaths relRootDir relImportPath + trace ("attempting to resolve (relative) require/import " <> show relImportPath) + resolveModule path exts >>= either notFound (\x -> x <$ traceResolve relImportPath path) + where + notFound xs = throwResolutionError $ NotFoundError relImportPath xs Language.TypeScript + +-- | Resolve a non-relative TypeScript import to a known 'ModuleName' or fail. +-- +-- import { b } from "moduleB" in source file /root/src/moduleA.ts +-- +-- /root/src/node_modules/moduleB.ts +-- /root/src/node_modules/moduleB/package.json (if it specifies a "types" property) +-- /root/src/node_modules/moduleB/index.ts +-- +-- /root/node_modules/moduleB.ts, etc +-- /node_modules/moduleB.ts, etc +resolveNonRelativePath :: ( Member (Modules address value) sig + , Member (Reader M.ModuleInfo) sig + , Member (Reader PackageInfo) sig + , Member (Reader Span) sig + , Member (Resumable (BaseError ResolutionError)) sig + , Member Trace sig + , Carrier sig m + ) + => FilePath + -> [String] + -> Evaluator term address value m M.ModulePath +resolveNonRelativePath name exts = do + M.ModuleInfo{..} <- currentModule + go "." modulePath mempty + where + nodeModulesPath dir = takeDirectory dir "node_modules" name + -- Recursively search in a 'node_modules' directory, stepping up a directory each time. + go root path searched = do + trace ("attempting to resolve (non-relative) require/import " <> show name) + res <- resolveModule (nodeModulesPath path) exts + case res of + Left xs | parentDir <- takeDirectory path , root /= parentDir -> go root parentDir (searched <> xs) + | otherwise -> notFound (searched <> xs) + Right m -> m <$ traceResolve name m + notFound xs = throwResolutionError $ NotFoundError name xs Language.TypeScript + +-- | Resolve a module name to a ModulePath. +resolveModule :: ( Member (Modules address value) sig + , Member (Reader PackageInfo) sig + , Member Trace sig + , Carrier sig m + ) + => FilePath -- ^ Module path used as directory to search in + -> [String] -- ^ File extensions to look for + -> Evaluator term address value m (Either [FilePath] M.ModulePath) +resolveModule path' exts = do + let path = makeRelative "." path' + PackageInfo{..} <- currentPackage + let packageDotJSON = Map.lookup (path "package.json") packageResolutions + let searchPaths = ((path <.>) <$> exts) + <> maybe mempty (:[]) packageDotJSON + <> (((path "index") <.>) <$> exts) + trace ("searching in " <> show searchPaths) + maybe (Left searchPaths) Right <$> resolve searchPaths + +typescriptExtensions :: [String] +typescriptExtensions = ["ts", "tsx", "d.ts"] + +javascriptExtensions :: [String] +javascriptExtensions = ["js"] diff --git a/src/Language/TSX/Syntax.hs b/src/Language/TSX/Syntax.hs new file mode 100644 index 000000000..caef2e738 --- /dev/null +++ b/src/Language/TSX/Syntax.hs @@ -0,0 +1,7 @@ +module Language.TSX.Syntax ( module X ) where + +import Language.TypeScript.Syntax.Import as X +import Language.TypeScript.Syntax.JavaScript as X +import Language.TSX.Syntax.JSX as X +import Language.TypeScript.Syntax.TypeScript as X +import Language.TypeScript.Syntax.Types as X diff --git a/src/Language/TSX/Syntax/JSX.hs b/src/Language/TSX/Syntax/JSX.hs new file mode 100644 index 000000000..ceb6129b5 --- /dev/null +++ b/src/Language/TSX/Syntax/JSX.hs @@ -0,0 +1,115 @@ +{-# LANGUAGE DeriveAnyClass, DerivingVia, DuplicateRecordFields #-} +{-# OPTIONS_GHC -Wno-missing-export-lists #-} +module Language.TypeScript.Syntax.JSX where + +import Prologue + +import Control.Abstract as Abstract +import Data.Abstract.Evaluatable +import Data.Abstract.ScopeGraph (AccessControl(..)) +import Data.JSON.Fields +import qualified Data.Text as T +import Diffing.Algorithm +import qualified Data.Map.Strict as Map +import qualified Data.Abstract.ScopeGraph as ScopeGraph + +data JsxElement a = JsxElement { jsxOpeningElement :: !a, jsxElements :: ![a], jsxClosingElement :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically JsxElement + +instance Evaluatable JsxElement + +newtype JsxText a = JsxText { contents :: T.Text } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically JsxText + +instance Evaluatable JsxText + +newtype JsxExpression a = JsxExpression { jsxExpression :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically JsxExpression + +instance Evaluatable JsxExpression + +data JsxOpeningElement a = JsxOpeningElement { jsxOpeningElementIdentifier :: !a, jsxAttributes :: ![a] } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically JsxOpeningElement + +instance Evaluatable JsxOpeningElement + +newtype JsxClosingElement a = JsxClosingElement { jsxClosingElementIdentifier :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically JsxClosingElement + +instance Evaluatable JsxClosingElement + +data JsxSelfClosingElement a = JsxSelfClosingElement { jsxSelfClosingElementIdentifier :: !a, jsxSelfClosingElementAttributes :: ![a] } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically JsxSelfClosingElement + +instance Evaluatable JsxSelfClosingElement + +data JsxAttribute a = JsxAttribute { jsxAttributeTarget :: !a, jsxAttributeValue :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically JsxAttribute + +instance Evaluatable JsxAttribute + +newtype ImplementsClause a = ImplementsClause { implementsClauseTypes :: [a] } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically ImplementsClause + +instance Evaluatable ImplementsClause + +data OptionalParameter a = OptionalParameter { optionalParameterContext :: ![a], optionalParameterSubject :: !a, optionalParameterAccessControl :: AccessControl } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically OptionalParameter + +instance Evaluatable OptionalParameter + +data RequiredParameter a = RequiredParameter { requiredParameterContext :: [a], requiredParameterSubject :: a, requiredParameterValue :: a, requiredParameterAccessControl :: AccessControl } + deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically RequiredParameter + +instance Declarations1 RequiredParameter where + liftDeclaredName declaredName RequiredParameter{..} = declaredName requiredParameterSubject + +instance Evaluatable RequiredParameter where + eval eval ref RequiredParameter{..} = do + span <- ask @Span + _ <- declareMaybeName (declaredName requiredParameterSubject) Default Public span ScopeGraph.RequiredParameter Nothing + + lhs <- ref requiredParameterSubject + rhs <- eval requiredParameterValue + + case declaredName requiredParameterValue of + Just rhsName -> do + assocScope <- associatedScope (Declaration rhsName) + case assocScope of + Just assocScope' -> do + objectScope <- newScope (Map.singleton Import [ assocScope' ]) + putSlotDeclarationScope lhs (Just objectScope) -- TODO: not sure if this is right + Nothing -> + pure () + Nothing -> + pure () + assign lhs rhs + pure rhs + +data RestParameter a = RestParameter { restParameterContext :: ![a], restParameterSubject :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically RestParameter + +instance Evaluatable RestParameter + +newtype JsxFragment a = JsxFragment { terms :: [a] } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically JsxFragment + +instance Evaluatable JsxFragment + +data JsxNamespaceName a = JsxNamespaceName { left :: a, right :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically JsxNamespaceName + +instance Evaluatable JsxNamespaceName diff --git a/src/Language/TSX/Syntax/Types.hs b/src/Language/TSX/Syntax/Types.hs new file mode 100644 index 000000000..93f2440c8 --- /dev/null +++ b/src/Language/TSX/Syntax/Types.hs @@ -0,0 +1,143 @@ +{-# LANGUAGE DeriveAnyClass, DerivingVia, DuplicateRecordFields #-} +{-# OPTIONS_GHC -Wno-missing-export-lists #-} +module Language.TypeScript.Syntax.Types where + +import Prologue + +import Control.Abstract hiding (Import) +import Data.Abstract.Evaluatable as Evaluatable +import Data.JSON.Fields +import qualified Data.Text as T +import Diffing.Algorithm +import qualified Data.Abstract.ScopeGraph as ScopeGraph + +-- | Lookup type for a type-level key in a typescript map. +data LookupType a = LookupType { lookupTypeIdentifier :: a, lookupTypeKey :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically LookupType + +instance Evaluatable LookupType + +data FunctionType a = FunctionType { functionTypeParameters :: !a, functionFormalParameters :: ![a], functionType :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically FunctionType + +instance Evaluatable FunctionType + +data TypeParameter a = TypeParameter { typeParameter :: !a, typeParameterConstraint :: !a, typeParameterDefaultType :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically TypeParameter + +instance Evaluatable TypeParameter + +data TypeAssertion a = TypeAssertion { typeAssertionParameters :: !a, typeAssertionExpression :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically TypeAssertion + +instance Evaluatable TypeAssertion + +newtype DefaultType a = DefaultType { defaultType :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically DefaultType + +instance Evaluatable DefaultType + +newtype ParenthesizedType a = ParenthesizedType { parenthesizedType :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically ParenthesizedType + +instance Evaluatable ParenthesizedType + +newtype PredefinedType a = PredefinedType { predefinedType :: T.Text } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically PredefinedType + +-- TODO: Implement Eval instance for PredefinedType +instance Evaluatable PredefinedType + +newtype TypeIdentifier a = TypeIdentifier { contents :: T.Text } + deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically TypeIdentifier + +instance Declarations1 TypeIdentifier where + liftDeclaredName _ (TypeIdentifier identifier) = Just (Evaluatable.name identifier) + +-- TODO: TypeIdentifier shouldn't evaluate to an address in the heap? +instance Evaluatable TypeIdentifier where + eval _ _ TypeIdentifier{..} = do + -- Add a reference to the type identifier in the current scope. + span <- ask @Span + reference (Reference (Evaluatable.name contents)) span ScopeGraph.TypeIdentifier (Declaration (Evaluatable.name contents)) + unit + +data NestedTypeIdentifier a = NestedTypeIdentifier { left :: !a, right :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically NestedTypeIdentifier + +instance Evaluatable NestedTypeIdentifier + +data GenericType a = GenericType { genericTypeIdentifier :: !a, genericTypeArguments :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically GenericType + +instance Evaluatable GenericType + +data TypePredicate a = TypePredicate { typePredicateIdentifier :: !a, typePredicateType :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically TypePredicate + +instance Evaluatable TypePredicate + +newtype ObjectType a = ObjectType { objectTypeElements :: [a] } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically ObjectType + +instance Evaluatable ObjectType + +newtype ArrayType a = ArrayType { arrayType :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically ArrayType + +instance Evaluatable ArrayType + +newtype FlowMaybeType a = FlowMaybeType { flowMaybeType :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically FlowMaybeType + +instance Evaluatable FlowMaybeType + +newtype TypeQuery a = TypeQuery { typeQuerySubject :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically TypeQuery + +instance Evaluatable TypeQuery + +newtype IndexTypeQuery a = IndexTypeQuery { indexTypeQuerySubject :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically IndexTypeQuery + +instance Evaluatable IndexTypeQuery + +newtype TypeArguments a = TypeArguments { typeArguments :: [a] } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically TypeArguments + +instance Evaluatable TypeArguments + +newtype ThisType a = ThisType { contents :: T.Text } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically ThisType + +instance Evaluatable ThisType + +newtype ExistentialType a = ExistentialType { contents :: T.Text } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically ExistentialType + +instance Evaluatable ExistentialType + +newtype LiteralType a = LiteralType { literalTypeSubject :: a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically LiteralType + +instance Evaluatable LiteralType diff --git a/src/Parsing/Parser.hs b/src/Parsing/Parser.hs index f0a5bd8f3..36f6ab093 100644 --- a/src/Parsing/Parser.hs +++ b/src/Parsing/Parser.hs @@ -98,6 +98,7 @@ someAnalysisParser _ PHP = SomeAnalysisParser phpParser (Proxy :: someAnalysisParser _ Python = SomeAnalysisParser pythonParser (Proxy :: Proxy 'Python) someAnalysisParser _ Ruby = SomeAnalysisParser rubyParser (Proxy :: Proxy 'Ruby) someAnalysisParser _ TypeScript = SomeAnalysisParser typescriptParser (Proxy :: Proxy 'TypeScript) +someAnalysisParser _ TSX = SomeAnalysisParser typescriptParser (Proxy :: Proxy 'TSX) someAnalysisParser _ l = error $ "Analysis not supported for: " <> show l diff --git a/src/Semantic/Api/Bridge.hs b/src/Semantic/Api/Bridge.hs index 0310c79af..43c904598 100644 --- a/src/Semantic/Api/Bridge.hs +++ b/src/Semantic/Api/Bridge.hs @@ -78,6 +78,7 @@ instance APIBridge T.Text Data.Language where Data.Python -> "Python" Data.Ruby -> "Ruby" Data.TypeScript -> "TypeScript" + Data.TSX -> "TSX" Data.PHP -> "PHP" apiLanguageToLanguage :: T.Text -> Data.Language @@ -92,6 +93,7 @@ instance APIBridge T.Text Data.Language where "Python" -> Data.Python "Ruby" -> Data.Ruby "TypeScript" -> Data.TypeScript + "TSX" -> Data.TSX "PHP" -> Data.PHP _ -> Data.Unknown diff --git a/src/Semantic/Api/Diffs.hs b/src/Semantic/Api/Diffs.hs index ecec3bece..025d63af3 100644 --- a/src/Semantic/Api/Diffs.hs +++ b/src/Semantic/Api/Diffs.hs @@ -131,13 +131,14 @@ doParse blobPair decorate = case languageForBlobPair blobPair of Go -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse goParser blob >>= decorate blob) Haskell -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse haskellParser blob >>= decorate blob) Java -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse javaParser blob >>= decorate blob) - JavaScript -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse typescriptParser blob >>= decorate blob) + JavaScript -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse tsxParser blob >>= decorate blob) JSON -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse jsonParser blob >>= decorate blob) - JSX -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse typescriptParser blob >>= decorate blob) + JSX -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse tsxParser blob >>= decorate blob) Markdown -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse markdownParser blob >>= decorate blob) Python -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse pythonParser blob >>= decorate blob) Ruby -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse rubyParser blob >>= decorate blob) TypeScript -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse typescriptParser blob >>= decorate blob) + TSX -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse tsxParser blob >>= decorate blob) PHP -> SomeTermPair <$> distributeFor blobPair (\ blob -> parse phpParser blob >>= decorate blob) _ -> noLanguageForBlob (pathForBlobPair blobPair) diff --git a/src/Semantic/Api/Terms.hs b/src/Semantic/Api/Terms.hs index defe42673..b76bcb31a 100644 --- a/src/Semantic/Api/Terms.hs +++ b/src/Semantic/Api/Terms.hs @@ -117,12 +117,13 @@ doParse blob = case blobLanguage blob of Go -> SomeTerm <$> parse goParser blob Haskell -> SomeTerm <$> parse haskellParser blob Java -> SomeTerm <$> parse javaParser blob - JavaScript -> SomeTerm <$> parse typescriptParser blob + JavaScript -> SomeTerm <$> parse tsxParser blob JSON -> SomeTerm <$> parse jsonParser blob - JSX -> SomeTerm <$> parse typescriptParser blob + JSX -> SomeTerm <$> parse tsxParser blob Markdown -> SomeTerm <$> parse markdownParser blob Python -> SomeTerm <$> parse pythonParser blob Ruby -> SomeTerm <$> parse rubyParser blob TypeScript -> SomeTerm <$> parse typescriptParser blob + TSX -> SomeTerm <$> parse tsxParser blob PHP -> SomeTerm <$> parse phpParser blob _ -> noLanguageForBlob (blobPath blob) From 6b1314586259801c0b3951ec3ff8ccf754442aeb Mon Sep 17 00:00:00 2001 From: joshvera Date: Thu, 6 Jun 2019 16:37:29 -0400 Subject: [PATCH 4/8] Move jsxElements out of TypeScript grammar Also removes typeAssertion from TSX grammar --- semantic.cabal | 4 +- src/Data/Abstract/AccessControls/Instances.hs | 20 +-- src/Data/Abstract/Evaluatable.hs | 2 + src/Language/Go/Assignment.hs | 2 +- src/Language/TSX/Assignment.hs | 12 +- src/Language/TSX/Syntax/JSX.hs | 49 +------- src/Language/TypeScript/Assignment.hs | 59 +-------- src/Language/TypeScript/Syntax.hs | 1 - src/Language/TypeScript/Syntax/JSX.hs | 115 ------------------ src/Language/TypeScript/Syntax/JavaScript.hs | 48 ++++++++ src/Parsing/Parser.hs | 7 ++ src/Tags/Taggable.hs | 21 ++-- 12 files changed, 92 insertions(+), 248 deletions(-) delete mode 100644 src/Language/TypeScript/Syntax/JSX.hs diff --git a/semantic.cabal b/semantic.cabal index c1d27ce30..ccb96efc0 100644 --- a/semantic.cabal +++ b/semantic.cabal @@ -202,12 +202,14 @@ library , Language.Ruby.Assignment , Language.Ruby.PrettyPrint , Language.Ruby.Syntax + , Language.TSX.Assignment + , Language.TSX.Syntax + , Language.TSX.Syntax.JSX , Language.TypeScript.Assignment , Language.TypeScript.Resolution , Language.TypeScript.Syntax , Language.TypeScript.Syntax.Import , Language.TypeScript.Syntax.JavaScript - , Language.TypeScript.Syntax.JSX , Language.TypeScript.Syntax.TypeScript , Language.TypeScript.Syntax.Types , Language.PHP.Assignment diff --git a/src/Data/Abstract/AccessControls/Instances.hs b/src/Data/Abstract/AccessControls/Instances.hs index abe3111bd..17a5f8e29 100644 --- a/src/Data/Abstract/AccessControls/Instances.hs +++ b/src/Data/Abstract/AccessControls/Instances.hs @@ -22,6 +22,7 @@ import qualified Language.Markdown.Syntax as Markdown import qualified Language.PHP.Syntax as PHP import qualified Language.Python.Syntax as Python import qualified Language.Ruby.Syntax as Ruby +import qualified Language.TSX.Syntax as TSX import qualified Language.TypeScript.Syntax as TypeScript import Data.Quieterm @@ -454,25 +455,26 @@ instance AccessControls1 Ruby.LowPrecedenceOr instance AccessControls1 Ruby.Module instance AccessControls1 Ruby.ZSuper +instance AccessControls1 TSX.JsxElement +instance AccessControls1 TSX.JsxOpeningElement +instance AccessControls1 TSX.JsxSelfClosingElement +instance AccessControls1 TSX.JsxAttribute +instance AccessControls1 TSX.JsxNamespaceName +instance AccessControls1 TSX.JsxText +instance AccessControls1 TSX.JsxExpression +instance AccessControls1 TSX.JsxClosingElement +instance AccessControls1 TSX.JsxFragment + instance AccessControls1 TypeScript.AnnotatedExpression instance AccessControls1 TypeScript.JavaScriptRequire instance AccessControls1 TypeScript.Debugger instance AccessControls1 TypeScript.Super instance AccessControls1 TypeScript.Undefined instance AccessControls1 TypeScript.With -instance AccessControls1 TypeScript.JsxElement -instance AccessControls1 TypeScript.JsxOpeningElement -instance AccessControls1 TypeScript.JsxSelfClosingElement -instance AccessControls1 TypeScript.JsxAttribute instance AccessControls1 TypeScript.OptionalParameter instance AccessControls1 TypeScript.RequiredParameter instance AccessControls1 TypeScript.RestParameter -instance AccessControls1 TypeScript.JsxNamespaceName -instance AccessControls1 TypeScript.JsxText -instance AccessControls1 TypeScript.JsxExpression -instance AccessControls1 TypeScript.JsxClosingElement instance AccessControls1 TypeScript.ImplementsClause -instance AccessControls1 TypeScript.JsxFragment instance AccessControls1 TypeScript.Import instance AccessControls1 TypeScript.QualifiedAliasedImport instance AccessControls1 TypeScript.QualifiedExportFrom diff --git a/src/Data/Abstract/Evaluatable.hs b/src/Data/Abstract/Evaluatable.hs index f08cee1ef..01e66a717 100644 --- a/src/Data/Abstract/Evaluatable.hs +++ b/src/Data/Abstract/Evaluatable.hs @@ -163,6 +163,8 @@ instance HasPrelude 'Ruby where defineClass (Declaration (X.name "Object")) [] $ do defineBuiltIn (Declaration $ X.name "inspect") Default Public Show +instance HasPrelude 'TSX + instance HasPrelude 'TypeScript where definePrelude _ = do defineSelf diff --git a/src/Language/Go/Assignment.hs b/src/Language/Go/Assignment.hs index 695856192..c97a52a94 100644 --- a/src/Language/Go/Assignment.hs +++ b/src/Language/Go/Assignment.hs @@ -262,7 +262,7 @@ floatLiteral :: Assignment Term floatLiteral = makeTerm <$> symbol FloatLiteral <*> (Literal.Float <$> source) identifier :: Assignment Term -identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') <*> (Syntax.Identifier . name <$> source) +identifier = makeTerm <$> symbol Identifier <*> (Syntax.Identifier . name <$> source) imaginaryLiteral :: Assignment Term imaginaryLiteral = makeTerm <$> symbol ImaginaryLiteral <*> (Literal.Complex <$> source) diff --git a/src/Language/TSX/Assignment.hs b/src/Language/TSX/Assignment.hs index 26967b955..839f7aeca 100644 --- a/src/Language/TSX/Assignment.hs +++ b/src/Language/TSX/Assignment.hs @@ -219,7 +219,6 @@ expression :: Assignment Term expression = handleError everything where everything = choice [ - typeAssertion, asExpression, nonNullExpression', importAlias', @@ -371,9 +370,6 @@ implementsClause' = makeTerm <$> symbol Grammar.ImplementsClause <*> children (T super :: Assignment Term super = makeTerm <$> symbol Grammar.Super <*> (TSX.Syntax.Super <$ rawSource) -typeAssertion :: Assignment Term -typeAssertion = makeTerm <$> symbol Grammar.TypeAssertion <*> children (TSX.Syntax.TypeAssertion <$> term typeArguments' <*> term expression) - asExpression :: Assignment Term asExpression = makeTerm <$> symbol AsExpression <*> children (Expression.Cast <$> term expression <*> term (ty <|> templateString)) @@ -402,7 +398,7 @@ false :: Assignment Term false = makeTerm <$> symbol Grammar.False <*> (Literal.false <$ rawSource) identifier :: Assignment Term -identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') <*> (Syntax.Identifier . name <$> source) +identifier = makeTerm <$> symbol Identifier <*> (Syntax.Identifier . name <$> source) class' :: Assignment Term class' = makeClass <$> symbol Class <*> children ((,,,,) <$> manyTerm decorator <*> term typeIdentifier <*> (symbol TypeParameters *> children (manyTerm typeParameter') <|> pure []) <*> (classHeritage' <|> pure []) <*> classBodyStatements) @@ -754,7 +750,7 @@ importStatement = makeImportTerm <$> symbol Grammar.ImportStatement <*> childr makeImportTerm loc ([x], from) = makeImportTerm1 loc from x makeImportTerm loc (xs, from) = makeTerm loc $ fmap (makeImportTerm1 loc from) xs importSymbol = symbol Grammar.ImportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> ((Just <$> rawIdentifier) <|> pure Nothing)) - rawIdentifier = (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> (name <$> source) + rawIdentifier = symbol Identifier *> (name <$> source) makeNameAliasPair from (Just alias) = (from, alias) makeNameAliasPair from Nothing = (from, from) @@ -813,7 +809,7 @@ exportStatement = makeTerm <$> symbol Grammar.ExportStatement <*> children (flip <|> symbol Grammar.ExportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> pure Nothing) makeNameAliasPair from (Just alias) = TSX.Syntax.Alias from alias makeNameAliasPair from Nothing = TSX.Syntax.Alias from from - rawIdentifier = (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> (name <$> source) + rawIdentifier = symbol Identifier *> (name <$> source) -- TODO: Need to validate that inline comments are still handled with this change in assigning to Path and not a Term. fromClause = symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source) @@ -889,7 +885,7 @@ variableDeclarator = where makeVarDecl loc (subject, annotations, value) = makeTerm loc (Statement.Assignment [annotations] subject value) - requireCall = symbol CallExpression *> children ((symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> do + requireCall = symbol CallExpression *> children (symbol Identifier *> do s <- source guard (s == "require") symbol Arguments *> children (symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source)) diff --git a/src/Language/TSX/Syntax/JSX.hs b/src/Language/TSX/Syntax/JSX.hs index ceb6129b5..d6d35f999 100644 --- a/src/Language/TSX/Syntax/JSX.hs +++ b/src/Language/TSX/Syntax/JSX.hs @@ -1,6 +1,6 @@ {-# LANGUAGE DeriveAnyClass, DerivingVia, DuplicateRecordFields #-} {-# OPTIONS_GHC -Wno-missing-export-lists #-} -module Language.TypeScript.Syntax.JSX where +module Language.TSX.Syntax.JSX where import Prologue @@ -55,53 +55,6 @@ data JsxAttribute a = JsxAttribute { jsxAttributeTarget :: !a, jsxAttributeValue instance Evaluatable JsxAttribute -newtype ImplementsClause a = ImplementsClause { implementsClauseTypes :: [a] } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically ImplementsClause - -instance Evaluatable ImplementsClause - -data OptionalParameter a = OptionalParameter { optionalParameterContext :: ![a], optionalParameterSubject :: !a, optionalParameterAccessControl :: AccessControl } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically OptionalParameter - -instance Evaluatable OptionalParameter - -data RequiredParameter a = RequiredParameter { requiredParameterContext :: [a], requiredParameterSubject :: a, requiredParameterValue :: a, requiredParameterAccessControl :: AccessControl } - deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically RequiredParameter - -instance Declarations1 RequiredParameter where - liftDeclaredName declaredName RequiredParameter{..} = declaredName requiredParameterSubject - -instance Evaluatable RequiredParameter where - eval eval ref RequiredParameter{..} = do - span <- ask @Span - _ <- declareMaybeName (declaredName requiredParameterSubject) Default Public span ScopeGraph.RequiredParameter Nothing - - lhs <- ref requiredParameterSubject - rhs <- eval requiredParameterValue - - case declaredName requiredParameterValue of - Just rhsName -> do - assocScope <- associatedScope (Declaration rhsName) - case assocScope of - Just assocScope' -> do - objectScope <- newScope (Map.singleton Import [ assocScope' ]) - putSlotDeclarationScope lhs (Just objectScope) -- TODO: not sure if this is right - Nothing -> - pure () - Nothing -> - pure () - assign lhs rhs - pure rhs - -data RestParameter a = RestParameter { restParameterContext :: ![a], restParameterSubject :: !a } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically RestParameter - -instance Evaluatable RestParameter - newtype JsxFragment a = JsxFragment { terms :: [a] } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) deriving (Eq1, Show1, Ord1) via Generically JsxFragment diff --git a/src/Language/TypeScript/Assignment.hs b/src/Language/TypeScript/Assignment.hs index 740c88957..4bf163b40 100644 --- a/src/Language/TypeScript/Assignment.hs +++ b/src/Language/TypeScript/Assignment.hs @@ -169,15 +169,6 @@ type Syntax = '[ , TypeScript.Syntax.ClassHeritage , TypeScript.Syntax.AbstractClass , TypeScript.Syntax.ImplementsClause - , TypeScript.Syntax.JsxElement - , TypeScript.Syntax.JsxSelfClosingElement - , TypeScript.Syntax.JsxOpeningElement - , TypeScript.Syntax.JsxText - , TypeScript.Syntax.JsxClosingElement - , TypeScript.Syntax.JsxExpression - , TypeScript.Syntax.JsxAttribute - , TypeScript.Syntax.JsxFragment - , TypeScript.Syntax.JsxNamespaceName , TypeScript.Syntax.OptionalParameter , TypeScript.Syntax.RequiredParameter , TypeScript.Syntax.RestParameter @@ -227,8 +218,6 @@ expression = handleError everything super, object, array, - jsxElement', - jsxFragment, class', anonymousClass, function, @@ -402,7 +391,7 @@ false :: Assignment Term false = makeTerm <$> symbol Grammar.False <*> (Literal.false <$ rawSource) identifier :: Assignment Term -identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') <*> (Syntax.Identifier . name <$> source) +identifier = makeTerm <$> symbol Identifier <*> (Syntax.Identifier . name <$> source) class' :: Assignment Term class' = makeClass <$> symbol Class <*> children ((,,,,) <$> manyTerm decorator <*> term typeIdentifier <*> (symbol TypeParameters *> children (manyTerm typeParameter') <|> pure []) <*> (classHeritage' <|> pure []) <*> classBodyStatements) @@ -414,46 +403,6 @@ object = makeTerm <$> (symbol Object <|> symbol ObjectPattern) <*> children (Lit array :: Assignment Term array = makeTerm <$> (symbol Array <|> symbol ArrayPattern) <*> children (Literal.Array <$> manyTerm (expression <|> spreadElement)) -jsxElement' :: Assignment Term -jsxElement' = choice [ jsxElement, jsxSelfClosingElement ] - -jsxElement :: Assignment Term -jsxElement = makeTerm <$> symbol Grammar.JsxElement <*> children (TypeScript.Syntax.JsxElement <$> term jsxOpeningElement' <*> manyTerm jsxChild <*> term jsxClosingElement') - -jsxFragment :: Assignment Term -jsxFragment = makeTerm <$> symbol Grammar.JsxFragment <*> children (TypeScript.Syntax.JsxFragment <$> manyTerm jsxChild) - -jsxChild :: Assignment Term -jsxChild = choice [ jsxElement', jsxExpression', jsxText ] - -jsxSelfClosingElement :: Assignment Term -jsxSelfClosingElement = makeTerm <$> symbol Grammar.JsxSelfClosingElement <*> children (TypeScript.Syntax.JsxSelfClosingElement <$> term jsxElementName <*> manyTerm jsxAttribute') - -jsxAttribute' :: Assignment Term -jsxAttribute' = jsxAttribute <|> jsxExpression' - -jsxOpeningElement' :: Assignment Term -jsxOpeningElement' = makeTerm <$> symbol Grammar.JsxOpeningElement <*> children (TypeScript.Syntax.JsxOpeningElement <$> term jsxElementName <*> manyTerm jsxAttribute') - -jsxElementName :: Assignment Term -jsxElementName = choice [ identifier, nestedIdentifier, jsxNamespaceName ] - -jsxNamespaceName :: Assignment Term -jsxNamespaceName = makeTerm <$> symbol Grammar.JsxNamespaceName <*> children (TypeScript.Syntax.JsxNamespaceName <$> identifier <*> identifier) - -jsxExpression' :: Assignment Term -jsxExpression' = makeTerm <$> symbol Grammar.JsxExpression <*> children (TypeScript.Syntax.JsxExpression <$> term (expressions <|> spreadElement <|> emptyTerm)) - -jsxText :: Assignment Term -jsxText = makeTerm <$> symbol Grammar.JsxText <*> (TypeScript.Syntax.JsxText <$> source) - -jsxClosingElement' :: Assignment Term -jsxClosingElement' = makeTerm <$> symbol Grammar.JsxClosingElement <*> children (TypeScript.Syntax.JsxClosingElement <$> term jsxElementName) - -jsxAttribute :: Assignment Term -jsxAttribute = makeTerm <$> symbol Grammar.JsxAttribute <*> children (TypeScript.Syntax.JsxAttribute <$> term (propertyIdentifier <|> jsxNamespaceName) <*> (term jsxAttributeValue <|> emptyTerm)) - where jsxAttributeValue = choice [ string, jsxExpression', jsxElement', jsxFragment ] - propertyIdentifier :: Assignment Term propertyIdentifier = makeTerm <$> symbol PropertyIdentifier <*> (Syntax.Identifier . name <$> source) @@ -754,7 +703,7 @@ importStatement = makeImportTerm <$> symbol Grammar.ImportStatement <*> childr makeImportTerm loc ([x], from) = makeImportTerm1 loc from x makeImportTerm loc (xs, from) = makeTerm loc $ fmap (makeImportTerm1 loc from) xs importSymbol = symbol Grammar.ImportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> ((Just <$> rawIdentifier) <|> pure Nothing)) - rawIdentifier = (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> (name <$> source) + rawIdentifier = symbol Identifier *> (name <$> source) makeNameAliasPair from (Just alias) = (from, alias) makeNameAliasPair from Nothing = (from, from) @@ -813,7 +762,7 @@ exportStatement = makeTerm <$> symbol Grammar.ExportStatement <*> children (flip <|> symbol Grammar.ExportSpecifier *> children (makeNameAliasPair <$> rawIdentifier <*> pure Nothing) makeNameAliasPair from (Just alias) = TypeScript.Syntax.Alias from alias makeNameAliasPair from Nothing = TypeScript.Syntax.Alias from from - rawIdentifier = (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> (name <$> source) + rawIdentifier = symbol Identifier *> (name <$> source) -- TODO: Need to validate that inline comments are still handled with this change in assigning to Path and not a Term. fromClause = symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source) @@ -889,7 +838,7 @@ variableDeclarator = where makeVarDecl loc (subject, annotations, value) = makeTerm loc (Statement.Assignment [annotations] subject value) - requireCall = symbol CallExpression *> children ((symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') *> do + requireCall = symbol CallExpression *> children (symbol Identifier *> do s <- source guard (s == "require") symbol Arguments *> children (symbol Grammar.String *> (TypeScript.Resolution.importPath <$> source)) diff --git a/src/Language/TypeScript/Syntax.hs b/src/Language/TypeScript/Syntax.hs index 38a11de42..e18502279 100644 --- a/src/Language/TypeScript/Syntax.hs +++ b/src/Language/TypeScript/Syntax.hs @@ -2,6 +2,5 @@ module Language.TypeScript.Syntax ( module X ) where import Language.TypeScript.Syntax.Import as X import Language.TypeScript.Syntax.JavaScript as X -import Language.TypeScript.Syntax.JSX as X import Language.TypeScript.Syntax.TypeScript as X import Language.TypeScript.Syntax.Types as X diff --git a/src/Language/TypeScript/Syntax/JSX.hs b/src/Language/TypeScript/Syntax/JSX.hs deleted file mode 100644 index ceb6129b5..000000000 --- a/src/Language/TypeScript/Syntax/JSX.hs +++ /dev/null @@ -1,115 +0,0 @@ -{-# LANGUAGE DeriveAnyClass, DerivingVia, DuplicateRecordFields #-} -{-# OPTIONS_GHC -Wno-missing-export-lists #-} -module Language.TypeScript.Syntax.JSX where - -import Prologue - -import Control.Abstract as Abstract -import Data.Abstract.Evaluatable -import Data.Abstract.ScopeGraph (AccessControl(..)) -import Data.JSON.Fields -import qualified Data.Text as T -import Diffing.Algorithm -import qualified Data.Map.Strict as Map -import qualified Data.Abstract.ScopeGraph as ScopeGraph - -data JsxElement a = JsxElement { jsxOpeningElement :: !a, jsxElements :: ![a], jsxClosingElement :: !a } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically JsxElement - -instance Evaluatable JsxElement - -newtype JsxText a = JsxText { contents :: T.Text } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically JsxText - -instance Evaluatable JsxText - -newtype JsxExpression a = JsxExpression { jsxExpression :: a } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically JsxExpression - -instance Evaluatable JsxExpression - -data JsxOpeningElement a = JsxOpeningElement { jsxOpeningElementIdentifier :: !a, jsxAttributes :: ![a] } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically JsxOpeningElement - -instance Evaluatable JsxOpeningElement - -newtype JsxClosingElement a = JsxClosingElement { jsxClosingElementIdentifier :: a } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically JsxClosingElement - -instance Evaluatable JsxClosingElement - -data JsxSelfClosingElement a = JsxSelfClosingElement { jsxSelfClosingElementIdentifier :: !a, jsxSelfClosingElementAttributes :: ![a] } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically JsxSelfClosingElement - -instance Evaluatable JsxSelfClosingElement - -data JsxAttribute a = JsxAttribute { jsxAttributeTarget :: !a, jsxAttributeValue :: !a } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically JsxAttribute - -instance Evaluatable JsxAttribute - -newtype ImplementsClause a = ImplementsClause { implementsClauseTypes :: [a] } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically ImplementsClause - -instance Evaluatable ImplementsClause - -data OptionalParameter a = OptionalParameter { optionalParameterContext :: ![a], optionalParameterSubject :: !a, optionalParameterAccessControl :: AccessControl } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically OptionalParameter - -instance Evaluatable OptionalParameter - -data RequiredParameter a = RequiredParameter { requiredParameterContext :: [a], requiredParameterSubject :: a, requiredParameterValue :: a, requiredParameterAccessControl :: AccessControl } - deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically RequiredParameter - -instance Declarations1 RequiredParameter where - liftDeclaredName declaredName RequiredParameter{..} = declaredName requiredParameterSubject - -instance Evaluatable RequiredParameter where - eval eval ref RequiredParameter{..} = do - span <- ask @Span - _ <- declareMaybeName (declaredName requiredParameterSubject) Default Public span ScopeGraph.RequiredParameter Nothing - - lhs <- ref requiredParameterSubject - rhs <- eval requiredParameterValue - - case declaredName requiredParameterValue of - Just rhsName -> do - assocScope <- associatedScope (Declaration rhsName) - case assocScope of - Just assocScope' -> do - objectScope <- newScope (Map.singleton Import [ assocScope' ]) - putSlotDeclarationScope lhs (Just objectScope) -- TODO: not sure if this is right - Nothing -> - pure () - Nothing -> - pure () - assign lhs rhs - pure rhs - -data RestParameter a = RestParameter { restParameterContext :: ![a], restParameterSubject :: !a } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically RestParameter - -instance Evaluatable RestParameter - -newtype JsxFragment a = JsxFragment { terms :: [a] } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically JsxFragment - -instance Evaluatable JsxFragment - -data JsxNamespaceName a = JsxNamespaceName { left :: a, right :: a } - deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) - deriving (Eq1, Show1, Ord1) via Generically JsxNamespaceName - -instance Evaluatable JsxNamespaceName diff --git a/src/Language/TypeScript/Syntax/JavaScript.hs b/src/Language/TypeScript/Syntax/JavaScript.hs index 95d10e2c8..229463cf0 100644 --- a/src/Language/TypeScript/Syntax/JavaScript.hs +++ b/src/Language/TypeScript/Syntax/JavaScript.hs @@ -13,6 +13,54 @@ import qualified Data.Map.Strict as Map import Diffing.Algorithm import Language.TypeScript.Resolution +newtype ImplementsClause a = ImplementsClause { implementsClauseTypes :: [a] } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically ImplementsClause + +instance Evaluatable ImplementsClause + +data OptionalParameter a = OptionalParameter { optionalParameterContext :: ![a], optionalParameterSubject :: !a, optionalParameterAccessControl :: AccessControl } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically OptionalParameter + +instance Evaluatable OptionalParameter + +data RequiredParameter a = RequiredParameter { requiredParameterContext :: [a], requiredParameterSubject :: a, requiredParameterValue :: a, requiredParameterAccessControl :: AccessControl } + deriving (Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically RequiredParameter + +instance Declarations1 RequiredParameter where + liftDeclaredName declaredName RequiredParameter{..} = declaredName requiredParameterSubject + +instance Evaluatable RequiredParameter where + eval eval ref RequiredParameter{..} = do + span <- ask @Span + _ <- declareMaybeName (declaredName requiredParameterSubject) Default Public span ScopeGraph.RequiredParameter Nothing + + lhs <- ref requiredParameterSubject + rhs <- eval requiredParameterValue + + case declaredName requiredParameterValue of + Just rhsName -> do + assocScope <- associatedScope (Declaration rhsName) + case assocScope of + Just assocScope' -> do + objectScope <- newScope (Map.singleton ScopeGraph.Import [ assocScope' ]) + putSlotDeclarationScope lhs (Just objectScope) -- TODO: not sure if this is right + Nothing -> + pure () + Nothing -> + pure () + assign lhs rhs + pure rhs + +data RestParameter a = RestParameter { restParameterContext :: ![a], restParameterSubject :: !a } + deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) + deriving (Eq1, Show1, Ord1) via Generically RestParameter + +instance Evaluatable RestParameter + + data JavaScriptRequire a = JavaScriptRequire { javascriptRequireIden :: !a, javascriptRequireFrom :: ImportPath } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) deriving (Eq1, Show1, Ord1) via Generically JavaScriptRequire diff --git a/src/Parsing/Parser.hs b/src/Parsing/Parser.hs index e40367939..5728befd2 100644 --- a/src/Parsing/Parser.hs +++ b/src/Parsing/Parser.hs @@ -20,6 +20,7 @@ module Parsing.Parser , pythonParser , pythonASTParser , rubyParser +, tsxParser , typescriptParser , typescriptASTParser , phpParser @@ -46,6 +47,7 @@ import qualified Language.Markdown.Assignment as Markdown import qualified Language.PHP.Assignment as PHP import qualified Language.Python.Assignment as Python import qualified Language.Ruby.Assignment as Ruby +import qualified Language.TSX.Assignment as TSX import qualified Language.TypeScript.Assignment as TypeScript import Prologue import TreeSitter.Go @@ -56,6 +58,7 @@ import qualified TreeSitter.Language as TS (Language, Symbol) import TreeSitter.PHP import TreeSitter.Python import TreeSitter.Ruby +import TreeSitter.TSX import TreeSitter.TypeScript @@ -155,6 +158,9 @@ jsonASTParser = ASTParser tree_sitter_json typescriptParser :: Parser TypeScript.Term typescriptParser = AssignmentParser (ASTParser tree_sitter_typescript) TypeScript.assignment +tsxParser :: Parser TSX.Term +tsxParser = AssignmentParser (ASTParser tree_sitter_tsx) TSX.assignment + typescriptASTParser :: Parser (AST [] TypeScript.Grammar) typescriptASTParser = ASTParser tree_sitter_typescript @@ -187,6 +193,7 @@ someASTParser JSX = Just (SomeASTParser (ASTParser tree_sitter_typescript someASTParser Python = Just (SomeASTParser (ASTParser tree_sitter_python :: Parser (AST [] Python.Grammar))) someASTParser Ruby = Just (SomeASTParser (ASTParser tree_sitter_ruby :: Parser (AST [] Ruby.Grammar))) someASTParser TypeScript = Just (SomeASTParser (ASTParser tree_sitter_typescript :: Parser (AST [] TypeScript.Grammar))) +someASTParser TSX = Just (SomeASTParser (ASTParser tree_sitter_tsx :: Parser (AST [] TSX.Grammar))) someASTParser PHP = Just (SomeASTParser (ASTParser tree_sitter_php :: Parser (AST [] PHP.Grammar))) someASTParser Markdown = Nothing someASTParser Unknown = Nothing diff --git a/src/Tags/Taggable.hs b/src/Tags/Taggable.hs index 397d7d5ab..7bb8e1e89 100644 --- a/src/Tags/Taggable.hs +++ b/src/Tags/Taggable.hs @@ -52,10 +52,10 @@ import qualified Language.Markdown.Syntax as Markdown import qualified Language.PHP.Syntax as PHP import qualified Language.Python.Syntax as Python import qualified Language.Ruby.Syntax as Ruby +import qualified Language.TSX.Syntax as TSX import qualified Language.TypeScript.Syntax as TypeScript - -- TODO: Move to src/Data data Token = Enter { tokenName :: Text, tokenSnippetRange :: Maybe Range } @@ -603,24 +603,25 @@ instance Taggable Ruby.LowPrecedenceOr instance Taggable Ruby.Assignment instance Taggable Ruby.ZSuper +instance Taggable TSX.JsxElement +instance Taggable TSX.JsxOpeningElement +instance Taggable TSX.JsxSelfClosingElement +instance Taggable TSX.JsxAttribute +instance Taggable TSX.JsxText +instance Taggable TSX.JsxExpression +instance Taggable TSX.JsxClosingElement +instance Taggable TSX.JsxFragment +instance Taggable TSX.JsxNamespaceName + instance Taggable TypeScript.JavaScriptRequire instance Taggable TypeScript.Debugger instance Taggable TypeScript.Super instance Taggable TypeScript.Undefined instance Taggable TypeScript.With -instance Taggable TypeScript.JsxElement -instance Taggable TypeScript.JsxOpeningElement -instance Taggable TypeScript.JsxSelfClosingElement -instance Taggable TypeScript.JsxAttribute instance Taggable TypeScript.OptionalParameter instance Taggable TypeScript.RequiredParameter instance Taggable TypeScript.RestParameter -instance Taggable TypeScript.JsxNamespaceName -instance Taggable TypeScript.JsxText -instance Taggable TypeScript.JsxExpression -instance Taggable TypeScript.JsxClosingElement instance Taggable TypeScript.ImplementsClause -instance Taggable TypeScript.JsxFragment instance Taggable TypeScript.Import instance Taggable TypeScript.QualifiedAliasedImport instance Taggable TypeScript.QualifiedExportFrom From 237c4d6b3fdfa07aec79935c8c5c76b87f6b2648 Mon Sep 17 00:00:00 2001 From: joshvera Date: Thu, 6 Jun 2019 18:44:15 -0400 Subject: [PATCH 5/8] Move jsx tests to tsx directory --- test/Integration/Spec.hs | 2 +- .../corpus/jsx-elements.A.tsx} | 0 .../corpus/jsx-elements.B.tsx} | 0 .../corpus/jsx-elements.diffA-B.txt | 0 .../corpus/jsx-elements.diffB-A.txt | 0 .../corpus/jsx-elements.parseA.txt | 0 .../corpus/jsx-elements.parseB.txt | 0 test/fixtures/typescript/corpus/import.diffA-B.txt | 12 ++++++------ test/fixtures/typescript/corpus/import.diffB-A.txt | 12 ++++++------ 9 files changed, 13 insertions(+), 13 deletions(-) rename test/fixtures/{typescript/corpus/jsx-elements.A.ts => tsx/corpus/jsx-elements.A.tsx} (100%) rename test/fixtures/{typescript/corpus/jsx-elements.B.ts => tsx/corpus/jsx-elements.B.tsx} (100%) rename test/fixtures/{typescript => tsx}/corpus/jsx-elements.diffA-B.txt (100%) rename test/fixtures/{typescript => tsx}/corpus/jsx-elements.diffB-A.txt (100%) rename test/fixtures/{typescript => tsx}/corpus/jsx-elements.parseA.txt (100%) rename test/fixtures/{typescript => tsx}/corpus/jsx-elements.parseB.txt (100%) diff --git a/test/Integration/Spec.hs b/test/Integration/Spec.hs index 64e3d4daa..bc1036289 100644 --- a/test/Integration/Spec.hs +++ b/test/Integration/Spec.hs @@ -10,7 +10,7 @@ import System.FilePath.Posix import SpecHelpers languages :: [FilePath] -languages = ["go", "javascript", "json", "python", "ruby", "typescript"] +languages = ["go", "javascript", "json", "python", "ruby", "typescript", "tsx"] spec :: TaskSession -> Spec spec config = parallel $ do diff --git a/test/fixtures/typescript/corpus/jsx-elements.A.ts b/test/fixtures/tsx/corpus/jsx-elements.A.tsx similarity index 100% rename from test/fixtures/typescript/corpus/jsx-elements.A.ts rename to test/fixtures/tsx/corpus/jsx-elements.A.tsx diff --git a/test/fixtures/typescript/corpus/jsx-elements.B.ts b/test/fixtures/tsx/corpus/jsx-elements.B.tsx similarity index 100% rename from test/fixtures/typescript/corpus/jsx-elements.B.ts rename to test/fixtures/tsx/corpus/jsx-elements.B.tsx diff --git a/test/fixtures/typescript/corpus/jsx-elements.diffA-B.txt b/test/fixtures/tsx/corpus/jsx-elements.diffA-B.txt similarity index 100% rename from test/fixtures/typescript/corpus/jsx-elements.diffA-B.txt rename to test/fixtures/tsx/corpus/jsx-elements.diffA-B.txt diff --git a/test/fixtures/typescript/corpus/jsx-elements.diffB-A.txt b/test/fixtures/tsx/corpus/jsx-elements.diffB-A.txt similarity index 100% rename from test/fixtures/typescript/corpus/jsx-elements.diffB-A.txt rename to test/fixtures/tsx/corpus/jsx-elements.diffB-A.txt diff --git a/test/fixtures/typescript/corpus/jsx-elements.parseA.txt b/test/fixtures/tsx/corpus/jsx-elements.parseA.txt similarity index 100% rename from test/fixtures/typescript/corpus/jsx-elements.parseA.txt rename to test/fixtures/tsx/corpus/jsx-elements.parseA.txt diff --git a/test/fixtures/typescript/corpus/jsx-elements.parseB.txt b/test/fixtures/tsx/corpus/jsx-elements.parseB.txt similarity index 100% rename from test/fixtures/typescript/corpus/jsx-elements.parseB.txt rename to test/fixtures/tsx/corpus/jsx-elements.parseB.txt diff --git a/test/fixtures/typescript/corpus/import.diffA-B.txt b/test/fixtures/typescript/corpus/import.diffA-B.txt index c6936b321..304e3666f 100644 --- a/test/fixtures/typescript/corpus/import.diffA-B.txt +++ b/test/fixtures/typescript/corpus/import.diffA-B.txt @@ -1,7 +1,10 @@ (Statements -{+(Import)+} -{+(QualifiedAliasedImport - {+(Identifier)+})+} +{ (Import) +->(Import) } +{ (QualifiedAliasedImport + {-(Identifier)-}) +->(QualifiedAliasedImport + {+(Identifier)+}) } {+(Import)+} {+(Import)+} {+(Import)+} @@ -14,9 +17,6 @@ {+(Identifier)+})+})+} {+(SideEffectImport)+} {-(Import)-} -{-(QualifiedAliasedImport - {-(Identifier)-})-} -{-(Import)-} {-(Import)-} {-(Import)-} {-(Statements diff --git a/test/fixtures/typescript/corpus/import.diffB-A.txt b/test/fixtures/typescript/corpus/import.diffB-A.txt index b19df5534..b83608474 100644 --- a/test/fixtures/typescript/corpus/import.diffB-A.txt +++ b/test/fixtures/typescript/corpus/import.diffB-A.txt @@ -1,7 +1,10 @@ (Statements -{+(Import)+} -{+(QualifiedAliasedImport - {+(Identifier)+})+} +{ (Import) +->(Import) } +{ (QualifiedAliasedImport + {-(Identifier)-}) +->(QualifiedAliasedImport + {+(Identifier)+}) } {+(Import)+} {+(Import)+} {+(Import)+} @@ -16,9 +19,6 @@ {+(QualifiedAliasedImport {+(Identifier)+})+} {-(Import)-} -{-(QualifiedAliasedImport - {-(Identifier)-})-} -{-(Import)-} {-(Import)-} {-(Import)-} {-(Statements From 72b04d7c9c42c96b0fa77a84ece189d7746e975f Mon Sep 17 00:00:00 2001 From: joshvera Date: Thu, 6 Jun 2019 18:57:35 -0400 Subject: [PATCH 6/8] bring this Go assignment back --- src/Language/Go/Assignment.hs | 2 +- src/Language/TSX/Syntax/JSX.hs | 5 +---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Language/Go/Assignment.hs b/src/Language/Go/Assignment.hs index c97a52a94..695856192 100644 --- a/src/Language/Go/Assignment.hs +++ b/src/Language/Go/Assignment.hs @@ -262,7 +262,7 @@ floatLiteral :: Assignment Term floatLiteral = makeTerm <$> symbol FloatLiteral <*> (Literal.Float <$> source) identifier :: Assignment Term -identifier = makeTerm <$> symbol Identifier <*> (Syntax.Identifier . name <$> source) +identifier = makeTerm <$> (symbol Identifier <|> symbol Identifier' <|> symbol Identifier'') <*> (Syntax.Identifier . name <$> source) imaginaryLiteral :: Assignment Term imaginaryLiteral = makeTerm <$> symbol ImaginaryLiteral <*> (Literal.Complex <$> source) diff --git a/src/Language/TSX/Syntax/JSX.hs b/src/Language/TSX/Syntax/JSX.hs index d6d35f999..9430e6743 100644 --- a/src/Language/TSX/Syntax/JSX.hs +++ b/src/Language/TSX/Syntax/JSX.hs @@ -4,14 +4,11 @@ module Language.TSX.Syntax.JSX where import Prologue -import Control.Abstract as Abstract import Data.Abstract.Evaluatable -import Data.Abstract.ScopeGraph (AccessControl(..)) import Data.JSON.Fields import qualified Data.Text as T import Diffing.Algorithm -import qualified Data.Map.Strict as Map -import qualified Data.Abstract.ScopeGraph as ScopeGraph + data JsxElement a = JsxElement { jsxOpeningElement :: !a, jsxElements :: ![a], jsxClosingElement :: !a } deriving (Declarations1, Diffable, Eq, Foldable, FreeVariables1, Functor, Generic1, Hashable1, NFData1, Ord, Show, ToJSONFields1, Traversable) From 7d49193f3b6aeb5cc86101d48036c6d3868d2548 Mon Sep 17 00:00:00 2001 From: joshvera Date: Thu, 6 Jun 2019 19:11:29 -0400 Subject: [PATCH 7/8] Add tsx tests --- test/Examples.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/Examples.hs b/test/Examples.hs index 1c3501ce9..b7c5b3ab2 100644 --- a/test/Examples.hs +++ b/test/Examples.hs @@ -83,7 +83,8 @@ languages :: [LanguageExample] languages = [ le "python" ".py" "examples" (Just "script/known_failures.txt") , le "ruby" ".rb" "examples" (Just "script/known_failures.txt") - , le "typescript" ".ts" "examples" (Just "script/known_failures.txt") + , le "typescript" ".ts" "examples" (Just "typescript/script/known_failures.txt") + , le "typescript" ".tsx" "examples" (Just "typescript/script/known_failures.txt") , le "typescript" ".js" "examples" Nothing -- parse JavaScript with TypeScript parser. , le "go" ".go" "examples" (Just "script/known-failures.txt") From bf75070b989564107e79fea7068ed12c5564dd56 Mon Sep 17 00:00:00 2001 From: joshvera Date: Fri, 7 Jun 2019 12:46:25 -0400 Subject: [PATCH 8/8] remove TSX.Resolution --- src/Language/TSX/Resolution.hs | 128 --------------------------------- 1 file changed, 128 deletions(-) delete mode 100644 src/Language/TSX/Resolution.hs diff --git a/src/Language/TSX/Resolution.hs b/src/Language/TSX/Resolution.hs deleted file mode 100644 index 6fd40cfea..000000000 --- a/src/Language/TSX/Resolution.hs +++ /dev/null @@ -1,128 +0,0 @@ -module Language.TypeScript.Resolution - ( ImportPath (..) - , IsRelative (..) - , importPath - , toName - , resolveWithNodejsStrategy - , resolveModule - , resolveNonRelativePath - , javascriptExtensions - , typescriptExtensions - ) where - -import qualified Data.Map as Map -import System.FilePath.Posix - -import Data.Abstract.BaseError -import Data.Abstract.Evaluatable -import qualified Data.Abstract.Module as M -import Data.Abstract.Package -import Data.Abstract.Path -import Data.ImportPath -import qualified Data.Language as Language - --- Node.js resolution algorithm: https://nodejs.org/api/modules.html#modules_all_together --- --- NB: TypeScript has a couple of different strategies, but the main one (and the --- only one we support) mimics Node.js. -resolveWithNodejsStrategy :: ( Member (Modules address value) sig - , Member (Reader M.ModuleInfo) sig - , Member (Reader PackageInfo) sig - , Member (Reader Span) sig - , Member (Resumable (BaseError ResolutionError)) sig - , Member Trace sig - , Carrier sig m - ) - => ImportPath - -> [String] - -> Evaluator term address value m M.ModulePath -resolveWithNodejsStrategy (ImportPath path NonRelative) exts = resolveNonRelativePath path exts -resolveWithNodejsStrategy (ImportPath path _) exts = resolveRelativePath path exts - --- | Resolve a relative TypeScript import to a known 'ModuleName' or fail. --- --- import { b } from "./moduleB" in /root/src/moduleA.ts --- --- /root/src/moduleB.ts --- /root/src/moduleB/package.json (if it specifies a "types" property) --- /root/src/moduleB/index.ts -resolveRelativePath :: ( Member (Modules address value) sig - , Member (Reader M.ModuleInfo) sig - , Member (Reader PackageInfo) sig - , Member (Reader Span) sig - , Member (Resumable (BaseError ResolutionError)) sig - , Member Trace sig - , Carrier sig m - ) - => FilePath - -> [String] - -> Evaluator term address value m M.ModulePath -resolveRelativePath relImportPath exts = do - M.ModuleInfo{..} <- currentModule - let relRootDir = takeDirectory modulePath - let path = joinPaths relRootDir relImportPath - trace ("attempting to resolve (relative) require/import " <> show relImportPath) - resolveModule path exts >>= either notFound (\x -> x <$ traceResolve relImportPath path) - where - notFound xs = throwResolutionError $ NotFoundError relImportPath xs Language.TypeScript - --- | Resolve a non-relative TypeScript import to a known 'ModuleName' or fail. --- --- import { b } from "moduleB" in source file /root/src/moduleA.ts --- --- /root/src/node_modules/moduleB.ts --- /root/src/node_modules/moduleB/package.json (if it specifies a "types" property) --- /root/src/node_modules/moduleB/index.ts --- --- /root/node_modules/moduleB.ts, etc --- /node_modules/moduleB.ts, etc -resolveNonRelativePath :: ( Member (Modules address value) sig - , Member (Reader M.ModuleInfo) sig - , Member (Reader PackageInfo) sig - , Member (Reader Span) sig - , Member (Resumable (BaseError ResolutionError)) sig - , Member Trace sig - , Carrier sig m - ) - => FilePath - -> [String] - -> Evaluator term address value m M.ModulePath -resolveNonRelativePath name exts = do - M.ModuleInfo{..} <- currentModule - go "." modulePath mempty - where - nodeModulesPath dir = takeDirectory dir "node_modules" name - -- Recursively search in a 'node_modules' directory, stepping up a directory each time. - go root path searched = do - trace ("attempting to resolve (non-relative) require/import " <> show name) - res <- resolveModule (nodeModulesPath path) exts - case res of - Left xs | parentDir <- takeDirectory path , root /= parentDir -> go root parentDir (searched <> xs) - | otherwise -> notFound (searched <> xs) - Right m -> m <$ traceResolve name m - notFound xs = throwResolutionError $ NotFoundError name xs Language.TypeScript - --- | Resolve a module name to a ModulePath. -resolveModule :: ( Member (Modules address value) sig - , Member (Reader PackageInfo) sig - , Member Trace sig - , Carrier sig m - ) - => FilePath -- ^ Module path used as directory to search in - -> [String] -- ^ File extensions to look for - -> Evaluator term address value m (Either [FilePath] M.ModulePath) -resolveModule path' exts = do - let path = makeRelative "." path' - PackageInfo{..} <- currentPackage - let packageDotJSON = Map.lookup (path "package.json") packageResolutions - let searchPaths = ((path <.>) <$> exts) - <> maybe mempty (:[]) packageDotJSON - <> (((path "index") <.>) <$> exts) - trace ("searching in " <> show searchPaths) - maybe (Left searchPaths) Right <$> resolve searchPaths - -typescriptExtensions :: [String] -typescriptExtensions = ["ts", "tsx", "d.ts"] - -javascriptExtensions :: [String] -javascriptExtensions = ["js"]