mirror of
https://github.com/github/semantic.git
synced 2024-11-23 08:27:56 +03:00
Add semantic-ruby
This commit is contained in:
parent
7bf9f8e9a1
commit
7481e626ed
@ -5,6 +5,7 @@ packages: .
|
||||
semantic-java
|
||||
semantic-json
|
||||
semantic-python
|
||||
semantic-ruby
|
||||
semantic-tags
|
||||
|
||||
jobs: $ncpus
|
||||
|
21
semantic-ruby/LICENSE
Normal file
21
semantic-ruby/LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 GitHub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
3
semantic-ruby/README.md
Normal file
3
semantic-ruby/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# Semantic support for Ruby
|
||||
|
||||
This package implements `semantic` support for Ruby using the `semantic-core` intermediate language.
|
2
semantic-ruby/Setup.hs
Normal file
2
semantic-ruby/Setup.hs
Normal file
@ -0,0 +1,2 @@
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
82
semantic-ruby/semantic-ruby.cabal
Normal file
82
semantic-ruby/semantic-ruby.cabal
Normal file
@ -0,0 +1,82 @@
|
||||
cabal-version: 2.4
|
||||
|
||||
name: semantic-ruby
|
||||
version: 0.0.0.0
|
||||
synopsis: Semantic support for Ruby.
|
||||
description: Semantic support for Ruby using the semantic-core intermediate language.
|
||||
homepage: https://github.com/github/semantic/tree/master/semantic-ruby#readme
|
||||
bug-reports: https://github.com/github/semantic/issues
|
||||
license: MIT
|
||||
license-file: LICENSE
|
||||
author: The Semantic authors
|
||||
maintainer: opensource+semantic@github.com
|
||||
copyright: (c) 2019 GitHub, Inc.
|
||||
category: Language
|
||||
build-type: Simple
|
||||
stability: alpha
|
||||
extra-source-files: README.md
|
||||
|
||||
tested-with: GHC == 8.6.5
|
||||
|
||||
common haskell
|
||||
default-language: Haskell2010
|
||||
build-depends: base ^>=4.12
|
||||
, fused-effects ^>= 1.0
|
||||
, fused-syntax
|
||||
, parsers ^>= 0.12.10
|
||||
, semantic-core ^>= 0.0
|
||||
, semantic-source ^>= 0.0
|
||||
, semantic-tags ^>= 0.0
|
||||
, text ^>= 1.2.3
|
||||
, tree-sitter ^>= 0.7
|
||||
, tree-sitter-ruby ^>= 0.3.1
|
||||
|
||||
ghc-options:
|
||||
-Weverything
|
||||
-Wno-missing-local-signatures
|
||||
-Wno-missing-import-lists
|
||||
-Wno-implicit-prelude
|
||||
-Wno-safe
|
||||
-Wno-unsafe
|
||||
-Wno-name-shadowing
|
||||
-Wno-monomorphism-restriction
|
||||
-Wno-missed-specialisations
|
||||
-Wno-all-missed-specialisations
|
||||
-Wno-star-is-type
|
||||
|
||||
library
|
||||
import: haskell
|
||||
exposed-modules:
|
||||
Language.Ruby
|
||||
Language.Ruby.Tags
|
||||
hs-source-dirs: src
|
||||
|
||||
-- test-suite test
|
||||
-- import: haskell
|
||||
-- type: exitcode-stdio-1.0
|
||||
-- hs-source-dirs: test
|
||||
-- main-is: Test.hs
|
||||
-- ghc-options: -threaded
|
||||
|
||||
-- other-modules: Directive
|
||||
-- , Instances
|
||||
|
||||
-- build-depends: semantic-ruby == 0.0.0.0
|
||||
-- , aeson ^>= 1.4.4
|
||||
-- , aeson-pretty ^>= 0.8.7
|
||||
-- , bytestring ^>= 0.10.8.2
|
||||
-- , containers ^>= 0.6
|
||||
-- , directory ^>= 1.3.3
|
||||
-- , exceptions ^>= 0.10.2
|
||||
-- , pathtype ^>= 0.8.1
|
||||
-- , pretty-show ^>= 1.9.5
|
||||
-- , process ^>= 1.6.5
|
||||
-- , resourcet ^>= 1.2.2
|
||||
-- , semantic-analysis ^>= 0
|
||||
-- , streaming ^>= 0.2.2
|
||||
-- , streaming-process ^>= 0.1
|
||||
-- , streaming-bytestring ^>= 0.1.6
|
||||
-- , tasty ^>= 1.2.3
|
||||
-- , tasty-hunit ^>= 0.10.0.2
|
||||
-- , trifecta >= 2 && <3
|
||||
-- , unordered-containers ^>= 0.2.10
|
19
semantic-ruby/src/Language/Ruby.hs
Normal file
19
semantic-ruby/src/Language/Ruby.hs
Normal file
@ -0,0 +1,19 @@
|
||||
-- | Semantic functionality for Ruby programs.
|
||||
module Language.Ruby
|
||||
( Term(..)
|
||||
, TreeSitter.Ruby.tree_sitter_ruby
|
||||
) where
|
||||
|
||||
import qualified Language.Ruby.Tags as PyTags
|
||||
import qualified Tags.Tagging.Precise as Tags
|
||||
import qualified TreeSitter.Ruby (tree_sitter_ruby)
|
||||
import qualified TreeSitter.Ruby.AST as Rb
|
||||
import qualified TreeSitter.Unmarshal as TS
|
||||
|
||||
newtype Term a = Term { getTerm :: Rb.Program a }
|
||||
|
||||
instance TS.Unmarshal Term where
|
||||
unmarshalNode node = Term <$> TS.unmarshalNode node
|
||||
|
||||
instance Tags.ToTags Term where
|
||||
tags src = Tags.runTagging src . PyTags.tags . getTerm
|
167
semantic-ruby/src/Language/Ruby/Tags.hs
Normal file
167
semantic-ruby/src/Language/Ruby/Tags.hs
Normal file
@ -0,0 +1,167 @@
|
||||
{-# LANGUAGE AllowAmbiguousTypes, DataKinds, DisambiguateRecordFields, FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, NamedFieldPuns, OverloadedStrings, ScopedTypeVariables, TypeApplications, TypeFamilies, TypeOperators, UndecidableInstances #-}
|
||||
module Language.Ruby.Tags
|
||||
( ToTags(..)
|
||||
) where
|
||||
|
||||
import AST.Element
|
||||
import Control.Effect.Reader
|
||||
import Control.Effect.Writer
|
||||
import Data.Maybe (listToMaybe)
|
||||
import Data.Monoid (Ap(..))
|
||||
import Data.List.NonEmpty (NonEmpty(..))
|
||||
import Data.Text as Text
|
||||
import GHC.Generics
|
||||
import Source.Loc
|
||||
import Source.Range
|
||||
import Source.Source as Source
|
||||
import Tags.Tag
|
||||
import qualified Tags.Tagging.Precise as Tags
|
||||
import qualified TreeSitter.Ruby.AST as Rb
|
||||
|
||||
class ToTags t where
|
||||
tags
|
||||
:: ( Has (Reader Source) sig m
|
||||
, Has (Writer Tags.Tags) sig m
|
||||
)
|
||||
=> t Loc
|
||||
-> m ()
|
||||
|
||||
instance (ToTagsBy strategy t, strategy ~ ToTagsInstance t) => ToTags t where
|
||||
tags = tags' @strategy
|
||||
|
||||
|
||||
class ToTagsBy (strategy :: Strategy) t where
|
||||
tags'
|
||||
:: ( Has (Reader Source) sig m
|
||||
, Has (Writer Tags.Tags) sig m
|
||||
)
|
||||
=> t Loc
|
||||
-> m ()
|
||||
|
||||
|
||||
data Strategy = Generic | Custom
|
||||
|
||||
type family ToTagsInstance t :: Strategy where
|
||||
ToTagsInstance (_ :+: _) = 'Custom
|
||||
ToTagsInstance Rb.Class = 'Custom
|
||||
ToTagsInstance Rb.Module = 'Custom
|
||||
ToTagsInstance Rb.Method = 'Custom
|
||||
ToTagsInstance Rb.SingletonMethod = 'Custom
|
||||
|
||||
ToTagsInstance Rb.Call = 'Custom
|
||||
ToTagsInstance Rb.Lhs = 'Custom
|
||||
ToTagsInstance Rb.MethodCall = 'Custom
|
||||
ToTagsInstance _ = 'Generic
|
||||
|
||||
|
||||
instance (ToTags l, ToTags r) => ToTagsBy 'Custom (l :+: r) where
|
||||
tags' (L1 l) = tags l
|
||||
tags' (R1 r) = tags r
|
||||
|
||||
yieldTag :: (Has (Reader Source) sig m, Has (Writer Tags.Tags) sig m) => Text -> Kind -> Loc -> Range -> m ()
|
||||
yieldTag name kind loc range = do
|
||||
src <- ask @Source
|
||||
let sliced = slice src range
|
||||
Tags.yield (Tag name kind loc (Tags.firstLine sliced) Nothing)
|
||||
|
||||
instance ToTagsBy 'Custom Rb.Class where
|
||||
tags' t@Rb.Class
|
||||
{ ann = loc@Loc { byteRange = range }
|
||||
, name = expr
|
||||
} = case expr of
|
||||
Prj Rb.Constant { text = name } -> yield name
|
||||
Prj Rb.ScopeResolution { name = Prj Rb.Constant { text = name } } -> yield name
|
||||
Prj Rb.ScopeResolution { name = Prj Rb.Identifier { text = name } } -> yield name
|
||||
_ -> gtags t
|
||||
where
|
||||
yield name = yieldTag name Class loc range >> gtags t
|
||||
|
||||
instance ToTagsBy 'Custom Rb.Module where
|
||||
tags' t@Rb.Module
|
||||
{ ann = loc@Loc { byteRange = range }
|
||||
, name = expr
|
||||
} = case expr of
|
||||
Prj Rb.Constant { text = name } -> yield name
|
||||
Prj Rb.ScopeResolution { name = Prj Rb.Constant { text = name } } -> yield name
|
||||
Prj Rb.ScopeResolution { name = Prj Rb.Identifier { text = name } } -> yield name
|
||||
_ -> gtags t
|
||||
where
|
||||
yield name = yieldTag name Module loc range >> gtags t
|
||||
|
||||
yieldMethodNameTag t loc range expr = case expr of
|
||||
Prj Rb.Identifier { text = name } -> yield name
|
||||
Prj Rb.Constant { text = name } -> yield name
|
||||
Prj Rb.ClassVariable { text = name } -> yield name
|
||||
Prj Rb.Operator { text = name } -> yield name
|
||||
Prj Rb.GlobalVariable { text = name } -> yield name
|
||||
Prj Rb.InstanceVariable { text = name } -> yield name
|
||||
Prj Rb.Setter { extraChildren = Rb.Identifier { text = name } } -> yield name
|
||||
-- TODO: Should we report symbol method names as tags?
|
||||
-- Prj Rb.Symbol { extraChildren = [Prj Rb.EscapeSequence { text = name }] } -> yield name
|
||||
_ -> gtags t
|
||||
where
|
||||
yield name = yieldTag name Function loc range >> gtags t
|
||||
|
||||
instance ToTagsBy 'Custom Rb.Method where
|
||||
tags' t@Rb.Method
|
||||
{ ann = loc@Loc { byteRange = range }
|
||||
, name = Rb.MethodName expr
|
||||
} = yieldMethodNameTag t loc range expr
|
||||
|
||||
instance ToTagsBy 'Custom Rb.SingletonMethod where
|
||||
tags' t@Rb.SingletonMethod
|
||||
{ ann = loc@Loc { byteRange = range }
|
||||
, name = Rb.MethodName expr
|
||||
} = yieldMethodNameTag t loc range expr
|
||||
|
||||
instance ToTagsBy 'Custom Rb.Call where
|
||||
tags' t@Rb.Call
|
||||
{ ann = loc@Loc { byteRange = range }
|
||||
, method = expr
|
||||
} = do
|
||||
case expr of
|
||||
Prj Rb.Identifier { text = name } -> yield name
|
||||
Prj Rb.Constant { text = name } -> yield name
|
||||
Prj Rb.Operator { text = name } -> yield name
|
||||
_ -> gtags t
|
||||
where
|
||||
yield name = yieldTag name Call loc range >> gtags t
|
||||
|
||||
instance ToTagsBy 'Custom Rb.Lhs where
|
||||
tags' t@(Rb.Lhs (Prj (Rb.Variable expr)))
|
||||
= case expr of
|
||||
Prj Rb.Identifier { ann = loc@Loc { byteRange = range }, text = name } -> yieldTag name Call loc range >> gtags t
|
||||
Prj Rb.Constant { ann = loc@Loc { byteRange = range }, text = name } -> yieldTag name Call loc range >> gtags t
|
||||
_ -> gtags t
|
||||
tags' t = gtags t
|
||||
|
||||
instance ToTagsBy 'Custom Rb.MethodCall where
|
||||
tags' t@Rb.MethodCall
|
||||
{ ann = loc@Loc { byteRange = range }
|
||||
, method = expr
|
||||
} = case expr of
|
||||
Prj (Rb.Variable (Prj Rb.Identifier { text = name })) -> yield name
|
||||
Prj (Rb.Variable (Prj Rb.Constant { text = name })) -> yield name
|
||||
Prj (Rb.Variable (Prj Rb.GlobalVariable { text = name })) -> yield name
|
||||
Prj (Rb.Variable (Prj Rb.ClassVariable { text = name })) -> yield name
|
||||
Prj (Rb.Variable (Prj Rb.InstanceVariable { text = name })) -> yield name
|
||||
_ -> gtags t
|
||||
where
|
||||
yield name = yieldTag name Call loc range >> gtags t
|
||||
|
||||
-- docComment :: Source -> (Rb.CompoundStatement :+: Rb.SimpleStatement) Loc -> Maybe Text
|
||||
-- docComment src (R1 (Rb.SimpleStatement (Prj Rb.ExpressionStatement { extraChildren = L1 (Prj (Rb.Expression (Prj (Rb.PrimaryExpression (Prj Rb.String { ann }))))) :|_ }))) = Just (toText (slice src (byteRange ann)))
|
||||
-- docComment _ _ = Nothing
|
||||
|
||||
gtags
|
||||
:: ( Has (Reader Source) sig m
|
||||
, Has (Writer Tags.Tags) sig m
|
||||
, Generic1 t
|
||||
, Tags.GFoldable1 ToTags (Rep1 t)
|
||||
)
|
||||
=> t Loc
|
||||
-> m ()
|
||||
gtags = getAp . Tags.gfoldMap1 @ToTags (Ap . tags) . from1
|
||||
|
||||
instance (Generic1 t, Tags.GFoldable1 ToTags (Rep1 t)) => ToTagsBy 'Generic t where
|
||||
tags' = gtags
|
@ -288,6 +288,7 @@ library
|
||||
, semantic-java ^>= 0
|
||||
, semantic-json ^>= 0
|
||||
, semantic-python ^>= 0
|
||||
, semantic-ruby ^>= 0
|
||||
, semantic-tags ^>= 0
|
||||
, semigroupoids ^>= 5.3.2
|
||||
, split ^>= 0.2.3.3
|
||||
|
Loading…
Reference in New Issue
Block a user