From 92b383cf45f9b4912d750fce1054b9286d0ce670 Mon Sep 17 00:00:00 2001 From: Timothy Clem Date: Thu, 15 Mar 2018 12:29:08 -0700 Subject: [PATCH] Extract some comment path to qualified name helpers --- src/Data/Abstract/FreeVariables.hs | 15 +++++++++++++++ src/Language/Go/Assignment.hs | 5 +---- src/Language/Ruby/Syntax.hs | 14 +++----------- src/Language/TypeScript/Assignment.hs | 9 --------- test/Analysis/Ruby/Spec.hs | 12 ++++-------- 5 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/Data/Abstract/FreeVariables.hs b/src/Data/Abstract/FreeVariables.hs index 2e73218c2..19d319cd5 100644 --- a/src/Data/Abstract/FreeVariables.hs +++ b/src/Data/Abstract/FreeVariables.hs @@ -5,16 +5,31 @@ import Prologue import Data.Term import Data.ByteString (intercalate) import qualified Data.List.NonEmpty as NonEmpty +import qualified Data.ByteString.Char8 as BC +import qualified Data.ByteString as B (filter) +import Data.Char (ord) -- | The type of variable names. type Name = NonEmpty ByteString +-- | Construct a qualified name from a 'ByteString' name :: ByteString -> Name name x = x :| [] +-- | Construct a qualified name from a list of 'ByteString's qualifiedName :: [ByteString] -> Name qualifiedName = NonEmpty.fromList +-- | Split a 'ByteString' path on `/`, stripping quotes and any `./` prefix. +splitOnPathSeparator :: ByteString -> [ByteString] +splitOnPathSeparator = BC.split '/' . BC.dropWhile (== '/') . BC.dropWhile (== '.') . stripQuotes + where stripQuotes = B.filter (/= fromIntegral (ord '\"')) + +-- | Construct a qualified 'Name' from a `/` delimited path. +pathToQualifiedName :: ByteString -> Name +pathToQualifiedName = qualifiedName . splitOnPathSeparator + +-- | User friendly version of a qualified 'Name'. friendlyName :: Name -> ByteString friendlyName xs = intercalate "." (NonEmpty.toList xs) diff --git a/src/Language/Go/Assignment.hs b/src/Language/Go/Assignment.hs index 7bfad97b8..575f5bef5 100644 --- a/src/Language/Go/Assignment.hs +++ b/src/Language/Go/Assignment.hs @@ -395,7 +395,7 @@ importDeclaration = makeTerm'' <$> symbol ImportDeclaration <*> children (manyTe namedImport = inj <$> (flip Declaration.QualifiedImport <$> packageIdentifier <*> importFromPath <*> pure []) -- `import "lib/Math"` plainImport = inj <$> (symbol InterpretedStringLiteral >>= \loc -> do - names <- pathToNames <$> source + names <- splitOnPathSeparator <$> source let from = makeTerm loc (Syntax.Identifier (qualifiedName names)) let alias = makeTerm loc (Syntax.Identifier (name (last names))) -- Go takes `import "lib/Math"` and uses `Math` as the qualified name (e.g. `Math.Sin()`) Declaration.QualifiedImport <$> pure from <*> pure alias <*> pure []) @@ -406,9 +406,6 @@ importDeclaration = makeTerm'' <$> symbol ImportDeclaration <*> children (manyTe importSpec = makeTerm' <$> symbol ImportSpec <*> children (sideEffectImport <|> dotImport <|> namedImport <|> plainImport) importSpecList = makeTerm <$> symbol ImportSpecList <*> children (manyTerm (importSpec <|> comment)) importFromPath = makeTerm <$> symbol InterpretedStringLiteral <*> (Syntax.Identifier <$> (pathToQualifiedName <$> source)) - pathToQualifiedName = qualifiedName . pathToNames - pathToNames = BC.split '/' . (BC.dropWhile (== '/')) . (BC.dropWhile (== '.')) . stripQuotes - stripQuotes = B.filter (/= (fromIntegral (ord '\"'))) indexExpression :: Assignment indexExpression = makeTerm <$> symbol IndexExpression <*> children (Expression.Subscript <$> expression <*> manyTerm expression) diff --git a/src/Language/Ruby/Syntax.hs b/src/Language/Ruby/Syntax.hs index af2bd25eb..211b708f1 100644 --- a/src/Language/Ruby/Syntax.hs +++ b/src/Language/Ruby/Syntax.hs @@ -2,16 +2,14 @@ module Language.Ruby.Syntax where import Data.Abstract.Environment +import Data.Abstract.FreeVariables import Data.Abstract.Evaluatable import Diffing.Algorithm -import Prelude hiding (fail) +-- import Prelude hiding (fail) import Prologue import qualified Data.Map as Map -import qualified Data.ByteString.Char8 as BC -import qualified Data.ByteString as B (filter) -import Data.Char (ord) -data Require a = Require { requirePath :: !a } +newtype Require a = Require { requirePath :: a } deriving (Diffable, Eq, Foldable, Functor, GAlign, Generic1, Mergeable, Ord, Show, Traversable, FreeVariables1) instance Eq1 Require where liftEq = genericLiftEq @@ -25,9 +23,3 @@ instance Evaluatable Require where importedEnv <- withGlobalEnv mempty (require (pathToQualifiedName path)) modifyGlobalEnv (flip (Map.foldrWithKey envInsert) (unEnvironment importedEnv)) unit - where - pathToQualifiedName :: ByteString -> Name - pathToQualifiedName = qualifiedName . BC.split '/' . (BC.dropWhile (== '/')) . (BC.dropWhile (== '.')) . stripQuotes - - stripQuotes :: ByteString -> ByteString - stripQuotes = B.filter (/= (fromIntegral (ord '\"'))) diff --git a/src/Language/TypeScript/Assignment.hs b/src/Language/TypeScript/Assignment.hs index 52f1af3c7..ab0df4765 100644 --- a/src/Language/TypeScript/Assignment.hs +++ b/src/Language/TypeScript/Assignment.hs @@ -9,9 +9,6 @@ module Language.TypeScript.Assignment import Assigning.Assignment hiding (Assignment, Error) import qualified Assigning.Assignment as Assignment import Data.Abstract.FreeVariables -import qualified Data.ByteString as B (filter) -import qualified Data.ByteString.Char8 as BC -import Data.Char (ord) import Data.Record import Data.Syntax (emptyTerm, handleError, parseError, infixContext, makeTerm, makeTerm', makeTerm'', makeTerm1, contextualize, postContextualize) import qualified Data.Syntax as Syntax @@ -676,12 +673,6 @@ importStatement = makeImportTerm <$> symbol Grammar.ImportStatement <*> childr fromClause :: Assignment fromClause = makeTerm <$> symbol Grammar.String <*> (Syntax.Identifier <$> (pathToQualifiedName <$> source)) - where - pathToQualifiedName :: ByteString -> Name - pathToQualifiedName = qualifiedName . BC.split '/' . (BC.dropWhile (== '/')) . (BC.dropWhile (== '.')) . stripQuotes - - stripQuotes :: ByteString -> ByteString - stripQuotes = B.filter (/= (fromIntegral (ord '\"'))) debuggerStatement :: Assignment debuggerStatement = makeTerm <$> symbol Grammar.DebuggerStatement <*> (TypeScript.Syntax.Debugger <$ source) diff --git a/test/Analysis/Ruby/Spec.hs b/test/Analysis/Ruby/Spec.hs index 3f13efb6f..58418abd6 100644 --- a/test/Analysis/Ruby/Spec.hs +++ b/test/Analysis/Ruby/Spec.hs @@ -10,19 +10,15 @@ import SpecHelpers spec :: Spec spec = parallel $ do describe "evalutes Ruby" $ do - it "require_relatives" $ do - res <- evaluate "main.rb" + it "require_relative method" $ do + env <- evaluate "main.rb" let expectedEnv = Environment $ fromList [ (qualifiedName ["foo"], addr 0) ] - assertEnvironment res expectedEnv + env `shouldBe` expectedEnv where - assertEnvironment result expectedEnv = case result of - Left e -> expectationFailure ("Evaluating expected to succeed, but failed with: " <> e) - Right res -> let Just (Interface _ env) = prjValue @(Interface Precise) res in env `shouldBe` expectedEnv - addr = Address . Precise fixtures = "test/fixtures/ruby/analysis/" - evaluate entry = fst . fst . fst . fst <$> + evaluate entry = snd . fst . fst . fst <$> evaluateFiles @RubyValue rubyParser [ fixtures <> entry , fixtures <> "foo.rb"