sibyl2

package module
v0.16.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 23, 2023 License: Apache-2.0 Imports: 11 Imported by: 4

README

sibyl 2

An easy-to-use logical layer on codebase.

中文文档

Status

Name Badge
Latest Version GitHub release (latest by date)
Unit Tests Go
Docker Image ImageBuild
Perf Tests perftest
Code Coverage codecov
Code Style Go Report Card

Overview

sibyl2 is a static code analyze service, for extracting, managing and offering metadata of your code in codebase. Inspired by semantic of GitHub.

  • Easy to use
  • Fast enough
  • Extensible
  • Multiple languages in one (Go/Java/Python ...)

What's logical layer?

SCM (GitHub, for example) manages code as plain text. We call it physical layer.

func TestExtractString(t *testing.T) {
    fileResult, err := ExtractFromString(javaCodeForExtract, &ExtractConfig{
        LangType:    core.LangJava,
        ExtractType: extractor.TypeExtractFunction,
    })
    if err != nil {
        panic(err)
    }
    for _, each := range fileResult.Units {
        core.Log.Debugf("result: %s", each.GetDesc())
    }
}

sibyl2 manages metadata of code. We call it logical layer.

{
  "_id": {
    "$oid": "641b085deae764d271e2f426"
  },
  "repo_id": "sibyl2",
  "rev_hash": "e995ef44372a93394199ea837b1e2eed375a71a0",
  "path": "extract_test.go",
  "signature": "sibyl2||TestExtractString|*testing.T|",
  "tags": [],
  "func": {
    "name": "TestExtractString",
    "receiver": "",
    "namespace": "sibyl2",
    "parameters": [
      {
        "type": "*testing.T",
        "name": "t"
      }
    ],
    "returns": null,
    "span": {
      "start": {
        "row": {
          "$numberLong": "34"
        },
        "column": {
          "$numberLong": "0"
        }
      },
      "end": {
        "row": {
          "$numberLong": "45"
        },
        "column": {
          "$numberLong": "1"
        }
      }
    },
    "extras": {},
    "lang": "GOLANG"
  }
}

Try it in 3 minutes

sibyl2 supports multiple database backends. It can also run with no middleware and database installed, if you just want to take a try.

Deployment

Users can access all the features with a simple binary file, without any extra dependencies and scripts.

You can download from the release page.

Or directly download with wget (linux only):

curl https://raw.githubusercontent.com/opensibyl/sibyl2/master/scripts/download_latest.sh | bash

Now you can start it:

./sibyl server

That's it. Server will run on port :9876. Data will be persisted in ./sibyl2Storage.

Upload

./sibyl upload --src . --url http://127.0.0.1:9876

You can upload from different machines. Usually it only takes a few seconds.

Access

Now all the data is ready! We have a built-in dashboard for visualization. Start it with:

./sibyl frontend

And open localhost:3000 you will see:

image

Of course, at the most time, we access data programmatically. You can access all the data via different kinds of languages, to build your own tools:

For example, git diff with logical?

// assume that we have edited these lines
affectedFileMap := map[string][]int{
    "pkg/core/parser.go": {4, 89, 90, 91, 92, 93, 94, 95, 96},
    "pkg/core/unit.go":   {27, 28, 29},
}

for fileName, lineList := range affectedFileMap {
    strLineList := make([]string, 0, len(lineList))
    for _, each := range lineList {
        strLineList = append(strLineList, strconv.Itoa(each))
    }

    affectedFunctions, _, err := apiClient.BasicQueryApi.
        ApiV1FuncctxGet(ctx).
        Repo(projectName).
        Rev(head.Hash().String()).
        File(fileName).
        Lines(strings.Join(strLineList, ",")).
        Execute()
	
    for _, eachFunc := range affectedFunctions {
        // get all the calls details?
        for _, eachCall := range eachFunc.Calls {
            detail, _, err := apiClient.SignatureQueryApi.
                ApiV1SignatureFuncGet(ctx).
                Repo(projectName).
                Rev(head.Hash().String()).
                Signature(eachCall).
                Execute()
            assert.Nil(t, err)
            core.Log.Infof("call: %v", detail)
        }
    }
}
Language Link
Golang https://github.com/opensibyl/sibyl-go-client
Java https://github.com/opensibyl/sibyl-java-client
JavaScript https://github.com/opensibyl/sibyl-javascript-client

See more examples about how to use for details.

Purpose & Principles

We hope to provide a unified logical layer for different tools in the entire DevOps process, sharing a single data source, rather than each tool performing its own set of duplicate parsing logic.

See About This Project: Code Snapshot Layer In DevOps for details.

Languages support

Languages Function Function Context Class
Golang Yes Yes Yes
Java Yes Yes Yes
Python Yes Yes Yes
Kotlin Yes Yes Yes
JavaScript Yes Yes Yes

Based on tree-sitter, it's very easy to add an extra language support.

In Production

We use mongo db as our official backend in production. All you need is adding a sibyl-server-config.json file:

{
  "binding": {
    "dbtype": "MONGO",
    "mongodbname": "sibyl2",
    "mongouri": "mongodb+srv://feng:<YOURPASSWORD>@XXXXXXXX.mongodb.net/test"
  }
}

Everything done.

mongo_func_detail

Performance

We have tested it on some famous repos, like guava. And that's why we can say it is " fast enough".

See https://github.com/williamfzc/sibyl2/actions/workflows/perf.yml for details.

Language Repo Cost
Golang https://github.com/gin-gonic/gin.git ~1s
Java https://github.com/spring-projects/spring-boot.git ~50s
Python https://github.com/psf/requests ~1s
Kotlin https://github.com/square/okhttp ~1s

Contribution

This project split into 3 main parts:

  • /cmd: Pure command line tool for general usage
  • /pkg/server: All-in-one service for production
  • others: Shared api and core

Workflow:

  • core: collect files and convert them to Unit.
  • extract: classify and process units into functions, symbols.
  • api: higher level analyze like callgraph

Issues / PRs are welcome!

References

License

Apache License Version 2.0, see LICENSE

Documentation

Index

Constants

View Source
const HomePage = "https://github.com/opensibyl/sibyl2"
View Source
const Version = "v0.16.1"

Version strictly sync with tag

Variables

This section is empty.

Functions

func Extract

func Extract(targetFile string, config *ExtractConfig) ([]*extractor.FileResult, error)

func ExtractClazz added in v0.10.0

func ExtractClazz(targetFile string, config *ExtractConfig) ([]*extractor.ClazzFileResult, error)

func ExtractFromBytes

func ExtractFromBytes(content []byte, config *ExtractConfig) (*extractor.FileResult, error)

func ExtractFromString

func ExtractFromString(content string, config *ExtractConfig) (*extractor.FileResult, error)

func ExtractFunction

func ExtractFunction(targetFile string, config *ExtractConfig) ([]*extractor.FunctionFileResult, error)

func ExtractSymbol

func ExtractSymbol(targetFile string, config *ExtractConfig) ([]*extractor.SymbolFileResult, error)

func QueryUnitsByIndexNames

func QueryUnitsByIndexNames[T extractor.DataType](result *extractor.BaseFileResult[T], indexNames ...string) []T

func QueryUnitsByIndexNamesInFiles

func QueryUnitsByIndexNamesInFiles[T extractor.DataType](result []*extractor.BaseFileResult[T], indexNames ...string) []T

func QueryUnitsByLines

func QueryUnitsByLines[T extractor.DataType](result *extractor.BaseFileResult[T], lines ...int) []T

Types

type AdjacencyMapType

type AdjacencyMapType = map[string]map[string]graph.Edge[string]

type ExtractConfig

type ExtractConfig struct {
	LangType    core.LangType
	ExtractType extractor.ExtractType
	FileFilter  func(path string) bool
}

ExtractConfig todo: should not use config ptr for parallel running

func DefaultConfig

func DefaultConfig() *ExtractConfig

type FuncGraph

type FuncGraph struct {
	ReverseCallGraph *FuncGraphType
	CallGraph        *FuncGraphType
}

FuncGraph

It is not a serious `call` graph. It based on references not real calls.

Why we used it: - We can still use something like `method_invocation` - But we mainly use it to evaluate the influence of a method - In many languages, scope of `invocation` is too small - For example, use `function` as a parameter.

func AnalyzeFuncGraph

func AnalyzeFuncGraph(funcFiles []*extractor.FunctionFileResult, symbolFiles []*extractor.SymbolFileResult) (*FuncGraph, error)

func (*FuncGraph) FindCalls

func (*FuncGraph) FindRelated

func (fg *FuncGraph) FindRelated(f *extractor.FunctionWithPath) *FunctionContext

func (*FuncGraph) FindReverseCalls

func (fg *FuncGraph) FindReverseCalls(f *extractor.FunctionWithPath) []*extractor.FunctionWithPath

type FuncGraphType

type FuncGraphType struct {
	graph.Graph[string, *extractor.FunctionWithPath]
	// contains filtered or unexported fields
}

func (*FuncGraphType) GetAdjacencyMap

func (fgt *FuncGraphType) GetAdjacencyMap() (*AdjacencyMapType, error)

type FunctionContext

type FunctionContext struct {
	*extractor.FunctionWithPath
	Calls        []*extractor.FunctionWithPath `json:"calls" bson:"calls"`
	ReverseCalls []*extractor.FunctionWithPath `json:"reverseCalls" bson:"reverseCalls"`
}

func (*FunctionContext) ToGraph

func (f *FunctionContext) ToGraph() *FuncGraphType

func (*FunctionContext) ToJson added in v0.8.0

func (f *FunctionContext) ToJson() ([]byte, error)

func (*FunctionContext) ToMap added in v0.8.0

func (f *FunctionContext) ToMap() (map[string]any, error)

ToMap export a very simple map without any custom structs. It will lose ptr to origin unit.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL