From 567414396c5e05e3a2d7d210a07038583b87099c Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 8 Jun 2017 14:25:47 -0700 Subject: [PATCH 001/146] Assign for statements (no else) --- src/Language/Python/Syntax.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index c834cb9e5..0f87fc7fc 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -55,6 +55,7 @@ type Syntax = , Statement.Assignment , Statement.Break , Statement.Continue + , Statement.ForEach , Statement.If , Statement.NoOp , Statement.Return @@ -101,6 +102,7 @@ statement = assertStatement <|> deleteStatement <|> execStatement <|> expressionStatement + <|> forStatement <|> globalStatement <|> ifStatement <|> identifier @@ -136,6 +138,10 @@ expression = await <|> tuple <|> unaryOperator +-- TODO: Assign for else clauses +forStatement :: Assignment +forStatement = makeTerm <$> symbol ForStatement <*> children (Statement.ForEach <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> (makeTerm <$> location <*> many expression)) + dottedName :: Assignment dottedName = makeTerm <$> symbol DottedName <*> children (Expression.ScopeResolution <$> many expression) From db416cfeb8566ecea8d0a87e532fc25e10c0b9fb Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 8 Jun 2017 14:31:57 -0700 Subject: [PATCH 002/146] Assign while statements - no else --- src/Language/Python/Syntax.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 0f87fc7fc..f8d4dbcfc 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -60,6 +60,7 @@ type Syntax = , Statement.NoOp , Statement.Return , Statement.Throw + , Statement.While , Statement.Yield , Language.Python.Syntax.Ellipsis , Syntax.Empty @@ -113,6 +114,7 @@ statement = assertStatement <|> printStatement <|> raiseStatement <|> returnStatement + <|> whileStatement expressionStatement :: Assignment expressionStatement = symbol ExpressionStatement *> children expression @@ -142,6 +144,9 @@ expression = await forStatement :: Assignment forStatement = makeTerm <$> symbol ForStatement <*> children (Statement.ForEach <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> (makeTerm <$> location <*> many expression)) +whileStatement :: Assignment +whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.While <$> expression <*> (makeTerm <$> location <*> many expression)) + dottedName :: Assignment dottedName = makeTerm <$> symbol DottedName <*> children (Expression.ScopeResolution <$> many expression) From c1b25cdcafa094ca0d3e1e7f655823c33e25ad48 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 8 Jun 2017 15:26:54 -0700 Subject: [PATCH 003/146] :fire: comments --- src/Data/Syntax/Statement.hs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Data/Syntax/Statement.hs b/src/Data/Syntax/Statement.hs index 14236d0de..12fd6516c 100644 --- a/src/Data/Syntax/Statement.hs +++ b/src/Data/Syntax/Statement.hs @@ -110,8 +110,6 @@ instance Show1 Throw where liftShowsPrec = genericLiftShowsPrec data Try with a = Try !a ![with a] deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) --- deriving instance (Eq a, Eq (with a)) => Eq (Try with a) --- deriving instance (Show a, Show (with a)) => Show (Try with a) instance Eq1 with => Eq1 (Try with) where liftEq = genericLiftEq instance Show1 with => Show1 (Try with) where liftShowsPrec = genericLiftShowsPrec From 5e4c46165aaeab3c512c7dd1b3d84c6b3d7d047a Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 8 Jun 2017 16:46:03 -0700 Subject: [PATCH 004/146] Assign finally statements --- src/Data/Syntax/Statement.hs | 6 +++--- src/Language/Python/Syntax.hs | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Data/Syntax/Statement.hs b/src/Data/Syntax/Statement.hs index 12fd6516c..d1dc1e652 100644 --- a/src/Data/Syntax/Statement.hs +++ b/src/Data/Syntax/Statement.hs @@ -108,11 +108,11 @@ newtype Throw a = Throw a instance Eq1 Throw where liftEq = genericLiftEq instance Show1 Throw where liftShowsPrec = genericLiftShowsPrec -data Try with a = Try !a ![with a] +data Try a = Try !a ![a] deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) -instance Eq1 with => Eq1 (Try with) where liftEq = genericLiftEq -instance Show1 with => Show1 (Try with) where liftShowsPrec = genericLiftShowsPrec +instance Eq1 Try where liftEq = genericLiftEq +instance Show1 Try where liftShowsPrec = genericLiftShowsPrec data Catch a = Catch !(Maybe a) !a deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index f8d4dbcfc..7bc019995 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -55,6 +55,7 @@ type Syntax = , Statement.Assignment , Statement.Break , Statement.Continue + , Statement.Finally , Statement.ForEach , Statement.If , Statement.NoOp @@ -103,6 +104,7 @@ statement = assertStatement <|> deleteStatement <|> execStatement <|> expressionStatement + <|> finallyClause <|> forStatement <|> globalStatement <|> ifStatement @@ -147,6 +149,8 @@ forStatement = makeTerm <$> symbol ForStatement <*> children (Statement.ForEach whileStatement :: Assignment whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.While <$> expression <*> (makeTerm <$> location <*> many expression)) +finallyClause :: Assignment +finallyClause = makeTerm <$> symbol FinallyClause <*> children (Statement.Finally <$> expression) dottedName :: Assignment dottedName = makeTerm <$> symbol DottedName <*> children (Expression.ScopeResolution <$> many expression) From ab67d72befa2276c779a9ff6b5012313ae9a06da Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 8 Jun 2017 16:46:57 -0700 Subject: [PATCH 005/146] Assign except clauses --- src/Language/Python/Syntax.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 7bc019995..8726e8c86 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -54,6 +54,7 @@ type Syntax = , Redirect , Statement.Assignment , Statement.Break + , Statement.Catch , Statement.Continue , Statement.Finally , Statement.ForEach @@ -102,6 +103,7 @@ statement = assertStatement <|> breakStatement <|> continueStatement <|> deleteStatement + <|> exceptClause <|> execStatement <|> expressionStatement <|> finallyClause @@ -149,6 +151,8 @@ forStatement = makeTerm <$> symbol ForStatement <*> children (Statement.ForEach whileStatement :: Assignment whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.While <$> expression <*> (makeTerm <$> location <*> many expression)) +exceptClause :: Assignment +exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> optional (makeTerm <$> location <*> many expression <* symbol AnonColon) <*> expression) finallyClause :: Assignment finallyClause = makeTerm <$> symbol FinallyClause <*> children (Statement.Finally <$> expression) dottedName :: Assignment From 508ead4cbb0892b230636bf39c4191ee4e5d4565 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 8 Jun 2017 16:47:25 -0700 Subject: [PATCH 006/146] Assign try statements --- src/Language/Python/Syntax.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 8726e8c86..57843fb3b 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -62,6 +62,7 @@ type Syntax = , Statement.NoOp , Statement.Return , Statement.Throw + , Statement.Try , Statement.While , Statement.Yield , Language.Python.Syntax.Ellipsis @@ -118,6 +119,7 @@ statement = assertStatement <|> printStatement <|> raiseStatement <|> returnStatement + <|> tryStatement <|> whileStatement expressionStatement :: Assignment @@ -151,6 +153,10 @@ forStatement = makeTerm <$> symbol ForStatement <*> children (Statement.ForEach whileStatement :: Assignment whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.While <$> expression <*> (makeTerm <$> location <*> many expression)) +-- TODO:: Assign try else clauses +tryStatement :: Assignment +tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many expression)) + exceptClause :: Assignment exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> optional (makeTerm <$> location <*> many expression <* symbol AnonColon) <*> expression) finallyClause :: Assignment From 938987b2ed1be3ed23631955cb4af01352037ed8 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 8 Jun 2017 16:47:38 -0700 Subject: [PATCH 007/146] :memo: todo for assigning while else clauses --- src/Language/Python/Syntax.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 57843fb3b..da9b3a403 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -150,6 +150,7 @@ expression = await forStatement :: Assignment forStatement = makeTerm <$> symbol ForStatement <*> children (Statement.ForEach <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> (makeTerm <$> location <*> many expression)) +-- TODO: Assign while else clauses whileStatement :: Assignment whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.While <$> expression <*> (makeTerm <$> location <*> many expression)) From f0eabfb1fa69340fb811e03f0f0b02d893b2cb86 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 8 Jun 2017 16:47:47 -0700 Subject: [PATCH 008/146] Whitespace --- src/Language/Python/Syntax.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index da9b3a403..2ccbdd663 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -160,6 +160,7 @@ tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> exceptClause :: Assignment exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> optional (makeTerm <$> location <*> many expression <* symbol AnonColon) <*> expression) + finallyClause :: Assignment finallyClause = makeTerm <$> symbol FinallyClause <*> children (Statement.Finally <$> expression) dottedName :: Assignment From 4e3b25e5aa025f7227e2b90e13f7c18c6180eae8 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 11:26:22 -0700 Subject: [PATCH 009/146] Fix comment --- src/Language/Python/Syntax.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 2ccbdd663..20a8ceb43 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -154,7 +154,7 @@ forStatement = makeTerm <$> symbol ForStatement <*> children (Statement.ForEach whileStatement :: Assignment whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.While <$> expression <*> (makeTerm <$> location <*> many expression)) --- TODO:: Assign try else clauses +-- TODO: Assign try else clauses tryStatement :: Assignment tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many expression)) From e444194044fe7e5e1a0a996e7a842e185df0f5dc Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 11:30:04 -0700 Subject: [PATCH 010/146] Add type field to Function --- src/Data/Syntax/Declaration.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Syntax/Declaration.hs b/src/Data/Syntax/Declaration.hs index 37c38daa6..d9b765ebc 100644 --- a/src/Data/Syntax/Declaration.hs +++ b/src/Data/Syntax/Declaration.hs @@ -7,7 +7,7 @@ import Data.Functor.Classes.Show.Generic import GHC.Generics import Prologue -data Function a = Function { functionName :: !a, functionParameters :: ![a], functionBody :: !a } +data Function a = Function { functionType :: !(Maybe a), functionName :: !a, functionParameters :: ![a], functionBody :: !a } deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) instance Eq1 Function where liftEq = genericLiftEq From cf87c11d2c5dea895177a1993c2b5a7a722f5380 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 11:31:27 -0700 Subject: [PATCH 011/146] Python lambdas don't define a type for the lambda expression --- src/Language/Python/Syntax.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 20a8ceb43..f8645fa62 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -362,7 +362,7 @@ none :: Assignment none = makeTerm <$> symbol None <*> (Literal.Null <$ source) lambda :: Assignment -lambda = makeTerm <$> symbol Lambda <*> children (Declaration.Function <$> lambdaIdentifier <*> lambdaParameters <*> lambdaBody) +lambda = makeTerm <$> symbol Lambda <*> children (Declaration.Function Nothing <$> lambdaIdentifier <*> lambdaParameters <*> lambdaBody) where lambdaIdentifier = makeTerm <$> symbol AnonLambda <*> (Syntax.Identifier <$> source) lambdaParameters = many identifier lambdaBody = expression From e9fbded9e8811f41460efaf860e5e1862d7bd267 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 11:31:42 -0700 Subject: [PATCH 012/146] Make TOC renderer aware of type function field --- src/Renderer/TOC.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Renderer/TOC.hs b/src/Renderer/TOC.hs index 1dfcb17e4..a134ea298 100644 --- a/src/Renderer/TOC.hs +++ b/src/Renderer/TOC.hs @@ -107,7 +107,7 @@ declarationAlgebra :: (InUnion fs Declaration.Function, InUnion fs Declaration.M -> Source -> RAlgebra (TermF (Union fs) (Record fields)) (Term (Union fs) (Record fields)) (Maybe Declaration) declarationAlgebra proxy source r - | Just (Declaration.Function (identifier, _) _ _) <- prj (tailF r) = Just $ FunctionDeclaration (getSource identifier) + | Just (Declaration.Function _ (identifier, _) _ _) <- prj (tailF r) = Just $ FunctionDeclaration (getSource identifier) | Just (Declaration.Method (identifier, _) _ _) <- prj (tailF r) = Just $ MethodDeclaration (getSource identifier) | Just (Syntax.Error err) <- prj (tailF r) = Just $ ErrorDeclaration (show (err `asProxyTypeOf` proxy)) | otherwise = Nothing From 333ea956481b889d19b7da35429511244bbe333e Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 11:33:00 -0700 Subject: [PATCH 013/146] Add TypedIdentifier constructor This may not be necessary in the long term, but I've added this to help model typed parameters in Python. --- src/Data/Syntax.hs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Data/Syntax.hs b/src/Data/Syntax.hs index 995e44d2f..72aac5c82 100644 --- a/src/Data/Syntax.hs +++ b/src/Data/Syntax.hs @@ -32,6 +32,13 @@ newtype Identifier a = Identifier ByteString instance Eq1 Identifier where liftEq = genericLiftEq instance Show1 Identifier where liftShowsPrec = genericLiftShowsPrec +-- | A typed identifier of some other construct, differentiated from `Identifier` with a type parameter (e.g. a typed variable or typed function parameter) +data TypedIdentifier a = TypedIdentifier { typedIdentifierType :: !a, typedIdentifierName :: !a } + deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) + +instance Eq1 TypedIdentifier where liftEq = genericLiftEq +instance Show1 TypedIdentifier where liftShowsPrec = genericLiftShowsPrec + -- | Empty syntax, with essentially no-op semantics. -- From e601c3e071d5b918499e2e4dd5e5448e29d02f4a Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 11:33:14 -0700 Subject: [PATCH 014/146] Assign async function definitions --- src/Language/Python/Syntax.hs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index f8645fa62..7cd65dafb 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -69,6 +69,7 @@ type Syntax = , Syntax.Empty , Syntax.Error Error , Syntax.Identifier + , Syntax.TypedIdentifier , [] ] @@ -126,7 +127,8 @@ expressionStatement :: Assignment expressionStatement = symbol ExpressionStatement *> children expression expression :: Assignment -expression = await +expression = asyncFunctionDefinition + <|> await <|> binaryOperator <|> booleanOperator <|> call @@ -144,6 +146,8 @@ expression = await <|> subscript <|> statement <|> tuple + <|> type' + <|> typedParameter <|> unaryOperator -- TODO: Assign for else clauses @@ -158,11 +162,29 @@ whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.Whil tryStatement :: Assignment tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many expression)) +asyncFunctionDefinition :: Assignment +asyncFunctionDefinition = makeTerm <$> symbol AsyncFunctionDefinition <*> children (do + functionName' <- identifier + functionParameters <- (symbol Parameters *> children (many expression)) + functionType <- optional (type') + functionBody <- expressionStatement + return $ Declaration.Function functionType functionName' functionParameters functionBody) + +typedParameter :: Assignment +typedParameter = makeTerm <$> symbol TypedParameter <*> children (flip Syntax.TypedIdentifier <$> identifier <*> type') + +type' :: Assignment +type' = symbol Type *> children (expression) + +parameters :: Assignment +parameters = makeTerm <$> symbol Parameters <*> children (many expression) + exceptClause :: Assignment exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> optional (makeTerm <$> location <*> many expression <* symbol AnonColon) <*> expression) finallyClause :: Assignment finallyClause = makeTerm <$> symbol FinallyClause <*> children (Statement.Finally <$> expression) + dottedName :: Assignment dottedName = makeTerm <$> symbol DottedName <*> children (Expression.ScopeResolution <$> many expression) From f5e91ef793d83ab2b212674ff43ae5411ec56a4d Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 11:35:38 -0700 Subject: [PATCH 015/146] :fire: unused parameters assignment --- src/Language/Python/Syntax.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 7cd65dafb..5d24ba296 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -176,9 +176,6 @@ typedParameter = makeTerm <$> symbol TypedParameter <*> children (flip Syntax.Ty type' :: Assignment type' = symbol Type *> children (expression) -parameters :: Assignment -parameters = makeTerm <$> symbol Parameters <*> children (many expression) - exceptClause :: Assignment exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> optional (makeTerm <$> location <*> many expression <* symbol AnonColon) <*> expression) From 55816f31276905ec610e3cf51655ccf7c16a23e9 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 12:03:54 -0700 Subject: [PATCH 016/146] Assign function definitions --- src/Language/Python/Syntax.hs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 5d24ba296..467317b7d 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -96,7 +96,7 @@ assignment :: Assignment assignment = makeTerm <$> symbol Module <*> children (many declaration) declaration :: Assignment -declaration = handleError $ comment <|> statement <|> expression +declaration = handleError $ asyncFunctionDefinition <|> comment <|> functionDefinition <|> statement <|> expression statement :: Assignment statement = assertStatement @@ -127,8 +127,7 @@ expressionStatement :: Assignment expressionStatement = symbol ExpressionStatement *> children expression expression :: Assignment -expression = asyncFunctionDefinition - <|> await +expression = await <|> binaryOperator <|> booleanOperator <|> call @@ -170,6 +169,14 @@ asyncFunctionDefinition = makeTerm <$> symbol AsyncFunctionDefinition <*> childr functionBody <- expressionStatement return $ Declaration.Function functionType functionName' functionParameters functionBody) +functionDefinition :: Assignment +functionDefinition = makeTerm <$> symbol FunctionDefinition <*> children (do + functionName' <- identifier + functionParameters <- (symbol Parameters *> children (many expression)) + functionType <- optional (type') + functionBody <- expressionStatement + return $ Declaration.Function functionType functionName' functionParameters functionBody) + typedParameter :: Assignment typedParameter = makeTerm <$> symbol TypedParameter <*> children (flip Syntax.TypedIdentifier <$> identifier <*> type') From eb4c87313fe9543a0dee0f26981caad05ff7132d Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 14:27:15 -0700 Subject: [PATCH 017/146] Combine async functiond and function definitions into single assignment --- src/Language/Python/Syntax.hs | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 467317b7d..fbe86c03b 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -96,7 +96,7 @@ assignment :: Assignment assignment = makeTerm <$> symbol Module <*> children (many declaration) declaration :: Assignment -declaration = handleError $ asyncFunctionDefinition <|> comment <|> functionDefinition <|> statement <|> expression +declaration = handleError $ comment <|> statement <|> expression <|> functionDefinition statement :: Assignment statement = assertStatement @@ -161,21 +161,17 @@ whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.Whil tryStatement :: Assignment tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many expression)) -asyncFunctionDefinition :: Assignment -asyncFunctionDefinition = makeTerm <$> symbol AsyncFunctionDefinition <*> children (do - functionName' <- identifier - functionParameters <- (symbol Parameters *> children (many expression)) - functionType <- optional (type') - functionBody <- expressionStatement - return $ Declaration.Function functionType functionName' functionParameters functionBody) - +-- TODO: Assign the 'async' portion functionDefinition :: Assignment -functionDefinition = makeTerm <$> symbol FunctionDefinition <*> children (do - functionName' <- identifier - functionParameters <- (symbol Parameters *> children (many expression)) - functionType <- optional (type') - functionBody <- expressionStatement - return $ Declaration.Function functionType functionName' functionParameters functionBody) +functionDefinition = makeTerm <$> symbol FunctionDefinition <*> children functionDefinition' + <|> makeTerm <$> symbol AsyncFunctionDefinition <*> children functionDefinition' + where + functionDefinition' = do + functionName' <- identifier + functionParameters <- (symbol Parameters *> children (many expression)) + functionType <- optional (type') + functionBody <- expressionStatement + return $ Declaration.Function functionType functionName' functionParameters functionBody typedParameter :: Assignment typedParameter = makeTerm <$> symbol TypedParameter <*> children (flip Syntax.TypedIdentifier <$> identifier <*> type') From e379cb64de822f27991398c564cefae0b918d06b Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 15:39:30 -0700 Subject: [PATCH 018/146] Assign class definitions --- src/Language/Python/Syntax.hs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index fbe86c03b..5ab012c5f 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -28,6 +28,7 @@ import qualified Term type Syntax = '[ Comment.Comment + , Declaration.Class , Declaration.Comprehension , Declaration.Function , Declaration.Import @@ -96,7 +97,7 @@ assignment :: Assignment assignment = makeTerm <$> symbol Module <*> children (many declaration) declaration :: Assignment -declaration = handleError $ comment <|> statement <|> expression <|> functionDefinition +declaration = handleError $ classDefinition <|> comment <|> functionDefinition <|> expression <|> statement statement :: Assignment statement = assertStatement @@ -173,6 +174,11 @@ functionDefinition = makeTerm <$> symbol FunctionDefinition <*> children f functionBody <- expressionStatement return $ Declaration.Function functionType functionName' functionParameters functionBody +classDefinition :: Assignment +classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration.Class <$> identifier <*> argumentList <*> (many declaration)) + where argumentList = symbol ArgumentList *> children (many expression) + <|> pure [] + typedParameter :: Assignment typedParameter = makeTerm <$> symbol TypedParameter <*> children (flip Syntax.TypedIdentifier <$> identifier <*> type') From baa4c1d1fe8a8ec99ca3911437884009a374962b Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 9 Jun 2017 16:10:06 -0700 Subject: [PATCH 019/146] Function definition tree does not always contain expressionStatement subtree --- src/Language/Python/Syntax.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 5ab012c5f..82369b9a2 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -171,7 +171,7 @@ functionDefinition = makeTerm <$> symbol FunctionDefinition <*> children f functionName' <- identifier functionParameters <- (symbol Parameters *> children (many expression)) functionType <- optional (type') - functionBody <- expressionStatement + functionBody <- makeTerm <$> location <*> many expression return $ Declaration.Function functionType functionName' functionParameters functionBody classDefinition :: Assignment From 3f1ceeed8b47343415db3b2cf44904e418676bea Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 12 Jun 2017 10:35:31 -0700 Subject: [PATCH 020/146] Update return statement assignments to accept empty return statements --- src/Language/Python/Syntax.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 3cdb7f4fb..f0b48fa66 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -344,7 +344,7 @@ await :: Assignment await = makeTerm <$> symbol Await <*> children (Expression.Call <$> (makeTerm <$> symbol AnonAwait <*> (Syntax.Identifier <$> source)) <*> many expression) returnStatement :: Assignment -returnStatement = makeTerm <$> symbol ReturnStatement <*> (Statement.Return <$> children expressionList) +returnStatement = makeTerm <$> symbol ReturnStatement <*> children (Statement.Return <$> (expressionList <|> emptyTerm)) deleteStatement :: Assignment deleteStatement = makeTerm <$> symbol DeleteStatement <*> children (Expression.Call <$> deleteIdentifier <* symbol ExpressionList <*> children (many expression)) From cea3b03a9ca7ec8e2600ef90e6b3799460ac5eff Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 12 Jun 2017 10:37:51 -0700 Subject: [PATCH 021/146] Add statements assignment --- src/Language/Python/Syntax.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index f0b48fa66..14b1e1349 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -320,6 +320,9 @@ import' = makeTerm <$> symbol ImportStatement <*> children (Declaration.Import < importFrom :: Assignment importFrom = makeTerm <$> symbol ImportFromStatement <*> children (Declaration.Import <$> many expression) +statements :: Assignment +statements = makeTerm <$> location <*> many statement + assertStatement :: Assignment assertStatement = makeTerm <$ symbol AssertStatement <*> location <*> children (Expression.Call <$> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier <$> source)) <*> many expression) From a242bc0dab89d21209c22571d36eaa6af119b447 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 12 Jun 2017 10:38:05 -0700 Subject: [PATCH 022/146] :fire: unnecessary parens --- src/Language/Python/Syntax.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 14b1e1349..337cc3bb0 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -183,7 +183,7 @@ typedParameter :: Assignment typedParameter = makeTerm <$> symbol TypedParameter <*> children (flip Syntax.TypedIdentifier <$> identifier <*> type') type' :: Assignment -type' = symbol Type *> children (expression) +type' = symbol Type *> children expression exceptClause :: Assignment exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> optional (makeTerm <$> location <*> many expression <* symbol AnonColon) <*> expression) From 636aa76832b726ccaea966d56f70b7f7d39bbf35 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 12 Jun 2017 10:38:30 -0700 Subject: [PATCH 023/146] Update function definition assignments --- src/Language/Python/Syntax.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 337cc3bb0..d0029814d 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -169,9 +169,9 @@ functionDefinition = makeTerm <$> symbol FunctionDefinition <*> children f where functionDefinition' = do functionName' <- identifier - functionParameters <- (symbol Parameters *> children (many expression)) - functionType <- optional (type') - functionBody <- makeTerm <$> location <*> many expression + functionParameters <- symbol Parameters *> children (many expression) + functionType <- optional type' + functionBody <- statements return $ Declaration.Function functionType functionName' functionParameters functionBody classDefinition :: Assignment From 4ee9ff63326f1d26cf7f0df4ae11d09c1cb4bd35 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 23 Jun 2017 19:28:10 -0400 Subject: [PATCH 024/146] Define a SourceSpan -> Range computation parameterized by the line ranges. --- src/Source.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Source.hs b/src/Source.hs index 2c8b07aed..e25a50a53 100644 --- a/src/Source.hs +++ b/src/Source.hs @@ -112,10 +112,13 @@ actualLineRangesWithin range = Prologue.drop 1 . scanl toRange (Range (start ran -- | Compute the byte 'Range' corresponding to a given 'SourceSpan' in a 'Source'. sourceSpanToRange :: Source -> SourceSpan -> Range -sourceSpanToRange source SourceSpan{..} = Range start end +sourceSpanToRange source = sourceSpanToRangeInLineRanges (actualLineRanges source) + +sourceSpanToRangeInLineRanges :: [Range] -> SourceSpan -> Range +sourceSpanToRangeInLineRanges lineRanges SourceSpan{..} = Range start end where start = pred (sumLengths leadingRanges + column spanStart) end = start + sumLengths (Prologue.take (line spanEnd - line spanStart) remainingRanges) + (column spanEnd - column spanStart) - (leadingRanges, remainingRanges) = splitAt (pred (line spanStart)) (actualLineRanges source) + (leadingRanges, remainingRanges) = splitAt (pred (line spanStart)) lineRanges sumLengths = sum . fmap rangeLength -- | Compute the 'SourceSpan' corresponding to a given byte 'Range' in a 'Source'. From c2d835e43a42ab22f3a023e3afe61e0dc5e384b9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Fri, 23 Jun 2017 19:30:02 -0400 Subject: [PATCH 025/146] Compute Markdown ranges within the known line ranges. --- src/Language/Markdown.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Language/Markdown.hs b/src/Language/Markdown.hs index ac07dd67d..dacf85f65 100644 --- a/src/Language/Markdown.hs +++ b/src/Language/Markdown.hs @@ -40,12 +40,14 @@ cmarkParser :: Source -> Cofree [] (Record (NodeType ': Location)) cmarkParser source = toTerm (totalRange source) (totalSpan source) $ commonmarkToNode [ optSourcePos, optSafe ] (toText source) where toTerm :: Range -> SourceSpan -> Node -> Cofree [] (Record (NodeType ': Location)) toTerm within withinSpan (Node position t children) = - let range = maybe within (sourceSpanToRange source . toSpan) position + let range = maybe within (sourceSpanToRangeInLineRanges lineRanges . toSpan) position span = maybe withinSpan toSpan position in cofree $ (t :. range :. span :. Nil) :< (toTerm range span <$> children) toSpan PosInfo{..} = SourceSpan (SourcePos startLine startColumn) (SourcePos endLine (succ endColumn)) + lineRanges = actualLineRanges source + toGrammar :: NodeType -> Grammar toGrammar DOCUMENT{} = Document toGrammar THEMATIC_BREAK{} = ThematicBreak From 4097d4bfc0d40b6b104aa5bc922b01fbcc1ddf97 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 09:30:34 -0400 Subject: [PATCH 026/146] Rename SourceSpan to Span and SourcePos to Pos. --- src/Data/Syntax/Assignment.hs | 34 +++++----- src/Info.hs | 17 +++-- src/Language/Markdown.hs | 6 +- src/Parser.hs | 6 +- src/Renderer/JSON.hs | 2 +- src/Renderer/TOC.hs | 18 +++--- src/Source.hs | 32 +++++----- src/SourceSpan.hs | 98 ++++++++++++----------------- src/TreeSitter.hs | 10 +-- test/Data/Syntax/Assignment/Spec.hs | 28 ++++----- test/SourceSpec.hs | 30 ++++----- test/TOCSpec.hs | 4 +- 12 files changed, 132 insertions(+), 153 deletions(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 154e659d9..6238e9d38 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -1,13 +1,13 @@ {-# LANGUAGE DataKinds, GADTs, InstanceSigs, MultiParamTypeClasses, RankNTypes, ScopedTypeVariables, StandaloneDeriving, TypeFamilies, TypeOperators #-} -- | Assignment of AST onto some other structure (typically terms). -- --- Parsing yields an AST represented as a Rose tree labelled with symbols in the language’s grammar and source locations (byte Range and SourceSpan). An Assignment represents a (partial) map from AST nodes onto some other structure; in essence, it’s a parser that operates over trees. (For our purposes, this structure is typically Terms annotated with source locations.) Assignments are able to match based on symbol, sequence, and hierarchy; thus, in @x = y@, both @x@ and @y@ might have the same symbol, @Identifier@, the left can be assigned to a variable declaration, while the right can be assigned to a variable reference. +-- Parsing yields an AST represented as a Rose tree labelled with symbols in the language’s grammar and source locations (byte Range and Span). An Assignment represents a (partial) map from AST nodes onto some other structure; in essence, it’s a parser that operates over trees. (For our purposes, this structure is typically Terms annotated with source locations.) Assignments are able to match based on symbol, sequence, and hierarchy; thus, in @x = y@, both @x@ and @y@ might have the same symbol, @Identifier@, the left can be assigned to a variable declaration, while the right can be assigned to a variable reference. -- -- Assignments can be any of the following primitive rules: -- -- 1. 'symbol' rules match a node against a specific symbol in the source language’s grammar; they succeed iff a) there is a current node, and b) its symbol is equal to the argument symbol. Matching a 'symbol' rule does not advance past the current node, meaning that you can match a node against a symbol and also e.g. match against the node’s 'children'. This also means that some care must be taken, as repeating a symbol with 'many' or 'some' (see below) will never advance past the current node and could therefore loop forever. -- --- 2. 'location' rules always succeed, and produce the current node’s Location (byte Range and SourceSpan). If there is no current node (i.e. if matching has advanced past the root node or past the last child node when operating within a 'children' rule), the location is instead the end of the most recently matched node, specified as a zero-width Range and SourceSpan. 'location' rules do not advance past the current node, meaning that you can both match a node’s 'location' and other properties. +-- 2. 'location' rules always succeed, and produce the current node’s Location (byte Range and Span). If there is no current node (i.e. if matching has advanced past the root node or past the last child node when operating within a 'children' rule), the location is instead the end of the most recently matched node, specified as a zero-width Range and Span. 'location' rules do not advance past the current node, meaning that you can both match a node’s 'location' and other properties. -- -- 3. 'source' rules succeed whenever there is a current node (i.e. matching has not advanced past the root node or the last child node when operating within a 'children' rule), and produce its source as a ByteString. 'source' is intended to match leaf nodes such as e.g. comments. 'source' rules advance past the current node. -- @@ -122,7 +122,7 @@ data AssignmentF ast grammar a where -- | Zero-width production of the current location. -- --- If assigning at the end of input or at the end of a list of children, the loccation will be returned as an empty Range and SourceSpan at the current offset. Otherwise, it will be the Range and SourceSpan of the current node. +-- If assigning at the end of input or at the end of a list of children, the loccation will be returned as an empty Range and Span at the current offset. Otherwise, it will be the Range and Span of the current node. location :: HasCallStack => Assignment ast grammar (Record Location) location = Location `Then` return @@ -155,7 +155,7 @@ while predicate step = many $ do -- | A location specified as possibly-empty intervals of bytes and line/column positions. -type Location = '[Info.Range, Info.SourceSpan] +type Location = '[Info.Range, Info.Span] -- | An AST node labelled with symbols and source location. type AST grammar = Cofree [] (Record (Maybe grammar ': Location)) @@ -167,7 +167,7 @@ data Result grammar a = Result { resultError :: Maybe (Error grammar), resultVal data Error grammar where Error :: HasCallStack - => { errorPos :: Info.SourcePos + => { errorPos :: Info.Pos , errorCause :: ErrorCause grammar } -> Error grammar @@ -184,13 +184,13 @@ data ErrorCause grammar printError :: Show grammar => Source.Source -> Error grammar -> IO () printError source error@Error{..} = do - withSGRCode [SetConsoleIntensity BoldIntensity] . putStrErr . (showSourcePos Nothing errorPos) . showString ": " $ "" - withSGRCode [SetColor Foreground Vivid Red] . putStrErr . (showString "error") . showString ": " . showExpectation error . showChar '\n' . showString (toS context) . (if isSuffixOf "\n" context then identity else showChar '\n') . showString (replicate (succ (Info.column errorPos + lineNumberDigits)) ' ') $ "" + withSGRCode [SetConsoleIntensity BoldIntensity] . putStrErr . (showPos Nothing errorPos) . showString ": " $ "" + withSGRCode [SetColor Foreground Vivid Red] . putStrErr . (showString "error") . showString ": " . showExpectation error . showChar '\n' . showString (toS context) . (if isSuffixOf "\n" context then identity else showChar '\n') . showString (replicate (succ (Info.posColumn errorPos + lineNumberDigits)) ' ') $ "" withSGRCode [SetColor Foreground Vivid Green] . putStrErr . (showChar '^') . showChar '\n' . showString (prettyCallStack callStack) $ "" - where context = maybe "\n" (Source.sourceText . sconcat) (nonEmpty [ Source.Source (toS (showLineNumber i)) <> Source.Source ": " <> l | (i, l) <- zip [1..] (Source.actualLines source), inRange (Info.line errorPos - 2, Info.line errorPos) i ]) + where context = maybe "\n" (Source.sourceText . sconcat) (nonEmpty [ Source.Source (toS (showLineNumber i)) <> Source.Source ": " <> l | (i, l) <- zip [1..] (Source.actualLines source), inRange (Info.posLine errorPos - 2, Info.posLine errorPos) i ]) showLineNumber n = let s = show n in replicate (lineNumberDigits - length s) ' ' <> s - lineNumberDigits = succ (floor (logBase 10 (fromIntegral (Info.line errorPos) :: Double))) + lineNumberDigits = succ (floor (logBase 10 (fromIntegral (Info.posLine errorPos) :: Double))) putStrErr = hPutStr stderr withSGRCode :: [SGR] -> IO a -> IO () @@ -218,11 +218,11 @@ showSymbols [a, b] = shows a . showString " or " . shows b showSymbols [a, b, c] = shows a . showString ", " . shows b . showString ", or " . shows c showSymbols (h:t) = shows h . showString ", " . showSymbols t -showSourcePos :: Maybe FilePath -> Info.SourcePos -> ShowS -showSourcePos path Info.SourcePos{..} = maybe (showParen True (showString "interactive")) showString path . showChar ':' . shows line . showChar ':' . shows column +showPos :: Maybe FilePath -> Info.Pos -> ShowS +showPos path Info.Pos{..} = maybe (showParen True (showString "interactive")) showString path . showChar ':' . shows posLine . showChar ':' . shows posColumn -- | Run an assignment over an AST exhaustively. -assign :: (HasField fields Info.Range, HasField fields Info.SourceSpan, HasField fields (Maybe grammar), Symbol grammar, Enum grammar, Eq grammar, Traversable f, HasCallStack) => Assignment (Cofree f (Record fields)) grammar a -> Source.Source -> Cofree f (Record fields) -> Result grammar a +assign :: (HasField fields Info.Range, HasField fields Info.Span, HasField fields (Maybe grammar), Symbol grammar, Enum grammar, Eq grammar, Traversable f, HasCallStack) => Assignment (Cofree f (Record fields)) grammar a -> Source.Source -> Cofree f (Record fields) -> Result grammar a assign = assignBy (\ (r :< _) -> getField r :. getField r :. getField r :. Nil) assignBy :: (Symbol grammar, Enum grammar, Eq grammar, Recursive ast, Foldable (Base ast), HasCallStack) => (forall x. Base ast x -> Record (Maybe grammar ': Location)) -> Assignment ast grammar a -> Source.Source -> ast -> Result grammar a @@ -241,7 +241,7 @@ runAssignment toRecord = iterFreer run . fmap ((pure .) . (,)) where run :: AssignmentF ast grammar x -> (x -> AssignmentState ast -> Result grammar (a, AssignmentState ast)) -> AssignmentState ast -> Result grammar (a, AssignmentState ast) run assignment yield initialState = case (assignment, stateNodes) of (Location, node : _) -> yield (rtail (toRecord (F.project node))) state - (Location, []) -> yield (Info.Range stateOffset stateOffset :. Info.SourceSpan statePos statePos :. Nil) state + (Location, []) -> yield (Info.Range stateOffset stateOffset :. Info.Span statePos statePos :. Nil) state (Project projection, node : _) -> yield (projection (F.project node)) state (Source, node : _) -> yield (Source.sourceText (Source.slice (offsetRange (Info.byteRange (toRecord (F.project node))) (negate stateOffset)) stateSource)) (advanceState (rtail . toRecord) state) (Children childAssignment, node : _) -> case assignAllFrom toRecord childAssignment state { stateNodes = toList (F.project node) } of @@ -255,7 +255,7 @@ runAssignment toRecord = iterFreer run . fmap ((pure .) . (,)) Result _ (Just (a, state')) -> pure (a, state') Result err Nothing -> maybe empty (flip yield state . handler) err (_, []) -> Result (Just (Error statePos (UnexpectedEndOfInput expectedSymbols))) Nothing - (_, node:_) -> let Info.SourceSpan startPos _ = Info.sourceSpan (toRecord (F.project node)) in Result (Error startPos . UnexpectedSymbol expectedSymbols <$> rhead (toRecord (F.project node)) <|> Just (Error startPos (ParseError expectedSymbols))) Nothing + (_, node:_) -> let Info.Span startPos _ = Info.sourceSpan (toRecord (F.project node)) in Result (Error startPos . UnexpectedSymbol expectedSymbols <$> rhead (toRecord (F.project node)) <|> Just (Error startPos (ParseError expectedSymbols))) Nothing where state@AssignmentState{..} = case assignment of Choose choices | all ((== Regular) . symbolType) (choiceSymbols choices) -> dropAnonymous (rhead . toRecord) initialState _ -> initialState @@ -277,14 +277,14 @@ advanceState toLocation state@AssignmentState{..} -- | State kept while running 'Assignment's. data AssignmentState ast = AssignmentState { stateOffset :: Int -- ^ The offset into the Source thus far reached, measured in bytes. - , statePos :: Info.SourcePos -- ^ The (1-indexed) line/column position in the Source thus far reached. + , statePos :: Info.Pos -- ^ The (1-indexed) line/column position in the Source thus far reached. , stateSource :: Source.Source -- ^ The remaining Source. Equal to dropping 'stateOffset' bytes off the original input Source. , stateNodes :: [ast] -- ^ The remaining nodes to assign. Note that 'children' rules recur into subterms, and thus this does not necessarily reflect all of the terms remaining to be assigned in the overall algorithm, only those “in scope.” } deriving (Eq, Show) makeState :: Source.Source -> [ast] -> AssignmentState ast -makeState source nodes = AssignmentState 0 (Info.SourcePos 1 1) source nodes +makeState source nodes = AssignmentState 0 (Info.Pos 1 1) source nodes -- Instances @@ -301,7 +301,7 @@ instance Enum grammar => Alternative (Assignment ast grammar) where instance Show grammar => Show1 (AssignmentF ast grammar) where liftShowsPrec sp sl d a = case a of - Location -> showString "Location" . sp d (Info.Range 0 0 :. Info.SourceSpan (Info.SourcePos 0 0) (Info.SourcePos 0 0) :. Nil) + Location -> showString "Location" . sp d (Info.Range 0 0 :. Info.Span (Info.Pos 1 1) (Info.Pos 1 1) :. Nil) Project projection -> showsUnaryWith (const (const (showChar '_'))) "Project" d projection Source -> showString "Source" . showChar ' ' . sp d "" Children a -> showsUnaryWith (liftShowsPrec sp sl) "Children" d a diff --git a/src/Info.hs b/src/Info.hs index 78748abf2..1055dedc7 100644 --- a/src/Info.hs +++ b/src/Info.hs @@ -8,11 +8,10 @@ module Info , Category(..) , category , setCategory -, SourceSpan(..) -, SourcePos(..) -, SourceSpans(..) +, Span(..) +, Pos(..) , sourceSpan -, setSourceSpan +, setSpan ) where import Category @@ -21,10 +20,10 @@ import Range import SourceSpan -- | The default set of fields produced by our parsers. -type DefaultFields = '[ Range, Category, SourceSpan ] +type DefaultFields = '[ Range, Category, Span ] -- | A type alias for HasField constraints commonly used throughout semantic-diff. -type HasDefaultFields fields = (HasField fields Category, HasField fields Range, HasField fields SourceSpan) +type HasDefaultFields fields = (HasField fields Category, HasField fields Range, HasField fields Span) byteRange :: HasField fields Range => Record fields -> Range byteRange = getField @@ -38,8 +37,8 @@ category = getField setCategory :: HasField fields Category => Record fields -> Category -> Record fields setCategory = setField -sourceSpan :: HasField fields SourceSpan => Record fields -> SourceSpan +sourceSpan :: HasField fields Span => Record fields -> Span sourceSpan = getField -setSourceSpan :: HasField fields SourceSpan => Record fields -> SourceSpan -> Record fields -setSourceSpan = setField +setSpan :: HasField fields Span => Record fields -> Span -> Record fields +setSpan = setField diff --git a/src/Language/Markdown.hs b/src/Language/Markdown.hs index dacf85f65..f6580ef90 100644 --- a/src/Language/Markdown.hs +++ b/src/Language/Markdown.hs @@ -38,13 +38,13 @@ data Grammar cmarkParser :: Source -> Cofree [] (Record (NodeType ': Location)) cmarkParser source = toTerm (totalRange source) (totalSpan source) $ commonmarkToNode [ optSourcePos, optSafe ] (toText source) - where toTerm :: Range -> SourceSpan -> Node -> Cofree [] (Record (NodeType ': Location)) + where toTerm :: Range -> Span -> Node -> Cofree [] (Record (NodeType ': Location)) toTerm within withinSpan (Node position t children) = - let range = maybe within (sourceSpanToRangeInLineRanges lineRanges . toSpan) position + let range = maybe within (spanToRangeInLineRanges lineRanges . toSpan) position span = maybe withinSpan toSpan position in cofree $ (t :. range :. span :. Nil) :< (toTerm range span <$> children) - toSpan PosInfo{..} = SourceSpan (SourcePos startLine startColumn) (SourcePos endLine (succ endColumn)) + toSpan PosInfo{..} = Span (Pos startLine startColumn) (Pos endLine (succ endColumn)) lineRanges = actualLineRanges source diff --git a/src/Parser.hs b/src/Parser.hs index 730dd6cd8..d2dfae2f1 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -96,7 +96,7 @@ runParser parser = case parser of LineByLineParser -> lineByLineParser errorTerm :: Syntax.Error (Error grammar) :< fs => Source -> Maybe (Error grammar) -> Term (Union fs) (Record Location) -errorTerm source err = cofree ((totalRange source :. totalSpan source :. Nil) :< inj (Syntax.Error (fromMaybe (Error (SourcePos 0 0) (UnexpectedEndOfInput [])) err))) +errorTerm source err = cofree ((totalRange source :. totalSpan source :. Nil) :< inj (Syntax.Error (fromMaybe (Error (Pos 0 0) (UnexpectedEndOfInput [])) err))) termErrors :: (Syntax.Error (Error grammar) :< fs, Functor (Union fs), Foldable (Union fs)) => Term (Union fs) a -> [Error grammar] termErrors = cata $ \ (_ :< s) -> case s of @@ -109,8 +109,8 @@ lineByLineParser source = pure . cofree . root $ case foldl' annotateLeaves ([], (leaves, _) -> cofree <$> leaves where lines = actualLines source - root children = (sourceRange :. Program :. rangeToSourceSpan source sourceRange :. Nil) :< Indexed children + root children = (sourceRange :. Program :. rangeToSpan source sourceRange :. Nil) :< Indexed children sourceRange = Source.totalRange source - leaf byteIndex line = (Range byteIndex (byteIndex + T.length line) :. Program :. rangeToSourceSpan source (Range byteIndex (byteIndex + T.length line)) :. Nil) :< Leaf line + leaf byteIndex line = (Range byteIndex (byteIndex + T.length line) :. Program :. rangeToSpan source (Range byteIndex (byteIndex + T.length line)) :. Nil) :< Leaf line annotateLeaves (accum, byteIndex) line = (accum <> [ leaf byteIndex (Source.toText line) ] , byteIndex + Source.length line) diff --git a/src/Renderer/JSON.hs b/src/Renderer/JSON.hs index bb0e62639..7409f4a8d 100644 --- a/src/Renderer/JSON.hs +++ b/src/Renderer/JSON.hs @@ -73,7 +73,7 @@ instance ToJSONFields Range where instance ToJSONFields Category where toJSONFields c = ["category" .= case c of { Other s -> s ; _ -> toS c }] -instance ToJSONFields SourceSpan where +instance ToJSONFields Span where toJSONFields sourceSpan = [ "sourceSpan" .= sourceSpan ] instance ToJSONFields a => ToJSONFields (Maybe a) where diff --git a/src/Renderer/TOC.hs b/src/Renderer/TOC.hs index 3c20c9b7e..64321e37e 100644 --- a/src/Renderer/TOC.hs +++ b/src/Renderer/TOC.hs @@ -60,14 +60,14 @@ data JSONSummary = JSONSummary { summaryCategoryName :: Text , summaryTermName :: Text - , summarySourceSpan :: SourceSpan + , summarySpan :: Span , summaryChangeType :: Text } - | ErrorSummary { error :: Text, errorSpan :: SourceSpan } + | ErrorSummary { error :: Text, errorSpan :: Span } deriving (Generic, Eq, Show) instance ToJSON JSONSummary where - toJSON JSONSummary{..} = object [ "changeType" .= summaryChangeType, "category" .= summaryCategoryName, "term" .= summaryTermName, "span" .= summarySourceSpan ] + toJSON JSONSummary{..} = object [ "changeType" .= summaryChangeType, "category" .= summaryCategoryName, "term" .= summaryTermName, "span" .= summarySpan ] toJSON ErrorSummary{..} = object [ "error" .= error, "span" .= errorSpan ] isValidSummary :: JSONSummary -> Bool @@ -171,7 +171,7 @@ dedupe = foldl' go [] similarDeclaration = (==) `on` fmap (toLower . declarationIdentifier) . getDeclaration -- | Construct a 'JSONSummary' from an 'Entry'. Returns 'Nothing' for 'Unchanged' patches. -entrySummary :: (HasField fields (Maybe Declaration), HasField fields SourceSpan) => Entry (Record fields) -> Maybe JSONSummary +entrySummary :: (HasField fields (Maybe Declaration), HasField fields Span) => Entry (Record fields) -> Maybe JSONSummary entrySummary entry = case entry of Unchanged _ -> Nothing Changed a -> recordSummary a "modified" @@ -180,13 +180,13 @@ entrySummary entry = case entry of Replaced a -> recordSummary a "modified" -- | Construct a 'JSONSummary' from a node annotation and a change type label. -recordSummary :: (HasField fields (Maybe Declaration), HasField fields SourceSpan) => Record fields -> Text -> Maybe JSONSummary +recordSummary :: (HasField fields (Maybe Declaration), HasField fields Span) => Record fields -> Text -> Maybe JSONSummary recordSummary record = case getDeclaration record of Just (ErrorDeclaration text) -> Just . const (ErrorSummary text (sourceSpan record)) Just declaration -> Just . JSONSummary (toCategoryName declaration) (declarationIdentifier declaration) (sourceSpan record) Nothing -> const Nothing -renderToCDiff :: (HasField fields (Maybe Declaration), HasField fields SourceSpan, Traversable f) => Both SourceBlob -> Diff f (Record fields) -> Summaries +renderToCDiff :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => Both SourceBlob -> Diff f (Record fields) -> Summaries renderToCDiff blobs = uncurry Summaries . bimap toMap toMap . List.partition isValidSummary . diffTOC where toMap [] = mempty toMap as = Map.singleton summaryKey (toJSON <$> as) @@ -196,15 +196,15 @@ renderToCDiff blobs = uncurry Summaries . bimap toMap toMap . List.partition isV | before == after -> after | otherwise -> before <> " -> " <> after -renderToCTerm :: (HasField fields (Maybe Declaration), HasField fields SourceSpan, Traversable f) => SourceBlob -> Term f (Record fields) -> Summaries +renderToCTerm :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => SourceBlob -> Term f (Record fields) -> Summaries renderToCTerm blob = uncurry Summaries . bimap toMap toMap . List.partition isValidSummary . termToC where toMap [] = mempty toMap as = Map.singleton (toS (path blob)) (toJSON <$> as) -diffTOC :: (HasField fields (Maybe Declaration), HasField fields SourceSpan, Traversable f) => Diff f (Record fields) -> [JSONSummary] +diffTOC :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => Diff f (Record fields) -> [JSONSummary] diffTOC = mapMaybe entrySummary . dedupe . tableOfContentsBy declaration -termToC :: (HasField fields (Maybe Declaration), HasField fields SourceSpan, Traversable f) => Term f (Record fields) -> [JSONSummary] +termToC :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => Term f (Record fields) -> [JSONSummary] termToC = mapMaybe (flip recordSummary "unchanged") . termTableOfContentsBy declaration -- The user-facing category name diff --git a/src/Source.hs b/src/Source.hs index e25a50a53..29e7e5b14 100644 --- a/src/Source.hs +++ b/src/Source.hs @@ -110,22 +110,22 @@ actualLineRangesWithin :: Range -> Source -> [Range] actualLineRangesWithin range = Prologue.drop 1 . scanl toRange (Range (start range) (start range)) . actualLines . slice range where toRange previous string = Range (end previous) $ end previous + B.length (sourceText string) --- | Compute the byte 'Range' corresponding to a given 'SourceSpan' in a 'Source'. -sourceSpanToRange :: Source -> SourceSpan -> Range -sourceSpanToRange source = sourceSpanToRangeInLineRanges (actualLineRanges source) +-- | Compute the byte 'Range' corresponding to a given 'Span' in a 'Source'. +spanToRange :: Source -> Span -> Range +spanToRange source = spanToRangeInLineRanges (actualLineRanges source) -sourceSpanToRangeInLineRanges :: [Range] -> SourceSpan -> Range -sourceSpanToRangeInLineRanges lineRanges SourceSpan{..} = Range start end - where start = pred (sumLengths leadingRanges + column spanStart) - end = start + sumLengths (Prologue.take (line spanEnd - line spanStart) remainingRanges) + (column spanEnd - column spanStart) - (leadingRanges, remainingRanges) = splitAt (pred (line spanStart)) lineRanges +spanToRangeInLineRanges :: [Range] -> Span -> Range +spanToRangeInLineRanges lineRanges Span{..} = Range start end + where start = pred (sumLengths leadingRanges + posColumn spanStart) + end = start + sumLengths (Prologue.take (posLine spanEnd - posLine spanStart) remainingRanges) + (posColumn spanEnd - posColumn spanStart) + (leadingRanges, remainingRanges) = splitAt (pred (posLine spanStart)) lineRanges sumLengths = sum . fmap rangeLength --- | Compute the 'SourceSpan' corresponding to a given byte 'Range' in a 'Source'. -rangeToSourceSpan :: Source -> Range -> SourceSpan -rangeToSourceSpan source (Range rangeStart rangeEnd) = SourceSpan startPos endPos - where startPos = SourcePos (firstLine + 1) (rangeStart - start firstRange + 1) - endPos = SourcePos (firstLine + Prologue.length lineRanges) (rangeEnd - start lastRange + 1) +-- | Compute the 'Span' corresponding to a given byte 'Range' in a 'Source'. +rangeToSpan :: Source -> Range -> Span +rangeToSpan source (Range rangeStart rangeEnd) = Span startPos endPos + where startPos = Pos (firstLine + 1) (rangeStart - start firstRange + 1) + endPos = Pos (firstLine + Prologue.length lineRanges) (rangeEnd - start lastRange + 1) firstLine = Prologue.length before (before, rest) = span ((< rangeStart) . end) (actualLineRanges source) (lineRanges, _) = span ((<= rangeEnd) . start) rest @@ -136,9 +136,9 @@ rangeToSourceSpan source (Range rangeStart rangeEnd) = SourceSpan startPos endPo totalRange :: Source -> Range totalRange = Range 0 . B.length . sourceText --- | Return a 'SourceSpan' that covers the entire text. -totalSpan :: Source -> SourceSpan -totalSpan source = SourceSpan (SourcePos 1 1) (SourcePos (Prologue.length ranges) (succ (end lastRange - start lastRange))) +-- | Return a 'Span' that covers the entire text. +totalSpan :: Source -> Span +totalSpan source = Span (Pos 1 1) (Pos (Prologue.length ranges) (succ (end lastRange - start lastRange))) where ranges = actualLineRanges source Just lastRange = getLast (foldMap (Last . Just) ranges) diff --git a/src/SourceSpan.hs b/src/SourceSpan.hs index 33d5c8cf5..2694f695e 100644 --- a/src/SourceSpan.hs +++ b/src/SourceSpan.hs @@ -1,9 +1,8 @@ {-# LANGUAGE DeriveAnyClass #-} {-# OPTIONS_GHC -funbox-strict-fields #-} --- | --- Source position and span information --- Mostly taken from purescript's SourcePos definition. +-- | Source position and span information -- +-- Mostly taken from purescript's SourcePos definition. module SourceSpan where import Data.Aeson ((.=), (.:)) @@ -14,87 +13,68 @@ import Data.These import Prologue import Test.LeanCheck --- | --- Source position information --- -data SourcePos = SourcePos - { -- | - -- Line number - -- - line :: Int - -- | - -- Column number - -- - , column :: Int - } deriving (Show, Read, Eq, Ord, Generic, Hashable, NFData) +-- | Source position information +data Pos = Pos + { posLine :: !Int + , posColumn :: !Int + } + deriving (Show, Read, Eq, Ord, Generic, Hashable, NFData) -displaySourcePos :: SourcePos -> Text -displaySourcePos SourcePos{..} = - "line " <> show line <> ", column " <> show column +instance A.ToJSON Pos where + toJSON Pos{..} = + A.toJSON [posLine, posColumn] -instance A.ToJSON SourcePos where - toJSON SourcePos{..} = - A.toJSON [line, column] - -instance A.FromJSON SourcePos where +instance A.FromJSON Pos where parseJSON arr = do [line, col] <- A.parseJSON arr - pure $ SourcePos line col + pure $ Pos line col -data SourceSpan = SourceSpan - { -- | - -- Start of the span - -- - spanStart :: SourcePos - -- End of the span - -- - , spanEnd :: SourcePos - } deriving (Show, Read, Eq, Ord, Generic, Hashable, NFData) +data Span = Span + { spanStart :: Pos + , spanEnd :: Pos + } + deriving (Show, Read, Eq, Ord, Generic, Hashable, NFData) -displayStartEndPos :: SourceSpan -> Text -displayStartEndPos sp = - displaySourcePos (spanStart sp) <> " - " <> displaySourcePos (spanEnd sp) +unionSpansFrom :: Foldable f => Span -> f Span -> Span +unionSpansFrom sourceSpan = maybe sourceSpan sconcat . nonEmpty . toList -unionSourceSpansFrom :: Foldable f => SourceSpan -> f SourceSpan -> SourceSpan -unionSourceSpansFrom sourceSpan = maybe sourceSpan sconcat . nonEmpty . toList +unionSpan :: Span -> Span -> Span +unionSpan (Span start1 end1) (Span start2 end2) = Span (min start1 start2) (max end1 end2) -unionSourceSpan :: SourceSpan -> SourceSpan -> SourceSpan -unionSourceSpan (SourceSpan start1 end1) (SourceSpan start2 end2) = SourceSpan (min start1 start2) (max end1 end2) +emptySpan :: Span +emptySpan = Span (Pos 1 1) (Pos 1 1) -emptySourceSpan :: SourceSpan -emptySourceSpan = SourceSpan (SourcePos 1 1) (SourcePos 1 1) +instance Semigroup Span where + a <> b = unionSpan a b -instance Semigroup SourceSpan where - a <> b = unionSourceSpan a b - -instance A.ToJSON SourceSpan where - toJSON SourceSpan{..} = +instance A.ToJSON Span where + toJSON Span{..} = A.object [ "start" .= spanStart , "end" .= spanEnd ] -instance A.FromJSON SourceSpan where - parseJSON = A.withObject "SourceSpan" $ \o -> - SourceSpan <$> +instance A.FromJSON Span where + parseJSON = A.withObject "Span" $ \o -> + Span <$> o .: "start" <*> o .: "end" -newtype SourceSpans = SourceSpans { unSourceSpans :: These SourceSpan SourceSpan } +newtype Spans = Spans { unSpans :: These Span Span } deriving (Eq, Show) -instance A.ToJSON SourceSpans where - toJSON (SourceSpans spans) = case spans of +instance A.ToJSON Spans where + toJSON (Spans spans) = case spans of (This span) -> A.object ["delete" .= span] (That span) -> A.object ["insert" .= span] (These span1 span2) -> A.object ["replace" .= (span1, span2)] - toEncoding (SourceSpans spans) = case spans of + toEncoding (Spans spans) = case spans of (This span) -> A.pairs $ "delete" .= span (That span) -> A.pairs $ "insert" .= span (These span1 span2) -> A.pairs $ "replace" .= (span1, span2) -instance Listable SourcePos where - tiers = cons2 SourcePos +instance Listable Pos where + tiers = cons2 Pos -instance Listable SourceSpan where - tiers = cons2 SourceSpan +instance Listable Span where + tiers = cons2 Span diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index c1aab154e..b4ba9c094 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -102,16 +102,16 @@ isNonEmpty = (/= Empty) . category . extract nodeRange :: Node -> Range nodeRange Node{..} = Range (fromIntegral nodeStartByte) (fromIntegral nodeEndByte) -nodeSpan :: Node -> SourceSpan -nodeSpan Node{..} = nodeStartPoint `seq` nodeEndPoint `seq` SourceSpan (pointPos nodeStartPoint) (pointPos nodeEndPoint) - where pointPos TSPoint{..} = pointRow `seq` pointColumn `seq` SourcePos (1 + fromIntegral pointRow) (1 + fromIntegral pointColumn) +nodeSpan :: Node -> Span +nodeSpan Node{..} = nodeStartPoint `seq` nodeEndPoint `seq` Span (pointPos nodeStartPoint) (pointPos nodeEndPoint) + where pointPos TSPoint{..} = pointRow `seq` pointColumn `seq` Pos (1 + fromIntegral pointRow) (1 + fromIntegral pointColumn) -assignTerm :: Language -> Source -> Record DefaultFields -> [ SyntaxTerm Text '[ Range, Category, SourceSpan ] ] -> IO [ SyntaxTerm Text '[ Range, Category, SourceSpan ] ] -> IO (SyntaxTerm Text '[ Range, Category, SourceSpan ]) +assignTerm :: Language -> Source -> Record DefaultFields -> [ SyntaxTerm Text DefaultFields ] -> IO [ SyntaxTerm Text DefaultFields ] -> IO (SyntaxTerm Text DefaultFields) assignTerm language source annotation children allChildren = cofree . (annotation :<) <$> case assignTermByLanguage language source (category annotation) children of Just a -> pure a _ -> defaultTermAssignment source (category annotation) children allChildren - where assignTermByLanguage :: Language -> Source -> Category -> [ SyntaxTerm Text '[ Range, Category, SourceSpan ] ] -> Maybe (S.Syntax Text (SyntaxTerm Text '[ Range, Category, SourceSpan ])) + where assignTermByLanguage :: Language -> Source -> Category -> [ SyntaxTerm Text DefaultFields ] -> Maybe (S.Syntax Text (SyntaxTerm Text DefaultFields)) assignTermByLanguage language = case language of C -> C.termAssignment Language.Go -> Go.termAssignment diff --git a/test/Data/Syntax/Assignment/Spec.hs b/test/Data/Syntax/Assignment/Spec.hs index 0fe683429..f38b1ebf7 100644 --- a/test/Data/Syntax/Assignment/Spec.hs +++ b/test/Data/Syntax/Assignment/Spec.hs @@ -14,20 +14,20 @@ spec :: Spec spec = do describe "Applicative" $ it "matches in sequence" $ - runAssignment headF ((,) <$> red <*> red) (makeState "helloworld" [node Red 0 5 [], node Red 5 10 []]) `shouldBe` Result Nothing (Just ((Out "hello", Out "world"), AssignmentState 10 (Info.SourcePos 1 11) "" [])) + runAssignment headF ((,) <$> red <*> red) (makeState "helloworld" [node Red 0 5 [], node Red 5 10 []]) `shouldBe` Result Nothing (Just ((Out "hello", Out "world"), AssignmentState 10 (Info.Pos 1 11) "" [])) describe "Alternative" $ do it "attempts multiple alternatives" $ - runAssignment headF (green <|> red) (makeState "hello" [node Red 0 5 []]) `shouldBe` Result Nothing (Just (Out "hello", AssignmentState 5 (Info.SourcePos 1 6) "" [])) + runAssignment headF (green <|> red) (makeState "hello" [node Red 0 5 []]) `shouldBe` Result Nothing (Just (Out "hello", AssignmentState 5 (Info.Pos 1 6) "" [])) it "matches repetitions" $ let s = "colourless green ideas sleep furiously" w = words s (_, nodes) = foldl (\ (i, prev) word -> (i + B.length word + 1, prev <> [node Red i (i + B.length word) []])) (0, []) w in - resultValue (runAssignment headF (many red) (makeState (Source s) nodes)) `shouldBe` Just (Out <$> w, AssignmentState (B.length s) (Info.SourcePos 1 (succ (B.length s))) "" []) + resultValue (runAssignment headF (many red) (makeState (Source s) nodes)) `shouldBe` Just (Out <$> w, AssignmentState (B.length s) (Info.Pos 1 (succ (B.length s))) "" []) it "matches one-or-more repetitions against one or more input nodes" $ - resultValue (runAssignment headF (some red) (makeState "hello" [node Red 0 5 []])) `shouldBe` Just ([Out "hello"], AssignmentState 5 (Info.SourcePos 1 6) "" []) + resultValue (runAssignment headF (some red) (makeState "hello" [node Red 0 5 []])) `shouldBe` Just ([Out "hello"], AssignmentState 5 (Info.Pos 1 6) "" []) describe "symbol" $ do it "matches nodes with the same symbol" $ @@ -42,24 +42,24 @@ spec = do assignBy headF source "hi" (node Red 0 2 []) `shouldBe` Result Nothing (Just "hi") it "advances past the current node" $ - snd <$> runAssignment headF source (makeState "hi" [ node Red 0 2 [] ]) `shouldBe` Result Nothing (Just (AssignmentState 2 (Info.SourcePos 1 3) "" [])) + snd <$> runAssignment headF source (makeState "hi" [ node Red 0 2 [] ]) `shouldBe` Result Nothing (Just (AssignmentState 2 (Info.Pos 1 3) "" [])) describe "children" $ do it "advances past the current node" $ - snd <$> runAssignment headF (children (pure (Out ""))) (makeState "a" [node Red 0 1 []]) `shouldBe` Result Nothing (Just (AssignmentState 1 (Info.SourcePos 1 2) "" [])) + snd <$> runAssignment headF (children (pure (Out ""))) (makeState "a" [node Red 0 1 []]) `shouldBe` Result Nothing (Just (AssignmentState 1 (Info.Pos 1 2) "" [])) it "matches if its subrule matches" $ () <$ runAssignment headF (children red) (makeState "a" [node Blue 0 1 [node Red 0 1 []]]) `shouldBe` Result Nothing (Just ()) it "does not match if its subrule does not match" $ - (runAssignment headF (children red) (makeState "a" [node Blue 0 1 [node Green 0 1 []]])) `shouldBe` Result (Just (Error (Info.SourcePos 1 1) (UnexpectedSymbol [Red] Green))) Nothing + (runAssignment headF (children red) (makeState "a" [node Blue 0 1 [node Green 0 1 []]])) `shouldBe` Result (Just (Error (Info.Pos 1 1) (UnexpectedSymbol [Red] Green))) Nothing it "matches nested children" $ runAssignment headF (symbol Red *> children (symbol Green *> children (symbol Blue *> source))) (makeState "1" [ node Red 0 1 [ node Green 0 1 [ node Blue 0 1 [] ] ] ]) `shouldBe` - Result Nothing (Just ("1", AssignmentState 1 (Info.SourcePos 1 2) "" [])) + Result Nothing (Just ("1", AssignmentState 1 (Info.Pos 1 2) "" [])) it "continues after children" $ resultValue (runAssignment headF @@ -68,7 +68,7 @@ spec = do (makeState "BC" [ node Red 0 1 [ node Green 0 1 [] ] , node Blue 1 2 [] ])) `shouldBe` - Just (["B", "C"], AssignmentState 2 (Info.SourcePos 1 3) "" []) + Just (["B", "C"], AssignmentState 2 (Info.Pos 1 3) "" []) it "matches multiple nested children" $ runAssignment headF @@ -76,20 +76,20 @@ spec = do (makeState "12" [ node Red 0 2 [ node Green 0 1 [ node Blue 0 1 [] ] , node Green 1 2 [ node Blue 1 2 [] ] ] ]) `shouldBe` - Result Nothing (Just (["1", "2"], AssignmentState 2 (Info.SourcePos 1 3) "" [])) + Result Nothing (Just (["1", "2"], AssignmentState 2 (Info.Pos 1 3) "" [])) describe "runAssignment" $ do it "drops anonymous nodes before matching symbols" $ - runAssignment headF red (makeState "magenta red" [node Magenta 0 7 [], node Red 8 11 []]) `shouldBe` Result Nothing (Just (Out "red", AssignmentState 11 (Info.SourcePos 1 12) "" [])) + runAssignment headF red (makeState "magenta red" [node Magenta 0 7 [], node Red 8 11 []]) `shouldBe` Result Nothing (Just (Out "red", AssignmentState 11 (Info.Pos 1 12) "" [])) it "does not drop anonymous nodes after matching" $ - runAssignment headF red (makeState "red magenta" [node Red 0 3 [], node Magenta 4 11 []]) `shouldBe` Result Nothing (Just (Out "red", AssignmentState 3 (Info.SourcePos 1 4) " magenta" [node Magenta 4 11 []])) + runAssignment headF red (makeState "red magenta" [node Red 0 3 [], node Magenta 4 11 []]) `shouldBe` Result Nothing (Just (Out "red", AssignmentState 3 (Info.Pos 1 4) " magenta" [node Magenta 4 11 []])) it "does not drop anonymous nodes when requested" $ - runAssignment headF ((,) <$> magenta <*> red) (makeState "magenta red" [node Magenta 0 7 [], node Red 8 11 []]) `shouldBe` Result Nothing (Just ((Out "magenta", Out "red"), AssignmentState 11 (Info.SourcePos 1 12) "" [])) + runAssignment headF ((,) <$> magenta <*> red) (makeState "magenta red" [node Magenta 0 7 [], node Red 8 11 []]) `shouldBe` Result Nothing (Just ((Out "magenta", Out "red"), AssignmentState 11 (Info.Pos 1 12) "" [])) node :: symbol -> Int -> Int -> [AST symbol] -> AST symbol -node symbol start end children = cofree $ (Just symbol :. Range start end :. Info.SourceSpan (Info.SourcePos 1 (succ start)) (Info.SourcePos 1 (succ end)) :. Nil) :< children +node symbol start end children = cofree $ (Just symbol :. Range start end :. Info.Span (Info.Pos 1 (succ start)) (Info.Pos 1 (succ end)) :. Nil) :< children data Grammar = Red | Green | Blue | Magenta deriving (Enum, Eq, Show) diff --git a/test/SourceSpec.hs b/test/SourceSpec.hs index 721b0cade..24f02608b 100644 --- a/test/SourceSpec.hs +++ b/test/SourceSpec.hs @@ -18,34 +18,34 @@ spec = parallel $ do prop "produces exhaustive ranges" $ \ source -> foldMap (`slice` source) (actualLineRanges source) `shouldBe` source - describe "sourceSpanToRange" $ do + describe "spanToRange" $ do prop "computes single-line ranges" . forAll (unListableByteString `mapT` tiers) $ \ s -> let source = Source s - spans = zipWith (\ i Range {..} -> SourceSpan (SourcePos i 1) (SourcePos i (succ (end - start)))) [1..] ranges + spans = zipWith (\ i Range {..} -> Span (Pos i 1) (Pos i (succ (end - start)))) [1..] ranges ranges = actualLineRanges source in - sourceSpanToRange source <$> spans `shouldBe` ranges + spanToRange source <$> spans `shouldBe` ranges prop "computes multi-line ranges" $ \ source -> - sourceSpanToRange source (totalSpan source) `shouldBe` totalRange source + spanToRange source (totalSpan source) `shouldBe` totalRange source prop "computes sub-line ranges" $ \ s -> let source = "*" <> s <> "*" in - sourceSpanToRange source (insetSpan (totalSpan source)) `shouldBe` insetRange (totalRange source) + spanToRange source (insetSpan (totalSpan source)) `shouldBe` insetRange (totalRange source) - prop "inverse of rangeToSourceSpan" $ - \ a b -> let s = a <> "\n" <> b in sourceSpanToRange s (totalSpan s) `shouldBe` totalRange s + prop "inverse of rangeToSpan" $ + \ a b -> let s = a <> "\n" <> b in spanToRange s (totalSpan s) `shouldBe` totalRange s - describe "rangeToSourceSpan" $ do - prop "inverse of sourceSpanToRange" $ - \ a b -> let s = a <> "\n" <> b in rangeToSourceSpan s (totalRange s) `shouldBe` totalSpan s + describe "rangeToSpan" $ do + prop "inverse of spanToRange" $ + \ a b -> let s = a <> "\n" <> b in rangeToSpan s (totalRange s) `shouldBe` totalSpan s describe "totalSpan" $ do prop "covers single lines" $ - \ n -> totalSpan (fromText (Text.replicate n "*")) `shouldBe` SourceSpan (SourcePos 1 1) (SourcePos 1 (max 1 (succ n))) + \ n -> totalSpan (fromText (Text.replicate n "*")) `shouldBe` Span (Pos 1 1) (Pos 1 (max 1 (succ n))) prop "covers multiple lines" $ - \ n -> totalSpan (fromText (Text.intersperse '\n' (Text.replicate n "*"))) `shouldBe` SourceSpan (SourcePos 1 1) (SourcePos (max 1 n) (if n > 0 then 2 else 1)) + \ n -> totalSpan (fromText (Text.intersperse '\n' (Text.replicate n "*"))) `shouldBe` Span (Pos 1 1) (Pos (max 1 n) (if n > 0 then 2 else 1)) prop "preserves characters" . forAll (toTiers (list +| [chr 0xa0..chr 0x24f])) $ \ c -> Text.unpack (toText (fromText (Text.singleton c))) `shouldBe` [c] @@ -54,9 +54,9 @@ spec = parallel $ do \ s -> fromText (toText s) `shouldBe` s -insetSpan :: SourceSpan -> SourceSpan -insetSpan sourceSpan = sourceSpan { spanStart = (spanStart sourceSpan) { column = succ (column (spanStart sourceSpan)) } - , spanEnd = (spanEnd sourceSpan) { column = pred (column (spanEnd sourceSpan)) } } +insetSpan :: Span -> Span +insetSpan sourceSpan = sourceSpan { spanStart = (spanStart sourceSpan) { posColumn = succ (posColumn (spanStart sourceSpan)) } + , spanEnd = (spanEnd sourceSpan) { posColumn = pred (posColumn (spanEnd sourceSpan)) } } insetRange :: Range -> Range insetRange Range {..} = Range (succ start) (pred end) diff --git a/test/TOCSpec.hs b/test/TOCSpec.hs index 28e1db7f0..125ee5b6c 100644 --- a/test/TOCSpec.hs +++ b/test/TOCSpec.hs @@ -214,8 +214,8 @@ isMethodOrFunction a = case runCofree (unListableF a) of blobsForPaths :: Both FilePath -> IO (Both SourceBlob) blobsForPaths = traverse (readFile . ("test/fixtures/toc/" <>)) -sourceSpanBetween :: (Int, Int) -> (Int, Int) -> SourceSpan -sourceSpanBetween (s1, e1) (s2, e2) = SourceSpan (SourcePos s1 e1) (SourcePos s2 e2) +sourceSpanBetween :: (Int, Int) -> (Int, Int) -> Span +sourceSpanBetween (s1, e1) (s2, e2) = Span (Pos s1 e1) (Pos s2 e2) blankDiff :: Diff' blankDiff = wrap (pure arrayInfo :< Indexed [ inserting (cofree $ literalInfo :< Leaf "\"a\"") ]) From 6e7122e09a80729a07beee8dce58bc25bd172e35 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 09:41:51 -0400 Subject: [PATCH 027/146] Rename the SourceSpan module to Data.Span. --- semantic-diff.cabal | 2 +- src/{SourceSpan.hs => Data/Span.hs} | 2 +- src/Info.hs | 2 +- src/Source.hs | 2 +- src/TreeSitter.hs | 2 +- test/SourceSpec.hs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename src/{SourceSpan.hs => Data/Span.hs} (98%) diff --git a/semantic-diff.cabal b/semantic-diff.cabal index ac2653338..4c58b593c 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -27,6 +27,7 @@ library , Data.Mergeable , Data.Mergeable.Generic , Data.Record + , Data.Span , Data.Syntax , Data.Syntax.Algebra , Data.Syntax.Assignment @@ -72,7 +73,6 @@ library , SES , SES.Myers , Source - , SourceSpan , SplitDiff , Syntax , Term diff --git a/src/SourceSpan.hs b/src/Data/Span.hs similarity index 98% rename from src/SourceSpan.hs rename to src/Data/Span.hs index 2694f695e..6592d11c2 100644 --- a/src/SourceSpan.hs +++ b/src/Data/Span.hs @@ -3,7 +3,7 @@ -- | Source position and span information -- -- Mostly taken from purescript's SourcePos definition. -module SourceSpan where +module Data.Span where import Data.Aeson ((.=), (.:)) import qualified Data.Aeson as A diff --git a/src/Info.hs b/src/Info.hs index 1055dedc7..64c553338 100644 --- a/src/Info.hs +++ b/src/Info.hs @@ -16,8 +16,8 @@ module Info import Category import Data.Record +import Data.Span import Range -import SourceSpan -- | The default set of fields produced by our parsers. type DefaultFields = '[ Range, Category, Span ] diff --git a/src/Source.hs b/src/Source.hs index 29e7e5b14..9717c49de 100644 --- a/src/Source.hs +++ b/src/Source.hs @@ -4,13 +4,13 @@ module Source where import qualified Data.ByteString as B import Data.List (span) +import Data.Span import Data.String (IsString(..)) import qualified Data.Text as T import Language import Numeric import Range import Prologue -import SourceSpan import System.IO (FilePath) import Test.LeanCheck diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index b4ba9c094..437ef34a4 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -10,6 +10,7 @@ import Category import Data.Functor.Foldable hiding (Nil) import Data.Ix import Data.Record +import Data.Span import qualified Data.Syntax.Assignment as A import Language import qualified Language.C as C @@ -27,7 +28,6 @@ import qualified Syntax as S import Term import Text.Parser.TreeSitter hiding (Language(..)) import qualified Text.Parser.TreeSitter as TS -import SourceSpan import Info -- | Returns a TreeSitter parser for the given language and TreeSitter grammar. diff --git a/test/SourceSpec.hs b/test/SourceSpec.hs index 24f02608b..9f535a9c9 100644 --- a/test/SourceSpec.hs +++ b/test/SourceSpec.hs @@ -4,7 +4,7 @@ import qualified Data.Text as Text import Prologue hiding (list) import Range import Source -import SourceSpan +import Data.Span import Test.Hspec import Test.Hspec.LeanCheck import Test.LeanCheck From 1edc6a2718d322c04074212ebd7e211be0aacb47 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 09:46:28 -0400 Subject: [PATCH 028/146] Rename the Range module to Data.Range. --- semantic-diff.cabal | 2 +- src/Alignment.hs | 2 +- src/{ => Data}/Range.hs | 2 +- src/Data/Syntax/Assignment.hs | 2 +- src/FDoc/RecursionSchemes.hs | 2 +- src/FDoc/Term.hs | 2 +- src/Info.hs | 2 +- src/Renderer/Patch.hs | 2 +- src/Source.hs | 2 +- src/TreeSitter.hs | 2 +- test/AlignmentSpec.hs | 2 +- test/PatchOutputSpec.hs | 2 +- test/RangeSpec.hs | 2 +- test/SourceSpec.hs | 4 ++-- 14 files changed, 15 insertions(+), 15 deletions(-) rename src/{ => Data}/Range.hs (99%) diff --git a/semantic-diff.cabal b/semantic-diff.cabal index 4c58b593c..de0a163a9 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -26,6 +26,7 @@ library , Data.Functor.Listable , Data.Mergeable , Data.Mergeable.Generic + , Data.Range , Data.Record , Data.Span , Data.Syntax @@ -60,7 +61,6 @@ library , Patch , Paths_semantic_diff , Prologue - , Range , Renderer , Renderer.JSON , Renderer.Patch diff --git a/src/Alignment.hs b/src/Alignment.hs index 1ae8c5f65..98e487be6 100644 --- a/src/Alignment.hs +++ b/src/Alignment.hs @@ -14,12 +14,12 @@ import Data.Bifunctor.Join import Data.Functor.Both import Data.List (partition) import Data.Maybe (fromJust) +import Data.Range import Data.Record import Data.These import Diff import Info import Patch -import Range import Source hiding (break, drop, take) import SplitDiff import Term diff --git a/src/Range.hs b/src/Data/Range.hs similarity index 99% rename from src/Range.hs rename to src/Data/Range.hs index 4859c37cb..2c0ef80a0 100644 --- a/src/Range.hs +++ b/src/Data/Range.hs @@ -1,5 +1,5 @@ {-# LANGUAGE DeriveAnyClass #-} -module Range where +module Data.Range where import qualified Data.Char as Char import Data.List (span) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 6238e9d38..14ea17ade 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -93,11 +93,11 @@ import Data.Functor.Foldable as F hiding (Nil) import qualified Data.IntMap.Lazy as IntMap import Data.Ix (inRange) import Data.List.NonEmpty (nonEmpty) +import Data.Range (offsetRange) import Data.Record import GHC.Stack import qualified Info import Prologue hiding (Alt, get, Location, state) -import Range (offsetRange) import qualified Source (Source(..), drop, slice, sourceText, actualLines) import System.Console.ANSI import Text.Parser.TreeSitter.Language diff --git a/src/FDoc/RecursionSchemes.hs b/src/FDoc/RecursionSchemes.hs index 34f092582..afb479273 100644 --- a/src/FDoc/RecursionSchemes.hs +++ b/src/FDoc/RecursionSchemes.hs @@ -1,8 +1,8 @@ {-# LANGUAGE DataKinds, ScopedTypeVariables, TypeFamilies, TypeOperators #-} module FDoc.RecursionSchemes where +import Data.Range import Data.Record -import Range import Category import Term import Syntax diff --git a/src/FDoc/Term.hs b/src/FDoc/Term.hs index ec6170664..0d90ebdcf 100644 --- a/src/FDoc/Term.hs +++ b/src/FDoc/Term.hs @@ -1,8 +1,8 @@ {-# LANGUAGE DataKinds, TypeOperators #-} module FDoc.Term where +import Data.Range import Data.Record -import Range import Category import Term import Syntax diff --git a/src/Info.hs b/src/Info.hs index 64c553338..50e441de2 100644 --- a/src/Info.hs +++ b/src/Info.hs @@ -15,9 +15,9 @@ module Info ) where import Category +import Data.Range import Data.Record import Data.Span -import Range -- | The default set of fields produced by our parsers. type DefaultFields = '[ Range, Category, Span ] diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index 475bd3d4d..f39dc8122 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -12,12 +12,12 @@ import Data.Bifunctor.Join import qualified Data.ByteString.Char8 as ByteString import Data.Functor.Both as Both import Data.List (span, unzip) +import Data.Range import Data.Record import Data.These import Diff import Patch import Prologue hiding (fst, snd) -import Range import qualified Source import Source hiding (break, drop, length, null, take) import SplitDiff diff --git a/src/Source.hs b/src/Source.hs index 9717c49de..9885b299a 100644 --- a/src/Source.hs +++ b/src/Source.hs @@ -4,12 +4,12 @@ module Source where import qualified Data.ByteString as B import Data.List (span) +import Data.Range import Data.Span import Data.String (IsString(..)) import qualified Data.Text as T import Language import Numeric -import Range import Prologue import System.IO (FilePath) import Test.LeanCheck diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 437ef34a4..c9ff9b866 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -9,6 +9,7 @@ import Prologue hiding (Constructor) import Category import Data.Functor.Foldable hiding (Nil) import Data.Ix +import Data.Range import Data.Record import Data.Span import qualified Data.Syntax.Assignment as A @@ -17,7 +18,6 @@ import qualified Language.C as C import qualified Language.Go as Go import qualified Language.TypeScript as TS import qualified Language.Ruby as Ruby -import Range import Source import qualified Syntax import Foreign diff --git a/test/AlignmentSpec.hs b/test/AlignmentSpec.hs index 0dc097ad4..f085dcf31 100644 --- a/test/AlignmentSpec.hs +++ b/test/AlignmentSpec.hs @@ -10,13 +10,13 @@ import Data.Functor.Both as Both import Data.Functor.Listable import Data.List (nub) import Data.Monoid hiding ((<>)) +import Data.Range import Data.Record import qualified Data.Text as Text import Data.These import Patch import Prologue hiding (fst, snd) import qualified Prologue -import Range import qualified Source import SplitDiff import Syntax diff --git a/test/PatchOutputSpec.hs b/test/PatchOutputSpec.hs index f5c837b29..5296ab5dc 100644 --- a/test/PatchOutputSpec.hs +++ b/test/PatchOutputSpec.hs @@ -2,8 +2,8 @@ module PatchOutputSpec where import Prologue import Data.Functor.Both +import Data.Range import Data.Record -import Range import Renderer.Patch import Source import Syntax diff --git a/test/RangeSpec.hs b/test/RangeSpec.hs index 21f64b7a6..3da0b6f16 100644 --- a/test/RangeSpec.hs +++ b/test/RangeSpec.hs @@ -1,7 +1,7 @@ module RangeSpec where +import Data.Range import Prologue -import Range import Test.Hspec (Spec, describe, it, parallel) import Test.Hspec.Expectations.Pretty diff --git a/test/SourceSpec.hs b/test/SourceSpec.hs index 9f535a9c9..043240616 100644 --- a/test/SourceSpec.hs +++ b/test/SourceSpec.hs @@ -1,10 +1,10 @@ module SourceSpec where +import Data.Range +import Data.Span import qualified Data.Text as Text import Prologue hiding (list) -import Range import Source -import Data.Span import Test.Hspec import Test.Hspec.LeanCheck import Test.LeanCheck From fc09d74b733e6c56762bdffb0789d1a7bc0705a3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 09:59:41 -0400 Subject: [PATCH 029/146] Rename the Source module to Data.Source. --- semantic-diff.cabal | 2 +- src/Alignment.hs | 2 +- src/Command/Files.hs | 2 +- src/{ => Data}/Source.hs | 20 ++++++++++---------- src/Data/Syntax/Assignment.hs | 2 +- src/Language/C.hs | 2 +- src/Language/Go.hs | 6 +++--- src/Language/Markdown.hs | 2 +- src/Language/Ruby.hs | 2 +- src/Language/TypeScript.hs | 4 ++-- src/Parser.hs | 4 ++-- src/Renderer/JSON.hs | 2 +- src/Renderer/Patch.hs | 4 ++-- src/Renderer/TOC.hs | 2 +- src/Semantic.hs | 2 +- src/Semantic/Task.hs | 2 +- src/TreeSitter.hs | 2 +- test/AlignmentSpec.hs | 2 +- test/CommandSpec.hs | 2 +- test/Data/Syntax/Assignment/Spec.hs | 2 +- test/PatchOutputSpec.hs | 2 +- test/SemanticSpec.hs | 2 +- test/SourceSpec.hs | 2 +- test/SpecHelpers.hs | 2 +- test/TOCSpec.hs | 2 +- 25 files changed, 39 insertions(+), 39 deletions(-) rename src/{ => Data}/Source.hs (91%) diff --git a/semantic-diff.cabal b/semantic-diff.cabal index de0a163a9..8ddec36f6 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -28,6 +28,7 @@ library , Data.Mergeable.Generic , Data.Range , Data.Record + , Data.Source , Data.Span , Data.Syntax , Data.Syntax.Algebra @@ -72,7 +73,6 @@ library , SemanticCmdLine , SES , SES.Myers - , Source , SplitDiff , Syntax , Term diff --git a/src/Alignment.hs b/src/Alignment.hs index 98e487be6..f8cd49ab5 100644 --- a/src/Alignment.hs +++ b/src/Alignment.hs @@ -15,12 +15,12 @@ import Data.Functor.Both import Data.List (partition) import Data.Maybe (fromJust) import Data.Range +import Data.Source hiding (break, drop, take) import Data.Record import Data.These import Diff import Info import Patch -import Source hiding (break, drop, take) import SplitDiff import Term diff --git a/src/Command/Files.hs b/src/Command/Files.hs index 41dee0e21..45d8787e1 100644 --- a/src/Command/Files.hs +++ b/src/Command/Files.hs @@ -10,13 +10,13 @@ import Control.Exception (catch, IOException) import Data.Aeson import Data.These import Data.Functor.Both +import Data.Source hiding (path) import Data.String import Language import Prologue hiding (readFile) import qualified Data.ByteString as B import qualified Data.ByteString.Lazy as BL import Prelude (fail) -import Source hiding (path) import System.FilePath diff --git a/src/Source.hs b/src/Data/Source.hs similarity index 91% rename from src/Source.hs rename to src/Data/Source.hs index 9885b299a..c92fbbcae 100644 --- a/src/Source.hs +++ b/src/Data/Source.hs @@ -1,6 +1,6 @@ {-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses #-} {-# OPTIONS_GHC -funbox-strict-fields #-} -module Source where +module Data.Source where import qualified Data.ByteString as B import Data.List (span) @@ -41,16 +41,16 @@ defaultPlainBlob :: SourceKind defaultPlainBlob = PlainBlob 0o100644 emptySourceBlob :: FilePath -> SourceBlob -emptySourceBlob filepath = SourceBlob Source.empty Source.nullOid filepath Nothing Nothing +emptySourceBlob filepath = SourceBlob Data.Source.empty Data.Source.nullOid filepath Nothing Nothing nullBlob :: SourceBlob -> Bool -nullBlob SourceBlob{..} = oid == nullOid || Source.null source +nullBlob SourceBlob{..} = oid == nullOid || Data.Source.null source blobExists :: SourceBlob -> Bool blobExists SourceBlob{..} = isJust blobKind sourceBlob :: FilePath -> Maybe Language -> Source -> SourceBlob -sourceBlob filepath language source = SourceBlob source Source.nullOid filepath (Just defaultPlainBlob) language +sourceBlob filepath language source = SourceBlob source Data.Source.nullOid filepath (Just defaultPlainBlob) language -- | Map blobs with Nothing blobKind to empty blobs. idOrEmptySourceBlob :: SourceBlob -> SourceBlob @@ -64,15 +64,15 @@ nullOid = "0000000000000000000000000000000000000000" empty :: Source empty = Source B.empty --- | Return a Source from a ByteString. +-- | Return a 'Source' from a 'ByteString'. fromText :: T.Text -> Source fromText = Source . encodeUtf8 --- | Return a Source that contains a slice of the given Source. +-- | Return a 'Source' that contains a slice of the given 'Source'. slice :: Range -> Source -> Source slice range = take . drop - where drop = Source.drop (start range) - take = Source.take (rangeLength range) + where drop = Data.Source.drop (start range) + take = Data.Source.take (rangeLength range) drop :: Int -> Source -> Source drop i = Source . drop . sourceText @@ -82,7 +82,7 @@ take :: Int -> Source -> Source take i = Source . take . sourceText where take = B.take i --- | Return the ByteString contained in the Source. +-- | Return the ByteString contained in the 'Source'. toText :: Source -> Text toText = decodeUtf8 . sourceText @@ -152,7 +152,7 @@ instance Semigroup Source where Source a <> Source b = Source (a <> b) instance Monoid Source where - mempty = Source.empty + mempty = Data.Source.empty mappend = (<>) instance Listable Source where diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 14ea17ade..addc8448d 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -95,10 +95,10 @@ import Data.Ix (inRange) import Data.List.NonEmpty (nonEmpty) import Data.Range (offsetRange) import Data.Record +import qualified Data.Source as Source (Source(..), drop, slice, sourceText, actualLines) import GHC.Stack import qualified Info import Prologue hiding (Alt, get, Location, state) -import qualified Source (Source(..), drop, slice, sourceText, actualLines) import System.Console.ANSI import Text.Parser.TreeSitter.Language import Text.Show hiding (show) diff --git a/src/Language/C.hs b/src/Language/C.hs index 5796bef6e..6538af1d9 100644 --- a/src/Language/C.hs +++ b/src/Language/C.hs @@ -1,9 +1,9 @@ {-# LANGUAGE DataKinds #-} module Language.C where +import Data.Source import Info import Prologue -import Source import qualified Syntax as S import Term diff --git a/src/Language/Go.hs b/src/Language/Go.hs index 056ec25df..e88946f7a 100644 --- a/src/Language/Go.hs +++ b/src/Language/Go.hs @@ -1,11 +1,11 @@ {-# LANGUAGE DataKinds #-} module Language.Go where -import Prologue +import Data.Source import Info -import Source -import Term +import Prologue import qualified Syntax as S +import Term termAssignment :: Source -- ^ The source of the term. diff --git a/src/Language/Markdown.hs b/src/Language/Markdown.hs index f6580ef90..172000c8f 100644 --- a/src/Language/Markdown.hs +++ b/src/Language/Markdown.hs @@ -7,10 +7,10 @@ module Language.Markdown import CMark import Data.Record +import Data.Source import Data.Syntax.Assignment (Location) import Info import Prologue hiding (Location) -import Source import Text.Parser.TreeSitter.Language (Symbol(..), SymbolType(..)) data Grammar diff --git a/src/Language/Ruby.hs b/src/Language/Ruby.hs index 323d61297..89921697f 100644 --- a/src/Language/Ruby.hs +++ b/src/Language/Ruby.hs @@ -2,9 +2,9 @@ module Language.Ruby where import Data.List (partition) +import Data.Source hiding (null) import Info import Prologue -import Source hiding (null) import Language import qualified Syntax as S import Term diff --git a/src/Language/TypeScript.hs b/src/Language/TypeScript.hs index b7db1e0df..625268cb0 100644 --- a/src/Language/TypeScript.hs +++ b/src/Language/TypeScript.hs @@ -1,10 +1,10 @@ {-# LANGUAGE DataKinds #-} module Language.TypeScript where +import Data.Source import Info -import Prologue -import Source import Language +import Prologue import qualified Syntax as S import Term diff --git a/src/Parser.hs b/src/Parser.hs index d2dfae2f1..5e815e376 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -11,10 +11,11 @@ module Parser ) where import qualified CMark +import Data.Functor.Foldable hiding (fold, Nil) import Data.Record +import Data.Source as Source import qualified Data.Syntax as Syntax import Data.Syntax.Assignment -import Data.Functor.Foldable hiding (fold, Nil) import qualified Data.Text as T import Data.Union import Info hiding (Empty, Go) @@ -24,7 +25,6 @@ import qualified Language.Markdown.Syntax as Markdown import qualified Language.Python.Syntax as Python import qualified Language.Ruby.Syntax as Ruby import Prologue hiding (Location) -import Source import Syntax hiding (Go) import System.IO (hPutStrLn) import System.Console.ANSI diff --git a/src/Renderer/JSON.hs b/src/Renderer/JSON.hs index 7409f4a8d..16f2062bd 100644 --- a/src/Renderer/JSON.hs +++ b/src/Renderer/JSON.hs @@ -12,12 +12,12 @@ import Data.Bifunctor.Join import Data.Functor.Both (Both) import qualified Data.Map as Map import Data.Record +import Data.Source import Data.Union import Info import Language import Patch import Prologue hiding ((++)) -import Source import Syntax as S -- diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index f39dc8122..8fae4c0e7 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -14,12 +14,12 @@ import Data.Functor.Both as Both import Data.List (span, unzip) import Data.Range import Data.Record +import Data.Source as Source hiding (break, drop, length, null, take) +import qualified Data.Source as Source import Data.These import Diff import Patch import Prologue hiding (fst, snd) -import qualified Source -import Source hiding (break, drop, length, null, take) import SplitDiff -- | Render a timed out file as a truncated diff. diff --git a/src/Renderer/TOC.hs b/src/Renderer/TOC.hs index 64321e37e..9d5181e6d 100644 --- a/src/Renderer/TOC.hs +++ b/src/Renderer/TOC.hs @@ -25,6 +25,7 @@ import Data.Functor.Listable import Data.List.NonEmpty (nonEmpty) import Data.Proxy import Data.Record +import Data.Source as Source hiding (null) import Data.Text (toLower) import Data.Text.Listable import Data.These @@ -35,7 +36,6 @@ import Patch import Prologue import qualified Data.List as List import qualified Data.Map as Map hiding (null) -import Source hiding (null) import Syntax as S import Data.Syntax.Algebra (RAlgebra) import qualified Data.Syntax as Syntax diff --git a/src/Semantic.hs b/src/Semantic.hs index 9ef476ab8..0a0b30fe7 100644 --- a/src/Semantic.hs +++ b/src/Semantic.hs @@ -13,6 +13,7 @@ import Data.Functor.Both as Both import Data.Functor.Classes (Eq1, Show1) import Data.Proxy import Data.Record +import Data.Source import qualified Data.Syntax.Declaration as Declaration import Data.Union import Diff @@ -26,7 +27,6 @@ import Parser import Prologue import Renderer import Semantic.Task as Task -import Source import Term import Text.Show diff --git a/src/Semantic/Task.hs b/src/Semantic/Task.hs index bd9d4bb88..d80abbd3d 100644 --- a/src/Semantic/Task.hs +++ b/src/Semantic/Task.hs @@ -18,11 +18,11 @@ import qualified Control.Concurrent.Async as Async import Control.Monad.Free.Freer import Data.Functor.Both as Both import Data.Record +import Data.Source import Data.Syntax.Algebra (RAlgebra, decoratorWithAlgebra) import Diff import Parser import Prologue -import Source import Term data TaskF output where diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index c9ff9b866..d5998e9f9 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -11,6 +11,7 @@ import Data.Functor.Foldable hiding (Nil) import Data.Ix import Data.Range import Data.Record +import Data.Source import Data.Span import qualified Data.Syntax.Assignment as A import Language @@ -18,7 +19,6 @@ import qualified Language.C as C import qualified Language.Go as Go import qualified Language.TypeScript as TS import qualified Language.Ruby as Ruby -import Source import qualified Syntax import Foreign import Foreign.C.String (peekCString) diff --git a/test/AlignmentSpec.hs b/test/AlignmentSpec.hs index f085dcf31..c24cf5b7c 100644 --- a/test/AlignmentSpec.hs +++ b/test/AlignmentSpec.hs @@ -12,12 +12,12 @@ import Data.List (nub) import Data.Monoid hiding ((<>)) import Data.Range import Data.Record +import qualified Data.Source as Source import qualified Data.Text as Text import Data.These import Patch import Prologue hiding (fst, snd) import qualified Prologue -import qualified Source import SplitDiff import Syntax import Term diff --git a/test/CommandSpec.hs b/test/CommandSpec.hs index 1953f09b0..3d767120a 100644 --- a/test/CommandSpec.hs +++ b/test/CommandSpec.hs @@ -3,10 +3,10 @@ module CommandSpec where import Command import Data.Functor.Both as Both import Data.Maybe +import Data.Source import Data.String import Language import Prologue hiding (readFile, toList) -import Source import Test.Hspec hiding (shouldBe, shouldNotBe, shouldThrow, errorCall) import Test.Hspec.Expectations.Pretty diff --git a/test/Data/Syntax/Assignment/Spec.hs b/test/Data/Syntax/Assignment/Spec.hs index f38b1ebf7..fdf393530 100644 --- a/test/Data/Syntax/Assignment/Spec.hs +++ b/test/Data/Syntax/Assignment/Spec.hs @@ -3,10 +3,10 @@ module Data.Syntax.Assignment.Spec where import Data.ByteString.Char8 as B (words, length) import Data.Record +import Data.Source hiding (source, length) import Data.Syntax.Assignment import Info import Prologue -import Source hiding (source, length) import Test.Hspec import Text.Parser.TreeSitter.Language (Symbol(..), SymbolType(..)) diff --git a/test/PatchOutputSpec.hs b/test/PatchOutputSpec.hs index 5296ab5dc..1ead512ae 100644 --- a/test/PatchOutputSpec.hs +++ b/test/PatchOutputSpec.hs @@ -4,8 +4,8 @@ import Prologue import Data.Functor.Both import Data.Range import Data.Record +import Data.Source as Source import Renderer.Patch -import Source import Syntax import Test.Hspec (Spec, describe, it, parallel) import Test.Hspec.Expectations.Pretty diff --git a/test/SemanticSpec.hs b/test/SemanticSpec.hs index b747c8840..24fec0f38 100644 --- a/test/SemanticSpec.hs +++ b/test/SemanticSpec.hs @@ -1,13 +1,13 @@ module SemanticSpec where import Data.Functor.Both as Both +import Data.Source import Language import Patch import Prologue import Renderer import Semantic import Semantic.Task -import Source import Syntax import Test.Hspec hiding (shouldBe, shouldNotBe, shouldThrow, errorCall) import Test.Hspec.Expectations.Pretty diff --git a/test/SourceSpec.hs b/test/SourceSpec.hs index 043240616..8aea3b9e7 100644 --- a/test/SourceSpec.hs +++ b/test/SourceSpec.hs @@ -1,10 +1,10 @@ module SourceSpec where import Data.Range +import Data.Source import Data.Span import qualified Data.Text as Text import Prologue hiding (list) -import Source import Test.Hspec import Test.Hspec.LeanCheck import Test.LeanCheck diff --git a/test/SpecHelpers.hs b/test/SpecHelpers.hs index f48fd1494..273dc98d4 100644 --- a/test/SpecHelpers.hs +++ b/test/SpecHelpers.hs @@ -10,6 +10,7 @@ module SpecHelpers import qualified Data.ByteString as B import Data.Functor.Both import Data.Functor.Listable +import Data.Source import Diff import Language import Patch @@ -17,7 +18,6 @@ import Prologue hiding (readFile) import Renderer import Semantic import Semantic.Task -import Source import System.FilePath import Term diff --git a/test/TOCSpec.hs b/test/TOCSpec.hs index 125ee5b6c..353f0db92 100644 --- a/test/TOCSpec.hs +++ b/test/TOCSpec.hs @@ -7,6 +7,7 @@ import Category as C import Data.Functor.Both import Data.Functor.Listable import Data.Record +import Data.Source import Data.Text.Listable import Data.These import Diff @@ -20,7 +21,6 @@ import Renderer.TOC import RWS import Semantic import Semantic.Task -import Source import SpecHelpers import Syntax as S import Term From 84c7029dd846baf9928d34b9031dc2efc2631c70 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:00:40 -0400 Subject: [PATCH 030/146] Stub in a Blob module. --- semantic-diff.cabal | 1 + src/Data/Blob.hs | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/Data/Blob.hs diff --git a/semantic-diff.cabal b/semantic-diff.cabal index 8ddec36f6..5cb25d44d 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -20,6 +20,7 @@ library , Command , Command.Files , Data.Align.Generic + , Data.Blob , Data.Functor.Both , Data.Functor.Classes.Eq.Generic , Data.Functor.Classes.Show.Generic diff --git a/src/Data/Blob.hs b/src/Data/Blob.hs new file mode 100644 index 000000000..1b7889e37 --- /dev/null +++ b/src/Data/Blob.hs @@ -0,0 +1 @@ +module Data.Blob where From fc51c92425ff2fc531c03beb5f94f180ef87ff17 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:09:50 -0400 Subject: [PATCH 031/146] Move SourceBlob into Data.Blob. --- src/Command/Files.hs | 3 ++- src/Data/Blob.hs | 49 +++++++++++++++++++++++++++++++++++++++++ src/Data/Source.hs | 45 ------------------------------------- src/Renderer/JSON.hs | 2 +- src/Renderer/Patch.hs | 1 + src/Renderer/TOC.hs | 1 + src/Semantic.hs | 1 + test/CommandSpec.hs | 1 + test/PatchOutputSpec.hs | 4 ++-- test/SemanticSpec.hs | 4 ++-- test/SpecHelpers.hs | 1 + test/TOCSpec.hs | 1 + 12 files changed, 62 insertions(+), 51 deletions(-) diff --git a/src/Command/Files.hs b/src/Command/Files.hs index 45d8787e1..4a58f8d01 100644 --- a/src/Command/Files.hs +++ b/src/Command/Files.hs @@ -10,7 +10,8 @@ import Control.Exception (catch, IOException) import Data.Aeson import Data.These import Data.Functor.Both -import Data.Source hiding (path) +import Data.Blob hiding (path) +import Data.Source import Data.String import Language import Prologue hiding (readFile) diff --git a/src/Data/Blob.hs b/src/Data/Blob.hs index 1b7889e37..17dd812b2 100644 --- a/src/Data/Blob.hs +++ b/src/Data/Blob.hs @@ -1 +1,50 @@ module Data.Blob where + +import Data.Source as Source +import Language +import Numeric +import Prologue + +-- | The source, oid, path, and Maybe SourceKind of a blob. +data SourceBlob = SourceBlob + { source :: Source -- ^ The UTF-8 encoded source text of the blob. + , oid :: ByteString -- ^ The Git object ID (SHA-1) of the blob. + , path :: FilePath -- ^ The file path to the blob. + , blobKind :: Maybe SourceKind -- ^ The kind of blob, Nothing denotes a blob that doesn't exist (e.g. on one side of a diff for adding a new file or deleting a file). + , blobLanguage :: Maybe Language -- ^ The language of this blob. Nothing denotes a langauge we don't support yet. + } + deriving (Show, Eq) + +-- | The kind of a blob, along with it's file mode. +data SourceKind = PlainBlob Word32 | ExecutableBlob Word32 | SymlinkBlob Word32 + deriving (Show, Eq) + +modeToDigits :: SourceKind -> ByteString +modeToDigits (PlainBlob mode) = toS $ showOct mode "" +modeToDigits (ExecutableBlob mode) = toS $ showOct mode "" +modeToDigits (SymlinkBlob mode) = toS $ showOct mode "" + +-- | The default plain blob mode +defaultPlainBlob :: SourceKind +defaultPlainBlob = PlainBlob 0o100644 + +emptySourceBlob :: FilePath -> SourceBlob +emptySourceBlob filepath = SourceBlob mempty nullOid filepath Nothing Nothing + +nullBlob :: SourceBlob -> Bool +nullBlob SourceBlob{..} = oid == nullOid || Source.null source + +blobExists :: SourceBlob -> Bool +blobExists SourceBlob{..} = isJust blobKind + +sourceBlob :: FilePath -> Maybe Language -> Source -> SourceBlob +sourceBlob filepath language source = SourceBlob source nullOid filepath (Just defaultPlainBlob) language + +-- | Map blobs with Nothing blobKind to empty blobs. +idOrEmptySourceBlob :: SourceBlob -> SourceBlob +idOrEmptySourceBlob blob = if isNothing (blobKind blob) + then blob { oid = nullOid, blobKind = Nothing } + else blob + +nullOid :: ByteString +nullOid = "0000000000000000000000000000000000000000" diff --git a/src/Data/Source.hs b/src/Data/Source.hs index c92fbbcae..9be54610f 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -8,58 +8,13 @@ import Data.Range import Data.Span import Data.String (IsString(..)) import qualified Data.Text as T -import Language -import Numeric import Prologue -import System.IO (FilePath) import Test.LeanCheck --- | The source, oid, path, and Maybe SourceKind of a blob. -data SourceBlob = SourceBlob - { source :: Source -- ^ The UTF-8 encoded source text of the blob. - , oid :: ByteString -- ^ The Git object ID (SHA-1) of the blob. - , path :: FilePath -- ^ The file path to the blob. - , blobKind :: Maybe SourceKind -- ^ The kind of blob, Nothing denotes a blob that doesn't exist (e.g. on one side of a diff for adding a new file or deleting a file). - , blobLanguage :: Maybe Language -- ^ The language of this blob. Nothing denotes a langauge we don't support yet. - } deriving (Show, Eq) - -- | The contents of a source file, represented as a ByteString. newtype Source = Source { sourceText :: B.ByteString } deriving (Eq, IsString, Show) --- | The kind of a blob, along with it's file mode. -data SourceKind = PlainBlob Word32 | ExecutableBlob Word32 | SymlinkBlob Word32 - deriving (Show, Eq) - -modeToDigits :: SourceKind -> ByteString -modeToDigits (PlainBlob mode) = toS $ showOct mode "" -modeToDigits (ExecutableBlob mode) = toS $ showOct mode "" -modeToDigits (SymlinkBlob mode) = toS $ showOct mode "" - --- | The default plain blob mode -defaultPlainBlob :: SourceKind -defaultPlainBlob = PlainBlob 0o100644 - -emptySourceBlob :: FilePath -> SourceBlob -emptySourceBlob filepath = SourceBlob Data.Source.empty Data.Source.nullOid filepath Nothing Nothing - -nullBlob :: SourceBlob -> Bool -nullBlob SourceBlob{..} = oid == nullOid || Data.Source.null source - -blobExists :: SourceBlob -> Bool -blobExists SourceBlob{..} = isJust blobKind - -sourceBlob :: FilePath -> Maybe Language -> Source -> SourceBlob -sourceBlob filepath language source = SourceBlob source Data.Source.nullOid filepath (Just defaultPlainBlob) language - --- | Map blobs with Nothing blobKind to empty blobs. -idOrEmptySourceBlob :: SourceBlob -> SourceBlob -idOrEmptySourceBlob blob = if isNothing (blobKind blob) - then blob { oid = nullOid, blobKind = Nothing } - else blob - -nullOid :: ByteString -nullOid = "0000000000000000000000000000000000000000" empty :: Source empty = Source B.empty diff --git a/src/Renderer/JSON.hs b/src/Renderer/JSON.hs index 16f2062bd..b8ffdd830 100644 --- a/src/Renderer/JSON.hs +++ b/src/Renderer/JSON.hs @@ -9,10 +9,10 @@ module Renderer.JSON import Data.Aeson (ToJSON, toJSON, encode, object, (.=)) import Data.Aeson as A hiding (json) import Data.Bifunctor.Join +import Data.Blob import Data.Functor.Both (Both) import qualified Data.Map as Map import Data.Record -import Data.Source import Data.Union import Info import Language diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index 8fae4c0e7..cfd83ad7b 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -9,6 +9,7 @@ module Renderer.Patch import Alignment import Data.Bifunctor.Join +import Data.Blob import qualified Data.ByteString.Char8 as ByteString import Data.Functor.Both as Both import Data.List (span, unzip) diff --git a/src/Renderer/TOC.hs b/src/Renderer/TOC.hs index 9d5181e6d..3cc348cf1 100644 --- a/src/Renderer/TOC.hs +++ b/src/Renderer/TOC.hs @@ -19,6 +19,7 @@ module Renderer.TOC import Data.Aeson import Data.Align (crosswalk) +import Data.Blob import Data.Functor.Both hiding (fst, snd) import qualified Data.Functor.Both as Both import Data.Functor.Listable diff --git a/src/Semantic.hs b/src/Semantic.hs index 0a0b30fe7..9f1f76ac2 100644 --- a/src/Semantic.hs +++ b/src/Semantic.hs @@ -9,6 +9,7 @@ module Semantic import Algorithm hiding (diff) import Data.Align.Generic (GAlign) +import Data.Blob import Data.Functor.Both as Both import Data.Functor.Classes (Eq1, Show1) import Data.Proxy diff --git a/test/CommandSpec.hs b/test/CommandSpec.hs index 3d767120a..b453dbccd 100644 --- a/test/CommandSpec.hs +++ b/test/CommandSpec.hs @@ -1,6 +1,7 @@ module CommandSpec where import Command +import Data.Blob import Data.Functor.Both as Both import Data.Maybe import Data.Source diff --git a/test/PatchOutputSpec.hs b/test/PatchOutputSpec.hs index 1ead512ae..4f1bbba9d 100644 --- a/test/PatchOutputSpec.hs +++ b/test/PatchOutputSpec.hs @@ -1,10 +1,10 @@ module PatchOutputSpec where import Prologue +import Data.Blob import Data.Functor.Both import Data.Range import Data.Record -import Data.Source as Source import Renderer.Patch import Syntax import Test.Hspec (Spec, describe, it, parallel) @@ -14,4 +14,4 @@ spec :: Spec spec = parallel $ do describe "hunks" $ do it "empty diffs have empty hunks" $ - hunks (wrap $ pure (Range 0 0 :. Nil) :< Leaf ("" :: Text)) (both (SourceBlob Source.empty "abcde" "path2.txt" (Just defaultPlainBlob) Nothing) (SourceBlob Source.empty "xyz" "path2.txt" (Just defaultPlainBlob) Nothing)) `shouldBe` [Hunk {offset = pure 0, changes = [], trailingContext = []}] + hunks (wrap $ pure (Range 0 0 :. Nil) :< Leaf ("" :: Text)) (both (SourceBlob mempty "abcde" "path2.txt" (Just defaultPlainBlob) Nothing) (SourceBlob mempty "xyz" "path2.txt" (Just defaultPlainBlob) Nothing)) `shouldBe` [Hunk {offset = pure 0, changes = [], trailingContext = []}] diff --git a/test/SemanticSpec.hs b/test/SemanticSpec.hs index 24fec0f38..881e177e0 100644 --- a/test/SemanticSpec.hs +++ b/test/SemanticSpec.hs @@ -1,7 +1,7 @@ module SemanticSpec where +import Data.Blob import Data.Functor.Both as Both -import Data.Source import Language import Patch import Prologue @@ -37,4 +37,4 @@ spec = parallel $ do (() <$) <$> result `shouldBe` pure (Delete ()) where - methodsBlob = SourceBlob (Source "def foo\nend\n") "ff7bbbe9495f61d9e1e58c597502d152bab1761e" "methods.rb" (Just defaultPlainBlob) (Just Ruby) + methodsBlob = SourceBlob "def foo\nend\n" "ff7bbbe9495f61d9e1e58c597502d152bab1761e" "methods.rb" (Just defaultPlainBlob) (Just Ruby) diff --git a/test/SpecHelpers.hs b/test/SpecHelpers.hs index 273dc98d4..f22812e22 100644 --- a/test/SpecHelpers.hs +++ b/test/SpecHelpers.hs @@ -7,6 +7,7 @@ module SpecHelpers , unListableDiff ) where +import Data.Blob import qualified Data.ByteString as B import Data.Functor.Both import Data.Functor.Listable diff --git a/test/TOCSpec.hs b/test/TOCSpec.hs index 353f0db92..680a73bdd 100644 --- a/test/TOCSpec.hs +++ b/test/TOCSpec.hs @@ -4,6 +4,7 @@ module TOCSpec where import Data.Aeson import Category as C +import Data.Blob import Data.Functor.Both import Data.Functor.Listable import Data.Record From bed2c473b2f70606a163da145d3defd02410fcb4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:15:31 -0400 Subject: [PATCH 032/146] Rename SourceBlob to Blob. --- src/Command/Files.hs | 33 +++++++++++++++++---------------- src/Data/Blob.hs | 34 +++++++++++++++++----------------- src/Renderer/JSON.hs | 6 +++--- src/Renderer/Patch.hs | 12 ++++++------ src/Renderer/TOC.hs | 4 ++-- src/Semantic.hs | 18 +++++++++--------- test/CommandSpec.hs | 12 ++++++------ test/PatchOutputSpec.hs | 2 +- test/SemanticSpec.hs | 6 +++--- test/SpecHelpers.hs | 6 +++--- test/TOCSpec.hs | 6 +++--- 11 files changed, 70 insertions(+), 69 deletions(-) diff --git a/src/Command/Files.hs b/src/Command/Files.hs index 4a58f8d01..fae0a0b49 100644 --- a/src/Command/Files.hs +++ b/src/Command/Files.hs @@ -10,7 +10,7 @@ import Control.Exception (catch, IOException) import Data.Aeson import Data.These import Data.Functor.Both -import Data.Blob hiding (path) +import qualified Data.Blob as Blob hiding (path) import Data.Source import Data.String import Language @@ -21,28 +21,28 @@ import Prelude (fail) import System.FilePath --- | Read a file to a SourceBlob, transcoding to UTF-8 along the way. -readFile :: FilePath -> Maybe Language -> IO SourceBlob +-- | Read a file to a Blob, transcoding to UTF-8 along the way. +readFile :: FilePath -> Maybe Language -> IO Blob.Blob readFile path language = do raw <- (Just <$> B.readFile path) `catch` (const (pure Nothing) :: IOException -> IO (Maybe ByteString)) - pure $ fromMaybe (emptySourceBlob path) (sourceBlob path language . Source <$> raw) + pure $ fromMaybe (Blob.emptyBlob path) (Blob.sourceBlob path language . Source <$> raw) -- | Return a language based on a FilePath's extension, or Nothing if extension is not found or not supported. languageForFilePath :: FilePath -> Maybe Language languageForFilePath = languageForType . toS . takeExtension -- | Read JSON encoded blob pairs from a handle. -readBlobPairsFromHandle :: Handle -> IO [Both SourceBlob] -readBlobPairsFromHandle = fmap toSourceBlobPairs . readFromHandle +readBlobPairsFromHandle :: Handle -> IO [Both Blob.Blob] +readBlobPairsFromHandle = fmap toBlobPairs . readFromHandle where - toSourceBlobPairs BlobDiff{..} = toSourceBlobPair <$> blobs - toSourceBlobPair blobs = Join (fromThese empty empty (runJoin (toSourceBlob <$> blobs))) - where empty = emptySourceBlob (mergeThese const (runJoin (path <$> blobs))) + toBlobPairs BlobDiff{..} = toBlobPair <$> blobs + toBlobPair blobs = Join (fromThese empty empty (runJoin (toBlob <$> blobs))) + where empty = Blob.emptyBlob (mergeThese const (runJoin (path <$> blobs))) -- | Read JSON encoded blobs from a handle. -readBlobsFromHandle :: Handle -> IO [SourceBlob] -readBlobsFromHandle = fmap toSourceBlobs . readFromHandle - where toSourceBlobs BlobParse{..} = fmap toSourceBlob blobs +readBlobsFromHandle :: Handle -> IO [Blob.Blob] +readBlobsFromHandle = fmap toBlobs . readFromHandle + where toBlobs BlobParse{..} = fmap toBlob blobs readFromHandle :: FromJSON a => Handle -> IO a readFromHandle h = do @@ -51,8 +51,8 @@ readFromHandle h = do Just d -> pure d Nothing -> die ("invalid input on " <> show h <> ", expecting JSON") -toSourceBlob :: Blob -> SourceBlob -toSourceBlob Blob{..} = sourceBlob path language' (Source (encodeUtf8 content)) +toBlob :: Blob -> Blob.Blob +toBlob Blob{..} = Blob.sourceBlob path language' (fromText content) where language' = case language of "" -> languageForFilePath path _ -> readMaybe language @@ -67,10 +67,11 @@ newtype BlobParse = BlobParse { blobs :: [Blob] } type BlobPair = Join These Blob data Blob = Blob - { path :: String + { path :: FilePath , content :: Text , language :: String - } deriving (Show, Generic, FromJSON) + } + deriving (Show, Generic, FromJSON) instance FromJSON BlobPair where parseJSON = withObject "BlobPair" $ \o -> do diff --git a/src/Data/Blob.hs b/src/Data/Blob.hs index 17dd812b2..5a0029719 100644 --- a/src/Data/Blob.hs +++ b/src/Data/Blob.hs @@ -5,44 +5,44 @@ import Language import Numeric import Prologue --- | The source, oid, path, and Maybe SourceKind of a blob. -data SourceBlob = SourceBlob +-- | The source, oid, path, and Maybe BlobKind of a blob. +data Blob = Blob { source :: Source -- ^ The UTF-8 encoded source text of the blob. , oid :: ByteString -- ^ The Git object ID (SHA-1) of the blob. , path :: FilePath -- ^ The file path to the blob. - , blobKind :: Maybe SourceKind -- ^ The kind of blob, Nothing denotes a blob that doesn't exist (e.g. on one side of a diff for adding a new file or deleting a file). + , blobKind :: Maybe BlobKind -- ^ The kind of blob, Nothing denotes a blob that doesn't exist (e.g. on one side of a diff for adding a new file or deleting a file). , blobLanguage :: Maybe Language -- ^ The language of this blob. Nothing denotes a langauge we don't support yet. } deriving (Show, Eq) --- | The kind of a blob, along with it's file mode. -data SourceKind = PlainBlob Word32 | ExecutableBlob Word32 | SymlinkBlob Word32 +-- | The kind and file mode of a 'Blob'. +data BlobKind = PlainBlob Word32 | ExecutableBlob Word32 | SymlinkBlob Word32 deriving (Show, Eq) -modeToDigits :: SourceKind -> ByteString +modeToDigits :: BlobKind -> ByteString modeToDigits (PlainBlob mode) = toS $ showOct mode "" modeToDigits (ExecutableBlob mode) = toS $ showOct mode "" modeToDigits (SymlinkBlob mode) = toS $ showOct mode "" -- | The default plain blob mode -defaultPlainBlob :: SourceKind +defaultPlainBlob :: BlobKind defaultPlainBlob = PlainBlob 0o100644 -emptySourceBlob :: FilePath -> SourceBlob -emptySourceBlob filepath = SourceBlob mempty nullOid filepath Nothing Nothing +emptyBlob :: FilePath -> Blob +emptyBlob filepath = Blob mempty nullOid filepath Nothing Nothing -nullBlob :: SourceBlob -> Bool -nullBlob SourceBlob{..} = oid == nullOid || Source.null source +nullBlob :: Blob -> Bool +nullBlob Blob{..} = oid == nullOid || Source.null source -blobExists :: SourceBlob -> Bool -blobExists SourceBlob{..} = isJust blobKind +blobExists :: Blob -> Bool +blobExists Blob{..} = isJust blobKind -sourceBlob :: FilePath -> Maybe Language -> Source -> SourceBlob -sourceBlob filepath language source = SourceBlob source nullOid filepath (Just defaultPlainBlob) language +sourceBlob :: FilePath -> Maybe Language -> Source -> Blob +sourceBlob filepath language source = Blob source nullOid filepath (Just defaultPlainBlob) language -- | Map blobs with Nothing blobKind to empty blobs. -idOrEmptySourceBlob :: SourceBlob -> SourceBlob -idOrEmptySourceBlob blob = if isNothing (blobKind blob) +idOrEmptyBlob :: Blob -> Blob +idOrEmptyBlob blob = if isNothing (blobKind blob) then blob { oid = nullOid, blobKind = Nothing } else blob diff --git a/src/Renderer/JSON.hs b/src/Renderer/JSON.hs index b8ffdd830..7a180c19e 100644 --- a/src/Renderer/JSON.hs +++ b/src/Renderer/JSON.hs @@ -25,7 +25,7 @@ import Syntax as S -- -- | Render a diff to a string representing its JSON. -renderJSONDiff :: ToJSON a => Both SourceBlob -> a -> Map.Map Text Value +renderJSONDiff :: ToJSON a => Both Blob -> a -> Map.Map Text Value renderJSONDiff blobs diff = Map.fromList [ ("diff", toJSON diff) , ("oids", toJSON (decodeUtf8 . oid <$> toList blobs)) @@ -120,5 +120,5 @@ instance ToJSON a => ToJSON (File a) where instance StringConv [Value] ByteString where strConv _ = toS . (<> "\n") . encode -renderJSONTerm :: ToJSON a => SourceBlob -> a -> [Value] -renderJSONTerm SourceBlob{..} = pure . toJSON . File path blobLanguage +renderJSONTerm :: ToJSON a => Blob -> a -> [Value] +renderJSONTerm Blob{..} = pure . toJSON . File path blobLanguage diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index cfd83ad7b..256eb0ca7 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -24,11 +24,11 @@ import Prologue hiding (fst, snd) import SplitDiff -- | Render a timed out file as a truncated diff. -truncatePatch :: Both SourceBlob -> ByteString +truncatePatch :: Both Blob -> ByteString truncatePatch blobs = header blobs <> "#timed_out\nTruncating diff: timeout reached.\n" -- | Render a diff in the traditional patch format. -renderPatch :: (HasField fields Range, Traversable f) => Both SourceBlob -> Diff f (Record fields) -> File +renderPatch :: (HasField fields Range, Traversable f) => Both Blob -> Diff f (Record fields) -> File renderPatch blobs diff = File $ if not (ByteString.null text) && ByteString.last text /= '\n' then text <> "\n\\ No newline at end of file\n" else text @@ -66,7 +66,7 @@ rowIncrement :: Join These a -> Both (Sum Int) rowIncrement = Join . fromThese (Sum 0) (Sum 0) . runJoin . (Sum 1 <$) -- | Given the before and after sources, render a hunk to a string. -showHunk :: Functor f => HasField fields Range => Both SourceBlob -> Hunk (SplitDiff f (Record fields)) -> ByteString +showHunk :: Functor f => HasField fields Range => Both Blob -> Hunk (SplitDiff f (Record fields)) -> ByteString showHunk blobs hunk = maybeOffsetHeader <> mconcat (showChange sources <$> changes hunk) <> showLines (snd sources) ' ' (maybeSnd . runJoin <$> trailingContext hunk) @@ -95,7 +95,7 @@ showLine source line | Just line <- line = Just . sourceText . (`slice` source) | otherwise = Nothing -- | Returns the header given two source blobs and a hunk. -header :: Both SourceBlob -> ByteString +header :: Both Blob -> ByteString header blobs = ByteString.intercalate "\n" ([filepathHeader, fileModeHeader] <> maybeFilepaths) <> "\n" where filepathHeader = "diff --git a/" <> pathA <> " b/" <> pathB fileModeHeader = case (modeA, modeB) of @@ -109,7 +109,7 @@ header blobs = ByteString.intercalate "\n" ([filepathHeader, fileModeHeader] <> ] (Nothing, Nothing) -> "" blobOidHeader = "index " <> oidA <> ".." <> oidB - modeHeader :: ByteString -> Maybe SourceKind -> ByteString -> ByteString + modeHeader :: ByteString -> Maybe BlobKind -> ByteString -> ByteString modeHeader ty maybeMode path = case maybeMode of Just _ -> ty <> "/" <> path Nothing -> "/dev/null" @@ -129,7 +129,7 @@ emptyHunk :: Hunk (SplitDiff a annotation) emptyHunk = Hunk { offset = mempty, changes = [], trailingContext = [] } -- | Render a diff as a series of hunks. -hunks :: (Traversable f, HasField fields Range) => Diff f (Record fields) -> Both SourceBlob -> [Hunk (SplitDiff [] (Record fields))] +hunks :: (Traversable f, HasField fields Range) => Diff f (Record fields) -> Both Blob -> [Hunk (SplitDiff [] (Record fields))] hunks _ blobs | sources <- source <$> blobs , sourcesEqual <- runBothWith (==) sources , sourcesNull <- runBothWith (&&) (Source.null <$> sources) diff --git a/src/Renderer/TOC.hs b/src/Renderer/TOC.hs index 3cc348cf1..90d4278d6 100644 --- a/src/Renderer/TOC.hs +++ b/src/Renderer/TOC.hs @@ -187,7 +187,7 @@ recordSummary record = case getDeclaration record of Just declaration -> Just . JSONSummary (toCategoryName declaration) (declarationIdentifier declaration) (sourceSpan record) Nothing -> const Nothing -renderToCDiff :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => Both SourceBlob -> Diff f (Record fields) -> Summaries +renderToCDiff :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => Both Blob -> Diff f (Record fields) -> Summaries renderToCDiff blobs = uncurry Summaries . bimap toMap toMap . List.partition isValidSummary . diffTOC where toMap [] = mempty toMap as = Map.singleton summaryKey (toJSON <$> as) @@ -197,7 +197,7 @@ renderToCDiff blobs = uncurry Summaries . bimap toMap toMap . List.partition isV | before == after -> after | otherwise -> before <> " -> " <> after -renderToCTerm :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => SourceBlob -> Term f (Record fields) -> Summaries +renderToCTerm :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => Blob -> Term f (Record fields) -> Summaries renderToCTerm blob = uncurry Summaries . bimap toMap toMap . List.partition isValidSummary . termToC where toMap [] = mempty toMap as = Map.singleton (toS (path blob)) (toJSON <$> as) diff --git a/src/Semantic.hs b/src/Semantic.hs index 9f1f76ac2..cbbb31c7c 100644 --- a/src/Semantic.hs +++ b/src/Semantic.hs @@ -40,12 +40,12 @@ import Text.Show -- - Built in concurrency where appropriate. -- - Easy to consume this interface from other application (e.g a cmdline or web server app). -parseBlobs :: (Monoid output, StringConv output ByteString) => TermRenderer output -> [SourceBlob] -> Task ByteString +parseBlobs :: (Monoid output, StringConv output ByteString) => TermRenderer output -> [Blob] -> Task ByteString parseBlobs renderer = fmap toS . distributeFoldMap (parseBlob renderer) . filter blobExists --- | A task to parse a 'SourceBlob' and render the resulting 'Term'. -parseBlob :: TermRenderer output -> SourceBlob -> Task output -parseBlob renderer blob@SourceBlob{..} = case (renderer, blobLanguage) of +-- | A task to parse a 'Blob' and render the resulting 'Term'. +parseBlob :: TermRenderer output -> Blob -> Task output +parseBlob renderer blob@Blob{..} = case (renderer, blobLanguage) of (ToCTermRenderer, Just Language.Markdown) -> parse markdownParser source >>= decorate (markupSectionAlgebra (Proxy :: Proxy Markdown.Error) source) >>= render (renderToCTerm blob) (ToCTermRenderer, Just Language.Python) -> parse pythonParser source >>= decorate (declarationAlgebra (Proxy :: Proxy Python.Error) source) . hoistCofree (weaken :: Union fs a -> Union (Declaration.Method ': fs) a) >>= render (renderToCTerm blob) (ToCTermRenderer, _) -> parse syntaxParser source >>= decorate (syntaxDeclarationAlgebra source) >>= render (renderToCTerm blob) @@ -62,11 +62,11 @@ parseBlob renderer blob@SourceBlob{..} = case (renderer, blobLanguage) of -diffBlobPairs :: (Monoid output, StringConv output ByteString) => DiffRenderer output -> [Both SourceBlob] -> Task ByteString +diffBlobPairs :: (Monoid output, StringConv output ByteString) => DiffRenderer output -> [Both Blob] -> Task ByteString diffBlobPairs renderer = fmap toS . distributeFoldMap (diffBlobPair renderer) . filter (any blobExists) --- | A task to parse a pair of 'SourceBlob's, diff them, and render the 'Diff'. -diffBlobPair :: DiffRenderer output -> Both SourceBlob -> Task output +-- | A task to parse a pair of 'Blob's, diff them, and render the 'Diff'. +diffBlobPair :: DiffRenderer output -> Both Blob -> Task output diffBlobPair renderer blobs = case (renderer, effectiveLanguage) of (ToCDiffRenderer, Just Language.Markdown) -> run (\ source -> parse markdownParser source >>= decorate (markupSectionAlgebra (Proxy :: Proxy Markdown.Error) source)) diffLinearly (renderToCDiff blobs) (ToCDiffRenderer, Just Language.Python) -> run (\ source -> parse pythonParser source >>= decorate (declarationAlgebra (Proxy :: Proxy Python.Error) source) . hoistCofree (weaken :: Union fs a -> Union (Declaration.Method ': fs) a)) diffLinearly (renderToCDiff blobs) @@ -90,8 +90,8 @@ diffBlobPair renderer blobs = case (renderer, effectiveLanguage) of diffLinearly :: (Eq1 f, GAlign f, Show1 f, Traversable f) => Both (Term f (Record fields)) -> Diff f (Record fields) diffLinearly = decoratingWith constructorLabel (diffTermsWith linearly comparableByConstructor) --- | A task to diff a pair of 'Term's, producing insertion/deletion 'Patch'es for non-existent 'SourceBlob's. -diffTermPair :: Functor f => Both SourceBlob -> Differ f a -> Both (Term f a) -> Task (Diff f a) +-- | A task to diff a pair of 'Term's, producing insertion/deletion 'Patch'es for non-existent 'Blob's. +diffTermPair :: Functor f => Both Blob -> Differ f a -> Both (Term f a) -> Task (Diff f a) diffTermPair blobs differ terms = case runJoin (blobExists <$> blobs) of (True, False) -> pure (deleting (Both.fst terms)) (False, True) -> pure (inserting (Both.snd terms)) diff --git a/test/CommandSpec.hs b/test/CommandSpec.hs index b453dbccd..7684ae284 100644 --- a/test/CommandSpec.hs +++ b/test/CommandSpec.hs @@ -31,26 +31,26 @@ spec = parallel $ do it "returns blobs when there's no before" $ do blobs <- blobsFromFilePath "test/fixtures/input/diff-no-before.json" - blobs `shouldBe` [both (emptySourceBlob "method.rb") b] + blobs `shouldBe` [both (emptyBlob "method.rb") b] it "returns blobs when there's null before" $ do blobs <- blobsFromFilePath "test/fixtures/input/diff-null-before.json" - blobs `shouldBe` [both (emptySourceBlob "method.rb") b] + blobs `shouldBe` [both (emptyBlob "method.rb") b] it "returns blobs when there's no after" $ do blobs <- blobsFromFilePath "test/fixtures/input/diff-no-after.json" - blobs `shouldBe` [both a (emptySourceBlob "method.rb")] + blobs `shouldBe` [both a (emptyBlob "method.rb")] it "returns blobs when there's null after" $ do blobs <- blobsFromFilePath "test/fixtures/input/diff-null-after.json" - blobs `shouldBe` [both a (emptySourceBlob "method.rb")] + blobs `shouldBe` [both a (emptyBlob "method.rb")] it "returns blobs for unsupported language" $ do h <- openFile "test/fixtures/input/diff-unsupported-language.json" ReadMode blobs <- readBlobPairsFromHandle h let b' = sourceBlob "test.kt" Nothing "fun main(args: Array) {\nprintln(\"hi\")\n}\n" - blobs `shouldBe` [both (emptySourceBlob "test.kt") b'] + blobs `shouldBe` [both (emptyBlob "test.kt") b'] it "detects language based on filepath for empty language" $ do blobs <- blobsFromFilePath "test/fixtures/input/diff-empty-language.json" @@ -80,4 +80,4 @@ spec = parallel $ do blobs <- readBlobPairsFromHandle h pure blobs -data Fixture = Fixture { shas :: Both String, expectedBlobs :: [Both SourceBlob] } +data Fixture = Fixture { shas :: Both String, expectedBlobs :: [Both Blob] } diff --git a/test/PatchOutputSpec.hs b/test/PatchOutputSpec.hs index 4f1bbba9d..65df22689 100644 --- a/test/PatchOutputSpec.hs +++ b/test/PatchOutputSpec.hs @@ -14,4 +14,4 @@ spec :: Spec spec = parallel $ do describe "hunks" $ do it "empty diffs have empty hunks" $ - hunks (wrap $ pure (Range 0 0 :. Nil) :< Leaf ("" :: Text)) (both (SourceBlob mempty "abcde" "path2.txt" (Just defaultPlainBlob) Nothing) (SourceBlob mempty "xyz" "path2.txt" (Just defaultPlainBlob) Nothing)) `shouldBe` [Hunk {offset = pure 0, changes = [], trailingContext = []}] + hunks (wrap $ pure (Range 0 0 :. Nil) :< Leaf ("" :: Text)) (both (Blob mempty "abcde" "path2.txt" (Just defaultPlainBlob) Nothing) (Blob mempty "xyz" "path2.txt" (Just defaultPlainBlob) Nothing)) `shouldBe` [Hunk {offset = pure 0, changes = [], trailingContext = []}] diff --git a/test/SemanticSpec.hs b/test/SemanticSpec.hs index 881e177e0..02061650d 100644 --- a/test/SemanticSpec.hs +++ b/test/SemanticSpec.hs @@ -29,12 +29,12 @@ spec = parallel $ do describe "diffTermPair" $ do it "produces an Insert when the first blob is missing" $ do - result <- runTask (diffTermPair (both (emptySourceBlob "/foo") (sourceBlob "/foo" Nothing "")) (runBothWith replacing) (pure (cofree (() :< [])))) + result <- runTask (diffTermPair (both (emptyBlob "/foo") (sourceBlob "/foo" Nothing "")) (runBothWith replacing) (pure (cofree (() :< [])))) (() <$) <$> result `shouldBe` pure (Insert ()) it "produces a Delete when the second blob is missing" $ do - result <- runTask (diffTermPair (both (sourceBlob "/foo" Nothing "") (emptySourceBlob "/foo")) (runBothWith replacing) (pure (cofree (() :< [])))) + result <- runTask (diffTermPair (both (sourceBlob "/foo" Nothing "") (emptyBlob "/foo")) (runBothWith replacing) (pure (cofree (() :< [])))) (() <$) <$> result `shouldBe` pure (Delete ()) where - methodsBlob = SourceBlob "def foo\nend\n" "ff7bbbe9495f61d9e1e58c597502d152bab1761e" "methods.rb" (Just defaultPlainBlob) (Just Ruby) + methodsBlob = Blob "def foo\nend\n" "ff7bbbe9495f61d9e1e58c597502d152bab1761e" "methods.rb" (Just defaultPlainBlob) (Just Ruby) diff --git a/test/SpecHelpers.hs b/test/SpecHelpers.hs index f22812e22..a2105e0fa 100644 --- a/test/SpecHelpers.hs +++ b/test/SpecHelpers.hs @@ -34,15 +34,15 @@ parseFilePath path = do blob <- readFile path runTask (parseBlob SExpressionTermRenderer blob) --- | Read a file to a SourceBlob. +-- | Read a file to a Blob. -- -- NB: This is intentionally duplicated from Command.Files because eventually -- we want to be able to test a core Semantic library that has no knowledge of -- the filesystem or Git. The tests, however, will still leverage reading files. -readFile :: FilePath -> IO SourceBlob +readFile :: FilePath -> IO Blob readFile path = do source <- (Just . Source <$> B.readFile path) `catch` (const (pure Nothing) :: IOException -> IO (Maybe Source)) - pure $ fromMaybe (emptySourceBlob path) (sourceBlob path (languageForFilePath path) <$> source) + pure $ fromMaybe (emptyBlob path) (sourceBlob path (languageForFilePath path) <$> source) -- | Returns a Maybe Language based on the FilePath's extension. languageForFilePath :: FilePath -> Maybe Language diff --git a/test/TOCSpec.hs b/test/TOCSpec.hs index 680a73bdd..de55625dd 100644 --- a/test/TOCSpec.hs +++ b/test/TOCSpec.hs @@ -212,7 +212,7 @@ isMethodOrFunction a = case runCofree (unListableF a) of (a :< _) | getField a == C.SingletonMethod -> True _ -> False -blobsForPaths :: Both FilePath -> IO (Both SourceBlob) +blobsForPaths :: Both FilePath -> IO (Both Blob) blobsForPaths = traverse (readFile . ("test/fixtures/toc/" <>)) sourceSpanBetween :: (Int, Int) -> (Int, Int) -> Span @@ -224,8 +224,8 @@ blankDiff = wrap (pure arrayInfo :< Indexed [ inserting (cofree $ literalInfo :< arrayInfo = Nothing :. Range 0 3 :. ArrayLiteral :. sourceSpanBetween (1, 1) (1, 5) :. Nil literalInfo = Nothing :. Range 1 2 :. StringLiteral :. sourceSpanBetween (1, 2) (1, 4) :. Nil -blankDiffBlobs :: Both SourceBlob -blankDiffBlobs = both (SourceBlob (fromText "[]") nullOid "a.js" (Just defaultPlainBlob) (Just TypeScript)) (SourceBlob (fromText "[a]") nullOid "b.js" (Just defaultPlainBlob) (Just TypeScript)) +blankDiffBlobs :: Both Blob +blankDiffBlobs = both (Blob (fromText "[]") nullOid "a.js" (Just defaultPlainBlob) (Just TypeScript)) (Blob (fromText "[a]") nullOid "b.js" (Just defaultPlainBlob) (Just TypeScript)) instance Listable Text where tiers = unListableText `mapT` tiers From 0d1967edb37492507e3de1cdd23cf654f03972ce Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:21:54 -0400 Subject: [PATCH 033/146] Rename the blob fields. --- src/Command/Files.hs | 2 +- src/Data/Blob.hs | 10 +++++----- src/Renderer/JSON.hs | 6 +++--- src/Renderer/Patch.hs | 12 ++++++------ src/Renderer/TOC.hs | 4 ++-- src/Semantic.hs | 30 +++++++++++++++--------------- test/CommandSpec.hs | 2 +- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/Command/Files.hs b/src/Command/Files.hs index fae0a0b49..74f2e5c7d 100644 --- a/src/Command/Files.hs +++ b/src/Command/Files.hs @@ -10,7 +10,7 @@ import Control.Exception (catch, IOException) import Data.Aeson import Data.These import Data.Functor.Both -import qualified Data.Blob as Blob hiding (path) +import qualified Data.Blob as Blob import Data.Source import Data.String import Language diff --git a/src/Data/Blob.hs b/src/Data/Blob.hs index 5a0029719..8327b20ab 100644 --- a/src/Data/Blob.hs +++ b/src/Data/Blob.hs @@ -7,9 +7,9 @@ import Prologue -- | The source, oid, path, and Maybe BlobKind of a blob. data Blob = Blob - { source :: Source -- ^ The UTF-8 encoded source text of the blob. - , oid :: ByteString -- ^ The Git object ID (SHA-1) of the blob. - , path :: FilePath -- ^ The file path to the blob. + { blobSource :: Source -- ^ The UTF-8 encoded source text of the blob. + , blobOid :: ByteString -- ^ The Git object ID (SHA-1) of the blob. + , blobPath :: FilePath -- ^ The file path to the blob. , blobKind :: Maybe BlobKind -- ^ The kind of blob, Nothing denotes a blob that doesn't exist (e.g. on one side of a diff for adding a new file or deleting a file). , blobLanguage :: Maybe Language -- ^ The language of this blob. Nothing denotes a langauge we don't support yet. } @@ -32,7 +32,7 @@ emptyBlob :: FilePath -> Blob emptyBlob filepath = Blob mempty nullOid filepath Nothing Nothing nullBlob :: Blob -> Bool -nullBlob Blob{..} = oid == nullOid || Source.null source +nullBlob Blob{..} = blobOid == nullOid || Source.null blobSource blobExists :: Blob -> Bool blobExists Blob{..} = isJust blobKind @@ -43,7 +43,7 @@ sourceBlob filepath language source = Blob source nullOid filepath (Just default -- | Map blobs with Nothing blobKind to empty blobs. idOrEmptyBlob :: Blob -> Blob idOrEmptyBlob blob = if isNothing (blobKind blob) - then blob { oid = nullOid, blobKind = Nothing } + then blob { blobOid = nullOid, blobKind = Nothing } else blob nullOid :: ByteString diff --git a/src/Renderer/JSON.hs b/src/Renderer/JSON.hs index 7a180c19e..e25ff737e 100644 --- a/src/Renderer/JSON.hs +++ b/src/Renderer/JSON.hs @@ -28,8 +28,8 @@ import Syntax as S renderJSONDiff :: ToJSON a => Both Blob -> a -> Map.Map Text Value renderJSONDiff blobs diff = Map.fromList [ ("diff", toJSON diff) - , ("oids", toJSON (decodeUtf8 . oid <$> toList blobs)) - , ("paths", toJSON (path <$> toList blobs)) + , ("oids", toJSON (decodeUtf8 . blobOid <$> toList blobs)) + , ("paths", toJSON (blobPath <$> toList blobs)) ] instance StringConv (Map Text Value) ByteString where @@ -121,4 +121,4 @@ instance StringConv [Value] ByteString where strConv _ = toS . (<> "\n") . encode renderJSONTerm :: ToJSON a => Blob -> a -> [Value] -renderJSONTerm Blob{..} = pure . toJSON . File path blobLanguage +renderJSONTerm Blob{..} = pure . toJSON . File blobPath blobLanguage diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index 256eb0ca7..d14ec3893 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -70,7 +70,7 @@ showHunk :: Functor f => HasField fields Range => Both Blob -> Hunk (SplitDiff f showHunk blobs hunk = maybeOffsetHeader <> mconcat (showChange sources <$> changes hunk) <> showLines (snd sources) ' ' (maybeSnd . runJoin <$> trailingContext hunk) - where sources = source <$> blobs + where sources = blobSource <$> blobs maybeOffsetHeader = if lengthA > 0 && lengthB > 0 then offsetHeader else mempty @@ -116,12 +116,12 @@ header blobs = ByteString.intercalate "\n" ([filepathHeader, fileModeHeader] <> maybeFilepaths = if (nullOid == oidA && Source.null (snd sources)) || (nullOid == oidB && Source.null (fst sources)) then [] else [ beforeFilepath, afterFilepath ] beforeFilepath = "--- " <> modeHeader "a" modeA pathA afterFilepath = "+++ " <> modeHeader "b" modeB pathB - sources = source <$> blobs - (pathA, pathB) = case runJoin $ toS . path <$> blobs of + sources = blobSource <$> blobs + (pathA, pathB) = case runJoin $ toS . blobPath <$> blobs of ("", path) -> (path, path) (path, "") -> (path, path) paths -> paths - (oidA, oidB) = runJoin $ oid <$> blobs + (oidA, oidB) = runJoin $ blobOid <$> blobs (modeA, modeB) = runJoin $ blobKind <$> blobs -- | A hunk representing no changes. @@ -130,12 +130,12 @@ emptyHunk = Hunk { offset = mempty, changes = [], trailingContext = [] } -- | Render a diff as a series of hunks. hunks :: (Traversable f, HasField fields Range) => Diff f (Record fields) -> Both Blob -> [Hunk (SplitDiff [] (Record fields))] -hunks _ blobs | sources <- source <$> blobs +hunks _ blobs | sources <- blobSource <$> blobs , sourcesEqual <- runBothWith (==) sources , sourcesNull <- runBothWith (&&) (Source.null <$> sources) , sourcesEqual || sourcesNull = [emptyHunk] -hunks diff blobs = hunksInRows (pure 1) $ alignDiff (source <$> blobs) diff +hunks diff blobs = hunksInRows (pure 1) $ alignDiff (blobSource <$> blobs) diff -- | Given beginning line numbers, turn rows in a split diff into hunks in a -- | patch. diff --git a/src/Renderer/TOC.hs b/src/Renderer/TOC.hs index 90d4278d6..eb1e39a88 100644 --- a/src/Renderer/TOC.hs +++ b/src/Renderer/TOC.hs @@ -191,7 +191,7 @@ renderToCDiff :: (HasField fields (Maybe Declaration), HasField fields Span, Tra renderToCDiff blobs = uncurry Summaries . bimap toMap toMap . List.partition isValidSummary . diffTOC where toMap [] = mempty toMap as = Map.singleton summaryKey (toJSON <$> as) - summaryKey = toS $ case runJoin (path <$> blobs) of + summaryKey = toS $ case runJoin (blobPath <$> blobs) of (before, after) | null before -> after | null after -> before | before == after -> after @@ -200,7 +200,7 @@ renderToCDiff blobs = uncurry Summaries . bimap toMap toMap . List.partition isV renderToCTerm :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => Blob -> Term f (Record fields) -> Summaries renderToCTerm blob = uncurry Summaries . bimap toMap toMap . List.partition isValidSummary . termToC where toMap [] = mempty - toMap as = Map.singleton (toS (path blob)) (toJSON <$> as) + toMap as = Map.singleton (toS (blobPath blob)) (toJSON <$> as) diffTOC :: (HasField fields (Maybe Declaration), HasField fields Span, Traversable f) => Diff f (Record fields) -> [JSONSummary] diffTOC = mapMaybe entrySummary . dedupe . tableOfContentsBy declaration diff --git a/src/Semantic.hs b/src/Semantic.hs index cbbb31c7c..0ebbfbe95 100644 --- a/src/Semantic.hs +++ b/src/Semantic.hs @@ -46,18 +46,18 @@ parseBlobs renderer = fmap toS . distributeFoldMap (parseBlob renderer) . filter -- | A task to parse a 'Blob' and render the resulting 'Term'. parseBlob :: TermRenderer output -> Blob -> Task output parseBlob renderer blob@Blob{..} = case (renderer, blobLanguage) of - (ToCTermRenderer, Just Language.Markdown) -> parse markdownParser source >>= decorate (markupSectionAlgebra (Proxy :: Proxy Markdown.Error) source) >>= render (renderToCTerm blob) - (ToCTermRenderer, Just Language.Python) -> parse pythonParser source >>= decorate (declarationAlgebra (Proxy :: Proxy Python.Error) source) . hoistCofree (weaken :: Union fs a -> Union (Declaration.Method ': fs) a) >>= render (renderToCTerm blob) - (ToCTermRenderer, _) -> parse syntaxParser source >>= decorate (syntaxDeclarationAlgebra source) >>= render (renderToCTerm blob) - (JSONTermRenderer, Just Language.Markdown) -> parse markdownParser source >>= render (renderJSONTerm blob) - (JSONTermRenderer, Just Language.Python) -> parse pythonParser source >>= render (renderJSONTerm blob) - (JSONTermRenderer, _) -> parse syntaxParser source >>= decorate identifierAlgebra >>= render (renderJSONTerm blob) - (SExpressionTermRenderer, Just Language.Markdown) -> parse markdownParser source >>= decorate (ConstructorLabel . constructorLabel) >>= render renderSExpressionTerm . fmap keepConstructorLabel - (SExpressionTermRenderer, Just Language.Python) -> parse pythonParser source >>= decorate (ConstructorLabel . constructorLabel) >>= render renderSExpressionTerm . fmap keepConstructorLabel - (SExpressionTermRenderer, _) -> parse syntaxParser source >>= render renderSExpressionTerm . fmap keepCategory + (ToCTermRenderer, Just Language.Markdown) -> parse markdownParser blobSource >>= decorate (markupSectionAlgebra (Proxy :: Proxy Markdown.Error) blobSource) >>= render (renderToCTerm blob) + (ToCTermRenderer, Just Language.Python) -> parse pythonParser blobSource >>= decorate (declarationAlgebra (Proxy :: Proxy Python.Error) blobSource) . hoistCofree (weaken :: Union fs a -> Union (Declaration.Method ': fs) a) >>= render (renderToCTerm blob) + (ToCTermRenderer, _) -> parse syntaxParser blobSource >>= decorate (syntaxDeclarationAlgebra blobSource) >>= render (renderToCTerm blob) + (JSONTermRenderer, Just Language.Markdown) -> parse markdownParser blobSource >>= render (renderJSONTerm blob) + (JSONTermRenderer, Just Language.Python) -> parse pythonParser blobSource >>= render (renderJSONTerm blob) + (JSONTermRenderer, _) -> parse syntaxParser blobSource >>= decorate identifierAlgebra >>= render (renderJSONTerm blob) + (SExpressionTermRenderer, Just Language.Markdown) -> parse markdownParser blobSource >>= decorate (ConstructorLabel . constructorLabel) >>= render renderSExpressionTerm . fmap keepConstructorLabel + (SExpressionTermRenderer, Just Language.Python) -> parse pythonParser blobSource >>= decorate (ConstructorLabel . constructorLabel) >>= render renderSExpressionTerm . fmap keepConstructorLabel + (SExpressionTermRenderer, _) -> parse syntaxParser blobSource >>= render renderSExpressionTerm . fmap keepCategory (IdentityTermRenderer, Just Language.Markdown) -> pure Nothing (IdentityTermRenderer, Just Language.Python) -> pure Nothing - (IdentityTermRenderer, _) -> Just <$> parse syntaxParser source + (IdentityTermRenderer, _) -> Just <$> parse syntaxParser blobSource where syntaxParser = parserForLanguage blobLanguage @@ -68,9 +68,9 @@ diffBlobPairs renderer = fmap toS . distributeFoldMap (diffBlobPair renderer) . -- | A task to parse a pair of 'Blob's, diff them, and render the 'Diff'. diffBlobPair :: DiffRenderer output -> Both Blob -> Task output diffBlobPair renderer blobs = case (renderer, effectiveLanguage) of - (ToCDiffRenderer, Just Language.Markdown) -> run (\ source -> parse markdownParser source >>= decorate (markupSectionAlgebra (Proxy :: Proxy Markdown.Error) source)) diffLinearly (renderToCDiff blobs) - (ToCDiffRenderer, Just Language.Python) -> run (\ source -> parse pythonParser source >>= decorate (declarationAlgebra (Proxy :: Proxy Python.Error) source) . hoistCofree (weaken :: Union fs a -> Union (Declaration.Method ': fs) a)) diffLinearly (renderToCDiff blobs) - (ToCDiffRenderer, _) -> run (\ source -> parse syntaxParser source >>= decorate (syntaxDeclarationAlgebra source)) diffTerms (renderToCDiff blobs) + (ToCDiffRenderer, Just Language.Markdown) -> run (\ blobSource -> parse markdownParser blobSource >>= decorate (markupSectionAlgebra (Proxy :: Proxy Markdown.Error) blobSource)) diffLinearly (renderToCDiff blobs) + (ToCDiffRenderer, Just Language.Python) -> run (\ blobSource -> parse pythonParser blobSource >>= decorate (declarationAlgebra (Proxy :: Proxy Python.Error) blobSource) . hoistCofree (weaken :: Union fs a -> Union (Declaration.Method ': fs) a)) diffLinearly (renderToCDiff blobs) + (ToCDiffRenderer, _) -> run (\ blobSource -> parse syntaxParser blobSource >>= decorate (syntaxDeclarationAlgebra blobSource)) diffTerms (renderToCDiff blobs) (JSONDiffRenderer, Just Language.Markdown) -> run (parse markdownParser) diffLinearly (renderJSONDiff blobs) (JSONDiffRenderer, Just Language.Python) -> run (parse pythonParser) diffLinearly (renderJSONDiff blobs) (JSONDiffRenderer, _) -> run (decorate identifierAlgebra <=< parse syntaxParser) diffTerms (renderJSONDiff blobs) @@ -80,12 +80,12 @@ diffBlobPair renderer blobs = case (renderer, effectiveLanguage) of (SExpressionDiffRenderer, Just Language.Markdown) -> run (decorate (ConstructorLabel . constructorLabel) <=< parse markdownParser) diffLinearly (renderSExpressionDiff . mapAnnotations keepConstructorLabel) (SExpressionDiffRenderer, Just Language.Python) -> run (decorate (ConstructorLabel . constructorLabel) <=< parse pythonParser) diffLinearly (renderSExpressionDiff . mapAnnotations keepConstructorLabel) (SExpressionDiffRenderer, _) -> run (parse syntaxParser) diffTerms (renderSExpressionDiff . mapAnnotations keepCategory) - (IdentityDiffRenderer, _) -> run (\ source -> parse syntaxParser source >>= decorate (syntaxDeclarationAlgebra source)) diffTerms Just + (IdentityDiffRenderer, _) -> run (\ blobSource -> parse syntaxParser blobSource >>= decorate (syntaxDeclarationAlgebra blobSource)) diffTerms Just where effectiveLanguage = runBothWith (<|>) (blobLanguage <$> blobs) syntaxParser = parserForLanguage effectiveLanguage run :: Functor f => (Source -> Task (Term f a)) -> (Both (Term f a) -> Diff f a) -> (Diff f a -> output) -> Task output - run parse diff renderer = distributeFor blobs (parse . source) >>= diffTermPair blobs diff >>= render renderer + run parse diff renderer = distributeFor blobs (parse . blobSource) >>= diffTermPair blobs diff >>= render renderer diffLinearly :: (Eq1 f, GAlign f, Show1 f, Traversable f) => Both (Term f (Record fields)) -> Diff f (Record fields) diffLinearly = decoratingWith constructorLabel (diffTermsWith linearly comparableByConstructor) diff --git a/test/CommandSpec.hs b/test/CommandSpec.hs index 7684ae284..32cefffed 100644 --- a/test/CommandSpec.hs +++ b/test/CommandSpec.hs @@ -16,7 +16,7 @@ spec = parallel $ do describe "readFile" $ do it "returns a blob for extant files" $ do blob <- readFile "semantic-diff.cabal" Nothing - path blob `shouldBe` "semantic-diff.cabal" + blobPath blob `shouldBe` "semantic-diff.cabal" it "returns a nullBlob for absent files" $ do blob <- readFile "this file should not exist" Nothing From 8e3d3cb1e1fb165e8bfdee6a9c8a98f2693d9bd6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:23:48 -0400 Subject: [PATCH 034/146] :fire: a redundant space. --- src/Data/Blob.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Blob.hs b/src/Data/Blob.hs index 8327b20ab..84e28c2dd 100644 --- a/src/Data/Blob.hs +++ b/src/Data/Blob.hs @@ -16,7 +16,7 @@ data Blob = Blob deriving (Show, Eq) -- | The kind and file mode of a 'Blob'. -data BlobKind = PlainBlob Word32 | ExecutableBlob Word32 | SymlinkBlob Word32 +data BlobKind = PlainBlob Word32 | ExecutableBlob Word32 | SymlinkBlob Word32 deriving (Show, Eq) modeToDigits :: BlobKind -> ByteString From 0979106e5071bc6886f921f5d8ca8c22ee5c4127 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:24:35 -0400 Subject: [PATCH 035/146] :fire: Data.Source.empty. --- src/Data/Source.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 9be54610f..4a78a025c 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -16,9 +16,6 @@ newtype Source = Source { sourceText :: B.ByteString } deriving (Eq, IsString, Show) -empty :: Source -empty = Source B.empty - -- | Return a 'Source' from a 'ByteString'. fromText :: T.Text -> Source fromText = Source . encodeUtf8 @@ -107,7 +104,7 @@ instance Semigroup Source where Source a <> Source b = Source (a <> b) instance Monoid Source where - mempty = Data.Source.empty + mempty = Source B.empty mappend = (<>) instance Listable Source where From 2cc9f28e37e3e1cfcdd16a7ea4464a88158002a5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:28:39 -0400 Subject: [PATCH 036/146] Rename Source.null to nullSource. --- src/Data/Blob.hs | 2 +- src/Data/Source.hs | 4 ++-- src/Language/Ruby.hs | 2 +- src/Renderer/Patch.hs | 7 +++---- src/Renderer/TOC.hs | 2 +- 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Data/Blob.hs b/src/Data/Blob.hs index 84e28c2dd..a9dc747b4 100644 --- a/src/Data/Blob.hs +++ b/src/Data/Blob.hs @@ -32,7 +32,7 @@ emptyBlob :: FilePath -> Blob emptyBlob filepath = Blob mempty nullOid filepath Nothing Nothing nullBlob :: Blob -> Bool -nullBlob Blob{..} = blobOid == nullOid || Source.null blobSource +nullBlob Blob{..} = blobOid == nullOid || nullSource blobSource blobExists :: Blob -> Bool blobExists Blob{..} = isJust blobKind diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 4a78a025c..07af7ca99 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -97,8 +97,8 @@ totalSpan source = Span (Pos 1 1) (Pos (Prologue.length ranges) (succ (end lastR length :: Source -> Int length = B.length . sourceText -null :: Source -> Bool -null = B.null . sourceText +nullSource :: Source -> Bool +nullSource = B.null . sourceText instance Semigroup Source where Source a <> Source b = Source (a <> b) diff --git a/src/Language/Ruby.hs b/src/Language/Ruby.hs index 89921697f..739484749 100644 --- a/src/Language/Ruby.hs +++ b/src/Language/Ruby.hs @@ -2,7 +2,7 @@ module Language.Ruby where import Data.List (partition) -import Data.Source hiding (null) +import Data.Source import Info import Prologue import Language diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index d14ec3893..9cf5ecece 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -15,8 +15,7 @@ import Data.Functor.Both as Both import Data.List (span, unzip) import Data.Range import Data.Record -import Data.Source as Source hiding (break, drop, length, null, take) -import qualified Data.Source as Source +import Data.Source as Source hiding (break, drop, length, take) import Data.These import Diff import Patch @@ -113,7 +112,7 @@ header blobs = ByteString.intercalate "\n" ([filepathHeader, fileModeHeader] <> modeHeader ty maybeMode path = case maybeMode of Just _ -> ty <> "/" <> path Nothing -> "/dev/null" - maybeFilepaths = if (nullOid == oidA && Source.null (snd sources)) || (nullOid == oidB && Source.null (fst sources)) then [] else [ beforeFilepath, afterFilepath ] + maybeFilepaths = if (nullOid == oidA && nullSource (snd sources)) || (nullOid == oidB && nullSource (fst sources)) then [] else [ beforeFilepath, afterFilepath ] beforeFilepath = "--- " <> modeHeader "a" modeA pathA afterFilepath = "+++ " <> modeHeader "b" modeB pathB sources = blobSource <$> blobs @@ -132,7 +131,7 @@ emptyHunk = Hunk { offset = mempty, changes = [], trailingContext = [] } hunks :: (Traversable f, HasField fields Range) => Diff f (Record fields) -> Both Blob -> [Hunk (SplitDiff [] (Record fields))] hunks _ blobs | sources <- blobSource <$> blobs , sourcesEqual <- runBothWith (==) sources - , sourcesNull <- runBothWith (&&) (Source.null <$> sources) + , sourcesNull <- runBothWith (&&) (nullSource <$> sources) , sourcesEqual || sourcesNull = [emptyHunk] hunks diff blobs = hunksInRows (pure 1) $ alignDiff (blobSource <$> blobs) diff diff --git a/src/Renderer/TOC.hs b/src/Renderer/TOC.hs index eb1e39a88..b036f78c5 100644 --- a/src/Renderer/TOC.hs +++ b/src/Renderer/TOC.hs @@ -26,7 +26,7 @@ import Data.Functor.Listable import Data.List.NonEmpty (nonEmpty) import Data.Proxy import Data.Record -import Data.Source as Source hiding (null) +import Data.Source as Source import Data.Text (toLower) import Data.Text.Listable import Data.These From a106d27eb9a63476d4fefef740a21ed689c8e25c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:32:26 -0400 Subject: [PATCH 037/146] Rename Source.length to sourceLength. --- src/Data/Source.hs | 10 +++++----- src/Parser.hs | 6 +++--- src/Renderer/Patch.hs | 2 +- test/SourceSpec.hs | 2 +- test/TOCSpec.hs | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 07af7ca99..6a8308292 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -77,8 +77,8 @@ spanToRangeInLineRanges lineRanges Span{..} = Range start end rangeToSpan :: Source -> Range -> Span rangeToSpan source (Range rangeStart rangeEnd) = Span startPos endPos where startPos = Pos (firstLine + 1) (rangeStart - start firstRange + 1) - endPos = Pos (firstLine + Prologue.length lineRanges) (rangeEnd - start lastRange + 1) - firstLine = Prologue.length before + endPos = Pos (firstLine + length lineRanges) (rangeEnd - start lastRange + 1) + firstLine = length before (before, rest) = span ((< rangeStart) . end) (actualLineRanges source) (lineRanges, _) = span ((<= rangeEnd) . start) rest Just firstRange = getFirst (foldMap (First . Just) lineRanges) @@ -90,12 +90,12 @@ totalRange = Range 0 . B.length . sourceText -- | Return a 'Span' that covers the entire text. totalSpan :: Source -> Span -totalSpan source = Span (Pos 1 1) (Pos (Prologue.length ranges) (succ (end lastRange - start lastRange))) +totalSpan source = Span (Pos 1 1) (Pos (length ranges) (succ (end lastRange - start lastRange))) where ranges = actualLineRanges source Just lastRange = getLast (foldMap (Last . Just) ranges) -length :: Source -> Int -length = B.length . sourceText +sourceLength :: Source -> Int +sourceLength = B.length . sourceText nullSource :: Source -> Bool nullSource = B.null . sourceText diff --git a/src/Parser.hs b/src/Parser.hs index 5e815e376..ddc361def 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -88,7 +88,7 @@ runParser parser = case parser of let errors = termErrors term `asTypeOf` toList err traverse_ (printError source) errors unless (Prologue.null errors) $ do - withSGRCode [SetConsoleIntensity BoldIntensity, SetColor Foreground Vivid Red] . hPutStrLn stderr . (shows (Prologue.length errors) . showChar ' ' . showString (if Prologue.length errors == 1 then "error" else "errors")) $ "" + withSGRCode [SetConsoleIntensity BoldIntensity, SetColor Foreground Vivid Red] . hPutStrLn stderr . (shows (length errors) . showChar ' ' . showString (if length errors == 1 then "error" else "errors")) $ "" pure term Nothing -> pure (errorTerm source err) TreeSitterParser language tslanguage -> treeSitterParser language tslanguage @@ -110,7 +110,7 @@ lineByLineParser source = pure . cofree . root $ case foldl' annotateLeaves ([], where lines = actualLines source root children = (sourceRange :. Program :. rangeToSpan source sourceRange :. Nil) :< Indexed children - sourceRange = Source.totalRange source + sourceRange = totalRange source leaf byteIndex line = (Range byteIndex (byteIndex + T.length line) :. Program :. rangeToSpan source (Range byteIndex (byteIndex + T.length line)) :. Nil) :< Leaf line annotateLeaves (accum, byteIndex) line = - (accum <> [ leaf byteIndex (Source.toText line) ] , byteIndex + Source.length line) + (accum <> [ leaf byteIndex (toText line) ] , byteIndex + sourceLength line) diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index 9cf5ecece..3de21171d 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -15,7 +15,7 @@ import Data.Functor.Both as Both import Data.List (span, unzip) import Data.Range import Data.Record -import Data.Source as Source hiding (break, drop, length, take) +import Data.Source as Source hiding (break, drop, take) import Data.These import Diff import Patch diff --git a/test/SourceSpec.hs b/test/SourceSpec.hs index 8aea3b9e7..6e06ff0e9 100644 --- a/test/SourceSpec.hs +++ b/test/SourceSpec.hs @@ -13,7 +13,7 @@ spec :: Spec spec = parallel $ do describe "actualLineRanges" $ do prop "produces 1 more range than there are newlines" $ - \ source -> Prologue.length (actualLineRanges source) `shouldBe` succ (Text.count "\n" (toText source)) + \ source -> length (actualLineRanges source) `shouldBe` succ (Text.count "\n" (toText source)) prop "produces exhaustive ranges" $ \ source -> foldMap (`slice` source) (actualLineRanges source) `shouldBe` source diff --git a/test/TOCSpec.hs b/test/TOCSpec.hs index de55625dd..ea564e67f 100644 --- a/test/TOCSpec.hs +++ b/test/TOCSpec.hs @@ -51,7 +51,7 @@ spec = parallel $ do \ diff -> let diff' = fmap (1 <$) <$> mapAnnotations (const (0 :: Int)) (wrap (pure 0 :< Indexed [unListableDiff diff :: Diff (Syntax ()) Int])) in tableOfContentsBy (\ (n :< _) -> if n == 0 then Just n else Nothing) diff' `shouldBe` if Prologue.null diff' then [Unchanged 0] - else replicate (Prologue.length diff') (Changed 0) + else replicate (length diff') (Changed 0) describe "diffTOC" $ do it "blank if there are no methods" $ @@ -153,7 +153,7 @@ type Diff' = SyntaxDiff Text (Maybe Declaration ': DefaultFields) type Term' = SyntaxTerm Text (Maybe Declaration ': DefaultFields) numTocSummaries :: Diff' -> Int -numTocSummaries diff = Prologue.length $ filter isValidSummary (diffTOC diff) +numTocSummaries diff = length $ filter isValidSummary (diffTOC diff) -- Return a diff where body is inserted in the expressions of a function. The function is present in both sides of the diff. programWithChange :: Term' -> Diff' From d7205325370be5cafcf5fc118821bbb86174515d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:37:01 -0400 Subject: [PATCH 038/146] :fire: idOrEmptyBlob. --- src/Data/Blob.hs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Data/Blob.hs b/src/Data/Blob.hs index a9dc747b4..ff6a5906d 100644 --- a/src/Data/Blob.hs +++ b/src/Data/Blob.hs @@ -40,11 +40,5 @@ blobExists Blob{..} = isJust blobKind sourceBlob :: FilePath -> Maybe Language -> Source -> Blob sourceBlob filepath language source = Blob source nullOid filepath (Just defaultPlainBlob) language --- | Map blobs with Nothing blobKind to empty blobs. -idOrEmptyBlob :: Blob -> Blob -idOrEmptyBlob blob = if isNothing (blobKind blob) - then blob { blobOid = nullOid, blobKind = Nothing } - else blob - nullOid :: ByteString nullOid = "0000000000000000000000000000000000000000" From 7575c0b55987e58519c681a26cf8e040d583cc1a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:37:17 -0400 Subject: [PATCH 039/146] Explicitly list the exports for Data.Blob. --- src/Data/Blob.hs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Data/Blob.hs b/src/Data/Blob.hs index ff6a5906d..e0c0cae94 100644 --- a/src/Data/Blob.hs +++ b/src/Data/Blob.hs @@ -1,4 +1,14 @@ -module Data.Blob where +module Data.Blob +( Blob(..) +, BlobKind(..) +, modeToDigits +, defaultPlainBlob +, emptyBlob +, nullBlob +, blobExists +, sourceBlob +, nullOid +) where import Data.Source as Source import Language From 0d67e6acc97a34ddd8272c82a0432fcb9c27300b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:37:39 -0400 Subject: [PATCH 040/146] :fire: a redundant GHC flag. --- src/Data/Source.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 6a8308292..4ec30c708 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -1,5 +1,4 @@ {-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses #-} -{-# OPTIONS_GHC -funbox-strict-fields #-} module Data.Source where import qualified Data.ByteString as B From 08c2c87fe05d35a69f68a254fc48fb703335582d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:38:11 -0400 Subject: [PATCH 041/146] =?UTF-8?q?Explicitly=20strictify=20Range=E2=80=99?= =?UTF-8?q?s=20fields.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Data/Range.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Range.hs b/src/Data/Range.hs index 2c0ef80a0..02fe4eaa8 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -10,7 +10,7 @@ import Prologue import Test.LeanCheck -- | A half-open interval of integers, defined by start & end indices. -data Range = Range { start :: Int, end :: Int } +data Range = Range { start :: !Int, end :: !Int } deriving (Eq, Show, Generic, NFData) -- | Return the length of the range. From 2c113280bc19d4dd8c6c729a329f71afd3b7319a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:38:31 -0400 Subject: [PATCH 042/146] =?UTF-8?q?Explicitly=20unpack=20Range=E2=80=99s?= =?UTF-8?q?=20fields.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Data/Range.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Range.hs b/src/Data/Range.hs index 02fe4eaa8..11ed2d32d 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -10,7 +10,7 @@ import Prologue import Test.LeanCheck -- | A half-open interval of integers, defined by start & end indices. -data Range = Range { start :: !Int, end :: !Int } +data Range = Range { start :: {-# UNPACK #-} !Int, end :: {-# UNPACK #-} !Int } deriving (Eq, Show, Generic, NFData) -- | Return the length of the range. From 7da94d77f61dd1f070f49e14e439fcb5c671f34f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:39:55 -0400 Subject: [PATCH 043/146] Fix up a couple of comments. --- src/Data/Range.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Data/Range.hs b/src/Data/Range.hs index 11ed2d32d..5be4a01bc 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -28,9 +28,9 @@ divideRange :: Range -> Int -> (Range, Range) divideRange Range{..} at = (Range start divider, Range divider end) where divider = max (min end at) start --- | Break a string down into words and sequences of punctuation. Return a list --- | strings with ranges, assuming that the first character in the string is --- | at the given index. +-- | Break a string down into words and sequences of punctuation. +-- +-- Returns a list strings with ranges, assuming that the first character in the string is at the given index. rangesAndWordsFrom :: Int -> String -> [(Range, String)] rangesAndWordsFrom _ "" = [] rangesAndWordsFrom startIndex string = fromMaybe [] $ take isWord <|> take isPunctuation <|> skip Char.isSpace @@ -42,9 +42,9 @@ rangesAndWordsFrom startIndex string = fromMaybe [] $ take isWord <|> take isPun parse transform predicate = case span predicate string of ([], _) -> Nothing (parsed, rest) -> Just . maybe identity (:) (transform parsed) $ rangesAndWordsFrom (endFor parsed) rest - -- | Is this a word character? - -- | Word characters are defined as in [Ruby’s `\p{Word}` syntax](http://ruby-doc.org/core-2.1.1/Regexp.html#class-Regexp-label-Character+Properties), i.e:. - -- | > A member of one of the following Unicode general category _Letter_, _Mark_, _Number_, _Connector_Punctuation_ + -- Is this a word character? + -- Word characters are defined as in [Ruby’s `\p{Word}` syntax](http://ruby-doc.org/core-2.1.1/Regexp.html#class-Regexp-label-Character+Properties), i.e:. + -- > A member of one of the following Unicode general category _Letter_, _Mark_, _Number_, _Connector_Punctuation_ isWord c = Char.isLetter c || Char.isNumber c || Char.isMark c || Char.generalCategory c == Char.ConnectorPunctuation isPunctuation c = not (Char.isSpace c || isWord c) From ed9b00cc904d747a549c94bc8fabb8b4592695ae Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:41:32 -0400 Subject: [PATCH 044/146] :fire: rangesAndWordsFrom. --- semantic-diff.cabal | 1 - src/Data/Range.hs | 23 ----------------------- test/RangeSpec.hs | 33 --------------------------------- test/Spec.hs | 2 -- 4 files changed, 59 deletions(-) delete mode 100644 test/RangeSpec.hs diff --git a/semantic-diff.cabal b/semantic-diff.cabal index 5cb25d44d..948522829 100644 --- a/semantic-diff.cabal +++ b/semantic-diff.cabal @@ -148,7 +148,6 @@ test-suite test , SemanticCmdLineSpec , InterpreterSpec , PatchOutputSpec - , RangeSpec , SES.Myers.Spec , SourceSpec , SpecHelpers diff --git a/src/Data/Range.hs b/src/Data/Range.hs index 5be4a01bc..8f3774561 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -1,11 +1,8 @@ {-# LANGUAGE DeriveAnyClass #-} module Data.Range where -import qualified Data.Char as Char -import Data.List (span) import Data.List.NonEmpty (nonEmpty) import Data.Semigroup -import Data.String import Prologue import Test.LeanCheck @@ -28,26 +25,6 @@ divideRange :: Range -> Int -> (Range, Range) divideRange Range{..} at = (Range start divider, Range divider end) where divider = max (min end at) start --- | Break a string down into words and sequences of punctuation. --- --- Returns a list strings with ranges, assuming that the first character in the string is at the given index. -rangesAndWordsFrom :: Int -> String -> [(Range, String)] -rangesAndWordsFrom _ "" = [] -rangesAndWordsFrom startIndex string = fromMaybe [] $ take isWord <|> take isPunctuation <|> skip Char.isSpace - where - save parsed = (Range startIndex $ endFor parsed, parsed) - take = parse (Just . save) - skip = parse (const Nothing) - endFor parsed = startIndex + length parsed - parse transform predicate = case span predicate string of - ([], _) -> Nothing - (parsed, rest) -> Just . maybe identity (:) (transform parsed) $ rangesAndWordsFrom (endFor parsed) rest - -- Is this a word character? - -- Word characters are defined as in [Ruby’s `\p{Word}` syntax](http://ruby-doc.org/core-2.1.1/Regexp.html#class-Regexp-label-Character+Properties), i.e:. - -- > A member of one of the following Unicode general category _Letter_, _Mark_, _Number_, _Connector_Punctuation_ - isWord c = Char.isLetter c || Char.isNumber c || Char.isMark c || Char.generalCategory c == Char.ConnectorPunctuation - isPunctuation c = not (Char.isSpace c || isWord c) - -- | Return Just the last index from a non-empty range, or if the range is empty, Nothing. maybeLastIndex :: Range -> Maybe Int maybeLastIndex (Range start end) | start == end = Nothing diff --git a/test/RangeSpec.hs b/test/RangeSpec.hs deleted file mode 100644 index 3da0b6f16..000000000 --- a/test/RangeSpec.hs +++ /dev/null @@ -1,33 +0,0 @@ -module RangeSpec where - -import Data.Range -import Prologue -import Test.Hspec (Spec, describe, it, parallel) -import Test.Hspec.Expectations.Pretty - -spec :: Spec -spec = parallel $ do - describe "rangesAndWordsFrom" $ do - it "should produce no ranges for the empty string" $ - rangesAndWordsFrom 0 mempty `shouldBe` [] - - it "should produce no ranges for whitespace" $ - rangesAndWordsFrom 0 " \t\n " `shouldBe` [] - - it "should produce a list containing the range of the string for a single-word string" $ - rangesAndWordsFrom 0 "word" `shouldBe` [ (Range 0 4, "word") ] - - it "should produce a list of ranges for whitespace-separated words" $ - rangesAndWordsFrom 0 "wordOne wordTwo" `shouldBe` [ (Range 0 7, "wordOne"), (Range 8 15, "wordTwo") ] - - it "should skip multiple whitespace characters" $ - rangesAndWordsFrom 0 "a b" `shouldBe` [ (Range 0 1, "a"), (Range 3 4, "b") ] - - it "should skip whitespace at the start" $ - rangesAndWordsFrom 0 " a b" `shouldBe` [ (Range 2 3, "a"), (Range 4 5, "b") ] - - it "should skip whitespace at the end" $ - rangesAndWordsFrom 0 "a b " `shouldBe` [ (Range 0 1, "a"), (Range 2 3, "b") ] - - it "should produce ranges offset by its start index" $ - rangesAndWordsFrom 100 "a b" `shouldBe` [ (Range 100 101, "a"), (Range 102 103, "b") ] diff --git a/test/Spec.hs b/test/Spec.hs index c90513c5d..0a7a6b459 100644 --- a/test/Spec.hs +++ b/test/Spec.hs @@ -9,7 +9,6 @@ import qualified Data.Syntax.Assignment.Spec import qualified DiffSpec import qualified InterpreterSpec import qualified PatchOutputSpec -import qualified RangeSpec import qualified SES.Myers.Spec import qualified SourceSpec import qualified TermSpec @@ -30,7 +29,6 @@ main = hspec $ do describe "Diff" DiffSpec.spec describe "Interpreter" InterpreterSpec.spec describe "PatchOutput" PatchOutputSpec.spec - describe "Range" RangeSpec.spec describe "SES.Myers" SES.Myers.Spec.spec describe "Source" SourceSpec.spec describe "Term" TermSpec.spec From 1bbc0a503a1fc9066a319b543d988f23e0032e62 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:42:48 -0400 Subject: [PATCH 045/146] :fire: maybeLastIndex. --- src/Data/Range.hs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Data/Range.hs b/src/Data/Range.hs index 8f3774561..bbd439a4e 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -25,11 +25,6 @@ divideRange :: Range -> Int -> (Range, Range) divideRange Range{..} at = (Range start divider, Range divider end) where divider = max (min end at) start --- | Return Just the last index from a non-empty range, or if the range is empty, Nothing. -maybeLastIndex :: Range -> Maybe Int -maybeLastIndex (Range start end) | start == end = Nothing -maybeLastIndex (Range _ end) = Just $ end - 1 - -- | Test two ranges for intersection. intersectsRange :: Range -> Range -> Bool intersectsRange range1 range2 = start range1 < end range2 && start range2 < end range1 From 09dd48f994b44d8e3370f7fc17e7b212e625a321 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:43:27 -0400 Subject: [PATCH 046/146] :fire: divideRange. --- src/Data/Range.hs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Data/Range.hs b/src/Data/Range.hs index bbd439a4e..6312176cc 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -18,13 +18,6 @@ rangeLength range = end range - start range offsetRange :: Range -> Int -> Range offsetRange a b = Range (start a + b) (end a + b) --- | Divide a range in two at the given coordinate. --- --- Passing a coordinate that does not lie between start and end will result in one of the ranges being empty. -divideRange :: Range -> Int -> (Range, Range) -divideRange Range{..} at = (Range start divider, Range divider end) - where divider = max (min end at) start - -- | Test two ranges for intersection. intersectsRange :: Range -> Range -> Bool intersectsRange range1 range2 = start range1 < end range2 && start range2 < end range1 From d368e44a57bc8a829a1753d1efce633e6c01dc44 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:44:21 -0400 Subject: [PATCH 047/146] :fire: intersectionRange. --- src/Data/Range.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Data/Range.hs b/src/Data/Range.hs index 6312176cc..10d7d37e6 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -22,10 +22,6 @@ offsetRange a b = Range (start a + b) (end a + b) intersectsRange :: Range -> Range -> Bool intersectsRange range1 range2 = start range1 < end range2 && start range2 < end range1 --- Return the (possibly empty, possibly ill-formed) intersection of two ranges. -intersectionRange :: Range -> Range -> Range -intersectionRange range1 range2 = Range (max (start range1) (start range2)) (min (end range1) (end range2)) - -- | Return a range that contains both the given ranges. unionRange :: Range -> Range -> Range unionRange (Range start1 end1) (Range start2 end2) = Range (min start1 start2) (max end1 end2) From 59b18baa9c45b4c009b6cd0181596d797ca785e6 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:45:15 -0400 Subject: [PATCH 048/146] :fire: unionRangesFrom. --- src/Data/Range.hs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Data/Range.hs b/src/Data/Range.hs index 10d7d37e6..46c469b1e 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -1,7 +1,6 @@ {-# LANGUAGE DeriveAnyClass #-} module Data.Range where -import Data.List.NonEmpty (nonEmpty) import Data.Semigroup import Prologue import Test.LeanCheck @@ -26,10 +25,6 @@ intersectsRange range1 range2 = start range1 < end range2 && start range2 < end unionRange :: Range -> Range -> Range unionRange (Range start1 end1) (Range start2 end2) = Range (min start1 start2) (max end1 end2) --- | Return a range that contains all the ranges in a Foldable, or the passed Range if the Foldable is empty. -unionRangesFrom :: Foldable f => Range -> f Range -> Range -unionRangesFrom range = maybe range sconcat . nonEmpty . toList - -- Instances From 062a7ca2bba337b197fda5f9621a102cc1319a41 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:45:55 -0400 Subject: [PATCH 049/146] :fire: unionRange. --- src/Data/Range.hs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Data/Range.hs b/src/Data/Range.hs index 46c469b1e..040479ab2 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -21,15 +21,11 @@ offsetRange a b = Range (start a + b) (end a + b) intersectsRange :: Range -> Range -> Bool intersectsRange range1 range2 = start range1 < end range2 && start range2 < end range1 --- | Return a range that contains both the given ranges. -unionRange :: Range -> Range -> Range -unionRange (Range start1 end1) (Range start2 end2) = Range (min start1 start2) (max end1 end2) - -- Instances instance Semigroup Range where - a <> b = unionRange a b + Range start1 end1 <> Range start2 end2 = Range (min start1 start2) (max end1 end2) instance Ord Range where a <= b = start a <= start b From 21878f2e80c07df7d540eda157428c71e159674b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:46:45 -0400 Subject: [PATCH 050/146] =?UTF-8?q?Explicitly=20list=20Data.Range=E2=80=99?= =?UTF-8?q?s=20exports.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Data/Range.hs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Data/Range.hs b/src/Data/Range.hs index 040479ab2..2f1d94dc9 100644 --- a/src/Data/Range.hs +++ b/src/Data/Range.hs @@ -1,5 +1,10 @@ {-# LANGUAGE DeriveAnyClass #-} -module Data.Range where +module Data.Range +( Range(..) +, rangeLength +, offsetRange +, intersectsRange +) where import Data.Semigroup import Prologue From 4ff3d9e8ec1d8bf25074572077e0a43fc92db1f9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:50:28 -0400 Subject: [PATCH 051/146] Rename sourceText to sourceBytes. --- src/Data/Source.hs | 22 +++++++++++----------- src/Data/Syntax/Assignment.hs | 6 +++--- src/Renderer/Patch.hs | 2 +- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 4ec30c708..deadfccdb 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -11,7 +11,7 @@ import Prologue import Test.LeanCheck -- | The contents of a source file, represented as a ByteString. -newtype Source = Source { sourceText :: B.ByteString } +newtype Source = Source { sourceBytes :: B.ByteString } deriving (Eq, IsString, Show) @@ -26,16 +26,16 @@ slice range = take . drop take = Data.Source.take (rangeLength range) drop :: Int -> Source -> Source -drop i = Source . drop . sourceText +drop i = Source . drop . sourceBytes where drop = B.drop i take :: Int -> Source -> Source -take i = Source . take . sourceText +take i = Source . take . sourceBytes where take = B.take i -- | Return the ByteString contained in the 'Source'. toText :: Source -> Text -toText = decodeUtf8 . sourceText +toText = decodeUtf8 . sourceBytes -- | Split the source into the longest prefix of elements that do not satisfy the predicate and the rest without copying. break :: (Word8 -> Bool) -> Source -> (Source, Source) @@ -43,7 +43,7 @@ break predicate (Source text) = let (start, remainder) = B.break predicate text -- | Split the contents of the source after newlines. actualLines :: Source -> [Source] -actualLines = fmap Source . actualLines' . sourceText +actualLines = fmap Source . actualLines' . sourceBytes where actualLines' text | B.null text = [ text ] | otherwise = case B.break (== toEnum (fromEnum '\n')) text of @@ -54,12 +54,12 @@ actualLines = fmap Source . actualLines' . sourceText -- | Compute the 'Range's of each line in a 'Source'. actualLineRanges :: Source -> [Range] actualLineRanges = Prologue.drop 1 . scanl toRange (Range 0 0) . actualLines - where toRange previous string = Range (end previous) $ end previous + B.length (sourceText string) + where toRange previous source = Range (end previous) $ end previous + sourceLength source -- | Compute the 'Range's of each line in a 'Range' of a 'Source'. actualLineRangesWithin :: Range -> Source -> [Range] actualLineRangesWithin range = Prologue.drop 1 . scanl toRange (Range (start range) (start range)) . actualLines . slice range - where toRange previous string = Range (end previous) $ end previous + B.length (sourceText string) + where toRange previous source = Range (end previous) $ end previous + sourceLength source -- | Compute the byte 'Range' corresponding to a given 'Span' in a 'Source'. spanToRange :: Source -> Span -> Range @@ -85,7 +85,7 @@ rangeToSpan source (Range rangeStart rangeEnd) = Span startPos endPos -- | Return a 'Range' that covers the entire text. totalRange :: Source -> Range -totalRange = Range 0 . B.length . sourceText +totalRange = Range 0 . B.length . sourceBytes -- | Return a 'Span' that covers the entire text. totalSpan :: Source -> Span @@ -94,10 +94,10 @@ totalSpan source = Span (Pos 1 1) (Pos (length ranges) (succ (end lastRange - st Just lastRange = getLast (foldMap (Last . Just) ranges) sourceLength :: Source -> Int -sourceLength = B.length . sourceText +sourceLength = B.length . sourceBytes nullSource :: Source -> Bool -nullSource = B.null . sourceText +nullSource = B.null . sourceBytes instance Semigroup Source where Source a <> Source b = Source (a <> b) @@ -120,4 +120,4 @@ instance Listable ListableByteString where , [chr 0xa0..chr 0x24f] ] -- Non-ASCII. instance StringConv Source ByteString where - strConv _ = sourceText + strConv _ = sourceBytes diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index addc8448d..6b0831b9f 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -95,7 +95,7 @@ import Data.Ix (inRange) import Data.List.NonEmpty (nonEmpty) import Data.Range (offsetRange) import Data.Record -import qualified Data.Source as Source (Source(..), drop, slice, sourceText, actualLines) +import qualified Data.Source as Source (Source(..), drop, slice, sourceBytes, actualLines) import GHC.Stack import qualified Info import Prologue hiding (Alt, get, Location, state) @@ -188,7 +188,7 @@ printError source error@Error{..} withSGRCode [SetColor Foreground Vivid Red] . putStrErr . (showString "error") . showString ": " . showExpectation error . showChar '\n' . showString (toS context) . (if isSuffixOf "\n" context then identity else showChar '\n') . showString (replicate (succ (Info.posColumn errorPos + lineNumberDigits)) ' ') $ "" withSGRCode [SetColor Foreground Vivid Green] . putStrErr . (showChar '^') . showChar '\n' . showString (prettyCallStack callStack) $ "" - where context = maybe "\n" (Source.sourceText . sconcat) (nonEmpty [ Source.Source (toS (showLineNumber i)) <> Source.Source ": " <> l | (i, l) <- zip [1..] (Source.actualLines source), inRange (Info.posLine errorPos - 2, Info.posLine errorPos) i ]) + where context = maybe "\n" (Source.sourceBytes . sconcat) (nonEmpty [ Source.Source (toS (showLineNumber i)) <> Source.Source ": " <> l | (i, l) <- zip [1..] (Source.actualLines source), inRange (Info.posLine errorPos - 2, Info.posLine errorPos) i ]) showLineNumber n = let s = show n in replicate (lineNumberDigits - length s) ' ' <> s lineNumberDigits = succ (floor (logBase 10 (fromIntegral (Info.posLine errorPos) :: Double))) putStrErr = hPutStr stderr @@ -243,7 +243,7 @@ runAssignment toRecord = iterFreer run . fmap ((pure .) . (,)) (Location, node : _) -> yield (rtail (toRecord (F.project node))) state (Location, []) -> yield (Info.Range stateOffset stateOffset :. Info.Span statePos statePos :. Nil) state (Project projection, node : _) -> yield (projection (F.project node)) state - (Source, node : _) -> yield (Source.sourceText (Source.slice (offsetRange (Info.byteRange (toRecord (F.project node))) (negate stateOffset)) stateSource)) (advanceState (rtail . toRecord) state) + (Source, node : _) -> yield (Source.sourceBytes (Source.slice (offsetRange (Info.byteRange (toRecord (F.project node))) (negate stateOffset)) stateSource)) (advanceState (rtail . toRecord) state) (Children childAssignment, node : _) -> case assignAllFrom toRecord childAssignment state { stateNodes = toList (F.project node) } of Result _ (Just (a, state')) -> yield a (advanceState (rtail . toRecord) state' { stateNodes = stateNodes }) Result err Nothing -> Result err Nothing diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index 3de21171d..eadb7a0fa 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -90,7 +90,7 @@ showLines source prefix lines = fromMaybe "" . mconcat $ fmap prepend . showLine -- | Given a source, render a line to a string. showLine :: Functor f => HasField fields Range => Source -> Maybe (SplitDiff f (Record fields)) -> Maybe ByteString -showLine source line | Just line <- line = Just . sourceText . (`slice` source) $ getRange line +showLine source line | Just line <- line = Just . sourceBytes . (`slice` source) $ getRange line | otherwise = Nothing -- | Returns the header given two source blobs and a hunk. From ca49dec2076782ffbdd730980deb3c6437f5b2e9 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:54:03 -0400 Subject: [PATCH 052/146] Avoid another trip through Text. --- src/TreeSitter.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index d5998e9f9..54d70e52d 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -7,6 +7,7 @@ module TreeSitter import Prologue hiding (Constructor) import Category +import Data.ByteString (useAsCStringLen) import Data.Functor.Foldable hiding (Nil) import Data.Ix import Data.Range @@ -23,7 +24,6 @@ import qualified Syntax import Foreign import Foreign.C.String (peekCString) import Foreign.Marshal.Array (allocaArray) -import Data.Text.Foreign (withCStringLen) import qualified Syntax as S import Term import Text.Parser.TreeSitter hiding (Language(..)) @@ -34,8 +34,8 @@ import Info treeSitterParser :: Language -> Ptr TS.Language -> Source -> IO (Term (Syntax.Syntax Text) (Record DefaultFields)) treeSitterParser language grammar source = bracket ts_document_new ts_document_free $ \ document -> do ts_document_set_language document grammar - withCStringLen (toText source) $ \ (sourceText, len) -> do - ts_document_set_input_string_with_length document sourceText len + useAsCStringLen (sourceBytes source) $ \ (sourceBytes, len) -> do + ts_document_set_input_string_with_length document sourceBytes len ts_document_parse_halt_on_error document term <- documentToTerm language document source pure term @@ -45,7 +45,7 @@ treeSitterParser language grammar source = bracket ts_document_new ts_document_f parseToAST :: (Bounded grammar, Enum grammar) => Ptr TS.Language -> Source -> IO (Cofree [] (Record (Maybe grammar ': A.Location))) parseToAST language source = bracket ts_document_new ts_document_free $ \ document -> do ts_document_set_language document language - root <- withCStringLen (toText source) $ \ (source, len) -> do + root <- useAsCStringLen (sourceBytes source) $ \ (source, len) -> do ts_document_set_input_string_with_length document source len ts_document_parse_halt_on_error document alloca (\ rootPtr -> do From 1be293ec79b4ecaccbc15c2cd9a1b4c3681c9008 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:55:07 -0400 Subject: [PATCH 053/146] Avoid copying the underlying ByteString. --- src/TreeSitter.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/TreeSitter.hs b/src/TreeSitter.hs index 54d70e52d..13670bca1 100644 --- a/src/TreeSitter.hs +++ b/src/TreeSitter.hs @@ -7,7 +7,7 @@ module TreeSitter import Prologue hiding (Constructor) import Category -import Data.ByteString (useAsCStringLen) +import Data.ByteString.Unsafe (unsafeUseAsCStringLen) import Data.Functor.Foldable hiding (Nil) import Data.Ix import Data.Range @@ -34,7 +34,7 @@ import Info treeSitterParser :: Language -> Ptr TS.Language -> Source -> IO (Term (Syntax.Syntax Text) (Record DefaultFields)) treeSitterParser language grammar source = bracket ts_document_new ts_document_free $ \ document -> do ts_document_set_language document grammar - useAsCStringLen (sourceBytes source) $ \ (sourceBytes, len) -> do + unsafeUseAsCStringLen (sourceBytes source) $ \ (sourceBytes, len) -> do ts_document_set_input_string_with_length document sourceBytes len ts_document_parse_halt_on_error document term <- documentToTerm language document source @@ -45,7 +45,7 @@ treeSitterParser language grammar source = bracket ts_document_new ts_document_f parseToAST :: (Bounded grammar, Enum grammar) => Ptr TS.Language -> Source -> IO (Cofree [] (Record (Maybe grammar ': A.Location))) parseToAST language source = bracket ts_document_new ts_document_free $ \ document -> do ts_document_set_language document language - root <- useAsCStringLen (sourceBytes source) $ \ (source, len) -> do + root <- unsafeUseAsCStringLen (sourceBytes source) $ \ (source, len) -> do ts_document_set_input_string_with_length document source len ts_document_parse_halt_on_error document alloca (\ rootPtr -> do From e3b697af1aee818ba1c5d6b218a0af5bc32f3730 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:58:56 -0400 Subject: [PATCH 054/146] :fire: unionSpansFrom. --- src/Data/Span.hs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Data/Span.hs b/src/Data/Span.hs index 6592d11c2..62be214ab 100644 --- a/src/Data/Span.hs +++ b/src/Data/Span.hs @@ -7,7 +7,6 @@ module Data.Span where import Data.Aeson ((.=), (.:)) import qualified Data.Aeson as A -import Data.List.NonEmpty (nonEmpty) import Data.Semigroup import Data.These import Prologue @@ -35,9 +34,6 @@ data Span = Span } deriving (Show, Read, Eq, Ord, Generic, Hashable, NFData) -unionSpansFrom :: Foldable f => Span -> f Span -> Span -unionSpansFrom sourceSpan = maybe sourceSpan sconcat . nonEmpty . toList - unionSpan :: Span -> Span -> Span unionSpan (Span start1 end1) (Span start2 end2) = Span (min start1 start2) (max end1 end2) From d87aa706aa0bfa29923ae3253fa6c257fa7ac1ad Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:59:03 -0400 Subject: [PATCH 055/146] :fire: unionSpan. --- src/Data/Span.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Data/Span.hs b/src/Data/Span.hs index 62be214ab..d6a041c64 100644 --- a/src/Data/Span.hs +++ b/src/Data/Span.hs @@ -34,14 +34,11 @@ data Span = Span } deriving (Show, Read, Eq, Ord, Generic, Hashable, NFData) -unionSpan :: Span -> Span -> Span -unionSpan (Span start1 end1) (Span start2 end2) = Span (min start1 start2) (max end1 end2) - emptySpan :: Span emptySpan = Span (Pos 1 1) (Pos 1 1) instance Semigroup Span where - a <> b = unionSpan a b + Span start1 end1 <> Span start2 end2 = Span (min start1 start2) (max end1 end2) instance A.ToJSON Span where toJSON Span{..} = From ed140c99370b66a6fe5fc862358d0262cd0121a5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:59:09 -0400 Subject: [PATCH 056/146] :fire: Spans. --- src/Data/Span.hs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/Data/Span.hs b/src/Data/Span.hs index d6a041c64..4b8319f55 100644 --- a/src/Data/Span.hs +++ b/src/Data/Span.hs @@ -8,7 +8,6 @@ module Data.Span where import Data.Aeson ((.=), (.:)) import qualified Data.Aeson as A import Data.Semigroup -import Data.These import Prologue import Test.LeanCheck @@ -52,20 +51,6 @@ instance A.FromJSON Span where o .: "start" <*> o .: "end" - -newtype Spans = Spans { unSpans :: These Span Span } - deriving (Eq, Show) - -instance A.ToJSON Spans where - toJSON (Spans spans) = case spans of - (This span) -> A.object ["delete" .= span] - (That span) -> A.object ["insert" .= span] - (These span1 span2) -> A.object ["replace" .= (span1, span2)] - toEncoding (Spans spans) = case spans of - (This span) -> A.pairs $ "delete" .= span - (That span) -> A.pairs $ "insert" .= span - (These span1 span2) -> A.pairs $ "replace" .= (span1, span2) - instance Listable Pos where tiers = cons2 Pos From fc004385b2a68cab96a677fe0201af9d3dee4790 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 10:59:21 -0400 Subject: [PATCH 057/146] =?UTF-8?q?List=20Data.Span=E2=80=99s=20exports=20?= =?UTF-8?q?explicitly.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Data/Span.hs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Data/Span.hs b/src/Data/Span.hs index 4b8319f55..c39954415 100644 --- a/src/Data/Span.hs +++ b/src/Data/Span.hs @@ -3,7 +3,11 @@ -- | Source position and span information -- -- Mostly taken from purescript's SourcePos definition. -module Data.Span where +module Data.Span +( Span(..) +, Pos(..) +, emptySpan +) where import Data.Aeson ((.=), (.:)) import qualified Data.Aeson as A From 4886a4585ccc4ea598a0e2b18559a96f6c95d820 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:08:14 -0400 Subject: [PATCH 058/146] =?UTF-8?q?Rearrange=20and=20group=20Data.Source?= =?UTF-8?q?=E2=80=99s=20functions.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Data/Source.hs | 49 ++++++++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index deadfccdb..4b5b7edc2 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -14,11 +14,36 @@ import Test.LeanCheck newtype Source = Source { sourceBytes :: B.ByteString } deriving (Eq, IsString, Show) +-- Measurement + +sourceLength :: Source -> Int +sourceLength = B.length . sourceBytes + +nullSource :: Source -> Bool +nullSource = B.null . sourceBytes + +-- | Return a 'Range' that covers the entire text. +totalRange :: Source -> Range +totalRange = Range 0 . B.length . sourceBytes + +-- | Return a 'Span' that covers the entire text. +totalSpan :: Source -> Span +totalSpan source = Span (Pos 1 1) (Pos (length ranges) (succ (end lastRange - start lastRange))) + where ranges = actualLineRanges source + Just lastRange = getLast (foldMap (Last . Just) ranges) + + +-- En/decoding -- | Return a 'Source' from a 'ByteString'. fromText :: T.Text -> Source fromText = Source . encodeUtf8 +-- | Return the ByteString contained in the 'Source'. +toText :: Source -> Text +toText = decodeUtf8 . sourceBytes + + -- | Return a 'Source' that contains a slice of the given 'Source'. slice :: Range -> Source -> Source slice range = take . drop @@ -33,14 +58,14 @@ take :: Int -> Source -> Source take i = Source . take . sourceBytes where take = B.take i --- | Return the ByteString contained in the 'Source'. -toText :: Source -> Text -toText = decodeUtf8 . sourceBytes + +-- Splitting -- | Split the source into the longest prefix of elements that do not satisfy the predicate and the rest without copying. break :: (Word8 -> Bool) -> Source -> (Source, Source) break predicate (Source text) = let (start, remainder) = B.break predicate text in (Source start, Source remainder) + -- | Split the contents of the source after newlines. actualLines :: Source -> [Source] actualLines = fmap Source . actualLines' . sourceBytes @@ -61,6 +86,9 @@ actualLineRangesWithin :: Range -> Source -> [Range] actualLineRangesWithin range = Prologue.drop 1 . scanl toRange (Range (start range) (start range)) . actualLines . slice range where toRange previous source = Range (end previous) $ end previous + sourceLength source + +-- Conversion + -- | Compute the byte 'Range' corresponding to a given 'Span' in a 'Source'. spanToRange :: Source -> Span -> Range spanToRange source = spanToRangeInLineRanges (actualLineRanges source) @@ -83,21 +111,8 @@ rangeToSpan source (Range rangeStart rangeEnd) = Span startPos endPos Just firstRange = getFirst (foldMap (First . Just) lineRanges) Just lastRange = getLast (foldMap (Last . Just) lineRanges) --- | Return a 'Range' that covers the entire text. -totalRange :: Source -> Range -totalRange = Range 0 . B.length . sourceBytes --- | Return a 'Span' that covers the entire text. -totalSpan :: Source -> Span -totalSpan source = Span (Pos 1 1) (Pos (length ranges) (succ (end lastRange - start lastRange))) - where ranges = actualLineRanges source - Just lastRange = getLast (foldMap (Last . Just) ranges) - -sourceLength :: Source -> Int -sourceLength = B.length . sourceBytes - -nullSource :: Source -> Bool -nullSource = B.null . sourceBytes +-- Instances instance Semigroup Source where Source a <> Source b = Source (a <> b) From 48f911485e1ff95eb8ca7106a06877225f56326f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:09:21 -0400 Subject: [PATCH 059/146] =?UTF-8?q?Explicitly=20list=20Data.Source?= =?UTF-8?q?=E2=80=99s=20exports.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Data/Source.hs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 4b5b7edc2..9efd889e5 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -1,5 +1,30 @@ {-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses #-} -module Data.Source where +module Data.Source +( Source(..) +-- Measurement +, sourceLength +, nullSource +, totalRange +, totalSpan +-- En/decoding +, fromText +, toText +-- Slicing +, slice +, drop +, take +-- Splitting +, break +, actualLines +, actualLineRanges +, actualLineRangesWithin +-- Conversion +, spanToRange +, spanToRangeInLineRanges +, rangeToSpan +-- Listable +, ListableByteString(..) +) where import qualified Data.ByteString as B import Data.List (span) @@ -7,7 +32,8 @@ import Data.Range import Data.Span import Data.String (IsString(..)) import qualified Data.Text as T -import Prologue +import Prologue hiding (break, drop, take) +import qualified Prologue import Test.LeanCheck -- | The contents of a source file, represented as a ByteString. From d2e4ce8dc34fe91667fa46722c15abbaf894d715 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:11:10 -0400 Subject: [PATCH 060/146] :fire: the export of Data.Source.take. --- src/Alignment.hs | 2 +- src/Data/Source.hs | 1 - src/Renderer/Patch.hs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Alignment.hs b/src/Alignment.hs index f8cd49ab5..776b516bd 100644 --- a/src/Alignment.hs +++ b/src/Alignment.hs @@ -15,7 +15,7 @@ import Data.Functor.Both import Data.List (partition) import Data.Maybe (fromJust) import Data.Range -import Data.Source hiding (break, drop, take) +import Data.Source hiding (break, drop) import Data.Record import Data.These import Diff diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 9efd889e5..4f48808fa 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -12,7 +12,6 @@ module Data.Source -- Slicing , slice , drop -, take -- Splitting , break , actualLines diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index eadb7a0fa..77d601275 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -15,7 +15,7 @@ import Data.Functor.Both as Both import Data.List (span, unzip) import Data.Range import Data.Record -import Data.Source as Source hiding (break, drop, take) +import Data.Source as Source hiding (break, drop) import Data.These import Diff import Patch From 323347446dbde1a9f271395a28b86de537155d9b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:13:22 -0400 Subject: [PATCH 061/146] Rename actualLine* to sourceLine*. --- src/Alignment.hs | 2 +- src/Data/Source.hs | 28 ++++++++++++++-------------- src/Data/Syntax/Assignment.hs | 4 ++-- src/Language/Markdown.hs | 2 +- src/Parser.hs | 2 +- test/AlignmentSpec.hs | 4 ++-- test/SourceSpec.hs | 8 ++++---- 7 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Alignment.hs b/src/Alignment.hs index 776b516bd..0b6eb2f6c 100644 --- a/src/Alignment.hs +++ b/src/Alignment.hs @@ -59,7 +59,7 @@ alignSyntax :: (Applicative f, HasField fields Range, Foldable g) => (forall a. alignSyntax toJoinThese toNode getRange sources (infos :< syntax) = catMaybes $ wrapInBranch <$> alignBranch getRange (join (toList syntax)) bothRanges where bothRanges = modifyJoin (fromThese [] []) lineRanges - lineRanges = toJoinThese $ actualLineRangesWithin . byteRange <$> infos <*> sources + lineRanges = toJoinThese $ sourceLineRangesWithin . byteRange <$> infos <*> sources wrapInBranch = applyThese $ toJoinThese (makeNode <$> infos) makeNode info (range, children) = toNode (setByteRange info range :< children) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 4f48808fa..f70f65406 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -14,9 +14,9 @@ module Data.Source , drop -- Splitting , break -, actualLines -, actualLineRanges -, actualLineRangesWithin +, sourceLines +, sourceLineRanges +, sourceLineRangesWithin -- Conversion , spanToRange , spanToRangeInLineRanges @@ -54,7 +54,7 @@ totalRange = Range 0 . B.length . sourceBytes -- | Return a 'Span' that covers the entire text. totalSpan :: Source -> Span totalSpan source = Span (Pos 1 1) (Pos (length ranges) (succ (end lastRange - start lastRange))) - where ranges = actualLineRanges source + where ranges = sourceLineRanges source Just lastRange = getLast (foldMap (Last . Just) ranges) @@ -92,23 +92,23 @@ break predicate (Source text) = let (start, remainder) = B.break predicate text -- | Split the contents of the source after newlines. -actualLines :: Source -> [Source] -actualLines = fmap Source . actualLines' . sourceBytes - where actualLines' text +sourceLines :: Source -> [Source] +sourceLines = fmap Source . sourceLines' . sourceBytes + where sourceLines' text | B.null text = [ text ] | otherwise = case B.break (== toEnum (fromEnum '\n')) text of (l, lines') -> case B.uncons lines' of Nothing -> [ l ] - Just (_, lines') -> (l <> B.singleton (toEnum (fromEnum '\n'))) : actualLines' lines' + Just (_, lines') -> (l <> B.singleton (toEnum (fromEnum '\n'))) : sourceLines' lines' -- | Compute the 'Range's of each line in a 'Source'. -actualLineRanges :: Source -> [Range] -actualLineRanges = Prologue.drop 1 . scanl toRange (Range 0 0) . actualLines +sourceLineRanges :: Source -> [Range] +sourceLineRanges = Prologue.drop 1 . scanl toRange (Range 0 0) . sourceLines where toRange previous source = Range (end previous) $ end previous + sourceLength source -- | Compute the 'Range's of each line in a 'Range' of a 'Source'. -actualLineRangesWithin :: Range -> Source -> [Range] -actualLineRangesWithin range = Prologue.drop 1 . scanl toRange (Range (start range) (start range)) . actualLines . slice range +sourceLineRangesWithin :: Range -> Source -> [Range] +sourceLineRangesWithin range = Prologue.drop 1 . scanl toRange (Range (start range) (start range)) . sourceLines . slice range where toRange previous source = Range (end previous) $ end previous + sourceLength source @@ -116,7 +116,7 @@ actualLineRangesWithin range = Prologue.drop 1 . scanl toRange (Range (start ran -- | Compute the byte 'Range' corresponding to a given 'Span' in a 'Source'. spanToRange :: Source -> Span -> Range -spanToRange source = spanToRangeInLineRanges (actualLineRanges source) +spanToRange source = spanToRangeInLineRanges (sourceLineRanges source) spanToRangeInLineRanges :: [Range] -> Span -> Range spanToRangeInLineRanges lineRanges Span{..} = Range start end @@ -131,7 +131,7 @@ rangeToSpan source (Range rangeStart rangeEnd) = Span startPos endPos where startPos = Pos (firstLine + 1) (rangeStart - start firstRange + 1) endPos = Pos (firstLine + length lineRanges) (rangeEnd - start lastRange + 1) firstLine = length before - (before, rest) = span ((< rangeStart) . end) (actualLineRanges source) + (before, rest) = span ((< rangeStart) . end) (sourceLineRanges source) (lineRanges, _) = span ((<= rangeEnd) . start) rest Just firstRange = getFirst (foldMap (First . Just) lineRanges) Just lastRange = getLast (foldMap (Last . Just) lineRanges) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 6b0831b9f..ac6b102c7 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -95,7 +95,7 @@ import Data.Ix (inRange) import Data.List.NonEmpty (nonEmpty) import Data.Range (offsetRange) import Data.Record -import qualified Data.Source as Source (Source(..), drop, slice, sourceBytes, actualLines) +import qualified Data.Source as Source (Source(..), drop, slice, sourceBytes, sourceLines) import GHC.Stack import qualified Info import Prologue hiding (Alt, get, Location, state) @@ -188,7 +188,7 @@ printError source error@Error{..} withSGRCode [SetColor Foreground Vivid Red] . putStrErr . (showString "error") . showString ": " . showExpectation error . showChar '\n' . showString (toS context) . (if isSuffixOf "\n" context then identity else showChar '\n') . showString (replicate (succ (Info.posColumn errorPos + lineNumberDigits)) ' ') $ "" withSGRCode [SetColor Foreground Vivid Green] . putStrErr . (showChar '^') . showChar '\n' . showString (prettyCallStack callStack) $ "" - where context = maybe "\n" (Source.sourceBytes . sconcat) (nonEmpty [ Source.Source (toS (showLineNumber i)) <> Source.Source ": " <> l | (i, l) <- zip [1..] (Source.actualLines source), inRange (Info.posLine errorPos - 2, Info.posLine errorPos) i ]) + where context = maybe "\n" (Source.sourceBytes . sconcat) (nonEmpty [ Source.Source (toS (showLineNumber i)) <> Source.Source ": " <> l | (i, l) <- zip [1..] (Source.sourceLines source), inRange (Info.posLine errorPos - 2, Info.posLine errorPos) i ]) showLineNumber n = let s = show n in replicate (lineNumberDigits - length s) ' ' <> s lineNumberDigits = succ (floor (logBase 10 (fromIntegral (Info.posLine errorPos) :: Double))) putStrErr = hPutStr stderr diff --git a/src/Language/Markdown.hs b/src/Language/Markdown.hs index 172000c8f..4e6d93788 100644 --- a/src/Language/Markdown.hs +++ b/src/Language/Markdown.hs @@ -46,7 +46,7 @@ cmarkParser source = toTerm (totalRange source) (totalSpan source) $ commonmarkT toSpan PosInfo{..} = Span (Pos startLine startColumn) (Pos endLine (succ endColumn)) - lineRanges = actualLineRanges source + lineRanges = sourceLineRanges source toGrammar :: NodeType -> Grammar toGrammar DOCUMENT{} = Document diff --git a/src/Parser.hs b/src/Parser.hs index ddc361def..624dbf93c 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -108,7 +108,7 @@ lineByLineParser :: Source -> IO (SyntaxTerm Text DefaultFields) lineByLineParser source = pure . cofree . root $ case foldl' annotateLeaves ([], 0) lines of (leaves, _) -> cofree <$> leaves where - lines = actualLines source + lines = sourceLines source root children = (sourceRange :. Program :. rangeToSpan source sourceRange :. Nil) :< Indexed children sourceRange = totalRange source leaf byteIndex line = (Range byteIndex (byteIndex + T.length line) :. Program :. rangeToSpan source (Range byteIndex (byteIndex + T.length line)) :. Nil) :< Leaf line diff --git a/test/AlignmentSpec.hs b/test/AlignmentSpec.hs index c24cf5b7c..3a84afe34 100644 --- a/test/AlignmentSpec.hs +++ b/test/AlignmentSpec.hs @@ -222,9 +222,9 @@ toAlignBranchInputs elements = (sources, join . (`evalState` both 0 0) . travers alignBranchElement element = case element of Child key contents -> Child key <$> joinCrosswalk lines contents Margin contents -> Margin <$> joinCrosswalk lines contents - where lines = fmap Source.toText . Source.actualLines . Source.fromText + where lines = fmap Source.toText . Source.sourceLines . Source.fromText sources = foldMap Source.fromText <$> bothContents elements - ranges = fmap (filter (\ (Range start end) -> start /= end)) $ Source.actualLineRangesWithin <$> (Source.totalRange <$> sources) <*> sources + ranges = fmap (filter (\ (Range start end) -> start /= end)) $ Source.sourceLineRangesWithin <$> (Source.totalRange <$> sources) <*> sources bothContents = foldMap (modifyJoin (fromThese [] []) . fmap (:[]) . branchElementContents) branchElementContents (Child _ contents) = contents branchElementContents (Margin contents) = contents diff --git a/test/SourceSpec.hs b/test/SourceSpec.hs index 6e06ff0e9..76509ab11 100644 --- a/test/SourceSpec.hs +++ b/test/SourceSpec.hs @@ -11,18 +11,18 @@ import Test.LeanCheck spec :: Spec spec = parallel $ do - describe "actualLineRanges" $ do + describe "sourceLineRanges" $ do prop "produces 1 more range than there are newlines" $ - \ source -> length (actualLineRanges source) `shouldBe` succ (Text.count "\n" (toText source)) + \ source -> length (sourceLineRanges source) `shouldBe` succ (Text.count "\n" (toText source)) prop "produces exhaustive ranges" $ - \ source -> foldMap (`slice` source) (actualLineRanges source) `shouldBe` source + \ source -> foldMap (`slice` source) (sourceLineRanges source) `shouldBe` source describe "spanToRange" $ do prop "computes single-line ranges" . forAll (unListableByteString `mapT` tiers) $ \ s -> let source = Source s spans = zipWith (\ i Range {..} -> Span (Pos i 1) (Pos i (succ (end - start)))) [1..] ranges - ranges = actualLineRanges source in + ranges = sourceLineRanges source in spanToRange source <$> spans `shouldBe` ranges prop "computes multi-line ranges" $ From 0bcb40bd8104ea7b36d41238c8267dfe0221af02 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:14:07 -0400 Subject: [PATCH 062/146] Spacing. --- src/Data/Source.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index f70f65406..005be9ca1 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -39,6 +39,7 @@ import Test.LeanCheck newtype Source = Source { sourceBytes :: B.ByteString } deriving (Eq, IsString, Show) + -- Measurement sourceLength :: Source -> Int From 43f9e7051776dd9d6789b553ac7023472019fb7f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:17:17 -0400 Subject: [PATCH 063/146] :fire: the export of Data.Source.break. --- src/Alignment.hs | 2 +- src/Data/Source.hs | 1 - src/Renderer/Patch.hs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Alignment.hs b/src/Alignment.hs index 0b6eb2f6c..7f0b81e99 100644 --- a/src/Alignment.hs +++ b/src/Alignment.hs @@ -15,7 +15,7 @@ import Data.Functor.Both import Data.List (partition) import Data.Maybe (fromJust) import Data.Range -import Data.Source hiding (break, drop) +import Data.Source hiding (drop) import Data.Record import Data.These import Diff diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 005be9ca1..7889b3d54 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -13,7 +13,6 @@ module Data.Source , slice , drop -- Splitting -, break , sourceLines , sourceLineRanges , sourceLineRangesWithin diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index 77d601275..32080836e 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -15,7 +15,7 @@ import Data.Functor.Both as Both import Data.List (span, unzip) import Data.Range import Data.Record -import Data.Source as Source hiding (break, drop) +import Data.Source as Source hiding (drop) import Data.These import Diff import Patch From 9c0d9c30fb5bc51e78b513fefe6822f571d0bf9e Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:22:27 -0400 Subject: [PATCH 064/146] Define sourceLines in terms of Data.Source.break. --- src/Data/Source.hs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 7889b3d54..483298a31 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -93,13 +93,12 @@ break predicate (Source text) = let (start, remainder) = B.break predicate text -- | Split the contents of the source after newlines. sourceLines :: Source -> [Source] -sourceLines = fmap Source . sourceLines' . sourceBytes - where sourceLines' text - | B.null text = [ text ] - | otherwise = case B.break (== toEnum (fromEnum '\n')) text of - (l, lines') -> case B.uncons lines' of - Nothing -> [ l ] - Just (_, lines') -> (l <> B.singleton (toEnum (fromEnum '\n'))) : sourceLines' lines' +sourceLines source + | nullSource source = [ source ] + | otherwise = case break (== toEnum (fromEnum '\n')) source of + (line, rest) + | nullSource rest -> [ line ] + | otherwise -> (line <> "\n") : sourceLines (drop 1 rest) -- | Compute the 'Range's of each line in a 'Source'. sourceLineRanges :: Source -> [Range] From ed1533f7fcc19d710e703545e130cc05cce0986f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:26:08 -0400 Subject: [PATCH 065/146] Rename Data.Source.{drop,take,break} to disambiguate. --- src/Alignment.hs | 2 +- src/Data/Source.hs | 31 +++++++++++++++---------------- src/Data/Syntax/Assignment.hs | 4 ++-- src/Renderer/Patch.hs | 2 +- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/Alignment.hs b/src/Alignment.hs index 7f0b81e99..105f740f6 100644 --- a/src/Alignment.hs +++ b/src/Alignment.hs @@ -15,7 +15,7 @@ import Data.Functor.Both import Data.List (partition) import Data.Maybe (fromJust) import Data.Range -import Data.Source hiding (drop) +import Data.Source import Data.Record import Data.These import Diff diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 483298a31..38a6e9725 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -11,7 +11,7 @@ module Data.Source , toText -- Slicing , slice -, drop +, dropSource -- Splitting , sourceLines , sourceLineRanges @@ -30,8 +30,7 @@ import Data.Range import Data.Span import Data.String (IsString(..)) import qualified Data.Text as T -import Prologue hiding (break, drop, take) -import qualified Prologue +import Prologue import Test.LeanCheck -- | The contents of a source file, represented as a ByteString. @@ -72,42 +71,42 @@ toText = decodeUtf8 . sourceBytes -- | Return a 'Source' that contains a slice of the given 'Source'. slice :: Range -> Source -> Source slice range = take . drop - where drop = Data.Source.drop (start range) - take = Data.Source.take (rangeLength range) + where drop = dropSource (start range) + take = takeSource (rangeLength range) -drop :: Int -> Source -> Source -drop i = Source . drop . sourceBytes +dropSource :: Int -> Source -> Source +dropSource i = Source . drop . sourceBytes where drop = B.drop i -take :: Int -> Source -> Source -take i = Source . take . sourceBytes +takeSource :: Int -> Source -> Source +takeSource i = Source . take . sourceBytes where take = B.take i -- Splitting -- | Split the source into the longest prefix of elements that do not satisfy the predicate and the rest without copying. -break :: (Word8 -> Bool) -> Source -> (Source, Source) -break predicate (Source text) = let (start, remainder) = B.break predicate text in (Source start, Source remainder) +breakSource :: (Word8 -> Bool) -> Source -> (Source, Source) +breakSource predicate (Source text) = let (start, remainder) = B.break predicate text in (Source start, Source remainder) -- | Split the contents of the source after newlines. sourceLines :: Source -> [Source] sourceLines source | nullSource source = [ source ] - | otherwise = case break (== toEnum (fromEnum '\n')) source of + | otherwise = case breakSource (== toEnum (fromEnum '\n')) source of (line, rest) | nullSource rest -> [ line ] - | otherwise -> (line <> "\n") : sourceLines (drop 1 rest) + | otherwise -> (line <> "\n") : sourceLines (dropSource 1 rest) -- | Compute the 'Range's of each line in a 'Source'. sourceLineRanges :: Source -> [Range] -sourceLineRanges = Prologue.drop 1 . scanl toRange (Range 0 0) . sourceLines +sourceLineRanges = drop 1 . scanl toRange (Range 0 0) . sourceLines where toRange previous source = Range (end previous) $ end previous + sourceLength source -- | Compute the 'Range's of each line in a 'Range' of a 'Source'. sourceLineRangesWithin :: Range -> Source -> [Range] -sourceLineRangesWithin range = Prologue.drop 1 . scanl toRange (Range (start range) (start range)) . sourceLines . slice range +sourceLineRangesWithin range = drop 1 . scanl toRange (Range (start range) (start range)) . sourceLines . slice range where toRange previous source = Range (end previous) $ end previous + sourceLength source @@ -120,7 +119,7 @@ spanToRange source = spanToRangeInLineRanges (sourceLineRanges source) spanToRangeInLineRanges :: [Range] -> Span -> Range spanToRangeInLineRanges lineRanges Span{..} = Range start end where start = pred (sumLengths leadingRanges + posColumn spanStart) - end = start + sumLengths (Prologue.take (posLine spanEnd - posLine spanStart) remainingRanges) + (posColumn spanEnd - posColumn spanStart) + end = start + sumLengths (take (posLine spanEnd - posLine spanStart) remainingRanges) + (posColumn spanEnd - posColumn spanStart) (leadingRanges, remainingRanges) = splitAt (pred (posLine spanStart)) lineRanges sumLengths = sum . fmap rangeLength diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index ac6b102c7..d98e41fd4 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -95,7 +95,7 @@ import Data.Ix (inRange) import Data.List.NonEmpty (nonEmpty) import Data.Range (offsetRange) import Data.Record -import qualified Data.Source as Source (Source(..), drop, slice, sourceBytes, sourceLines) +import qualified Data.Source as Source (Source(..), dropSource, slice, sourceBytes, sourceLines) import GHC.Stack import qualified Info import Prologue hiding (Alt, get, Location, state) @@ -271,7 +271,7 @@ dropAnonymous toSymbol state = state { stateNodes = dropWhile ((`notElem` [Just advanceState :: Recursive ast => (forall x. Base ast x -> Record Location) -> AssignmentState ast -> AssignmentState ast advanceState toLocation state@AssignmentState{..} | node : rest <- stateNodes - , range :. span :. Nil <- toLocation (F.project node) = AssignmentState (Info.end range) (Info.spanEnd span) (Source.drop (Info.end range - stateOffset) stateSource) rest + , range :. span :. Nil <- toLocation (F.project node) = AssignmentState (Info.end range) (Info.spanEnd span) (Source.dropSource (Info.end range - stateOffset) stateSource) rest | otherwise = state -- | State kept while running 'Assignment's. diff --git a/src/Renderer/Patch.hs b/src/Renderer/Patch.hs index 32080836e..65d96948d 100644 --- a/src/Renderer/Patch.hs +++ b/src/Renderer/Patch.hs @@ -15,7 +15,7 @@ import Data.Functor.Both as Both import Data.List (span, unzip) import Data.Range import Data.Record -import Data.Source as Source hiding (drop) +import Data.Source import Data.These import Diff import Patch From b7ea75a9bd48d362ecbd969cf40034c50743d12f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:32:04 -0400 Subject: [PATCH 066/146] Define Source abstractly. --- src/Command/Files.hs | 2 +- src/Data/Source.hs | 7 ++++++- src/Data/Syntax/Assignment.hs | 4 ++-- test/Data/Syntax/Assignment/Spec.hs | 2 +- test/SourceSpec.hs | 2 +- test/SpecHelpers.hs | 2 +- 6 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Command/Files.hs b/src/Command/Files.hs index 74f2e5c7d..848efe380 100644 --- a/src/Command/Files.hs +++ b/src/Command/Files.hs @@ -25,7 +25,7 @@ import System.FilePath readFile :: FilePath -> Maybe Language -> IO Blob.Blob readFile path language = do raw <- (Just <$> B.readFile path) `catch` (const (pure Nothing) :: IOException -> IO (Maybe ByteString)) - pure $ fromMaybe (Blob.emptyBlob path) (Blob.sourceBlob path language . Source <$> raw) + pure $ fromMaybe (Blob.emptyBlob path) (Blob.sourceBlob path language . fromBytes <$> raw) -- | Return a language based on a FilePath's extension, or Nothing if extension is not found or not supported. languageForFilePath :: FilePath -> Maybe Language diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 38a6e9725..d28c7c778 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -1,6 +1,8 @@ {-# LANGUAGE GeneralizedNewtypeDeriving, MultiParamTypeClasses #-} module Data.Source -( Source(..) +( Source +, sourceBytes +, fromBytes -- Measurement , sourceLength , nullSource @@ -37,6 +39,9 @@ import Test.LeanCheck newtype Source = Source { sourceBytes :: B.ByteString } deriving (Eq, IsString, Show) +fromBytes :: ByteString -> Source +fromBytes = Source + -- Measurement diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index d98e41fd4..e68b6f536 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -95,7 +95,7 @@ import Data.Ix (inRange) import Data.List.NonEmpty (nonEmpty) import Data.Range (offsetRange) import Data.Record -import qualified Data.Source as Source (Source(..), dropSource, slice, sourceBytes, sourceLines) +import qualified Data.Source as Source (Source, dropSource, fromBytes, slice, sourceBytes, sourceLines) import GHC.Stack import qualified Info import Prologue hiding (Alt, get, Location, state) @@ -188,7 +188,7 @@ printError source error@Error{..} withSGRCode [SetColor Foreground Vivid Red] . putStrErr . (showString "error") . showString ": " . showExpectation error . showChar '\n' . showString (toS context) . (if isSuffixOf "\n" context then identity else showChar '\n') . showString (replicate (succ (Info.posColumn errorPos + lineNumberDigits)) ' ') $ "" withSGRCode [SetColor Foreground Vivid Green] . putStrErr . (showChar '^') . showChar '\n' . showString (prettyCallStack callStack) $ "" - where context = maybe "\n" (Source.sourceBytes . sconcat) (nonEmpty [ Source.Source (toS (showLineNumber i)) <> Source.Source ": " <> l | (i, l) <- zip [1..] (Source.sourceLines source), inRange (Info.posLine errorPos - 2, Info.posLine errorPos) i ]) + where context = maybe "\n" (Source.sourceBytes . sconcat) (nonEmpty [ Source.fromBytes (toS (showLineNumber i)) <> Source.fromBytes ": " <> l | (i, l) <- zip [1..] (Source.sourceLines source), inRange (Info.posLine errorPos - 2, Info.posLine errorPos) i ]) showLineNumber n = let s = show n in replicate (lineNumberDigits - length s) ' ' <> s lineNumberDigits = succ (floor (logBase 10 (fromIntegral (Info.posLine errorPos) :: Double))) putStrErr = hPutStr stderr diff --git a/test/Data/Syntax/Assignment/Spec.hs b/test/Data/Syntax/Assignment/Spec.hs index fdf393530..90e361c7b 100644 --- a/test/Data/Syntax/Assignment/Spec.hs +++ b/test/Data/Syntax/Assignment/Spec.hs @@ -24,7 +24,7 @@ spec = do let s = "colourless green ideas sleep furiously" w = words s (_, nodes) = foldl (\ (i, prev) word -> (i + B.length word + 1, prev <> [node Red i (i + B.length word) []])) (0, []) w in - resultValue (runAssignment headF (many red) (makeState (Source s) nodes)) `shouldBe` Just (Out <$> w, AssignmentState (B.length s) (Info.Pos 1 (succ (B.length s))) "" []) + resultValue (runAssignment headF (many red) (makeState (fromBytes s) nodes)) `shouldBe` Just (Out <$> w, AssignmentState (B.length s) (Info.Pos 1 (succ (B.length s))) "" []) it "matches one-or-more repetitions against one or more input nodes" $ resultValue (runAssignment headF (some red) (makeState "hello" [node Red 0 5 []])) `shouldBe` Just ([Out "hello"], AssignmentState 5 (Info.Pos 1 6) "" []) diff --git a/test/SourceSpec.hs b/test/SourceSpec.hs index 76509ab11..c6f9af89d 100644 --- a/test/SourceSpec.hs +++ b/test/SourceSpec.hs @@ -20,7 +20,7 @@ spec = parallel $ do describe "spanToRange" $ do prop "computes single-line ranges" . forAll (unListableByteString `mapT` tiers) $ - \ s -> let source = Source s + \ s -> let source = fromBytes s spans = zipWith (\ i Range {..} -> Span (Pos i 1) (Pos i (succ (end - start)))) [1..] ranges ranges = sourceLineRanges source in spanToRange source <$> spans `shouldBe` ranges diff --git a/test/SpecHelpers.hs b/test/SpecHelpers.hs index a2105e0fa..a36177eb0 100644 --- a/test/SpecHelpers.hs +++ b/test/SpecHelpers.hs @@ -41,7 +41,7 @@ parseFilePath path = do -- the filesystem or Git. The tests, however, will still leverage reading files. readFile :: FilePath -> IO Blob readFile path = do - source <- (Just . Source <$> B.readFile path) `catch` (const (pure Nothing) :: IOException -> IO (Maybe Source)) + source <- (Just . fromBytes <$> B.readFile path) `catch` (const (pure Nothing) :: IOException -> IO (Maybe Source)) pure $ fromMaybe (emptyBlob path) (sourceBlob path (languageForFilePath path) <$> source) -- | Returns a Maybe Language based on the FilePath's extension. From eaece7951a54d2b8b2eb57118d1f5176c3687073 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:35:13 -0400 Subject: [PATCH 067/146] Define sourceLineRanges in terms of sourceLineRangesWithin. --- src/Data/Source.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index d28c7c778..29589164b 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -106,8 +106,7 @@ sourceLines source -- | Compute the 'Range's of each line in a 'Source'. sourceLineRanges :: Source -> [Range] -sourceLineRanges = drop 1 . scanl toRange (Range 0 0) . sourceLines - where toRange previous source = Range (end previous) $ end previous + sourceLength source +sourceLineRanges source = sourceLineRangesWithin (totalRange source) source -- | Compute the 'Range's of each line in a 'Range' of a 'Source'. sourceLineRangesWithin :: Range -> Source -> [Range] From 3b1c2644f273b1216bc41a17bd3bde2652d3776a Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:47:38 -0400 Subject: [PATCH 068/146] Use ord to define sourceLines. --- src/Data/Source.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 29589164b..e8a9ea51e 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -27,6 +27,7 @@ module Data.Source ) where import qualified Data.ByteString as B +import Data.Char (ord) import Data.List (span) import Data.Range import Data.Span @@ -99,7 +100,7 @@ breakSource predicate (Source text) = let (start, remainder) = B.break predicate sourceLines :: Source -> [Source] sourceLines source | nullSource source = [ source ] - | otherwise = case breakSource (== toEnum (fromEnum '\n')) source of + | otherwise = case breakSource (== toEnum (ord '\n')) source of (line, rest) | nullSource rest -> [ line ] | otherwise -> (line <> "\n") : sourceLines (dropSource 1 rest) From 35baa874d5b68e4a53727a8a2ebd36ce739df5fe Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 11:58:17 -0400 Subject: [PATCH 069/146] Define sourceLineRangesWithin without constructing intermediate sources. --- src/Data/Source.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index e8a9ea51e..17e93581d 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -111,8 +111,7 @@ sourceLineRanges source = sourceLineRangesWithin (totalRange source) source -- | Compute the 'Range's of each line in a 'Range' of a 'Source'. sourceLineRangesWithin :: Range -> Source -> [Range] -sourceLineRangesWithin range = drop 1 . scanl toRange (Range (start range) (start range)) . sourceLines . slice range - where toRange previous source = Range (end previous) $ end previous + sourceLength source +sourceLineRangesWithin range = uncurry (zipWith Range) . ((start range:) &&& (<> [ end range ])) . fmap (+ succ (start range)) . B.elemIndices (toEnum (ord '\n')) . sourceBytes . slice range -- Conversion From b9143d40ea9319d511aa784e39d7d55148c778c3 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 12:02:27 -0400 Subject: [PATCH 070/146] Define sourceLines in terms of sourceLineRanges. --- src/Data/Source.hs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 17e93581d..be3c7671e 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -98,12 +98,7 @@ breakSource predicate (Source text) = let (start, remainder) = B.break predicate -- | Split the contents of the source after newlines. sourceLines :: Source -> [Source] -sourceLines source - | nullSource source = [ source ] - | otherwise = case breakSource (== toEnum (ord '\n')) source of - (line, rest) - | nullSource rest -> [ line ] - | otherwise -> (line <> "\n") : sourceLines (dropSource 1 rest) +sourceLines source = (`slice` source) <$> sourceLineRanges source -- | Compute the 'Range's of each line in a 'Source'. sourceLineRanges :: Source -> [Range] From 8e57a0b88bc0d251a085ab6c42d1dcf97f4bf863 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 12:02:38 -0400 Subject: [PATCH 071/146] :fire: breakSource. --- src/Data/Source.hs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index be3c7671e..7f3162f38 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -91,11 +91,6 @@ takeSource i = Source . take . sourceBytes -- Splitting --- | Split the source into the longest prefix of elements that do not satisfy the predicate and the rest without copying. -breakSource :: (Word8 -> Bool) -> Source -> (Source, Source) -breakSource predicate (Source text) = let (start, remainder) = B.break predicate text in (Source start, Source remainder) - - -- | Split the contents of the source after newlines. sourceLines :: Source -> [Source] sourceLines source = (`slice` source) <$> sourceLineRanges source From aed530b79b4e20c23a43ee0114676207f30c6fd4 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 12:03:27 -0400 Subject: [PATCH 072/146] Correct some misalignment. --- src/Data/Source.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 7f3162f38..bb5ffcae3 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -120,13 +120,13 @@ spanToRangeInLineRanges lineRanges Span{..} = Range start end -- | Compute the 'Span' corresponding to a given byte 'Range' in a 'Source'. rangeToSpan :: Source -> Range -> Span rangeToSpan source (Range rangeStart rangeEnd) = Span startPos endPos - where startPos = Pos (firstLine + 1) (rangeStart - start firstRange + 1) + where startPos = Pos (firstLine + 1) (rangeStart - start firstRange + 1) endPos = Pos (firstLine + length lineRanges) (rangeEnd - start lastRange + 1) firstLine = length before (before, rest) = span ((< rangeStart) . end) (sourceLineRanges source) (lineRanges, _) = span ((<= rangeEnd) . start) rest Just firstRange = getFirst (foldMap (First . Just) lineRanges) - Just lastRange = getLast (foldMap (Last . Just) lineRanges) + Just lastRange = getLast (foldMap (Last . Just) lineRanges) -- Instances From 8284540ba01adc894282c7baa7e7892df9e05249 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 12:10:37 -0400 Subject: [PATCH 073/146] Quote the reference to ByteString. --- src/Data/Source.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index bb5ffcae3..3c9e157a7 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -36,7 +36,7 @@ import qualified Data.Text as T import Prologue import Test.LeanCheck --- | The contents of a source file, represented as a ByteString. +-- | The contents of a source file, represented as a 'ByteString'. newtype Source = Source { sourceBytes :: B.ByteString } deriving (Eq, IsString, Show) From 6b3f35c04605c68e55c27de48cd51677712d2a13 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 12:32:43 -0400 Subject: [PATCH 074/146] Compute spanToRangeInLineRanges in constant time. --- src/Data/Source.hs | 18 +++++++++++------- src/Language/Markdown.hs | 2 +- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 3c9e157a7..38e318659 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -21,11 +21,13 @@ module Data.Source -- Conversion , spanToRange , spanToRangeInLineRanges +, sourceLineRangesByLineNumber , rangeToSpan -- Listable , ListableByteString(..) ) where +import Data.Array import qualified Data.ByteString as B import Data.Char (ord) import Data.List (span) @@ -108,14 +110,16 @@ sourceLineRangesWithin range = uncurry (zipWith Range) . ((start range:) &&& (<> -- | Compute the byte 'Range' corresponding to a given 'Span' in a 'Source'. spanToRange :: Source -> Span -> Range -spanToRange source = spanToRangeInLineRanges (sourceLineRanges source) +spanToRange source = spanToRangeInLineRanges (sourceLineRangesByLineNumber source) -spanToRangeInLineRanges :: [Range] -> Span -> Range -spanToRangeInLineRanges lineRanges Span{..} = Range start end - where start = pred (sumLengths leadingRanges + posColumn spanStart) - end = start + sumLengths (take (posLine spanEnd - posLine spanStart) remainingRanges) + (posColumn spanEnd - posColumn spanStart) - (leadingRanges, remainingRanges) = splitAt (pred (posLine spanStart)) lineRanges - sumLengths = sum . fmap rangeLength +spanToRangeInLineRanges :: Array Int Range -> Span -> Range +spanToRangeInLineRanges lineRanges Span{..} = Range + (start (lineRanges ! posLine spanStart) + pred (posColumn spanStart)) + (start (lineRanges ! posLine spanEnd) + pred (posColumn spanEnd)) + +sourceLineRangesByLineNumber :: Source -> Array Int Range +sourceLineRangesByLineNumber source = listArray (1, length lineRanges) lineRanges + where lineRanges = sourceLineRanges source -- | Compute the 'Span' corresponding to a given byte 'Range' in a 'Source'. rangeToSpan :: Source -> Range -> Span diff --git a/src/Language/Markdown.hs b/src/Language/Markdown.hs index 4e6d93788..a3bb79671 100644 --- a/src/Language/Markdown.hs +++ b/src/Language/Markdown.hs @@ -46,7 +46,7 @@ cmarkParser source = toTerm (totalRange source) (totalSpan source) $ commonmarkT toSpan PosInfo{..} = Span (Pos startLine startColumn) (Pos endLine (succ endColumn)) - lineRanges = sourceLineRanges source + lineRanges = sourceLineRangesByLineNumber source toGrammar :: NodeType -> Grammar toGrammar DOCUMENT{} = Document From af48c1d68455c048dc98c34e7961dee8236a4a9b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 12:44:00 -0400 Subject: [PATCH 075/146] Simplify the line by line parser. --- src/Parser.hs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Parser.hs b/src/Parser.hs index 624dbf93c..af48b0820 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -16,7 +16,6 @@ import Data.Record import Data.Source as Source import qualified Data.Syntax as Syntax import Data.Syntax.Assignment -import qualified Data.Text as T import Data.Union import Info hiding (Empty, Go) import Language @@ -105,12 +104,5 @@ termErrors = cata $ \ (_ :< s) -> case s of -- | A fallback parser that treats a file simply as rows of strings. lineByLineParser :: Source -> IO (SyntaxTerm Text DefaultFields) -lineByLineParser source = pure . cofree . root $ case foldl' annotateLeaves ([], 0) lines of - (leaves, _) -> cofree <$> leaves - where - lines = sourceLines source - root children = (sourceRange :. Program :. rangeToSpan source sourceRange :. Nil) :< Indexed children - sourceRange = totalRange source - leaf byteIndex line = (Range byteIndex (byteIndex + T.length line) :. Program :. rangeToSpan source (Range byteIndex (byteIndex + T.length line)) :. Nil) :< Leaf line - annotateLeaves (accum, byteIndex) line = - (accum <> [ leaf byteIndex (toText line) ] , byteIndex + sourceLength line) +lineByLineParser source = pure . cofree $ (totalRange source :. Program :. totalSpan source :. Nil) :< Indexed (zipWith toLine [1..] (sourceLineRanges source)) + where toLine line range = cofree $ (range :. Program :. Span (Pos line 1) (Pos line (end range)) :. Nil) :< Leaf (toText (slice range source)) From 1beabcdbdc4a76dd47fc6f211df8bd0ccdd13999 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 12:44:11 -0400 Subject: [PATCH 076/146] The line by line parser is pure. --- src/Parser.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Parser.hs b/src/Parser.hs index af48b0820..bee6db6b9 100644 --- a/src/Parser.hs +++ b/src/Parser.hs @@ -92,7 +92,7 @@ runParser parser = case parser of Nothing -> pure (errorTerm source err) TreeSitterParser language tslanguage -> treeSitterParser language tslanguage MarkdownParser -> pure . cmarkParser - LineByLineParser -> lineByLineParser + LineByLineParser -> pure . lineByLineParser errorTerm :: Syntax.Error (Error grammar) :< fs => Source -> Maybe (Error grammar) -> Term (Union fs) (Record Location) errorTerm source err = cofree ((totalRange source :. totalSpan source :. Nil) :< inj (Syntax.Error (fromMaybe (Error (Pos 0 0) (UnexpectedEndOfInput [])) err))) @@ -103,6 +103,6 @@ termErrors = cata $ \ (_ :< s) -> case s of _ -> fold s -- | A fallback parser that treats a file simply as rows of strings. -lineByLineParser :: Source -> IO (SyntaxTerm Text DefaultFields) -lineByLineParser source = pure . cofree $ (totalRange source :. Program :. totalSpan source :. Nil) :< Indexed (zipWith toLine [1..] (sourceLineRanges source)) +lineByLineParser :: Source -> SyntaxTerm Text DefaultFields +lineByLineParser source = cofree $ (totalRange source :. Program :. totalSpan source :. Nil) :< Indexed (zipWith toLine [1..] (sourceLineRanges source)) where toLine line range = cofree $ (range :. Program :. Span (Pos line 1) (Pos line (end range)) :. Nil) :< Leaf (toText (slice range source)) From 78b607ddbcf760c01e076e9a0b30599cb59c6add Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 14:22:31 -0400 Subject: [PATCH 077/146] :fire: redundant parens. --- src/Language/Markdown/Syntax.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Language/Markdown/Syntax.hs b/src/Language/Markdown/Syntax.hs index 16ba1df5e..e4da925b4 100644 --- a/src/Language/Markdown/Syntax.hs +++ b/src/Language/Markdown/Syntax.hs @@ -62,7 +62,7 @@ paragraph :: Assignment paragraph = makeTerm <$> symbol Paragraph <*> children (Markup.Paragraph <$> many inlineElement) list :: Assignment -list = (cofree .) . (:<) <$> symbol List <*> (project (\ (((CMark.LIST CMark.ListAttributes{..}) :. _) :< _) -> case listType of +list = (cofree .) . (:<) <$> symbol List <*> (project (\ ((CMark.LIST CMark.ListAttributes{..} :. _) :< _) -> case listType of CMark.BULLET_LIST -> inj . Markup.UnorderedList CMark.ORDERED_LIST -> inj . Markup.OrderedList) <*> children (many item)) @@ -81,7 +81,7 @@ blockQuote :: Assignment blockQuote = makeTerm <$> symbol BlockQuote <*> children (Markup.BlockQuote <$> many blockElement) codeBlock :: Assignment -codeBlock = makeTerm <$> symbol CodeBlock <*> (Markup.Code <$> project (\ (((CMark.CODE_BLOCK language _) :. _) :< _) -> nullText language) <*> source) +codeBlock = makeTerm <$> symbol CodeBlock <*> (Markup.Code <$> project (\ ((CMark.CODE_BLOCK language _ :. _) :< _) -> nullText language) <*> source) thematicBreak :: Assignment thematicBreak = makeTerm <$> symbol ThematicBreak <*> (Markup.ThematicBreak <$ source) @@ -105,10 +105,10 @@ text :: Assignment text = makeTerm <$> symbol Text <*> (Markup.Text <$> source) link :: Assignment -link = makeTerm <$> symbol Link <*> (uncurry Markup.Link <$> project (\ (((CMark.LINK url title) :. _) :< _) -> (toS url, nullText title))) <* source +link = makeTerm <$> symbol Link <*> (uncurry Markup.Link <$> project (\ ((CMark.LINK url title :. _) :< _) -> (toS url, nullText title))) <* source image :: Assignment -image = makeTerm <$> symbol Image <*> (uncurry Markup.Image <$> project (\ (((CMark.IMAGE url title) :. _) :< _) -> (toS url, nullText title))) <* source +image = makeTerm <$> symbol Image <*> (uncurry Markup.Image <$> project (\ ((CMark.IMAGE url title :. _) :< _) -> (toS url, nullText title))) <* source code :: Assignment code = makeTerm <$> symbol Code <*> (Markup.Code Nothing <$> source) From a182406b6b57da6f19a4719aae1a700baf8358af Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 14:25:43 -0400 Subject: [PATCH 078/146] Fewer parens. --- src/Language/Markdown/Syntax.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Language/Markdown/Syntax.hs b/src/Language/Markdown/Syntax.hs index e4da925b4..f6bed6da6 100644 --- a/src/Language/Markdown/Syntax.hs +++ b/src/Language/Markdown/Syntax.hs @@ -84,7 +84,7 @@ codeBlock :: Assignment codeBlock = makeTerm <$> symbol CodeBlock <*> (Markup.Code <$> project (\ ((CMark.CODE_BLOCK language _ :. _) :< _) -> nullText language) <*> source) thematicBreak :: Assignment -thematicBreak = makeTerm <$> symbol ThematicBreak <*> (Markup.ThematicBreak <$ source) +thematicBreak = makeTerm <$> symbol ThematicBreak <*> pure Markup.ThematicBreak <* source htmlBlock :: Assignment htmlBlock = makeTerm <$> symbol HTMLBlock <*> (Markup.HTMLBlock <$> source) @@ -114,10 +114,10 @@ code :: Assignment code = makeTerm <$> symbol Code <*> (Markup.Code Nothing <$> source) lineBreak :: Assignment -lineBreak = makeTerm <$> symbol LineBreak <*> (Markup.LineBreak <$ source) +lineBreak = makeTerm <$> symbol LineBreak <*> pure Markup.LineBreak <* source softBreak :: Assignment -softBreak = makeTerm <$> symbol SoftBreak <*> (Markup.LineBreak <$ source) +softBreak = makeTerm <$> symbol SoftBreak <*> pure Markup.LineBreak <* source -- Implementation details From 854e4fbcc2ccec8eba44f8eb26d5fd2c66891d30 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 14:28:31 -0400 Subject: [PATCH 079/146] Change how some comments are listed. --- src/Data/Syntax/Assignment.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index e68b6f536..f06c5f010 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -128,13 +128,13 @@ location = Location `Then` return -- | Zero-width projection of the current node. -- --- Since this is zero-width, care must be taken not to repeat it without chaining on other rules. I.e. 'many (project f *> b)' is fine, but 'many (project f)' is not. +-- Since this is zero-width, care must be taken not to repeat it without chaining on other rules. I.e. @many (project f *> b)@ is fine, but @many (project f)@ is not. project :: HasCallStack => (forall x. Base ast x -> a) -> Assignment ast grammar a project projection = Project projection `Then` return -- | Zero-width match of a node with the given symbol, producing the current node’s location. -- --- Since this is zero-width, care must be taken not to repeat it without chaining on other rules. I.e. 'many (symbol A *> b)' is fine, but 'many (symbol A)' is not. +-- Since this is zero-width, care must be taken not to repeat it without chaining on other rules. I.e. @many (symbol A *> b)@ is fine, but @many (symbol A)@ is not. symbol :: (Enum grammar, Eq grammar, HasCallStack) => grammar -> Assignment ast grammar (Record Location) symbol s = withFrozenCallStack $ Choose (IntMap.singleton (fromEnum s) ()) `Then` (const location) @@ -248,7 +248,7 @@ runAssignment toRecord = iterFreer run . fmap ((pure .) . (,)) Result _ (Just (a, state')) -> yield a (advanceState (rtail . toRecord) state' { stateNodes = stateNodes }) Result err Nothing -> Result err Nothing (Choose choices, node : _) | Just symbol :. _ <- toRecord (F.project node), Just a <- IntMap.lookup (fromEnum symbol) choices -> yield a state - -- Nullability: some rules, e.g. 'pure a' and 'many a', should match at the end of input. Either side of an alternation may be nullable, ergo Alt can match at the end of input. + -- Nullability: some rules, e.g. @pure a@ and @many a@, should match at the end of input. Either side of an alternation may be nullable, ergo Alt can match at the end of input. (Alt a b, _) -> yield a state <|> yield b state (Throw e, _) -> Result (Just e) Nothing (Catch during handler, _) -> case yield during state of From 04bde799fd91b24cd90f81d32411426ba24638a7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 14:33:10 -0400 Subject: [PATCH 080/146] Eta-reduce. --- src/Data/Syntax/Assignment.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index f06c5f010..4bda68646 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -284,7 +284,7 @@ data AssignmentState ast = AssignmentState deriving (Eq, Show) makeState :: Source.Source -> [ast] -> AssignmentState ast -makeState source nodes = AssignmentState 0 (Info.Pos 1 1) source nodes +makeState = AssignmentState 0 (Info.Pos 1 1) -- Instances From 81b8ab22b9551963c10c631d628bb13098c76d8c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 14:36:41 -0400 Subject: [PATCH 081/146] :fire: some redundant parens. --- src/Data/Syntax/Assignment.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 4bda68646..8140deffa 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -184,9 +184,9 @@ data ErrorCause grammar printError :: Show grammar => Source.Source -> Error grammar -> IO () printError source error@Error{..} = do - withSGRCode [SetConsoleIntensity BoldIntensity] . putStrErr . (showPos Nothing errorPos) . showString ": " $ "" - withSGRCode [SetColor Foreground Vivid Red] . putStrErr . (showString "error") . showString ": " . showExpectation error . showChar '\n' . showString (toS context) . (if isSuffixOf "\n" context then identity else showChar '\n') . showString (replicate (succ (Info.posColumn errorPos + lineNumberDigits)) ' ') $ "" - withSGRCode [SetColor Foreground Vivid Green] . putStrErr . (showChar '^') . showChar '\n' . showString (prettyCallStack callStack) $ "" + withSGRCode [SetConsoleIntensity BoldIntensity] . putStrErr . showPos Nothing errorPos . showString ": " $ "" + withSGRCode [SetColor Foreground Vivid Red] . putStrErr . showString "error" . showString ": " . showExpectation error . showChar '\n' . showString (toS context) . (if isSuffixOf "\n" context then identity else showChar '\n') . showString (replicate (succ (Info.posColumn errorPos + lineNumberDigits)) ' ') $ "" + withSGRCode [SetColor Foreground Vivid Green] . putStrErr . showChar '^' . showChar '\n' . showString (prettyCallStack callStack) $ "" where context = maybe "\n" (Source.sourceBytes . sconcat) (nonEmpty [ Source.fromBytes (toS (showLineNumber i)) <> Source.fromBytes ": " <> l | (i, l) <- zip [1..] (Source.sourceLines source), inRange (Info.posLine errorPos - 2, Info.posLine errorPos) i ]) showLineNumber n = let s = show n in replicate (lineNumberDigits - length s) ' ' <> s From 7d7e41221e1cf74acef3ffc5aba396150db78536 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 14:37:34 -0400 Subject: [PATCH 082/146] Reformat a little. --- src/Data/Syntax/Assignment.hs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 8140deffa..c970b8fcc 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -182,12 +182,10 @@ data ErrorCause grammar -- | Pretty-print an Error with reference to the source where it occurred. printError :: Show grammar => Source.Source -> Error grammar -> IO () -printError source error@Error{..} - = do - withSGRCode [SetConsoleIntensity BoldIntensity] . putStrErr . showPos Nothing errorPos . showString ": " $ "" - withSGRCode [SetColor Foreground Vivid Red] . putStrErr . showString "error" . showString ": " . showExpectation error . showChar '\n' . showString (toS context) . (if isSuffixOf "\n" context then identity else showChar '\n') . showString (replicate (succ (Info.posColumn errorPos + lineNumberDigits)) ' ') $ "" - withSGRCode [SetColor Foreground Vivid Green] . putStrErr . showChar '^' . showChar '\n' . showString (prettyCallStack callStack) $ "" - +printError source error@Error{..} = do + withSGRCode [SetConsoleIntensity BoldIntensity] . putStrErr . showPos Nothing errorPos . showString ": " $ "" + withSGRCode [SetColor Foreground Vivid Red] . putStrErr . showString "error" . showString ": " . showExpectation error . showChar '\n' . showString (toS context) . (if isSuffixOf "\n" context then identity else showChar '\n') . showString (replicate (succ (Info.posColumn errorPos + lineNumberDigits)) ' ') $ "" + withSGRCode [SetColor Foreground Vivid Green] . putStrErr . showChar '^' . showChar '\n' . showString (prettyCallStack callStack) $ "" where context = maybe "\n" (Source.sourceBytes . sconcat) (nonEmpty [ Source.fromBytes (toS (showLineNumber i)) <> Source.fromBytes ": " <> l | (i, l) <- zip [1..] (Source.sourceLines source), inRange (Info.posLine errorPos - 2, Info.posLine errorPos) i ]) showLineNumber n = let s = show n in replicate (lineNumberDigits - length s) ' ' <> s lineNumberDigits = succ (floor (logBase 10 (fromIntegral (Info.posLine errorPos) :: Double))) From 3278506866f3c49631f11ff5e694f4a6dd1a0f14 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 14:59:00 -0400 Subject: [PATCH 083/146] Simplify how images and links are projected. --- src/Language/Markdown/Syntax.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Language/Markdown/Syntax.hs b/src/Language/Markdown/Syntax.hs index f6bed6da6..fd6999ec5 100644 --- a/src/Language/Markdown/Syntax.hs +++ b/src/Language/Markdown/Syntax.hs @@ -105,10 +105,10 @@ text :: Assignment text = makeTerm <$> symbol Text <*> (Markup.Text <$> source) link :: Assignment -link = makeTerm <$> symbol Link <*> (uncurry Markup.Link <$> project (\ ((CMark.LINK url title :. _) :< _) -> (toS url, nullText title))) <* source +link = makeTerm <$> symbol Link <*> project (\ ((CMark.LINK url title :. _) :< _) -> Markup.Link (toS url) (nullText title)) <* source image :: Assignment -image = makeTerm <$> symbol Image <*> (uncurry Markup.Image <$> project (\ ((CMark.IMAGE url title :. _) :< _) -> (toS url, nullText title))) <* source +image = makeTerm <$> symbol Image <*> project (\ ((CMark.IMAGE url title :. _) :< _) -> Markup.Image (toS url) (nullText title)) <* source code :: Assignment code = makeTerm <$> symbol Code <*> (Markup.Code Nothing <$> source) From d44684cd4e80bfb2be7d7b1ad38efbeada7e5696 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 15:01:00 -0400 Subject: [PATCH 084/146] Simplify how sections and code blocks are projected. --- src/Language/Markdown/Syntax.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Language/Markdown/Syntax.hs b/src/Language/Markdown/Syntax.hs index fd6999ec5..e4d788691 100644 --- a/src/Language/Markdown/Syntax.hs +++ b/src/Language/Markdown/Syntax.hs @@ -71,7 +71,7 @@ item = makeTerm <$> symbol Item <*> children (many blockElement) section :: Assignment section = makeTerm <$> symbol Heading <*> (heading >>= \ headingTerm -> Markup.Section headingTerm <$> while (((<) `on` level) headingTerm) blockElement) - where heading = makeTerm <$> symbol Heading <*> (Markup.Heading <$> project (\ ((CMark.HEADING level :. _) :< _) -> level) <*> children (many inlineElement)) + where heading = makeTerm <$> symbol Heading <*> (project (\ ((CMark.HEADING level :. _) :< _) -> Markup.Heading level) <*> children (many inlineElement)) level term = case term of _ | Just section <- prj (unwrap term) -> level (Markup.sectionHeading section) _ | Just heading <- prj (unwrap term) -> Markup.headingLevel heading @@ -81,7 +81,7 @@ blockQuote :: Assignment blockQuote = makeTerm <$> symbol BlockQuote <*> children (Markup.BlockQuote <$> many blockElement) codeBlock :: Assignment -codeBlock = makeTerm <$> symbol CodeBlock <*> (Markup.Code <$> project (\ ((CMark.CODE_BLOCK language _ :. _) :< _) -> nullText language) <*> source) +codeBlock = makeTerm <$> symbol CodeBlock <*> (project (\ ((CMark.CODE_BLOCK language _ :. _) :< _) -> Markup.Code (nullText language)) <*> source) thematicBreak :: Assignment thematicBreak = makeTerm <$> symbol ThematicBreak <*> pure Markup.ThematicBreak <* source From 5d75659c6e251ecb788e1bc211604a830ec9bc3c Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 15:22:58 -0400 Subject: [PATCH 085/146] Define spanToRange tacitly. --- src/Data/Source.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Source.hs b/src/Data/Source.hs index 38e318659..5f036b37e 100644 --- a/src/Data/Source.hs +++ b/src/Data/Source.hs @@ -110,7 +110,7 @@ sourceLineRangesWithin range = uncurry (zipWith Range) . ((start range:) &&& (<> -- | Compute the byte 'Range' corresponding to a given 'Span' in a 'Source'. spanToRange :: Source -> Span -> Range -spanToRange source = spanToRangeInLineRanges (sourceLineRangesByLineNumber source) +spanToRange = spanToRangeInLineRanges . sourceLineRangesByLineNumber spanToRangeInLineRanges :: Array Int Range -> Span -> Range spanToRangeInLineRanges lineRanges Span{..} = Range From f2b6cdb223ce8f52d5e5dc213f35b08865ae30db Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 15:46:07 -0400 Subject: [PATCH 086/146] Deal with nonsensical end lines. --- src/Language/Markdown.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Markdown.hs b/src/Language/Markdown.hs index a3bb79671..3e196bf4e 100644 --- a/src/Language/Markdown.hs +++ b/src/Language/Markdown.hs @@ -44,7 +44,7 @@ cmarkParser source = toTerm (totalRange source) (totalSpan source) $ commonmarkT span = maybe withinSpan toSpan position in cofree $ (t :. range :. span :. Nil) :< (toTerm range span <$> children) - toSpan PosInfo{..} = Span (Pos startLine startColumn) (Pos endLine (succ endColumn)) + toSpan PosInfo{..} = Span (Pos startLine startColumn) (Pos (max startLine endLine) (succ endColumn)) lineRanges = sourceLineRangesByLineNumber source From 4a00ee3e23f1523d7118f89c5e46e75ebf0f2875 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 15:55:51 -0400 Subject: [PATCH 087/146] Make sure the end column makes sense. --- src/Language/Markdown.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Markdown.hs b/src/Language/Markdown.hs index 3e196bf4e..aa74f29b3 100644 --- a/src/Language/Markdown.hs +++ b/src/Language/Markdown.hs @@ -44,7 +44,7 @@ cmarkParser source = toTerm (totalRange source) (totalSpan source) $ commonmarkT span = maybe withinSpan toSpan position in cofree $ (t :. range :. span :. Nil) :< (toTerm range span <$> children) - toSpan PosInfo{..} = Span (Pos startLine startColumn) (Pos (max startLine endLine) (succ endColumn)) + toSpan PosInfo{..} = Span (Pos startLine startColumn) (Pos (max startLine endLine) (succ (if endLine <= startLine then max startColumn endColumn else endColumn))) lineRanges = sourceLineRangesByLineNumber source From 1bbb252738eb0a288ff41fa710bb2c0735d5e6f8 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 16:44:00 -0400 Subject: [PATCH 088/146] Return is the left-identity of alternation. --- src/Data/Syntax/Assignment.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index c970b8fcc..0e07f89e9 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -292,6 +292,7 @@ instance Enum grammar => Alternative (Assignment ast grammar) where empty = Empty `Then` return (<|>) :: HasCallStack => Assignment ast grammar a -> Assignment ast grammar a -> Assignment ast grammar a a <|> b = case (a, b) of + (Return a, _) -> pure a (_, Empty `Then` _) -> a (Empty `Then` _, _) -> b (Choose choices1 `Then` continue1, Choose choices2 `Then` continue2) -> Choose (IntMap.union (fmap continue1 choices1) (fmap continue2 choices2)) `Then` identity From 7df59da28117a65cd654554a6cf972a84e47eb62 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 16:51:00 -0400 Subject: [PATCH 089/146] Frame the <|> rule in terms of the choices along each side. --- src/Data/Syntax/Assignment.hs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 0e07f89e9..30085b5a6 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -291,12 +291,12 @@ instance Enum grammar => Alternative (Assignment ast grammar) where empty :: HasCallStack => Assignment ast grammar a empty = Empty `Then` return (<|>) :: HasCallStack => Assignment ast grammar a -> Assignment ast grammar a -> Assignment ast grammar a - a <|> b = case (a, b) of - (Return a, _) -> pure a - (_, Empty `Then` _) -> a - (Empty `Then` _, _) -> b - (Choose choices1 `Then` continue1, Choose choices2 `Then` continue2) -> Choose (IntMap.union (fmap continue1 choices1) (fmap continue2 choices2)) `Then` identity - _ -> wrap $ Alt a b + Return a <|> _ = Return a + a <|> b | Just c <- (liftA2 (<>) `on` choices) a b = Choose c `Then` identity + | otherwise = wrap $ Alt a b + where choices (Choose choices `Then` continue) = Just (continue <$> choices) + choices (Empty `Then` _) = Just mempty + choices _ = Nothing instance Show grammar => Show1 (AssignmentF ast grammar) where liftShowsPrec sp sl d a = case a of From eaa4423decedd57953f4b3373944f50ca1be43f5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 17:10:04 -0400 Subject: [PATCH 090/146] Define a Many rule. --- src/Data/Syntax/Assignment.hs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 30085b5a6..9bd68f899 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -115,6 +115,7 @@ data AssignmentF ast grammar a where Source :: HasCallStack => AssignmentF ast grammar ByteString Children :: HasCallStack => Assignment ast grammar a -> AssignmentF ast grammar a Choose :: HasCallStack => IntMap.IntMap a -> AssignmentF ast grammar a + Many :: HasCallStack => Assignment ast grammar a -> AssignmentF ast grammar [a] Alt :: HasCallStack => a -> a -> AssignmentF ast grammar a Empty :: HasCallStack => AssignmentF ast grammar a Throw :: HasCallStack => Error grammar -> AssignmentF ast grammar a @@ -246,6 +247,8 @@ runAssignment toRecord = iterFreer run . fmap ((pure .) . (,)) Result _ (Just (a, state')) -> yield a (advanceState (rtail . toRecord) state' { stateNodes = stateNodes }) Result err Nothing -> Result err Nothing (Choose choices, node : _) | Just symbol :. _ <- toRecord (F.project node), Just a <- IntMap.lookup (fromEnum symbol) choices -> yield a state + (Many _, []) -> yield [] state + (Many rule, _) -> uncurry yield (runMany rule state) -- Nullability: some rules, e.g. @pure a@ and @many a@, should match at the end of input. Either side of an alternation may be nullable, ergo Alt can match at the end of input. (Alt a b, _) -> yield a state <|> yield b state (Throw e, _) -> Result (Just e) Nothing @@ -261,6 +264,10 @@ runAssignment toRecord = iterFreer run . fmap ((pure .) . (,)) Choose choices -> choiceSymbols choices _ -> [] choiceSymbols choices = (toEnum :: Int -> grammar) <$> IntMap.keys choices + runMany :: Assignment ast grammar v -> AssignmentState ast -> ([v], AssignmentState ast) + runMany rule state = case runAssignment toRecord rule state of + Result _ (Just (a, state')) -> first (a :) (runMany rule state') + _ -> ([], state) dropAnonymous :: (Symbol grammar, Recursive ast) => (forall x. Base ast x -> Maybe grammar) -> AssignmentState ast -> AssignmentState ast dropAnonymous toSymbol state = state { stateNodes = dropWhile ((`notElem` [Just Regular, Nothing]) . fmap symbolType . toSymbol . F.project) (stateNodes state) } @@ -297,6 +304,8 @@ instance Enum grammar => Alternative (Assignment ast grammar) where where choices (Choose choices `Then` continue) = Just (continue <$> choices) choices (Empty `Then` _) = Just mempty choices _ = Nothing + many :: HasCallStack => Assignment ast grammar a -> Assignment ast grammar [a] + many a = Many a `Then` return instance Show grammar => Show1 (AssignmentF ast grammar) where liftShowsPrec sp sl d a = case a of @@ -305,6 +314,7 @@ instance Show grammar => Show1 (AssignmentF ast grammar) where Source -> showString "Source" . showChar ' ' . sp d "" Children a -> showsUnaryWith (liftShowsPrec sp sl) "Children" d a Choose choices -> showsUnaryWith (liftShowsPrec (liftShowsPrec sp sl) (liftShowList sp sl)) "Choose" d (IntMap.toList choices) + Many a -> showsUnaryWith (liftShowsPrec (\ d a -> sp d [a]) (sl . pure)) "Many" d a Alt a b -> showsBinaryWith sp sp "Alt" d a b Empty -> showString "Empty" Throw e -> showsUnaryWith showsPrec "Throw" d e From 2be307e967dc0da38f386f9bc2f4ea51f5475ad7 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 17:16:57 -0400 Subject: [PATCH 091/146] `many` participates in committed choice. --- src/Data/Syntax/Assignment.hs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 9bd68f899..a84d59570 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -301,8 +301,10 @@ instance Enum grammar => Alternative (Assignment ast grammar) where Return a <|> _ = Return a a <|> b | Just c <- (liftA2 (<>) `on` choices) a b = Choose c `Then` identity | otherwise = wrap $ Alt a b - where choices (Choose choices `Then` continue) = Just (continue <$> choices) + where choices :: Assignment ast grammar a -> Maybe (IntMap (Assignment ast grammar a)) + choices (Choose choices `Then` continue) = Just (continue <$> choices) choices (Empty `Then` _) = Just mempty + choices (Many rule `Then` continue) = fmap (const (Many rule `Then` continue)) <$> choices rule choices _ = Nothing many :: HasCallStack => Assignment ast grammar a -> Assignment ast grammar [a] many a = Many a `Then` return From 8b79e0e05656e70c6bfc105a6990e1110366fc9d Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 17:30:41 -0400 Subject: [PATCH 092/146] :fire: redundant imports. --- test/CommandSpec.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/CommandSpec.hs b/test/CommandSpec.hs index 32cefffed..7922a547b 100644 --- a/test/CommandSpec.hs +++ b/test/CommandSpec.hs @@ -4,7 +4,6 @@ import Command import Data.Blob import Data.Functor.Both as Both import Data.Maybe -import Data.Source import Data.String import Language import Prologue hiding (readFile, toList) From 0f9ccec7de98a5536cd6a870cc5eac99a8fbc684 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 17:30:57 -0400 Subject: [PATCH 093/146] :fire: redundant hidden symbols. --- test/Data/Syntax/Assignment/Spec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Data/Syntax/Assignment/Spec.hs b/test/Data/Syntax/Assignment/Spec.hs index 90e361c7b..78b6a00d7 100644 --- a/test/Data/Syntax/Assignment/Spec.hs +++ b/test/Data/Syntax/Assignment/Spec.hs @@ -3,7 +3,7 @@ module Data.Syntax.Assignment.Spec where import Data.ByteString.Char8 as B (words, length) import Data.Record -import Data.Source hiding (source, length) +import Data.Source import Data.Syntax.Assignment import Info import Prologue From fe29a865c3060daec2159246a82b50cc2b1ac21f Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 17:30:57 -0400 Subject: [PATCH 094/146] :fire: redundant hidden symbols. --- test/Data/Syntax/Assignment/Spec.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Data/Syntax/Assignment/Spec.hs b/test/Data/Syntax/Assignment/Spec.hs index 90e361c7b..78b6a00d7 100644 --- a/test/Data/Syntax/Assignment/Spec.hs +++ b/test/Data/Syntax/Assignment/Spec.hs @@ -3,7 +3,7 @@ module Data.Syntax.Assignment.Spec where import Data.ByteString.Char8 as B (words, length) import Data.Record -import Data.Source hiding (source, length) +import Data.Source import Data.Syntax.Assignment import Info import Prologue From 2fe08397ee5550c2008656371fe49dac18115d61 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Sat, 24 Jun 2017 17:30:41 -0400 Subject: [PATCH 095/146] :fire: redundant imports. --- test/CommandSpec.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/test/CommandSpec.hs b/test/CommandSpec.hs index 32cefffed..7922a547b 100644 --- a/test/CommandSpec.hs +++ b/test/CommandSpec.hs @@ -4,7 +4,6 @@ import Command import Data.Blob import Data.Functor.Both as Both import Data.Maybe -import Data.Source import Data.String import Language import Prologue hiding (readFile, toList) From 10e81996fa91763257f753b132a55d0de1b6c530 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 26 Jun 2017 10:03:08 -0400 Subject: [PATCH 096/146] :fire: Empty. --- src/Data/Syntax/Assignment.hs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index a84d59570..e0c7fc1ab 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -117,7 +117,6 @@ data AssignmentF ast grammar a where Choose :: HasCallStack => IntMap.IntMap a -> AssignmentF ast grammar a Many :: HasCallStack => Assignment ast grammar a -> AssignmentF ast grammar [a] Alt :: HasCallStack => a -> a -> AssignmentF ast grammar a - Empty :: HasCallStack => AssignmentF ast grammar a Throw :: HasCallStack => Error grammar -> AssignmentF ast grammar a Catch :: HasCallStack => a -> (Error grammar -> a) -> AssignmentF ast grammar a @@ -296,14 +295,13 @@ makeState = AssignmentState 0 (Info.Pos 1 1) instance Enum grammar => Alternative (Assignment ast grammar) where empty :: HasCallStack => Assignment ast grammar a - empty = Empty `Then` return + empty = Choose mempty `Then` return (<|>) :: HasCallStack => Assignment ast grammar a -> Assignment ast grammar a -> Assignment ast grammar a Return a <|> _ = Return a a <|> b | Just c <- (liftA2 (<>) `on` choices) a b = Choose c `Then` identity | otherwise = wrap $ Alt a b where choices :: Assignment ast grammar a -> Maybe (IntMap (Assignment ast grammar a)) choices (Choose choices `Then` continue) = Just (continue <$> choices) - choices (Empty `Then` _) = Just mempty choices (Many rule `Then` continue) = fmap (const (Many rule `Then` continue)) <$> choices rule choices _ = Nothing many :: HasCallStack => Assignment ast grammar a -> Assignment ast grammar [a] @@ -318,7 +316,6 @@ instance Show grammar => Show1 (AssignmentF ast grammar) where Choose choices -> showsUnaryWith (liftShowsPrec (liftShowsPrec sp sl) (liftShowList sp sl)) "Choose" d (IntMap.toList choices) Many a -> showsUnaryWith (liftShowsPrec (\ d a -> sp d [a]) (sl . pure)) "Many" d a Alt a b -> showsBinaryWith sp sp "Alt" d a b - Empty -> showString "Empty" Throw e -> showsUnaryWith showsPrec "Throw" d e Catch during handler -> showsBinaryWith sp (const (const (showChar '_'))) "Catch" d during handler From 89ec9e11c04591548cf7048824b5cf6a2375db93 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 26 Jun 2017 11:44:08 -0400 Subject: [PATCH 097/146] Avoid slicing down the source when advancing through the state. --- src/Data/Syntax/Assignment.hs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index e0c7fc1ab..32c84dc4c 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -93,9 +93,8 @@ import Data.Functor.Foldable as F hiding (Nil) import qualified Data.IntMap.Lazy as IntMap import Data.Ix (inRange) import Data.List.NonEmpty (nonEmpty) -import Data.Range (offsetRange) import Data.Record -import qualified Data.Source as Source (Source, dropSource, fromBytes, slice, sourceBytes, sourceLines) +import qualified Data.Source as Source (Source, fromBytes, slice, sourceBytes, sourceLines) import GHC.Stack import qualified Info import Prologue hiding (Alt, get, Location, state) @@ -241,7 +240,7 @@ runAssignment toRecord = iterFreer run . fmap ((pure .) . (,)) (Location, node : _) -> yield (rtail (toRecord (F.project node))) state (Location, []) -> yield (Info.Range stateOffset stateOffset :. Info.Span statePos statePos :. Nil) state (Project projection, node : _) -> yield (projection (F.project node)) state - (Source, node : _) -> yield (Source.sourceBytes (Source.slice (offsetRange (Info.byteRange (toRecord (F.project node))) (negate stateOffset)) stateSource)) (advanceState (rtail . toRecord) state) + (Source, node : _) -> yield (Source.sourceBytes (Source.slice (Info.byteRange (toRecord (F.project node))) stateSource)) (advanceState (rtail . toRecord) state) (Children childAssignment, node : _) -> case assignAllFrom toRecord childAssignment state { stateNodes = toList (F.project node) } of Result _ (Just (a, state')) -> yield a (advanceState (rtail . toRecord) state' { stateNodes = stateNodes }) Result err Nothing -> Result err Nothing @@ -275,7 +274,7 @@ dropAnonymous toSymbol state = state { stateNodes = dropWhile ((`notElem` [Just advanceState :: Recursive ast => (forall x. Base ast x -> Record Location) -> AssignmentState ast -> AssignmentState ast advanceState toLocation state@AssignmentState{..} | node : rest <- stateNodes - , range :. span :. Nil <- toLocation (F.project node) = AssignmentState (Info.end range) (Info.spanEnd span) (Source.dropSource (Info.end range - stateOffset) stateSource) rest + , range :. span :. Nil <- toLocation (F.project node) = AssignmentState (Info.end range) (Info.spanEnd span) stateSource rest | otherwise = state -- | State kept while running 'Assignment's. From af3038fc1f05ca14602295a5bc1c567f8101e320 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 26 Jun 2017 11:44:20 -0400 Subject: [PATCH 098/146] Evaluate the spine of the list strictly. --- src/Data/Syntax/Assignment.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index 32c84dc4c..b7d156ff5 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -264,7 +264,7 @@ runAssignment toRecord = iterFreer run . fmap ((pure .) . (,)) choiceSymbols choices = (toEnum :: Int -> grammar) <$> IntMap.keys choices runMany :: Assignment ast grammar v -> AssignmentState ast -> ([v], AssignmentState ast) runMany rule state = case runAssignment toRecord rule state of - Result _ (Just (a, state')) -> first (a :) (runMany rule state') + Result _ (Just (a, state')) -> let (as, state'') = runMany rule state' in as `seq` (a : as, state'') _ -> ([], state) dropAnonymous :: (Symbol grammar, Recursive ast) => (forall x. Base ast x -> Maybe grammar) -> AssignmentState ast -> AssignmentState ast From 006dac8f6880fadfae7a3d28c85ba48e6295ea2b Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 26 Jun 2017 12:12:46 -0400 Subject: [PATCH 099/146] Inline `run`. --- src/Data/Syntax/Assignment.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Data/Syntax/Assignment.hs b/src/Data/Syntax/Assignment.hs index b7d156ff5..3b9617791 100644 --- a/src/Data/Syntax/Assignment.hs +++ b/src/Data/Syntax/Assignment.hs @@ -266,6 +266,7 @@ runAssignment toRecord = iterFreer run . fmap ((pure .) . (,)) runMany rule state = case runAssignment toRecord rule state of Result _ (Just (a, state')) -> let (as, state'') = runMany rule state' in as `seq` (a : as, state'') _ -> ([], state) + {-# INLINE run #-} dropAnonymous :: (Symbol grammar, Recursive ast) => (forall x. Base ast x -> Maybe grammar) -> AssignmentState ast -> AssignmentState ast dropAnonymous toSymbol state = state { stateNodes = dropWhile ((`notElem` [Just Regular, Nothing]) . fmap symbolType . toSymbol . F.project) (stateNodes state) } From 5c44267e275966fed138a06e816a4e4d8a9138e5 Mon Sep 17 00:00:00 2001 From: Rob Rix Date: Mon, 26 Jun 2017 12:56:56 -0400 Subject: [PATCH 100/146] Fix the specs. --- test/Data/Syntax/Assignment/Spec.hs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/Data/Syntax/Assignment/Spec.hs b/test/Data/Syntax/Assignment/Spec.hs index 78b6a00d7..fc986cf0f 100644 --- a/test/Data/Syntax/Assignment/Spec.hs +++ b/test/Data/Syntax/Assignment/Spec.hs @@ -14,20 +14,20 @@ spec :: Spec spec = do describe "Applicative" $ it "matches in sequence" $ - runAssignment headF ((,) <$> red <*> red) (makeState "helloworld" [node Red 0 5 [], node Red 5 10 []]) `shouldBe` Result Nothing (Just ((Out "hello", Out "world"), AssignmentState 10 (Info.Pos 1 11) "" [])) + runAssignment headF ((,) <$> red <*> red) (makeState "helloworld" [node Red 0 5 [], node Red 5 10 []]) `shouldBe` Result Nothing (Just ((Out "hello", Out "world"), AssignmentState 10 (Info.Pos 1 11) "helloworld" [])) describe "Alternative" $ do it "attempts multiple alternatives" $ - runAssignment headF (green <|> red) (makeState "hello" [node Red 0 5 []]) `shouldBe` Result Nothing (Just (Out "hello", AssignmentState 5 (Info.Pos 1 6) "" [])) + runAssignment headF (green <|> red) (makeState "hello" [node Red 0 5 []]) `shouldBe` Result Nothing (Just (Out "hello", AssignmentState 5 (Info.Pos 1 6) "hello" [])) it "matches repetitions" $ let s = "colourless green ideas sleep furiously" w = words s (_, nodes) = foldl (\ (i, prev) word -> (i + B.length word + 1, prev <> [node Red i (i + B.length word) []])) (0, []) w in - resultValue (runAssignment headF (many red) (makeState (fromBytes s) nodes)) `shouldBe` Just (Out <$> w, AssignmentState (B.length s) (Info.Pos 1 (succ (B.length s))) "" []) + resultValue (runAssignment headF (many red) (makeState (fromBytes s) nodes)) `shouldBe` Just (Out <$> w, AssignmentState (B.length s) (Info.Pos 1 (succ (B.length s))) (fromBytes s) []) it "matches one-or-more repetitions against one or more input nodes" $ - resultValue (runAssignment headF (some red) (makeState "hello" [node Red 0 5 []])) `shouldBe` Just ([Out "hello"], AssignmentState 5 (Info.Pos 1 6) "" []) + resultValue (runAssignment headF (some red) (makeState "hello" [node Red 0 5 []])) `shouldBe` Just ([Out "hello"], AssignmentState 5 (Info.Pos 1 6) "hello" []) describe "symbol" $ do it "matches nodes with the same symbol" $ @@ -42,11 +42,11 @@ spec = do assignBy headF source "hi" (node Red 0 2 []) `shouldBe` Result Nothing (Just "hi") it "advances past the current node" $ - snd <$> runAssignment headF source (makeState "hi" [ node Red 0 2 [] ]) `shouldBe` Result Nothing (Just (AssignmentState 2 (Info.Pos 1 3) "" [])) + snd <$> runAssignment headF source (makeState "hi" [ node Red 0 2 [] ]) `shouldBe` Result Nothing (Just (AssignmentState 2 (Info.Pos 1 3) "hi" [])) describe "children" $ do it "advances past the current node" $ - snd <$> runAssignment headF (children (pure (Out ""))) (makeState "a" [node Red 0 1 []]) `shouldBe` Result Nothing (Just (AssignmentState 1 (Info.Pos 1 2) "" [])) + snd <$> runAssignment headF (children (pure (Out ""))) (makeState "a" [node Red 0 1 []]) `shouldBe` Result Nothing (Just (AssignmentState 1 (Info.Pos 1 2) "a" [])) it "matches if its subrule matches" $ () <$ runAssignment headF (children red) (makeState "a" [node Blue 0 1 [node Red 0 1 []]]) `shouldBe` Result Nothing (Just ()) @@ -59,7 +59,7 @@ spec = do (symbol Red *> children (symbol Green *> children (symbol Blue *> source))) (makeState "1" [ node Red 0 1 [ node Green 0 1 [ node Blue 0 1 [] ] ] ]) `shouldBe` - Result Nothing (Just ("1", AssignmentState 1 (Info.Pos 1 2) "" [])) + Result Nothing (Just ("1", AssignmentState 1 (Info.Pos 1 2) "1" [])) it "continues after children" $ resultValue (runAssignment headF @@ -68,7 +68,7 @@ spec = do (makeState "BC" [ node Red 0 1 [ node Green 0 1 [] ] , node Blue 1 2 [] ])) `shouldBe` - Just (["B", "C"], AssignmentState 2 (Info.Pos 1 3) "" []) + Just (["B", "C"], AssignmentState 2 (Info.Pos 1 3) "BC" []) it "matches multiple nested children" $ runAssignment headF @@ -76,17 +76,17 @@ spec = do (makeState "12" [ node Red 0 2 [ node Green 0 1 [ node Blue 0 1 [] ] , node Green 1 2 [ node Blue 1 2 [] ] ] ]) `shouldBe` - Result Nothing (Just (["1", "2"], AssignmentState 2 (Info.Pos 1 3) "" [])) + Result Nothing (Just (["1", "2"], AssignmentState 2 (Info.Pos 1 3) "12" [])) describe "runAssignment" $ do it "drops anonymous nodes before matching symbols" $ - runAssignment headF red (makeState "magenta red" [node Magenta 0 7 [], node Red 8 11 []]) `shouldBe` Result Nothing (Just (Out "red", AssignmentState 11 (Info.Pos 1 12) "" [])) + runAssignment headF red (makeState "magenta red" [node Magenta 0 7 [], node Red 8 11 []]) `shouldBe` Result Nothing (Just (Out "red", AssignmentState 11 (Info.Pos 1 12) "magenta red" [])) it "does not drop anonymous nodes after matching" $ - runAssignment headF red (makeState "red magenta" [node Red 0 3 [], node Magenta 4 11 []]) `shouldBe` Result Nothing (Just (Out "red", AssignmentState 3 (Info.Pos 1 4) " magenta" [node Magenta 4 11 []])) + runAssignment headF red (makeState "red magenta" [node Red 0 3 [], node Magenta 4 11 []]) `shouldBe` Result Nothing (Just (Out "red", AssignmentState 3 (Info.Pos 1 4) "red magenta" [node Magenta 4 11 []])) it "does not drop anonymous nodes when requested" $ - runAssignment headF ((,) <$> magenta <*> red) (makeState "magenta red" [node Magenta 0 7 [], node Red 8 11 []]) `shouldBe` Result Nothing (Just ((Out "magenta", Out "red"), AssignmentState 11 (Info.Pos 1 12) "" [])) + runAssignment headF ((,) <$> magenta <*> red) (makeState "magenta red" [node Magenta 0 7 [], node Red 8 11 []]) `shouldBe` Result Nothing (Just ((Out "magenta", Out "red"), AssignmentState 11 (Info.Pos 1 12) "magenta red" [])) node :: symbol -> Int -> Int -> [AST symbol] -> AST symbol node symbol start end children = cofree $ (Just symbol :. Range start end :. Info.Span (Info.Pos 1 (succ start)) (Info.Pos 1 (succ end)) :. Nil) :< children From cf381ab701a04958bd72ec372a4fa778f94dfa0c Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 26 Jun 2017 16:10:00 -0700 Subject: [PATCH 101/146] Bump typescript --- languages/typescript/vendor/tree-sitter-typescript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/typescript/vendor/tree-sitter-typescript b/languages/typescript/vendor/tree-sitter-typescript index 8a6082ee4..3afca1145 160000 --- a/languages/typescript/vendor/tree-sitter-typescript +++ b/languages/typescript/vendor/tree-sitter-typescript @@ -1 +1 @@ -Subproject commit 8a6082ee4acc58abb9760a3367318977bde84e0a +Subproject commit 3afca11458848f88587707a05af369d5badf5558 From 32a22a2a5c7a67e45f6314a766758e2a9d1100b4 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 26 Jun 2017 16:58:39 -0700 Subject: [PATCH 102/146] Update integration tests for javascript and typescript --- .../javascript/boolean-operator.diffA-B.txt | 3 +- .../javascript/boolean-operator.diffB-A.txt | 3 +- .../javascript/constructor-call.diff+A.txt | 4 +- .../javascript/constructor-call.diff+B.txt | 4 +- .../javascript/constructor-call.diff-A.txt | 4 +- .../javascript/constructor-call.diff-B.txt | 4 +- .../javascript/constructor-call.diffA-B.txt | 4 +- .../javascript/constructor-call.diffB-A.txt | 4 +- .../javascript/constructor-call.parseA.txt | 4 +- .../javascript/constructor-call.parseB.txt | 4 +- .../javascript/delete-operator.diffA-B.txt | 6 +-- .../javascript/delete-operator.diffB-A.txt | 6 +-- test/fixtures/javascript/export.diffA-B.txt | 54 +++++++++---------- test/fixtures/javascript/export.diffB-A.txt | 18 +++---- test/fixtures/javascript/if.diffA-B.txt | 11 ++-- test/fixtures/javascript/if.diffB-A.txt | 11 ++-- .../relational-operator.diffA-B.txt | 3 +- .../relational-operator.diffB-A.txt | 3 +- .../javascript/type-operator.diffA-B.txt | 8 +-- .../javascript/type-operator.diffB-A.txt | 8 +-- .../ambient-declarations.diff+A.txt | 4 +- .../ambient-declarations.diff+B.txt | 4 +- .../ambient-declarations.diff-A.txt | 4 +- .../ambient-declarations.diff-B.txt | 4 +- .../ambient-declarations.diffA-B.txt | 4 +- .../ambient-declarations.diffB-A.txt | 4 +- .../ambient-declarations.parseA.txt | 4 +- .../ambient-declarations.parseB.txt | 4 +- .../typescript/constructor-call.diff+A.txt | 4 +- .../typescript/constructor-call.diff+B.txt | 4 +- .../typescript/constructor-call.diff-A.txt | 4 +- .../typescript/constructor-call.diff-B.txt | 4 +- .../typescript/constructor-call.diffA-B.txt | 4 +- .../typescript/constructor-call.diffB-A.txt | 4 +- .../typescript/constructor-call.parseA.txt | 4 +- .../typescript/constructor-call.parseB.txt | 4 +- test/fixtures/typescript/export.diffA-B.txt | 54 +++++++++---------- test/fixtures/typescript/export.diffB-A.txt | 18 +++---- test/fixtures/typescript/interface.diff+A.txt | 2 +- test/fixtures/typescript/interface.diff+B.txt | 2 +- test/fixtures/typescript/interface.diff-A.txt | 2 +- test/fixtures/typescript/interface.diff-B.txt | 2 +- .../fixtures/typescript/interface.diffA-B.txt | 2 +- .../fixtures/typescript/interface.diffB-A.txt | 2 +- test/fixtures/typescript/interface.parseA.txt | 2 +- test/fixtures/typescript/interface.parseB.txt | 2 +- .../typescript/method-definition.diff+B.txt | 1 + .../typescript/method-definition.diff-B.txt | 1 + .../typescript/method-definition.diffA-B.txt | 1 + .../typescript/method-definition.diffB-A.txt | 1 + .../typescript/method-definition.parseB.txt | 1 + 51 files changed, 171 insertions(+), 152 deletions(-) diff --git a/test/fixtures/javascript/boolean-operator.diffA-B.txt b/test/fixtures/javascript/boolean-operator.diffA-B.txt index 78868446c..b28c3bba9 100644 --- a/test/fixtures/javascript/boolean-operator.diffA-B.txt +++ b/test/fixtures/javascript/boolean-operator.diffA-B.txt @@ -2,5 +2,6 @@ (ExpressionStatements (BooleanOperator (Identifier) - { (Other "||") -> (Other "&&") } + { (Other "||") + ->(Other "&&") } (Identifier)))) diff --git a/test/fixtures/javascript/boolean-operator.diffB-A.txt b/test/fixtures/javascript/boolean-operator.diffB-A.txt index f8d9a25a9..2779c18e2 100644 --- a/test/fixtures/javascript/boolean-operator.diffB-A.txt +++ b/test/fixtures/javascript/boolean-operator.diffB-A.txt @@ -2,5 +2,6 @@ (ExpressionStatements (BooleanOperator (Identifier) - { (Other "&&") -> (Other "||") } + { (Other "&&") + ->(Other "||") } (Identifier)))) diff --git a/test/fixtures/javascript/constructor-call.diff+A.txt b/test/fixtures/javascript/constructor-call.diff+A.txt index d92216c44..57882ffe4 100644 --- a/test/fixtures/javascript/constructor-call.diff+A.txt +++ b/test/fixtures/javascript/constructor-call.diff+A.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral)))))+} diff --git a/test/fixtures/javascript/constructor-call.diff+B.txt b/test/fixtures/javascript/constructor-call.diff+B.txt index d92216c44..57882ffe4 100644 --- a/test/fixtures/javascript/constructor-call.diff+B.txt +++ b/test/fixtures/javascript/constructor-call.diff+B.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral)))))+} diff --git a/test/fixtures/javascript/constructor-call.diff-A.txt b/test/fixtures/javascript/constructor-call.diff-A.txt index 5e2573b4c..ece591c60 100644 --- a/test/fixtures/javascript/constructor-call.diff-A.txt +++ b/test/fixtures/javascript/constructor-call.diff-A.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral)))))-} diff --git a/test/fixtures/javascript/constructor-call.diff-B.txt b/test/fixtures/javascript/constructor-call.diff-B.txt index 5e2573b4c..ece591c60 100644 --- a/test/fixtures/javascript/constructor-call.diff-B.txt +++ b/test/fixtures/javascript/constructor-call.diff-B.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral)))))-} diff --git a/test/fixtures/javascript/constructor-call.diffA-B.txt b/test/fixtures/javascript/constructor-call.diffA-B.txt index 653e57bb7..f1de77fef 100644 --- a/test/fixtures/javascript/constructor-call.diffA-B.txt +++ b/test/fixtures/javascript/constructor-call.diffA-B.txt @@ -2,8 +2,8 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) { (StringLiteral) ->(StringLiteral) })))) diff --git a/test/fixtures/javascript/constructor-call.diffB-A.txt b/test/fixtures/javascript/constructor-call.diffB-A.txt index 653e57bb7..f1de77fef 100644 --- a/test/fixtures/javascript/constructor-call.diffB-A.txt +++ b/test/fixtures/javascript/constructor-call.diffB-A.txt @@ -2,8 +2,8 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) { (StringLiteral) ->(StringLiteral) })))) diff --git a/test/fixtures/javascript/constructor-call.parseA.txt b/test/fixtures/javascript/constructor-call.parseA.txt index d09bd1e9e..fa44af92b 100644 --- a/test/fixtures/javascript/constructor-call.parseA.txt +++ b/test/fixtures/javascript/constructor-call.parseA.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral))))) diff --git a/test/fixtures/javascript/constructor-call.parseB.txt b/test/fixtures/javascript/constructor-call.parseB.txt index d09bd1e9e..fa44af92b 100644 --- a/test/fixtures/javascript/constructor-call.parseB.txt +++ b/test/fixtures/javascript/constructor-call.parseB.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral))))) diff --git a/test/fixtures/javascript/delete-operator.diffA-B.txt b/test/fixtures/javascript/delete-operator.diffA-B.txt index 25c33123f..1e6d91079 100644 --- a/test/fixtures/javascript/delete-operator.diffA-B.txt +++ b/test/fixtures/javascript/delete-operator.diffA-B.txt @@ -2,11 +2,9 @@ (ExpressionStatements (Operator (Other "delete") - { - (SubscriptAccess + { (SubscriptAccess (Identifier) (StringLiteral)) - -> - (MemberAccess + ->(MemberAccess (Identifier) (Identifier)) }))) diff --git a/test/fixtures/javascript/delete-operator.diffB-A.txt b/test/fixtures/javascript/delete-operator.diffB-A.txt index e202c9976..1ba7f50a6 100644 --- a/test/fixtures/javascript/delete-operator.diffB-A.txt +++ b/test/fixtures/javascript/delete-operator.diffB-A.txt @@ -2,11 +2,9 @@ (ExpressionStatements (Operator (Other "delete") - { - (MemberAccess + { (MemberAccess (Identifier) (Identifier)) - -> - (SubscriptAccess + ->(SubscriptAccess (Identifier) (StringLiteral)) }))) diff --git a/test/fixtures/javascript/export.diffA-B.txt b/test/fixtures/javascript/export.diffA-B.txt index 1ae760377..cc64cdb54 100644 --- a/test/fixtures/javascript/export.diffA-B.txt +++ b/test/fixtures/javascript/export.diffA-B.txt @@ -13,49 +13,49 @@ { (Identifier) ->(Identifier) })) (Export - (Other "export_specifier" - { (Identifier) - ->(Identifier)} - { (Identifier) - ->(Identifier)}) - (Other "export_specifier" - { (Identifier) - ->(Identifier)} - { (Identifier) - ->(Identifier)}) - (Other "export_specifier" - { (Identifier) - ->(Identifier)})) -(Export + (Other "export_specifier" + { (Identifier) + ->(Identifier) } + { (Identifier) + ->(Identifier) }) + (Other "export_specifier" + { (Identifier) + ->(Identifier) } + { (Identifier) + ->(Identifier) }) + (Other "export_specifier" + { (Identifier) + ->(Identifier) })) + (Export (VarDecl { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarDecl { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarDecl { (Identifier) - ->(Identifier)})) -(Export + ->(Identifier) })) + (Export (VarAssignment { (Identifier) - ->(Identifier)} + ->(Identifier) } { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarAssignment { (Identifier) - ->(Identifier)} + ->(Identifier) } { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarDecl { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarDecl { (Identifier) - ->(Identifier)})) -(Export -{ (Identifier) -->(Identifier)}) + ->(Identifier) })) + (Export + { (Identifier) + ->(Identifier) }) {+(Export (Function (Identifier) diff --git a/test/fixtures/javascript/export.diffB-A.txt b/test/fixtures/javascript/export.diffB-A.txt index 4f82be907..19e5bd579 100644 --- a/test/fixtures/javascript/export.diffB-A.txt +++ b/test/fixtures/javascript/export.diffB-A.txt @@ -64,16 +64,16 @@ (Function (Params))) (Export - {+(Function - (Identifier) - (Params))+} - {-(Other "export_specifier" - (Identifier) - (Identifier))-}) - {+(Export + {+(Function + (Identifier) + (Params))+} + {-(Other "export_specifier" + (Identifier) + (Identifier))-}) +{+(Export (Other "export_specifier" - (Identifier) - (Identifier)))+} + (Identifier) + (Identifier)))+} (Export { (StringLiteral) ->(StringLiteral) }) diff --git a/test/fixtures/javascript/if.diffA-B.txt b/test/fixtures/javascript/if.diffA-B.txt index 48ae65bd9..309bccd7f 100644 --- a/test/fixtures/javascript/if.diffA-B.txt +++ b/test/fixtures/javascript/if.diffA-B.txt @@ -1,9 +1,14 @@ (Program (If - { (Identifier) -> (MemberAccess (Identifier) (Identifier)) } + { (Identifier) + ->(MemberAccess + (Identifier) + (Identifier)) } (ExpressionStatements (ExpressionStatements (FunctionCall (Identifier) - { (Identifier) -> (Identifier) })) - { +(ExpressionStatements (Identifier))+ }))) + { (Identifier) + ->(Identifier) })) + {+(ExpressionStatements + (Identifier))+}))) diff --git a/test/fixtures/javascript/if.diffB-A.txt b/test/fixtures/javascript/if.diffB-A.txt index 39dc44434..84c98f6c5 100644 --- a/test/fixtures/javascript/if.diffB-A.txt +++ b/test/fixtures/javascript/if.diffB-A.txt @@ -1,9 +1,14 @@ (Program (If - { (MemberAccess (Identifier) (Identifier)) -> (Identifier) } + { (MemberAccess + (Identifier) + (Identifier)) + ->(Identifier) } (ExpressionStatements (ExpressionStatements (FunctionCall (Identifier) - { (Identifier) -> (Identifier) })) - { -(ExpressionStatements (Identifier))- }))) + { (Identifier) + ->(Identifier) })) + {-(ExpressionStatements + (Identifier))-}))) diff --git a/test/fixtures/javascript/relational-operator.diffA-B.txt b/test/fixtures/javascript/relational-operator.diffA-B.txt index 2e2f7cef5..e2e3822e6 100644 --- a/test/fixtures/javascript/relational-operator.diffA-B.txt +++ b/test/fixtures/javascript/relational-operator.diffA-B.txt @@ -2,5 +2,6 @@ (ExpressionStatements (RelationalOperator (Identifier) - { (Other "<") -> (Other "<=") } + { (Other "<") + ->(Other "<=") } (Identifier)))) diff --git a/test/fixtures/javascript/relational-operator.diffB-A.txt b/test/fixtures/javascript/relational-operator.diffB-A.txt index 66188264a..a378295ee 100644 --- a/test/fixtures/javascript/relational-operator.diffB-A.txt +++ b/test/fixtures/javascript/relational-operator.diffB-A.txt @@ -2,5 +2,6 @@ (ExpressionStatements (RelationalOperator (Identifier) - { (Other "<=") -> (Other "<") } + { (Other "<=") + ->(Other "<") } (Identifier)))) diff --git a/test/fixtures/javascript/type-operator.diffA-B.txt b/test/fixtures/javascript/type-operator.diffA-B.txt index d8380c3d4..1e252481b 100644 --- a/test/fixtures/javascript/type-operator.diffA-B.txt +++ b/test/fixtures/javascript/type-operator.diffA-B.txt @@ -1,6 +1,8 @@ (Program (ExpressionStatements (Operator - { (Other "typeof") -> (Identifier) } - { (Identifier) -> (Other "instanceof") } - { +(Identifier)+ }))) + { (Other "typeof") + ->(Identifier) } + { (Identifier) + ->(Other "instanceof") } + {+(Identifier)+}))) diff --git a/test/fixtures/javascript/type-operator.diffB-A.txt b/test/fixtures/javascript/type-operator.diffB-A.txt index 180011f7e..afd50a3b8 100644 --- a/test/fixtures/javascript/type-operator.diffB-A.txt +++ b/test/fixtures/javascript/type-operator.diffB-A.txt @@ -1,6 +1,8 @@ (Program (ExpressionStatements (Operator - { (Identifier) -> (Other "typeof") } - { (Other "instanceof") -> (Identifier) } - { -(Identifier)- }))) + { (Identifier) + ->(Other "typeof") } + { (Other "instanceof") + ->(Identifier) } + {-(Identifier)-}))) diff --git a/test/fixtures/typescript/ambient-declarations.diff+A.txt b/test/fixtures/typescript/ambient-declarations.diff+A.txt index c06516d10..d20ef2266 100644 --- a/test/fixtures/typescript/ambient-declarations.diff+A.txt +++ b/test/fixtures/typescript/ambient-declarations.diff+A.txt @@ -65,7 +65,7 @@ (Other "ambient_declaration" (Class (Identifier) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params @@ -77,7 +77,7 @@ (Identifier) (Ty (Other "predefined_type"))) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params) diff --git a/test/fixtures/typescript/ambient-declarations.diff+B.txt b/test/fixtures/typescript/ambient-declarations.diff+B.txt index 16f039032..ce4696918 100644 --- a/test/fixtures/typescript/ambient-declarations.diff+B.txt +++ b/test/fixtures/typescript/ambient-declarations.diff+B.txt @@ -11,7 +11,7 @@ (Other "ambient_declaration" (Class (Identifier) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params @@ -23,7 +23,7 @@ (Identifier) (Ty (Other "predefined_type"))) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params) diff --git a/test/fixtures/typescript/ambient-declarations.diff-A.txt b/test/fixtures/typescript/ambient-declarations.diff-A.txt index 8f181a651..3da629909 100644 --- a/test/fixtures/typescript/ambient-declarations.diff-A.txt +++ b/test/fixtures/typescript/ambient-declarations.diff-A.txt @@ -65,7 +65,7 @@ (Other "ambient_declaration" (Class (Identifier) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params @@ -77,7 +77,7 @@ (Identifier) (Ty (Other "predefined_type"))) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params) diff --git a/test/fixtures/typescript/ambient-declarations.diff-B.txt b/test/fixtures/typescript/ambient-declarations.diff-B.txt index e3f5d6b86..fa9e710f6 100644 --- a/test/fixtures/typescript/ambient-declarations.diff-B.txt +++ b/test/fixtures/typescript/ambient-declarations.diff-B.txt @@ -11,7 +11,7 @@ (Other "ambient_declaration" (Class (Identifier) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params @@ -23,7 +23,7 @@ (Identifier) (Ty (Other "predefined_type"))) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params) diff --git a/test/fixtures/typescript/ambient-declarations.diffA-B.txt b/test/fixtures/typescript/ambient-declarations.diffA-B.txt index 86a4e1f8f..59b600a05 100644 --- a/test/fixtures/typescript/ambient-declarations.diffA-B.txt +++ b/test/fixtures/typescript/ambient-declarations.diffA-B.txt @@ -72,7 +72,7 @@ (Other "ambient_declaration" (Class (Identifier) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params @@ -84,7 +84,7 @@ (Identifier) (Ty (Other "predefined_type"))) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params) diff --git a/test/fixtures/typescript/ambient-declarations.diffB-A.txt b/test/fixtures/typescript/ambient-declarations.diffB-A.txt index 2aa4d247d..cb306c9d3 100644 --- a/test/fixtures/typescript/ambient-declarations.diffB-A.txt +++ b/test/fixtures/typescript/ambient-declarations.diffB-A.txt @@ -74,7 +74,7 @@ (Other "ambient_declaration" (Class (Identifier) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params @@ -86,7 +86,7 @@ (Identifier) (Ty (Other "predefined_type"))) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params) diff --git a/test/fixtures/typescript/ambient-declarations.parseA.txt b/test/fixtures/typescript/ambient-declarations.parseA.txt index aaac7b6b1..c247a7e53 100644 --- a/test/fixtures/typescript/ambient-declarations.parseA.txt +++ b/test/fixtures/typescript/ambient-declarations.parseA.txt @@ -65,7 +65,7 @@ (Other "ambient_declaration" (Class (Identifier) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params @@ -77,7 +77,7 @@ (Identifier) (Ty (Other "predefined_type"))) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params) diff --git a/test/fixtures/typescript/ambient-declarations.parseB.txt b/test/fixtures/typescript/ambient-declarations.parseB.txt index d39522612..ae6650ac6 100644 --- a/test/fixtures/typescript/ambient-declarations.parseB.txt +++ b/test/fixtures/typescript/ambient-declarations.parseB.txt @@ -11,7 +11,7 @@ (Other "ambient_declaration" (Class (Identifier) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params @@ -23,7 +23,7 @@ (Identifier) (Ty (Other "predefined_type"))) - (Other "ambient_method_declaration" + (Method (Identifier) (Other "call_signature" (Params) diff --git a/test/fixtures/typescript/constructor-call.diff+A.txt b/test/fixtures/typescript/constructor-call.diff+A.txt index d92216c44..57882ffe4 100644 --- a/test/fixtures/typescript/constructor-call.diff+A.txt +++ b/test/fixtures/typescript/constructor-call.diff+A.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral)))))+} diff --git a/test/fixtures/typescript/constructor-call.diff+B.txt b/test/fixtures/typescript/constructor-call.diff+B.txt index d92216c44..57882ffe4 100644 --- a/test/fixtures/typescript/constructor-call.diff+B.txt +++ b/test/fixtures/typescript/constructor-call.diff+B.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral)))))+} diff --git a/test/fixtures/typescript/constructor-call.diff-A.txt b/test/fixtures/typescript/constructor-call.diff-A.txt index 5e2573b4c..ece591c60 100644 --- a/test/fixtures/typescript/constructor-call.diff-A.txt +++ b/test/fixtures/typescript/constructor-call.diff-A.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral)))))-} diff --git a/test/fixtures/typescript/constructor-call.diff-B.txt b/test/fixtures/typescript/constructor-call.diff-B.txt index 5e2573b4c..ece591c60 100644 --- a/test/fixtures/typescript/constructor-call.diff-B.txt +++ b/test/fixtures/typescript/constructor-call.diff-B.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral)))))-} diff --git a/test/fixtures/typescript/constructor-call.diffA-B.txt b/test/fixtures/typescript/constructor-call.diffA-B.txt index 653e57bb7..f1de77fef 100644 --- a/test/fixtures/typescript/constructor-call.diffA-B.txt +++ b/test/fixtures/typescript/constructor-call.diffA-B.txt @@ -2,8 +2,8 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) { (StringLiteral) ->(StringLiteral) })))) diff --git a/test/fixtures/typescript/constructor-call.diffB-A.txt b/test/fixtures/typescript/constructor-call.diffB-A.txt index 653e57bb7..f1de77fef 100644 --- a/test/fixtures/typescript/constructor-call.diffB-A.txt +++ b/test/fixtures/typescript/constructor-call.diffB-A.txt @@ -2,8 +2,8 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) { (StringLiteral) ->(StringLiteral) })))) diff --git a/test/fixtures/typescript/constructor-call.parseA.txt b/test/fixtures/typescript/constructor-call.parseA.txt index d09bd1e9e..fa44af92b 100644 --- a/test/fixtures/typescript/constructor-call.parseA.txt +++ b/test/fixtures/typescript/constructor-call.parseA.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral))))) diff --git a/test/fixtures/typescript/constructor-call.parseB.txt b/test/fixtures/typescript/constructor-call.parseB.txt index d09bd1e9e..fa44af92b 100644 --- a/test/fixtures/typescript/constructor-call.parseB.txt +++ b/test/fixtures/typescript/constructor-call.parseB.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (Identifier) - (Identifier) + (MemberAccess + (Identifier)) (NumberLiteral) (StringLiteral))))) diff --git a/test/fixtures/typescript/export.diffA-B.txt b/test/fixtures/typescript/export.diffA-B.txt index 1ae760377..cc64cdb54 100644 --- a/test/fixtures/typescript/export.diffA-B.txt +++ b/test/fixtures/typescript/export.diffA-B.txt @@ -13,49 +13,49 @@ { (Identifier) ->(Identifier) })) (Export - (Other "export_specifier" - { (Identifier) - ->(Identifier)} - { (Identifier) - ->(Identifier)}) - (Other "export_specifier" - { (Identifier) - ->(Identifier)} - { (Identifier) - ->(Identifier)}) - (Other "export_specifier" - { (Identifier) - ->(Identifier)})) -(Export + (Other "export_specifier" + { (Identifier) + ->(Identifier) } + { (Identifier) + ->(Identifier) }) + (Other "export_specifier" + { (Identifier) + ->(Identifier) } + { (Identifier) + ->(Identifier) }) + (Other "export_specifier" + { (Identifier) + ->(Identifier) })) + (Export (VarDecl { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarDecl { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarDecl { (Identifier) - ->(Identifier)})) -(Export + ->(Identifier) })) + (Export (VarAssignment { (Identifier) - ->(Identifier)} + ->(Identifier) } { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarAssignment { (Identifier) - ->(Identifier)} + ->(Identifier) } { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarDecl { (Identifier) - ->(Identifier)}) + ->(Identifier) }) (VarDecl { (Identifier) - ->(Identifier)})) -(Export -{ (Identifier) -->(Identifier)}) + ->(Identifier) })) + (Export + { (Identifier) + ->(Identifier) }) {+(Export (Function (Identifier) diff --git a/test/fixtures/typescript/export.diffB-A.txt b/test/fixtures/typescript/export.diffB-A.txt index 4f82be907..19e5bd579 100644 --- a/test/fixtures/typescript/export.diffB-A.txt +++ b/test/fixtures/typescript/export.diffB-A.txt @@ -64,16 +64,16 @@ (Function (Params))) (Export - {+(Function - (Identifier) - (Params))+} - {-(Other "export_specifier" - (Identifier) - (Identifier))-}) - {+(Export + {+(Function + (Identifier) + (Params))+} + {-(Other "export_specifier" + (Identifier) + (Identifier))-}) +{+(Export (Other "export_specifier" - (Identifier) - (Identifier)))+} + (Identifier) + (Identifier)))+} (Export { (StringLiteral) ->(StringLiteral) }) diff --git a/test/fixtures/typescript/interface.diff+A.txt b/test/fixtures/typescript/interface.diff+A.txt index dd6f12d0a..11daa681d 100644 --- a/test/fixtures/typescript/interface.diff+A.txt +++ b/test/fixtures/typescript/interface.diff+A.txt @@ -5,7 +5,7 @@ (Other "type_parameter" (Identifier))) (Other "property_signature" - (Identifier) + (Other "reserved_identifier") (Ty (Other "literal_type" (StringLiteral)))) diff --git a/test/fixtures/typescript/interface.diff+B.txt b/test/fixtures/typescript/interface.diff+B.txt index 050794a34..78a9928f0 100644 --- a/test/fixtures/typescript/interface.diff+B.txt +++ b/test/fixtures/typescript/interface.diff+B.txt @@ -2,7 +2,7 @@ (Interface (Identifier) (Other "property_signature" - (Identifier) + (Other "reserved_identifier") (Ty (Other "literal_type" (StringLiteral)))) diff --git a/test/fixtures/typescript/interface.diff-A.txt b/test/fixtures/typescript/interface.diff-A.txt index 58734602f..7be7c366a 100644 --- a/test/fixtures/typescript/interface.diff-A.txt +++ b/test/fixtures/typescript/interface.diff-A.txt @@ -5,7 +5,7 @@ (Other "type_parameter" (Identifier))) (Other "property_signature" - (Identifier) + (Other "reserved_identifier") (Ty (Other "literal_type" (StringLiteral)))) diff --git a/test/fixtures/typescript/interface.diff-B.txt b/test/fixtures/typescript/interface.diff-B.txt index 786af8732..a18d2b864 100644 --- a/test/fixtures/typescript/interface.diff-B.txt +++ b/test/fixtures/typescript/interface.diff-B.txt @@ -2,7 +2,7 @@ (Interface (Identifier) (Other "property_signature" - (Identifier) + (Other "reserved_identifier") (Ty (Other "literal_type" (StringLiteral)))) diff --git a/test/fixtures/typescript/interface.diffA-B.txt b/test/fixtures/typescript/interface.diffA-B.txt index db2a6818a..bbcc65206 100644 --- a/test/fixtures/typescript/interface.diffA-B.txt +++ b/test/fixtures/typescript/interface.diffA-B.txt @@ -6,7 +6,7 @@ (Other "type_parameter" (Identifier)))-} (Other "property_signature" - (Identifier) + (Other "reserved_identifier") (Ty (Other "literal_type" { (StringLiteral) diff --git a/test/fixtures/typescript/interface.diffB-A.txt b/test/fixtures/typescript/interface.diffB-A.txt index 7c2af1d46..321f14cdd 100644 --- a/test/fixtures/typescript/interface.diffB-A.txt +++ b/test/fixtures/typescript/interface.diffB-A.txt @@ -6,7 +6,7 @@ (Other "type_parameter" (Identifier)))+} (Other "property_signature" - (Identifier) + (Other "reserved_identifier") (Ty (Other "literal_type" { (StringLiteral) diff --git a/test/fixtures/typescript/interface.parseA.txt b/test/fixtures/typescript/interface.parseA.txt index 15111744b..45aa609f7 100644 --- a/test/fixtures/typescript/interface.parseA.txt +++ b/test/fixtures/typescript/interface.parseA.txt @@ -5,7 +5,7 @@ (Other "type_parameter" (Identifier))) (Other "property_signature" - (Identifier) + (Other "reserved_identifier") (Ty (Other "literal_type" (StringLiteral)))) diff --git a/test/fixtures/typescript/interface.parseB.txt b/test/fixtures/typescript/interface.parseB.txt index b32e0d5b5..00c7ca26b 100644 --- a/test/fixtures/typescript/interface.parseB.txt +++ b/test/fixtures/typescript/interface.parseB.txt @@ -2,7 +2,7 @@ (Interface (Identifier) (Other "property_signature" - (Identifier) + (Other "reserved_identifier") (Ty (Other "literal_type" (StringLiteral)))) diff --git a/test/fixtures/typescript/method-definition.diff+B.txt b/test/fixtures/typescript/method-definition.diff+B.txt index ac46acf1e..9aff9da23 100644 --- a/test/fixtures/typescript/method-definition.diff+B.txt +++ b/test/fixtures/typescript/method-definition.diff+B.txt @@ -5,6 +5,7 @@ (Method (Other "accessibility_modifier") (Other "readonly") + (Other "reserved_identifier") (Identifier) (Params) (Ty diff --git a/test/fixtures/typescript/method-definition.diff-B.txt b/test/fixtures/typescript/method-definition.diff-B.txt index a758a4ca6..cb29f6918 100644 --- a/test/fixtures/typescript/method-definition.diff-B.txt +++ b/test/fixtures/typescript/method-definition.diff-B.txt @@ -5,6 +5,7 @@ (Method (Other "accessibility_modifier") (Other "readonly") + (Other "reserved_identifier") (Identifier) (Params) (Ty diff --git a/test/fixtures/typescript/method-definition.diffA-B.txt b/test/fixtures/typescript/method-definition.diffA-B.txt index d29c20610..c5737a673 100644 --- a/test/fixtures/typescript/method-definition.diffA-B.txt +++ b/test/fixtures/typescript/method-definition.diffA-B.txt @@ -5,6 +5,7 @@ (Method (Other "accessibility_modifier") {+(Other "readonly")+} + {+(Other "reserved_identifier")+} (Identifier) (Params) (Ty diff --git a/test/fixtures/typescript/method-definition.diffB-A.txt b/test/fixtures/typescript/method-definition.diffB-A.txt index 0d6fa95bc..f58ee1425 100644 --- a/test/fixtures/typescript/method-definition.diffB-A.txt +++ b/test/fixtures/typescript/method-definition.diffB-A.txt @@ -5,6 +5,7 @@ (Method (Other "accessibility_modifier") {-(Other "readonly")-} + {-(Other "reserved_identifier")-} (Identifier) (Params) (Ty diff --git a/test/fixtures/typescript/method-definition.parseB.txt b/test/fixtures/typescript/method-definition.parseB.txt index 6cd4e1c6b..3eb0017f5 100644 --- a/test/fixtures/typescript/method-definition.parseB.txt +++ b/test/fixtures/typescript/method-definition.parseB.txt @@ -5,6 +5,7 @@ (Method (Other "accessibility_modifier") (Other "readonly") + (Other "reserved_identifier") (Identifier) (Params) (Ty From a2c8f97818105f3b593b159cf02186332e3743f6 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Tue, 27 Jun 2017 09:54:14 -0700 Subject: [PATCH 103/146] Re-bump tree-sitter-typescript --- languages/typescript/vendor/tree-sitter-typescript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/typescript/vendor/tree-sitter-typescript b/languages/typescript/vendor/tree-sitter-typescript index 3afca1145..56d41bd99 160000 --- a/languages/typescript/vendor/tree-sitter-typescript +++ b/languages/typescript/vendor/tree-sitter-typescript @@ -1 +1 @@ -Subproject commit 3afca11458848f88587707a05af369d5badf5558 +Subproject commit 56d41bd993b4251240c019f4deabbb1abc3e1a44 From 050650f4311061e69371da49152f4a1d1ab4bf8f Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Tue, 27 Jun 2017 10:25:47 -0700 Subject: [PATCH 104/146] Re-generate tests --- test/fixtures/javascript/constructor-call.diff+A.txt | 4 ++-- test/fixtures/javascript/constructor-call.diff+B.txt | 4 ++-- test/fixtures/javascript/constructor-call.diff-A.txt | 4 ++-- test/fixtures/javascript/constructor-call.diff-B.txt | 4 ++-- test/fixtures/javascript/constructor-call.diffA-B.txt | 4 ++-- test/fixtures/javascript/constructor-call.diffB-A.txt | 4 ++-- test/fixtures/javascript/constructor-call.parseA.txt | 4 ++-- test/fixtures/javascript/constructor-call.parseB.txt | 4 ++-- test/fixtures/typescript/constructor-call.diff+A.txt | 4 ++-- test/fixtures/typescript/constructor-call.diff+B.txt | 4 ++-- test/fixtures/typescript/constructor-call.diff-A.txt | 4 ++-- test/fixtures/typescript/constructor-call.diff-B.txt | 4 ++-- test/fixtures/typescript/constructor-call.diffA-B.txt | 4 ++-- test/fixtures/typescript/constructor-call.diffB-A.txt | 4 ++-- test/fixtures/typescript/constructor-call.parseA.txt | 4 ++-- test/fixtures/typescript/constructor-call.parseB.txt | 4 ++-- 16 files changed, 32 insertions(+), 32 deletions(-) diff --git a/test/fixtures/javascript/constructor-call.diff+A.txt b/test/fixtures/javascript/constructor-call.diff+A.txt index 57882ffe4..4c12295af 100644 --- a/test/fixtures/javascript/constructor-call.diff+A.txt +++ b/test/fixtures/javascript/constructor-call.diff+A.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral)))))+} diff --git a/test/fixtures/javascript/constructor-call.diff+B.txt b/test/fixtures/javascript/constructor-call.diff+B.txt index 57882ffe4..4c12295af 100644 --- a/test/fixtures/javascript/constructor-call.diff+B.txt +++ b/test/fixtures/javascript/constructor-call.diff+B.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral)))))+} diff --git a/test/fixtures/javascript/constructor-call.diff-A.txt b/test/fixtures/javascript/constructor-call.diff-A.txt index ece591c60..e5ed42b57 100644 --- a/test/fixtures/javascript/constructor-call.diff-A.txt +++ b/test/fixtures/javascript/constructor-call.diff-A.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral)))))-} diff --git a/test/fixtures/javascript/constructor-call.diff-B.txt b/test/fixtures/javascript/constructor-call.diff-B.txt index ece591c60..e5ed42b57 100644 --- a/test/fixtures/javascript/constructor-call.diff-B.txt +++ b/test/fixtures/javascript/constructor-call.diff-B.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral)))))-} diff --git a/test/fixtures/javascript/constructor-call.diffA-B.txt b/test/fixtures/javascript/constructor-call.diffA-B.txt index f1de77fef..e815f5b3a 100644 --- a/test/fixtures/javascript/constructor-call.diffA-B.txt +++ b/test/fixtures/javascript/constructor-call.diffA-B.txt @@ -2,8 +2,8 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) { (StringLiteral) ->(StringLiteral) })))) diff --git a/test/fixtures/javascript/constructor-call.diffB-A.txt b/test/fixtures/javascript/constructor-call.diffB-A.txt index f1de77fef..e815f5b3a 100644 --- a/test/fixtures/javascript/constructor-call.diffB-A.txt +++ b/test/fixtures/javascript/constructor-call.diffB-A.txt @@ -2,8 +2,8 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) { (StringLiteral) ->(StringLiteral) })))) diff --git a/test/fixtures/javascript/constructor-call.parseA.txt b/test/fixtures/javascript/constructor-call.parseA.txt index fa44af92b..e66a2b711 100644 --- a/test/fixtures/javascript/constructor-call.parseA.txt +++ b/test/fixtures/javascript/constructor-call.parseA.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral))))) diff --git a/test/fixtures/javascript/constructor-call.parseB.txt b/test/fixtures/javascript/constructor-call.parseB.txt index fa44af92b..e66a2b711 100644 --- a/test/fixtures/javascript/constructor-call.parseB.txt +++ b/test/fixtures/javascript/constructor-call.parseB.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral))))) diff --git a/test/fixtures/typescript/constructor-call.diff+A.txt b/test/fixtures/typescript/constructor-call.diff+A.txt index 57882ffe4..4c12295af 100644 --- a/test/fixtures/typescript/constructor-call.diff+A.txt +++ b/test/fixtures/typescript/constructor-call.diff+A.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral)))))+} diff --git a/test/fixtures/typescript/constructor-call.diff+B.txt b/test/fixtures/typescript/constructor-call.diff+B.txt index 57882ffe4..4c12295af 100644 --- a/test/fixtures/typescript/constructor-call.diff+B.txt +++ b/test/fixtures/typescript/constructor-call.diff+B.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral)))))+} diff --git a/test/fixtures/typescript/constructor-call.diff-A.txt b/test/fixtures/typescript/constructor-call.diff-A.txt index ece591c60..e5ed42b57 100644 --- a/test/fixtures/typescript/constructor-call.diff-A.txt +++ b/test/fixtures/typescript/constructor-call.diff-A.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral)))))-} diff --git a/test/fixtures/typescript/constructor-call.diff-B.txt b/test/fixtures/typescript/constructor-call.diff-B.txt index ece591c60..e5ed42b57 100644 --- a/test/fixtures/typescript/constructor-call.diff-B.txt +++ b/test/fixtures/typescript/constructor-call.diff-B.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral)))))-} diff --git a/test/fixtures/typescript/constructor-call.diffA-B.txt b/test/fixtures/typescript/constructor-call.diffA-B.txt index f1de77fef..e815f5b3a 100644 --- a/test/fixtures/typescript/constructor-call.diffA-B.txt +++ b/test/fixtures/typescript/constructor-call.diffA-B.txt @@ -2,8 +2,8 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) { (StringLiteral) ->(StringLiteral) })))) diff --git a/test/fixtures/typescript/constructor-call.diffB-A.txt b/test/fixtures/typescript/constructor-call.diffB-A.txt index f1de77fef..e815f5b3a 100644 --- a/test/fixtures/typescript/constructor-call.diffB-A.txt +++ b/test/fixtures/typescript/constructor-call.diffB-A.txt @@ -2,8 +2,8 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) { (StringLiteral) ->(StringLiteral) })))) diff --git a/test/fixtures/typescript/constructor-call.parseA.txt b/test/fixtures/typescript/constructor-call.parseA.txt index fa44af92b..e66a2b711 100644 --- a/test/fixtures/typescript/constructor-call.parseA.txt +++ b/test/fixtures/typescript/constructor-call.parseA.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral))))) diff --git a/test/fixtures/typescript/constructor-call.parseB.txt b/test/fixtures/typescript/constructor-call.parseB.txt index fa44af92b..e66a2b711 100644 --- a/test/fixtures/typescript/constructor-call.parseB.txt +++ b/test/fixtures/typescript/constructor-call.parseB.txt @@ -2,7 +2,7 @@ (ExpressionStatements (Constructor (FunctionCall - (MemberAccess - (Identifier)) + (Other "reserved_identifier") + (Identifier) (NumberLiteral) (StringLiteral))))) From babcd7df197b4b6c7293fc96f01954a626fb3e8f Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Wed, 28 Jun 2017 10:52:13 -0700 Subject: [PATCH 105/146] Bump typescript --- languages/typescript/vendor/tree-sitter-typescript | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/typescript/vendor/tree-sitter-typescript b/languages/typescript/vendor/tree-sitter-typescript index 56d41bd99..af8b9373c 160000 --- a/languages/typescript/vendor/tree-sitter-typescript +++ b/languages/typescript/vendor/tree-sitter-typescript @@ -1 +1 @@ -Subproject commit 56d41bd993b4251240c019f4deabbb1abc3e1a44 +Subproject commit af8b9373c7b260e84e89c38be63e01bd26878184 From 9d0cef141a5d2d23d4af3792fcec76cbafc67589 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 29 Jun 2017 13:32:23 -0700 Subject: [PATCH 106/146] :fire: Data.Syntax.TypedIdentifier --- src/Data/Syntax.hs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/Data/Syntax.hs b/src/Data/Syntax.hs index 72aac5c82..995e44d2f 100644 --- a/src/Data/Syntax.hs +++ b/src/Data/Syntax.hs @@ -32,13 +32,6 @@ newtype Identifier a = Identifier ByteString instance Eq1 Identifier where liftEq = genericLiftEq instance Show1 Identifier where liftShowsPrec = genericLiftShowsPrec --- | A typed identifier of some other construct, differentiated from `Identifier` with a type parameter (e.g. a typed variable or typed function parameter) -data TypedIdentifier a = TypedIdentifier { typedIdentifierType :: !a, typedIdentifierName :: !a } - deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) - -instance Eq1 TypedIdentifier where liftEq = genericLiftEq -instance Show1 TypedIdentifier where liftShowsPrec = genericLiftShowsPrec - -- | Empty syntax, with essentially no-op semantics. -- From 150a0c246123dc6729c32fcb82eb592d0fd03eb2 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 29 Jun 2017 13:32:44 -0700 Subject: [PATCH 107/146] Add Eq1 and Show instances for Data.Syntax.Type.Annotation --- src/Data/Syntax/Type.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Data/Syntax/Type.hs b/src/Data/Syntax/Type.hs index 3cbb03b33..7202a4cb1 100644 --- a/src/Data/Syntax/Type.hs +++ b/src/Data/Syntax/Type.hs @@ -10,6 +10,9 @@ import Prologue hiding (Product) data Annotation a = Annotation { annotationSubject :: !a, annotationType :: !a } deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) +instance Eq1 Annotation where liftEq = genericLiftEq +instance Show1 Annotation where liftShowsPrec = genericLiftShowsPrec + newtype Product a = Product { productElements :: [a] } deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) From 8df150fa170ceec73fdb9173788ad0d449f66cb8 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 29 Jun 2017 13:33:16 -0700 Subject: [PATCH 108/146] Update Language.Python.Syntax typedParameter to use Data.Syntax.Type.Annotation --- src/Language/Python/Syntax.hs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index d0029814d..b6f71e006 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -19,6 +19,7 @@ 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 Data.Union import GHC.Generics import GHC.Stack @@ -70,7 +71,7 @@ type Syntax = , Syntax.Empty , Syntax.Error Error , Syntax.Identifier - , Syntax.TypedIdentifier + , Type.Annotation , [] ] @@ -180,7 +181,7 @@ classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration. <|> pure [] typedParameter :: Assignment -typedParameter = makeTerm <$> symbol TypedParameter <*> children (flip Syntax.TypedIdentifier <$> identifier <*> type') +typedParameter = makeTerm <$> symbol TypedParameter <*> children (Type.Annotation <$> identifier <*> type') type' :: Assignment type' = symbol Type *> children expression From 246f2b8c74fb360bd8bedd4c03bfec83e9626338 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 29 Jun 2017 15:03:57 -0700 Subject: [PATCH 109/146] :fire: functionType field on Data.Syntax.Declaration.Function --- src/Data/Syntax/Declaration.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Syntax/Declaration.hs b/src/Data/Syntax/Declaration.hs index d9b765ebc..37c38daa6 100644 --- a/src/Data/Syntax/Declaration.hs +++ b/src/Data/Syntax/Declaration.hs @@ -7,7 +7,7 @@ import Data.Functor.Classes.Show.Generic import GHC.Generics import Prologue -data Function a = Function { functionType :: !(Maybe a), functionName :: !a, functionParameters :: ![a], functionBody :: !a } +data Function a = Function { functionName :: !a, functionParameters :: ![a], functionBody :: !a } deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) instance Eq1 Function where liftEq = genericLiftEq From 4c4e61e0008cd31bd8ea821497b52e6dc564b81d Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 29 Jun 2017 15:04:23 -0700 Subject: [PATCH 110/146] Update TOC renderer --- src/Renderer/TOC.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Renderer/TOC.hs b/src/Renderer/TOC.hs index e9ddbf4d0..b036f78c5 100644 --- a/src/Renderer/TOC.hs +++ b/src/Renderer/TOC.hs @@ -110,7 +110,7 @@ declarationAlgebra :: (Declaration.Function :< fs, Declaration.Method :< fs, Syn -> Source -> RAlgebra (TermF (Union fs) (Record fields)) (Term (Union fs) (Record fields)) (Maybe Declaration) declarationAlgebra proxy source r - | Just (Declaration.Function _ (identifier, _) _ _) <- prj (tailF r) = Just $ FunctionDeclaration (getSource identifier) + | Just (Declaration.Function (identifier, _) _ _) <- prj (tailF r) = Just $ FunctionDeclaration (getSource identifier) | Just (Declaration.Method (identifier, _) _ _) <- prj (tailF r) = Just $ MethodDeclaration (getSource identifier) | Just (Syntax.Error err) <- prj (tailF r) = Just $ ErrorDeclaration (show (err `asProxyTypeOf` proxy)) | otherwise = Nothing From b585c01b32b882a96f9d8c3de8e99e225aca00fe Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 29 Jun 2017 15:52:41 -0700 Subject: [PATCH 111/146] Assign functionDefinition and asyncFunctionDefinition - Uses Data.Syntax.Type.Annotation to capture the function definition type - Uses Data.Syntax.Type.Annotation to capture if function definition is async --- src/Language/Python/Syntax.hs | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index b6f71e006..5823f1667 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -98,7 +98,7 @@ assignment :: Assignment assignment = makeTerm <$> symbol Module <*> children (many declaration) declaration :: Assignment -declaration = handleError $ classDefinition <|> comment <|> functionDefinition <|> expression <|> statement +declaration = handleError $ classDefinition <|> comment <|> functionDefinition <|> asyncFunctionDefinition <|> expression <|> statement statement :: Assignment statement = assertStatement @@ -163,17 +163,26 @@ whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.Whil tryStatement :: Assignment tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many expression)) --- TODO: Assign the 'async' portion functionDefinition :: Assignment -functionDefinition = makeTerm <$> symbol FunctionDefinition <*> children functionDefinition' - <|> makeTerm <$> symbol AsyncFunctionDefinition <*> children functionDefinition' - where - functionDefinition' = do - functionName' <- identifier - functionParameters <- symbol Parameters *> children (many expression) - functionType <- optional type' - functionBody <- statements - return $ Declaration.Function functionType functionName' functionParameters functionBody +functionDefinition = symbol FunctionDefinition >>= \ location -> children $ do + functionName' <- identifier + functionParameters <- symbol Parameters *> children (many expression) + functionType <- optional type' + functionBody <- statements + return $ case functionType of + Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty) + Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a + +asyncFunctionDefinition :: Assignment +asyncFunctionDefinition = symbol AsyncFunctionDefinition >>= \ location -> children $ do + async' <- makeTerm <$> symbol AnonAsync <*> (Syntax.Identifier <$> source) + functionName' <- identifier + functionParameters <- symbol Parameters *> children (many expression) + functionType <- optional type' + functionBody <- statements + return $ case functionType of + Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty)) async' + Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a) async' classDefinition :: Assignment classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration.Class <$> identifier <*> argumentList <*> (many declaration)) From 29bdbaf52c0445437fcdf4ddeee4d60843c6aa44 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 29 Jun 2017 16:45:30 -0700 Subject: [PATCH 112/146] Assing lambda with Type.Annotation - Maintain consistency with functionDefinition and asyncFunctionDefinition assignments --- src/Language/Python/Syntax.hs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 5823f1667..6f4407f1f 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -403,10 +403,11 @@ none :: Assignment none = makeTerm <$> symbol None <*> (Literal.Null <$ source) lambda :: Assignment -lambda = makeTerm <$> symbol Lambda <*> children (Declaration.Function Nothing <$> lambdaIdentifier <*> lambdaParameters <*> lambdaBody) - where lambdaIdentifier = makeTerm <$> symbol AnonLambda <*> (Syntax.Identifier <$> source) - lambdaParameters = many identifier - lambdaBody = expression +lambda = symbol Lambda >>= \ location -> children $ do + lambdaIdentifier <- makeTerm <$> symbol AnonLambda <*> (Syntax.Identifier <$> source) + lambdaParameters <- many identifier + lambdaBody <- expression + pure $ makeTerm location $ Type.Annotation (makeTerm location (Declaration.Function lambdaIdentifier lambdaParameters lambdaBody)) (makeTerm location Syntax.Empty) comprehension :: Assignment comprehension = makeTerm <$> symbol GeneratorExpression <*> children (comprehensionDeclaration expression) From c2800edd0b151a61334b16ee4ed6eac3e28ec9a2 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 29 Jun 2017 16:45:44 -0700 Subject: [PATCH 113/146] Favor `pure` over `return` --- src/Language/Python/Syntax.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 6f4407f1f..53b4d9780 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -169,7 +169,7 @@ functionDefinition = symbol FunctionDefinition >>= \ location -> children $ do functionParameters <- symbol Parameters *> children (many expression) functionType <- optional type' functionBody <- statements - return $ case functionType of + pure $ case functionType of Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty) Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a @@ -180,7 +180,7 @@ asyncFunctionDefinition = symbol AsyncFunctionDefinition >>= \ location -> child functionParameters <- symbol Parameters *> children (many expression) functionType <- optional type' functionBody <- statements - return $ case functionType of + pure $ case functionType of Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty)) async' Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a) async' From 1e05fbf7542b77f7fc6342189a0c628399b3e9b6 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 30 Jun 2017 17:21:04 -0700 Subject: [PATCH 114/146] Update functionDefinition and asyncFunctionDefinition assignments --- src/Language/Python/Syntax.hs | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 53b4d9780..6118df3fa 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -164,25 +164,21 @@ tryStatement :: Assignment tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many expression)) functionDefinition :: Assignment -functionDefinition = symbol FunctionDefinition >>= \ location -> children $ do - functionName' <- identifier - functionParameters <- symbol Parameters *> children (many expression) - functionType <- optional type' - functionBody <- statements - pure $ case functionType of - Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty) - Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a +functionDefinition = symbol FunctionDefinition >>= \ loc -> children (make loc <$> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration)) + where + make location functionName' functionParameters ty functionBody = case ty of + Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty) + Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a asyncFunctionDefinition :: Assignment -asyncFunctionDefinition = symbol AsyncFunctionDefinition >>= \ location -> children $ do - async' <- makeTerm <$> symbol AnonAsync <*> (Syntax.Identifier <$> source) - functionName' <- identifier - functionParameters <- symbol Parameters *> children (many expression) - functionType <- optional type' - functionBody <- statements - pure $ case functionType of - Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty)) async' - Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a) async' +asyncFunctionDefinition = symbol AsyncFunctionDefinition >>= \ loc -> children (make loc <$> async' <*> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration)) + where + make location async' functionName' functionParameters ty functionBody = case ty of + Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty)) async' + Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a) async' + +async' :: Assignment +async' = makeTerm <$> symbol AnonAsync <*> (Syntax.Identifier <$> source) classDefinition :: Assignment classDefinition = makeTerm <$> symbol ClassDefinition <*> children (Declaration.Class <$> identifier <*> argumentList <*> (many declaration)) From 48141cbe0a8bd0a506c0578f40c2100d1d3cb149 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 30 Jun 2017 17:23:06 -0700 Subject: [PATCH 115/146] Add Data.Syntax.Statement.Let --- src/Data/Syntax/Statement.hs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Data/Syntax/Statement.hs b/src/Data/Syntax/Statement.hs index d1dc1e652..112dd6941 100644 --- a/src/Data/Syntax/Statement.hs +++ b/src/Data/Syntax/Statement.hs @@ -30,6 +30,14 @@ newtype Pattern a = Pattern a instance Eq1 Pattern where liftEq = genericLiftEq instance Show1 Pattern where liftShowsPrec = genericLiftShowsPrec + +data Let a = Let { letVariable :: !a, letValue :: !a, letBody :: !a } + deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) + +instance Eq1 Let where liftEq = genericLiftEq +instance Show1 Let where liftShowsPrec = genericLiftShowsPrec + + -- Assignment -- | Assignment to a variable or other lvalue. From 2bbec1e6e647ee87490d14680ebb4ef5edab85c5 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 30 Jun 2017 17:25:43 -0700 Subject: [PATCH 116/146] Add Data.Syntax.Statement.Else for handling Python for else, and while else statements --- src/Data/Syntax/Statement.hs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Data/Syntax/Statement.hs b/src/Data/Syntax/Statement.hs index 112dd6941..cc08bbe60 100644 --- a/src/Data/Syntax/Statement.hs +++ b/src/Data/Syntax/Statement.hs @@ -14,6 +14,14 @@ data If a = If { ifCondition :: !a, ifThenBody :: !a, ifElseBody :: !a } instance Eq1 If where liftEq = genericLiftEq instance Show1 If where liftShowsPrec = genericLiftShowsPrec +-- | Else statement. The else condition is any term, that upon successful completion, continues evaluation to the elseBody, e.g. `for ... else` in Python. +data Else a = Else { elseCondition :: !a, elseBody :: !a } + deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) + +instance Eq1 Else where liftEq = genericLiftEq +instance Show1 Else where liftShowsPrec = genericLiftShowsPrec + + -- TODO: Alternative definition would flatten if/else if/else chains: data If a = If ![(a, a)] !(Maybe a) -- | A pattern-matching or computed jump control-flow statement, like 'switch' in C or JavaScript, or 'case' in Ruby or Haskell. From 9ab480a90dfaa072cd66fedaf7ee31760a20e1b5 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 30 Jun 2017 17:52:13 -0700 Subject: [PATCH 117/146] Assign for statements with else clauses --- src/Language/Python/Syntax.hs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 6118df3fa..014969e81 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -58,6 +58,7 @@ type Syntax = , Statement.Break , Statement.Catch , Statement.Continue + , Statement.Else , Statement.Finally , Statement.ForEach , Statement.If @@ -151,9 +152,12 @@ expression = await <|> typedParameter <|> unaryOperator --- TODO: Assign for else clauses forStatement :: Assignment -forStatement = makeTerm <$> symbol ForStatement <*> children (Statement.ForEach <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> (makeTerm <$> location <*> many expression)) +forStatement = symbol ForStatement >>= \ loc -> children (make loc <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> (makeTerm <$> location <*> many expression) <*> (optional (makeTerm <$> symbol ElseClause <*> children (many declaration)))) + where + make loc variables expressionList expressions elseClause = case elseClause of + Nothing -> makeTerm loc $ (Statement.ForEach variables expressionList expressions) + Just a -> makeTerm loc $ (Statement.Else (makeTerm loc $ Statement.ForEach variables expressionList expressions) a) -- TODO: Assign while else clauses whileStatement :: Assignment From 19dcdc3fd971c404e53c597d3624b4e9244e5f7d Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 30 Jun 2017 18:00:35 -0700 Subject: [PATCH 118/146] Assign while statements with else clauses --- src/Language/Python/Syntax.hs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 014969e81..df7f34e96 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -159,9 +159,12 @@ forStatement = symbol ForStatement >>= \ loc -> children (make loc <$> (makeTerm Nothing -> makeTerm loc $ (Statement.ForEach variables expressionList expressions) Just a -> makeTerm loc $ (Statement.Else (makeTerm loc $ Statement.ForEach variables expressionList expressions) a) --- TODO: Assign while else clauses whileStatement :: Assignment -whileStatement = makeTerm <$> symbol WhileStatement <*> children (Statement.While <$> expression <*> (makeTerm <$> location <*> many expression)) +whileStatement = symbol WhileStatement >>= \ loc -> children (make loc <$> expression <*> (makeTerm <$> location <*> many expression) <*> (optional (makeTerm <$> symbol ElseClause <*> children (many declaration)))) + where + make loc whileCondition whileBody whileElseClause = case whileElseClause of + Nothing -> makeTerm loc $ (Statement.While whileCondition whileBody) + Just a -> makeTerm loc $ (Statement.Else (makeTerm loc $ Statement.While whileCondition whileBody) a) -- TODO: Assign try else clauses tryStatement :: Assignment From b1a7dba4ec5eeee7d45e148d6ed742dfe0f53391 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 30 Jun 2017 18:00:45 -0700 Subject: [PATCH 119/146] Rename arguments --- src/Language/Python/Syntax.hs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index df7f34e96..bb67562ad 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -155,9 +155,9 @@ expression = await forStatement :: Assignment forStatement = symbol ForStatement >>= \ loc -> children (make loc <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> (makeTerm <$> location <*> many expression) <*> (optional (makeTerm <$> symbol ElseClause <*> children (many declaration)))) where - make loc variables expressionList expressions elseClause = case elseClause of - Nothing -> makeTerm loc $ (Statement.ForEach variables expressionList expressions) - Just a -> makeTerm loc $ (Statement.Else (makeTerm loc $ Statement.ForEach variables expressionList expressions) a) + make loc variables expressionList forBody forElseClause = case forElseClause of + Nothing -> makeTerm loc $ (Statement.ForEach variables expressionList forBody) + Just a -> makeTerm loc $ (Statement.Else (makeTerm loc $ Statement.ForEach variables expressionList forBody) a) whileStatement :: Assignment whileStatement = symbol WhileStatement >>= \ loc -> children (make loc <$> expression <*> (makeTerm <$> location <*> many expression) <*> (optional (makeTerm <$> symbol ElseClause <*> children (many declaration)))) From 6d1ac8af87c3042d637019ff5fbcd098b9b152bf Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 30 Jun 2017 18:00:54 -0700 Subject: [PATCH 120/146] :fire: unused function --- src/Language/Python/Syntax.hs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index bb67562ad..e0299cd73 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -333,9 +333,6 @@ import' = makeTerm <$> symbol ImportStatement <*> children (Declaration.Import < importFrom :: Assignment importFrom = makeTerm <$> symbol ImportFromStatement <*> children (Declaration.Import <$> many expression) -statements :: Assignment -statements = makeTerm <$> location <*> many statement - assertStatement :: Assignment assertStatement = makeTerm <$ symbol AssertStatement <*> location <*> children (Expression.Call <$> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier <$> source)) <*> many expression) From 64538daa3a05f818c282dfc341ed02aa880ab1bc Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Wed, 5 Jul 2017 17:32:38 -0700 Subject: [PATCH 121/146] Update Data.Syntax.Statement.Catch to require two terms --- src/Data/Syntax/Statement.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Syntax/Statement.hs b/src/Data/Syntax/Statement.hs index cc08bbe60..17f708ffe 100644 --- a/src/Data/Syntax/Statement.hs +++ b/src/Data/Syntax/Statement.hs @@ -130,7 +130,7 @@ data Try a = Try !a ![a] instance Eq1 Try where liftEq = genericLiftEq instance Show1 Try where liftShowsPrec = genericLiftShowsPrec -data Catch a = Catch !(Maybe a) !a +data Catch a = Catch !a !a deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) instance Eq1 Catch where liftEq = genericLiftEq From 84cd43a1ff122472b54527cdb0c4d71a93053589 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Wed, 5 Jul 2017 17:34:09 -0700 Subject: [PATCH 122/146] Assign tryStatements with except clauses --- src/Language/Python/Syntax.hs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index e0299cd73..3fe969276 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -168,7 +168,8 @@ whileStatement = symbol WhileStatement >>= \ loc -> children (make loc <$> expre -- TODO: Assign try else clauses tryStatement :: Assignment -tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many expression)) +tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many (expression <|> elseClause))) + where elseClause = makeTerm <$> symbol ElseClause <*> children (Statement.Else <$> emptyTerm <*> (makeTerm <$> location <*> (many expression))) functionDefinition :: Assignment functionDefinition = symbol FunctionDefinition >>= \ loc -> children (make loc <$> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration)) @@ -198,8 +199,9 @@ typedParameter = makeTerm <$> symbol TypedParameter <*> children (Type.Annotatio type' :: Assignment type' = symbol Type *> children expression +-- TODO: support As expressions exceptClause :: Assignment -exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> optional (makeTerm <$> location <*> many expression <* symbol AnonColon) <*> expression) +exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> (expression <|> emptyTerm) <*> expression) finallyClause :: Assignment finallyClause = makeTerm <$> symbol FinallyClause <*> children (Statement.Finally <$> expression) From 64b2845138d559774e6f3697adc8b3ce62e06c41 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Wed, 5 Jul 2017 17:49:02 -0700 Subject: [PATCH 123/146] Assign multiple identifiers for except clauses and many expressions --- src/Language/Python/Syntax.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 3fe969276..adcaaf20e 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -201,7 +201,7 @@ type' = symbol Type *> children expression -- TODO: support As expressions exceptClause :: Assignment -exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> (expression <|> emptyTerm) <*> expression) +exceptClause = makeTerm <$> symbol ExceptClause <*> children (Statement.Catch <$> (makeTerm <$> location <*> (many identifier)) <*> (makeTerm <$> location <*> (many expression))) finallyClause :: Assignment finallyClause = makeTerm <$> symbol FinallyClause <*> children (Statement.Finally <$> expression) From 97d6cefb0bfbe704d6d1e27d5d7584edbbd86399 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Wed, 5 Jul 2017 18:37:16 -0700 Subject: [PATCH 124/146] Assign withStatements --- src/Language/Python/Syntax.hs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index adcaaf20e..2250e0a1a 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -62,6 +62,7 @@ type Syntax = , Statement.Finally , Statement.ForEach , Statement.If + , Statement.Let , Statement.NoOp , Statement.Return , Statement.Throw @@ -125,6 +126,7 @@ statement = assertStatement <|> returnStatement <|> tryStatement <|> whileStatement + <|> withStatement expressionStatement :: Assignment expressionStatement = symbol ExpressionStatement *> children expression @@ -152,6 +154,12 @@ expression = await <|> typedParameter <|> unaryOperator +withStatement :: Assignment +withStatement = makeTerm <$> symbol WithStatement <*> (children $ do + (value, variable) <- (symbol WithItem *> (children $ (,) <$> identifier <*> identifier)) + body <- expression + pure (Statement.Let variable value body)) + forStatement :: Assignment forStatement = symbol ForStatement >>= \ loc -> children (make loc <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> (makeTerm <$> location <*> many expression) <*> (optional (makeTerm <$> symbol ElseClause <*> children (many declaration)))) where From 5010d8962dfa68c026ca7cdcbf1d19ff28d23543 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 6 Jul 2017 11:02:55 -0700 Subject: [PATCH 125/146] Simplify Data.Syntax.Literal.String --- src/Data/Syntax/Literal.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Data/Syntax/Literal.hs b/src/Data/Syntax/Literal.hs index ec715d5b9..05c6a2137 100644 --- a/src/Data/Syntax/Literal.hs +++ b/src/Data/Syntax/Literal.hs @@ -4,7 +4,6 @@ module Data.Syntax.Literal where import Data.Align.Generic import Data.Functor.Classes.Eq.Generic import Data.Functor.Classes.Show.Generic -import Data.Union import GHC.Generics import Prologue hiding (Set) @@ -53,7 +52,7 @@ instance Show1 Range where liftShowsPrec = genericLiftShowsPrec -- Strings, symbols -newtype String a = String { stringElements :: [Union '[InterpolationElement, TextElement] a] } +newtype String a = String { stringElements :: [a] } deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) instance Eq1 String where liftEq = genericLiftEq From a3c22babce617c7ad35414dd19938acc4a52ba17 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 6 Jul 2017 12:01:56 -0700 Subject: [PATCH 126/146] Update classScope -> classBody for consistency --- src/Data/Syntax/Declaration.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Syntax/Declaration.hs b/src/Data/Syntax/Declaration.hs index 37c38daa6..8e30d460d 100644 --- a/src/Data/Syntax/Declaration.hs +++ b/src/Data/Syntax/Declaration.hs @@ -31,7 +31,7 @@ instance Eq1 Variable where liftEq = genericLiftEq instance Show1 Variable where liftShowsPrec = genericLiftShowsPrec -data Class a = Class { classIdentifier :: !a, classSuperclasses :: ![a], classScope :: ![a] } +data Class a = Class { classIdentifier :: !a, classSuperclasses :: ![a], classBody :: ![a] } deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) instance Eq1 Class where liftEq = genericLiftEq From 9267ba91df21380afcb89776d2103e0e8ca6079b Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 6 Jul 2017 12:02:10 -0700 Subject: [PATCH 127/146] Add Data.Syntax.Declaration.Decorator --- src/Data/Syntax/Declaration.hs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Data/Syntax/Declaration.hs b/src/Data/Syntax/Declaration.hs index 8e30d460d..34eacde8d 100644 --- a/src/Data/Syntax/Declaration.hs +++ b/src/Data/Syntax/Declaration.hs @@ -37,6 +37,12 @@ data Class a = Class { classIdentifier :: !a, classSuperclasses :: ![a], classBo instance Eq1 Class where liftEq = genericLiftEq instance Show1 Class where liftShowsPrec = genericLiftShowsPrec +data Decorator a = Decorator { decoratorIdentifier :: !a, decoratorParamaters :: ![a], decoratorBody :: !a } + deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) + +instance Eq1 Class where liftEq = genericLiftEq +instance Show1 Class where liftShowsPrec = genericLiftShowsPrec + -- TODO: Generics, constraints. From b4e81ab360c99e73ed6584e822db143feec024e6 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 6 Jul 2017 12:57:34 -0700 Subject: [PATCH 128/146] Fix names for Decorator instances --- src/Data/Syntax/Declaration.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Data/Syntax/Declaration.hs b/src/Data/Syntax/Declaration.hs index 34eacde8d..19f6afd7f 100644 --- a/src/Data/Syntax/Declaration.hs +++ b/src/Data/Syntax/Declaration.hs @@ -40,8 +40,8 @@ instance Show1 Class where liftShowsPrec = genericLiftShowsPrec data Decorator a = Decorator { decoratorIdentifier :: !a, decoratorParamaters :: ![a], decoratorBody :: !a } deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) -instance Eq1 Class where liftEq = genericLiftEq -instance Show1 Class where liftShowsPrec = genericLiftShowsPrec +instance Eq1 Decorator where liftEq = genericLiftEq +instance Show1 Decorator where liftShowsPrec = genericLiftShowsPrec -- TODO: Generics, constraints. From 352d090ce030b9108576fbb88755817c63699d84 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 6 Jul 2017 12:58:09 -0700 Subject: [PATCH 129/146] Assign decoratedDefinitions --- src/Language/Python/Syntax.hs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 2250e0a1a..d39b08707 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -31,6 +31,7 @@ type Syntax = '[ Comment.Comment , Declaration.Class , Declaration.Comprehension + , Declaration.Decorator , Declaration.Function , Declaration.Import , Declaration.Variable @@ -100,7 +101,7 @@ assignment :: Assignment assignment = makeTerm <$> symbol Module <*> children (many declaration) declaration :: Assignment -declaration = handleError $ classDefinition <|> comment <|> functionDefinition <|> asyncFunctionDefinition <|> expression <|> statement +declaration = handleError $ classDefinition <|> comment <|> decoratedDefinition <|> functionDefinition <|> asyncFunctionDefinition <|> expression <|> statement statement :: Assignment statement = assertStatement @@ -154,6 +155,12 @@ expression = await <|> typedParameter <|> unaryOperator +decoratedDefinition :: Assignment +decoratedDefinition = makeTerm <$> symbol DecoratedDefinition <*> (children $ do + (a, b) <- (symbol Decorator *> (children ((,) <$> expression <*> (symbol ArgumentList *> children ((many expression) <|> (many emptyTerm)))))) + dec <- declaration + pure (Declaration.Decorator a b dec)) + withStatement :: Assignment withStatement = makeTerm <$> symbol WithStatement <*> (children $ do (value, variable) <- (symbol WithItem *> (children $ (,) <$> identifier <*> identifier)) From a9b609681190793fe9151f23c3481cfd7da7426b Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Thu, 6 Jul 2017 14:56:31 -0700 Subject: [PATCH 130/146] ++tree-sitter and languages --- languages/c/vendor/tree-sitter-c | 2 +- languages/python/vendor/tree-sitter-python | 2 +- languages/ruby/vendor/tree-sitter-ruby | 2 +- vendor/haskell-tree-sitter | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/languages/c/vendor/tree-sitter-c b/languages/c/vendor/tree-sitter-c index d9c324ffc..debe919f8 160000 --- a/languages/c/vendor/tree-sitter-c +++ b/languages/c/vendor/tree-sitter-c @@ -1 +1 @@ -Subproject commit d9c324ffce1d252da76ee8b585e20262cc3a3a57 +Subproject commit debe919f846e2f28dd4700e0cf39889e5fd5994a diff --git a/languages/python/vendor/tree-sitter-python b/languages/python/vendor/tree-sitter-python index 148edad8b..07fb4ede1 160000 --- a/languages/python/vendor/tree-sitter-python +++ b/languages/python/vendor/tree-sitter-python @@ -1 +1 @@ -Subproject commit 148edad8bf31c70ede718cff0ba1f5cb3abc401e +Subproject commit 07fb4ede133845f00661e890fa9475a9ec4d5d28 diff --git a/languages/ruby/vendor/tree-sitter-ruby b/languages/ruby/vendor/tree-sitter-ruby index 7c0c68390..b54bb16d4 160000 --- a/languages/ruby/vendor/tree-sitter-ruby +++ b/languages/ruby/vendor/tree-sitter-ruby @@ -1 +1 @@ -Subproject commit 7c0c68390ae6c7a456499cc1087773cd4d02185c +Subproject commit b54bb16d4bee3dcabf728a3dd7d3015c9f970782 diff --git a/vendor/haskell-tree-sitter b/vendor/haskell-tree-sitter index 147f687cb..cbc18ad73 160000 --- a/vendor/haskell-tree-sitter +++ b/vendor/haskell-tree-sitter @@ -1 +1 @@ -Subproject commit 147f687cb70033f699216135f12a451dc6bf8c87 +Subproject commit cbc18ad73654a4244ba47aac1cfd42099b82b59c From 6c2e7500c4780d02c1421f04fe1d34d8a77d0d35 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Thu, 6 Jul 2017 18:31:37 -0700 Subject: [PATCH 131/146] Assign keyword argument --- src/Language/Python/Syntax.hs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index d39b08707..d001298e2 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -144,6 +144,7 @@ expression = await <|> ellipsis <|> expressionList <|> lambda + <|> keywordArgument <|> keywordIdentifier <|> literal <|> memberAccess @@ -160,6 +161,8 @@ decoratedDefinition = makeTerm <$> symbol DecoratedDefinition <*> (children $ do (a, b) <- (symbol Decorator *> (children ((,) <$> expression <*> (symbol ArgumentList *> children ((many expression) <|> (many emptyTerm)))))) dec <- declaration pure (Declaration.Decorator a b dec)) +keywordArgument :: Assignment +keywordArgument = makeTerm <$> symbol KeywordArgument <*> children (Declaration.Variable <$> expression <*> emptyTerm <*> expression) withStatement :: Assignment withStatement = makeTerm <$> symbol WithStatement <*> (children $ do From c3e4c82be50ea69662e4bf78d8a014fce6d43d05 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 7 Jul 2017 09:48:22 -0700 Subject: [PATCH 132/146] :fire: old comment --- src/Language/Python/Syntax.hs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index d001298e2..4d85a03fc 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -184,7 +184,6 @@ whileStatement = symbol WhileStatement >>= \ loc -> children (make loc <$> expre Nothing -> makeTerm loc $ (Statement.While whileCondition whileBody) Just a -> makeTerm loc $ (Statement.Else (makeTerm loc $ Statement.While whileCondition whileBody) a) --- TODO: Assign try else clauses tryStatement :: Assignment tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many (expression <|> elseClause))) where elseClause = makeTerm <$> symbol ElseClause <*> children (Statement.Else <$> emptyTerm <*> (makeTerm <$> location <*> (many expression))) From e563a0908ba283a7c668eb55c12b2ce317daf15b Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 7 Jul 2017 10:37:42 -0700 Subject: [PATCH 133/146] :fire: unnecessary $ --- src/Language/Python/Syntax.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 4d85a03fc..34cf0c585 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -174,15 +174,15 @@ forStatement :: Assignment forStatement = symbol ForStatement >>= \ loc -> children (make loc <$> (makeTerm <$> symbol Variables <*> children (many expression)) <*> expressionList <*> (makeTerm <$> location <*> many expression) <*> (optional (makeTerm <$> symbol ElseClause <*> children (many declaration)))) where make loc variables expressionList forBody forElseClause = case forElseClause of - Nothing -> makeTerm loc $ (Statement.ForEach variables expressionList forBody) - Just a -> makeTerm loc $ (Statement.Else (makeTerm loc $ Statement.ForEach variables expressionList forBody) a) + Nothing -> makeTerm loc (Statement.ForEach variables expressionList forBody) + Just a -> makeTerm loc (Statement.Else (makeTerm loc $ Statement.ForEach variables expressionList forBody) a) whileStatement :: Assignment whileStatement = symbol WhileStatement >>= \ loc -> children (make loc <$> expression <*> (makeTerm <$> location <*> many expression) <*> (optional (makeTerm <$> symbol ElseClause <*> children (many declaration)))) where make loc whileCondition whileBody whileElseClause = case whileElseClause of - Nothing -> makeTerm loc $ (Statement.While whileCondition whileBody) - Just a -> makeTerm loc $ (Statement.Else (makeTerm loc $ Statement.While whileCondition whileBody) a) + Nothing -> makeTerm loc (Statement.While whileCondition whileBody) + Just a -> makeTerm loc (Statement.Else (makeTerm loc $ Statement.While whileCondition whileBody) a) tryStatement :: Assignment tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> expression <*> (many (expression <|> elseClause))) From fbd5b5713710db2729875722eaf876f8d18ac951 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 7 Jul 2017 10:38:02 -0700 Subject: [PATCH 134/146] Remove case for function and async function assignments --- src/Language/Python/Syntax.hs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 34cf0c585..e68d881c3 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -191,16 +191,12 @@ tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> functionDefinition :: Assignment functionDefinition = symbol FunctionDefinition >>= \ loc -> children (make loc <$> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration)) where - make location functionName' functionParameters ty functionBody = case ty of - Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty) - Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a + make loc functionName' functionParameters ty functionBody = makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function functionName' functionParameters functionBody) (maybe (makeTerm loc Syntax.Empty) identity ty) asyncFunctionDefinition :: Assignment asyncFunctionDefinition = symbol AsyncFunctionDefinition >>= \ loc -> children (make loc <$> async' <*> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration)) where - make location async' functionName' functionParameters ty functionBody = case ty of - Nothing -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) (makeTerm location Syntax.Empty)) async' - Just a -> makeTerm location $ Type.Annotation (makeTerm location $ Type.Annotation (makeTerm location $ Declaration.Function functionName' functionParameters functionBody) a) async' + make loc async' functionName' functionParameters ty functionBody = makeTerm loc $ Type.Annotation (makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function functionName' functionParameters functionBody) (maybe (makeTerm loc Syntax.Empty) identity ty)) async' async' :: Assignment async' = makeTerm <$> symbol AnonAsync <*> (Syntax.Identifier <$> source) From 2d3f48887b0173ca01d38f7ed87777827a34b07a Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 7 Jul 2017 11:58:31 -0700 Subject: [PATCH 135/146] Bump tree-sitter-python to capture lambda parameters --- languages/python/vendor/tree-sitter-python | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages/python/vendor/tree-sitter-python b/languages/python/vendor/tree-sitter-python index 148edad8b..bbb3639e9 160000 --- a/languages/python/vendor/tree-sitter-python +++ b/languages/python/vendor/tree-sitter-python @@ -1 +1 @@ -Subproject commit 148edad8bf31c70ede718cff0ba1f5cb3abc401e +Subproject commit bbb3639e95e07c7b19268f54c4307fc4142288a6 From 6563d4ce2bb632201209b1147587a25762b7b6ab Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 7 Jul 2017 12:07:13 -0700 Subject: [PATCH 136/146] Rework functionDefinition assignment --- src/Language/Python/Syntax.hs | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index e68d881c3..508a69a2e 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -101,7 +101,7 @@ assignment :: Assignment assignment = makeTerm <$> symbol Module <*> children (many declaration) declaration :: Assignment -declaration = handleError $ classDefinition <|> comment <|> decoratedDefinition <|> functionDefinition <|> asyncFunctionDefinition <|> expression <|> statement +declaration = handleError $ classDefinition <|> comment <|> decoratedDefinition <|> functionDefinition <|> expression <|> statement statement :: Assignment statement = assertStatement @@ -130,7 +130,7 @@ statement = assertStatement <|> withStatement expressionStatement :: Assignment -expressionStatement = symbol ExpressionStatement *> children expression +expressionStatement = symbol ExpressionStatement *> children declaration expression :: Assignment expression = await @@ -143,7 +143,6 @@ expression = await <|> dottedName <|> ellipsis <|> expressionList - <|> lambda <|> keywordArgument <|> keywordIdentifier <|> literal @@ -189,14 +188,12 @@ tryStatement = makeTerm <$> symbol TryStatement <*> children (Statement.Try <$> where elseClause = makeTerm <$> symbol ElseClause <*> children (Statement.Else <$> emptyTerm <*> (makeTerm <$> location <*> (many expression))) functionDefinition :: Assignment -functionDefinition = symbol FunctionDefinition >>= \ loc -> children (make loc <$> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration)) +functionDefinition = (symbol FunctionDefinition >>= \ loc -> children (makeFunctionDeclaration loc <$> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration))) + <|> (symbol AsyncFunctionDefinition >>= \ loc -> children (makeAsyncFunctionDeclaration loc <$> async' <*> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration))) + <|> (symbol Lambda >>= \ loc -> children (makeFunctionDeclaration loc <$> (makeTerm <$> symbol AnonLambda <*> (Syntax.Identifier <$> source)) <*> ((symbol LambdaParameters *> children (many expression)) <|> (pure [])) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration))) where - make loc functionName' functionParameters ty functionBody = makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function functionName' functionParameters functionBody) (maybe (makeTerm loc Syntax.Empty) identity ty) - -asyncFunctionDefinition :: Assignment -asyncFunctionDefinition = symbol AsyncFunctionDefinition >>= \ loc -> children (make loc <$> async' <*> identifier <*> (symbol Parameters *> children (many expression)) <*> (optional (symbol Type *> children expression)) <*> (makeTerm <$> location <*> many declaration)) - where - make loc async' functionName' functionParameters ty functionBody = makeTerm loc $ Type.Annotation (makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function functionName' functionParameters functionBody) (maybe (makeTerm loc Syntax.Empty) identity ty)) async' + makeFunctionDeclaration loc functionName' functionParameters ty functionBody = makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function functionName' functionParameters functionBody) (maybe (makeTerm loc Syntax.Empty) identity ty) + makeAsyncFunctionDeclaration loc async' functionName' functionParameters ty functionBody = makeTerm loc $ Type.Annotation (makeTerm loc $ Type.Annotation (makeTerm loc $ Declaration.Function functionName' functionParameters functionBody) (maybe (makeTerm loc Syntax.Empty) identity ty)) async' async' :: Assignment async' = makeTerm <$> symbol AnonAsync <*> (Syntax.Identifier <$> source) @@ -417,13 +414,6 @@ boolean = makeTerm <$> symbol Grammar.True <*> (Literal.true <$ source) none :: Assignment none = makeTerm <$> symbol None <*> (Literal.Null <$ source) -lambda :: Assignment -lambda = symbol Lambda >>= \ location -> children $ do - lambdaIdentifier <- makeTerm <$> symbol AnonLambda <*> (Syntax.Identifier <$> source) - lambdaParameters <- many identifier - lambdaBody <- expression - pure $ makeTerm location $ Type.Annotation (makeTerm location (Declaration.Function lambdaIdentifier lambdaParameters lambdaBody)) (makeTerm location Syntax.Empty) - comprehension :: Assignment comprehension = makeTerm <$> symbol GeneratorExpression <*> children (comprehensionDeclaration expression) <|> makeTerm <$> symbol ListComprehension <*> children (comprehensionDeclaration expression) From 9634dcb94ac14a21008f36dda20828e5aca578f3 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 7 Jul 2017 12:21:16 -0700 Subject: [PATCH 137/146] Add comment about decorator --- src/Data/Syntax/Declaration.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Data/Syntax/Declaration.hs b/src/Data/Syntax/Declaration.hs index 19f6afd7f..520de0c93 100644 --- a/src/Data/Syntax/Declaration.hs +++ b/src/Data/Syntax/Declaration.hs @@ -37,6 +37,7 @@ data Class a = Class { classIdentifier :: !a, classSuperclasses :: ![a], classBo instance Eq1 Class where liftEq = genericLiftEq instance Show1 Class where liftShowsPrec = genericLiftShowsPrec +-- | A decorator in Python data Decorator a = Decorator { decoratorIdentifier :: !a, decoratorParamaters :: ![a], decoratorBody :: !a } deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) From 1e84cc3f8ee95168e343b423b84c9b0ea0462cb1 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Fri, 7 Jul 2017 13:03:42 -0700 Subject: [PATCH 138/146] Add comment for python grammar version --- src/Language/Python/Grammar.hs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Language/Python/Grammar.hs b/src/Language/Python/Grammar.hs index 4d1d4486d..71be316cd 100644 --- a/src/Language/Python/Grammar.hs +++ b/src/Language/Python/Grammar.hs @@ -6,4 +6,5 @@ import Text.Parser.TreeSitter.Language import Text.Parser.TreeSitter.Python -- | Statically-known rules corresponding to symbols in the grammar. +-- v1 - bump this to regenerate mkSymbolDatatype (mkName "Grammar") tree_sitter_python From f715e6fdf115dc6360fc19ceb605e45fe1c3c7e4 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Mon, 10 Jul 2017 11:15:03 -0700 Subject: [PATCH 139/146] Show 'Heading N' instead of 'Section' for md toc summaries --- src/Renderer/TOC.hs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Renderer/TOC.hs b/src/Renderer/TOC.hs index b036f78c5..c2ae4dbd4 100644 --- a/src/Renderer/TOC.hs +++ b/src/Renderer/TOC.hs @@ -28,6 +28,7 @@ import Data.Proxy import Data.Record import Data.Source as Source import Data.Text (toLower) +import qualified Data.Text as T import Data.Text.Listable import Data.These import Data.Union @@ -213,7 +214,7 @@ toCategoryName :: Declaration -> Text toCategoryName declaration = case declaration of FunctionDeclaration _ -> "Function" MethodDeclaration _ -> "Method" - SectionDeclaration _ -> "Section" + SectionDeclaration x -> "Heading " <> show (T.length (T.takeWhile (== '#') x)) ErrorDeclaration _ -> "ParseError" instance Listable Declaration where From ef0810d3db1d1f732500cc951291727fa058fe2f Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Mon, 10 Jul 2017 12:54:03 -0700 Subject: [PATCH 140/146] Test markdown toc summary rendering --- test/TOCSpec.hs | 6 ++++++ test/fixtures/toc/markdown/headings.A.md | 3 +++ test/fixtures/toc/markdown/headings.B.md | 5 +++++ 3 files changed, 14 insertions(+) create mode 100644 test/fixtures/toc/markdown/headings.A.md create mode 100644 test/fixtures/toc/markdown/headings.B.md diff --git a/test/TOCSpec.hs b/test/TOCSpec.hs index ea564e67f..af3f9ef62 100644 --- a/test/TOCSpec.hs +++ b/test/TOCSpec.hs @@ -149,6 +149,12 @@ spec = parallel $ do output <- runTask (diffBlobPair ToCDiffRenderer blobs) toS output `shouldBe` ("{\"changes\":{\"test/fixtures/toc/ruby/methods.A.rb -> test/fixtures/toc/ruby/methods.X.rb\":[{\"span\":{\"start\":[4,1],\"end\":[5,4]},\"category\":\"Method\",\"term\":\"baz\",\"changeType\":\"removed\"}]},\"errors\":{\"test/fixtures/toc/ruby/methods.A.rb -> test/fixtures/toc/ruby/methods.X.rb\":[{\"span\":{\"start\":[1,1],\"end\":[3,1]},\"error\":\"def bar\\nen\\n\"}]}}\n" :: ByteString) + it "summarizes Markdown headings" $ do + blobs <- blobsForPaths (both "markdown/headings.A.md" "markdown/headings.B.md") + output <- runTask (diffBlobPair ToCDiffRenderer blobs) + toS output `shouldBe` ("{\"changes\":{\"test/fixtures/toc/markdown/headings.A.md -> test/fixtures/toc/markdown/headings.B.md\":[{\"span\":{\"start\":[5,1],\"end\":[5,7]},\"category\":\"Heading 2\",\"term\":\"## Two\",\"changeType\":\"added\"}]},\"errors\":{}}\n" :: ByteString) + + type Diff' = SyntaxDiff Text (Maybe Declaration ': DefaultFields) type Term' = SyntaxTerm Text (Maybe Declaration ': DefaultFields) diff --git a/test/fixtures/toc/markdown/headings.A.md b/test/fixtures/toc/markdown/headings.A.md new file mode 100644 index 000000000..449ac1be0 --- /dev/null +++ b/test/fixtures/toc/markdown/headings.A.md @@ -0,0 +1,3 @@ +# One + +Just some text diff --git a/test/fixtures/toc/markdown/headings.B.md b/test/fixtures/toc/markdown/headings.B.md new file mode 100644 index 000000000..5e657695c --- /dev/null +++ b/test/fixtures/toc/markdown/headings.B.md @@ -0,0 +1,5 @@ +# One + +Just some text + +## Two From c4206016e917d5df03ff93acd84e59ef4aceba0c Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 10 Jul 2017 13:53:33 -0700 Subject: [PATCH 141/146] Reflow declaration rule --- src/Language/Python/Syntax.hs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 508a69a2e..d507b3211 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -101,7 +101,12 @@ assignment :: Assignment assignment = makeTerm <$> symbol Module <*> children (many declaration) declaration :: Assignment -declaration = handleError $ classDefinition <|> comment <|> decoratedDefinition <|> functionDefinition <|> expression <|> statement +declaration = handleError $ classDefinition + <|> comment + <|> decoratedDefinition + <|> expression + <|> functionDefinition + <|> statement statement :: Assignment statement = assertStatement From a64d85410c8b99310cf0e042c890a3cfc41a9925 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 10 Jul 2017 13:53:42 -0700 Subject: [PATCH 142/146] Assign default parameters --- src/Language/Python/Syntax.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index d507b3211..19838467b 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -145,6 +145,7 @@ expression = await <|> comparisonOperator <|> comprehension <|> conditionalExpression + <|> defaultParameter <|> dottedName <|> ellipsis <|> expressionList @@ -160,6 +161,9 @@ expression = await <|> typedParameter <|> unaryOperator +defaultParameter :: Assignment +defaultParameter = makeTerm <$> symbol DefaultParameter <*> children (Statement.Assignment <$> expression <*> expression) + decoratedDefinition :: Assignment decoratedDefinition = makeTerm <$> symbol DecoratedDefinition <*> (children $ do (a, b) <- (symbol Decorator *> (children ((,) <$> expression <*> (symbol ArgumentList *> children ((many expression) <|> (many emptyTerm)))))) From a03300c920acdba28a0aa76811980cf81cb14b47 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 10 Jul 2017 13:59:40 -0700 Subject: [PATCH 143/146] Add test covering default parameters in Python --- test/fixtures/python/function-definition.A.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/fixtures/python/function-definition.A.py b/test/fixtures/python/function-definition.A.py index fc3117d43..9b792c9f0 100644 --- a/test/fixtures/python/function-definition.A.py +++ b/test/fixtures/python/function-definition.A.py @@ -6,3 +6,6 @@ def c(d): def g(g, h,): i + +def h(i=j): + i From c46a0bd6155cdca5fe22f7f1eb1d77604717e8ea Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 10 Jul 2017 15:58:29 -0700 Subject: [PATCH 144/146] :memo: --- src/Data/Syntax/Statement.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Data/Syntax/Statement.hs b/src/Data/Syntax/Statement.hs index 17f708ffe..5a6ea79d0 100644 --- a/src/Data/Syntax/Statement.hs +++ b/src/Data/Syntax/Statement.hs @@ -38,7 +38,7 @@ newtype Pattern a = Pattern a instance Eq1 Pattern where liftEq = genericLiftEq instance Show1 Pattern where liftShowsPrec = genericLiftShowsPrec - +-- | A let statement or local binding, like 'a as b' or 'let a = b'. data Let a = Let { letVariable :: !a, letValue :: !a, letBody :: !a } deriving (Eq, Foldable, Functor, GAlign, Generic1, Show, Traversable) From b35091f7542efd8b94145f65746cd3da17965404 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 10 Jul 2017 15:58:41 -0700 Subject: [PATCH 145/146] Assign aliased imports --- src/Language/Python/Syntax.hs | 4 ++++ test/fixtures/python/import-statement.A.py | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 19838467b..03ecca3f3 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -124,6 +124,7 @@ statement = assertStatement <|> ifStatement <|> identifier <|> import' + <|> importAlias <|> importFrom <|> nonlocalStatement <|> passStatement @@ -354,6 +355,9 @@ import' = makeTerm <$> symbol ImportStatement <*> children (Declaration.Import < importFrom :: Assignment importFrom = makeTerm <$> symbol ImportFromStatement <*> children (Declaration.Import <$> many expression) +importAlias :: Assignment +importAlias = makeTerm <$> symbol AliasedImport <*> children (flip Statement.Let <$> expression <*> expression <*> emptyTerm) + assertStatement :: Assignment assertStatement = makeTerm <$ symbol AssertStatement <*> location <*> children (Expression.Call <$> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier <$> source)) <*> many expression) diff --git a/test/fixtures/python/import-statement.A.py b/test/fixtures/python/import-statement.A.py index 212b3db10..245079e6a 100644 --- a/test/fixtures/python/import-statement.A.py +++ b/test/fixtures/python/import-statement.A.py @@ -1,2 +1,2 @@ -import a, b -import b.c as d +import a, b as c +import b.c as d, e From d6e101711710ca8e87cb21bc3aa3c3e352662b29 Mon Sep 17 00:00:00 2001 From: Rick Winfrey Date: Mon, 10 Jul 2017 16:11:03 -0700 Subject: [PATCH 146/146] Assign wildcard (*) in import from statements --- src/Language/Python/Syntax.hs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Language/Python/Syntax.hs b/src/Language/Python/Syntax.hs index 03ecca3f3..3c952c3ed 100644 --- a/src/Language/Python/Syntax.hs +++ b/src/Language/Python/Syntax.hs @@ -133,6 +133,7 @@ statement = assertStatement <|> returnStatement <|> tryStatement <|> whileStatement + <|> wildcardImport <|> withStatement expressionStatement :: Assignment @@ -358,6 +359,9 @@ importFrom = makeTerm <$> symbol ImportFromStatement <*> children (Declaration.I importAlias :: Assignment importAlias = makeTerm <$> symbol AliasedImport <*> children (flip Statement.Let <$> expression <*> expression <*> emptyTerm) +wildcardImport :: Assignment +wildcardImport = makeTerm <$> symbol WildcardImport <*> (Syntax.Identifier <$> source) + assertStatement :: Assignment assertStatement = makeTerm <$ symbol AssertStatement <*> location <*> children (Expression.Call <$> (makeTerm <$> symbol AnonAssert <*> (Syntax.Identifier <$> source)) <*> many expression)