Help us shape the future of Go! Take the 2026 Go Developer Survey

analysis

package
v0.7.2 Latest Latest
Warning

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

Go to latest
Published: Apr 19, 2026 License: MIT Imports: 38 Imported by: 0

Documentation

Overview

scope resolution implementation for JS and TS files

Index

Constants

This section is empty.

Variables

View Source
var ErrUnsupportedLanguage = fmt.Errorf("unsupported language")

ParseFile parses the file at the given path using the appropriate tree-sitter grammar.

View Source
var ScopeNodes = []string{
	"statement_block",
	"function_declaration",
	"function_expression",
	"for_statement",
	"for_in_statement",
	"for_of_statement",
	"program",
	"arrow_function",
	"class_body",

	"method_definition",
}

Functions

func ChildWithFieldName added in v0.4.0

func ChildWithFieldName(node *sitter.Node, fieldName string) *sitter.Node

func ChildrenOfType added in v0.4.0

func ChildrenOfType(node *sitter.Node, nodeType string) []*sitter.Node

func ChildrenWithFieldName added in v0.4.0

func ChildrenWithFieldName(node *sitter.Node, fieldName string) []*sitter.Node

ChildrenWithFieldName returns all the children of a node with a specific field name. Tree-sitter can have multiple children with the same field name.

func ContainsSkipcq added in v0.7.0

func ContainsSkipcq(skipLines []*SkipComment, issue *Issue) bool

func FindMatchingChild added in v0.4.0

func FindMatchingChild(node *sitter.Node, predicate func(*sitter.Node) bool) *sitter.Node

FindMatchingChild iterates over all children of a node—both named and unnamed—and returns the first child that matches the predicate function.

func FirstChildOfType added in v0.4.0

func FirstChildOfType(node *sitter.Node, nodeType string) *sitter.Node

func GetEscapedCommentIdentifierFromPath added in v0.3.0

func GetEscapedCommentIdentifierFromPath(path string) string

func GetExtFromLanguage added in v0.4.0

func GetExtFromLanguage(lang Language) string

func IssueAsTextFromJson added in v0.3.0

func IssueAsTextFromJson(jsonData []byte) ([]byte, error)

func Preorder

func Preorder(pass *Pass, fn func(*sitter.Node))

func ReadFromBytes added in v0.7.1

func ReadFromBytes(fileContent []byte) (Analyzer, YamlAnalyzer, error)

ReadFromBytes reads a pattern checker definition from bytes array

func ReadFromFile added in v0.7.1

func ReadFromFile(filePath string) (Analyzer, YamlAnalyzer, error)

ReadFromFile reads a pattern checker definition from a YAML config file.

func ReportIssues

func ReportIssues(issues []*Issue, format string) ([]byte, error)

func RunAnalyzerTests added in v0.3.0

func RunAnalyzerTests(testDir string, analyzers []*Analyzer) (string, string, bool, error)

func RunYamlAnalyzer added in v0.7.1

func RunYamlAnalyzer(YamlAnalyzer *YamlAnalyzer) func(pass *Pass) (any, error)

func RunYamlTests added in v0.7.1

func RunYamlTests(testDir string) (passed bool, err error)

func WalkTree added in v0.4.0

func WalkTree(node *sitter.Node, walker Walker)

Types

type Analyzer

type Analyzer struct {
	Name        string
	Description string
	Category    Category
	Severity    Severity
	Language    Language
	Requires    []*Analyzer
	Run         func(*Pass) (any, error)
	ResultType  reflect.Type
}

type Category

type Category string
const (
	CategoryStyle       Category = "style"
	CategoryBugRisk     Category = "bug-risk"
	CategoryAntipattern Category = "antipattern"
	CategoryPerformance Category = "performance"
	CategorySecurity    Category = "security"
)

func (Category) IsValid

func (c Category) IsValid() bool

type Issue

type Issue struct {
	// The category of the issue
	Category Category
	// The severity of the issue
	Severity Severity
	// The message to display to the user
	Message string
	// The file path of the file that the issue was found in
	Filepath string
	// (optional) The AST node that caused the issue
	Node *sitter.Node
	// Id is a unique ID for the issue.
	// Issue that have 'Id's can be explained using the `globstar desc` command.
	Id *string
}

func IssueFromJson added in v0.3.0

func IssueFromJson(jsonData []byte) (*Issue, error)

func RunAnalyzers

func RunAnalyzers(path string, analyzers []*Analyzer, fileFilter func(string) bool) ([]*Issue, error)

func (*Issue) AsJson

func (i *Issue) AsJson() ([]byte, error)

func (*Issue) AsText

func (i *Issue) AsText() ([]byte, error)

type Language

type Language int
const (
	LangUnknown Language = iota
	LangPy
	LangJs  // vanilla JS and JSX
	LangTs  // TypeScript (not TSX)
	LangTsx // TypeScript with JSX extension
	LangJava
	LangRuby
	LangRust
	LangYaml
	LangCss
	LangDockerfile
	LangMarkdown
	LangSql
	LangKotlin
	LangOCaml
	LangLua
	LangBash
	LangCsharp
	LangElixir
	LangElm
	LangGo
	LangGroovy
	LangHcl
	LangHtml
	LangPhp
	LangScala
	LangSwift
)

func DecodeLanguage added in v0.7.1

func DecodeLanguage(language string) Language

func LanguageFromFilePath

func LanguageFromFilePath(path string) Language

LanguageFromFilePath returns the Language of the file at the given path returns `LangUnkown` if the language is not recognized (e.g: `.txt` files).

func (Language) Grammar

func (lang Language) Grammar() *sitter.Language

tsGrammarForLang returns the tree-sitter grammar for the given language. May return `nil` when `lang` is `LangUnkown`.

type NodeFilter added in v0.7.1

type NodeFilter struct {
	// contains filtered or unexported fields
}

NodeFilter is a filter that can be applied to a PatternChecker to restrict the nodes that the checker is applied to. The checker is only applied to nodes that have a parent matching (or not matching) the query.

type ParseResult

type ParseResult struct {
	// Ast is the root node of the tree-sitter parse-tree
	// representing this file
	Ast *sitter.Node
	// Source is the raw source code of the file
	Source []byte
	// FilePath is the path to the file that was parsed
	FilePath string
	// Language is the tree-sitter language used to parse the file
	TsLanguage *sitter.Language
	// Language is the language of the file
	Language Language
	// ScopeTree represents the scope hierarchy of the file.
	// Can be nil if scope support for this language has not been implemented yet.
	ScopeTree *ScopeTree
}

ParseResult is the result of parsing a file.

func Parse

func Parse(filePath string, source []byte, language Language, grammar *sitter.Language) (*ParseResult, error)

func ParseFile

func ParseFile(filePath string) (*ParseResult, error)

type Pass

type Pass struct {
	Analyzer    *Analyzer
	FileContext *ParseResult
	Files       []*ParseResult
	ResultOf    map[*Analyzer]any
	Report      func(*Pass, *sitter.Node, string)
	// TODO (opt): the cache should ideally not be stored in-memory
	ResultCache map[*Analyzer]map[*ParseResult]any
}

type PathFilter added in v0.7.1

type PathFilter struct {
	ExcludeGlobs []glob.Glob
	IncludeGlobs []glob.Glob
}

PathFilter is a glob that can be applied to a PatternChecker to restrict the files that the checker is applied to.

type Reference added in v0.4.0

type Reference struct {
	// IsWriteRef determines if this reference is a write reference.
	// For write refs, only the expression being assigned is stored.
	// i.e: for `a = 3`, this list will store the `3` node, not the assignment node
	IsWriteRef bool
	// Variable stores the variable being referenced
	Variable *Variable
	// Node stores the node that references the variable
	Node *sitter.Node
}

Reference represents a variable reference inside a source file Cross-file references like those in Golang and C++ (macros/extern) are NOT supported, so this shouldn't be used for checkers like "unused-variable", but is safe to use for checkers like "unused-import"

type Scope added in v0.4.0

type Scope struct {
	// AstNode is the AST node that introduces this scope into the scope tree
	AstNode *sitter.Node
	// Variables is a map of variable name to an object representing it
	Variables map[string]*Variable
	// Upper is the parent scope of this scope
	Upper *Scope
	// Children is a list of scopes that are children of this scope
	Children []*Scope
}

func NewScope added in v0.4.0

func NewScope(upper *Scope) *Scope

func (*Scope) Lookup added in v0.4.0

func (s *Scope) Lookup(name string) *Variable

Lookup searches for a variable in the current scope and its parents

type ScopeBuilder added in v0.4.0

type ScopeBuilder interface {
	GetLanguage() Language
	// NodeCreatesScope returns true if the node introduces a new scope
	// into the scope tree
	NodeCreatesScope(node *sitter.Node) bool
	// DeclaresVariable determines if we can extract new variables out of this AST node
	DeclaresVariable(node *sitter.Node) bool
	// CollectVariables extracts variables from the node and adds them to the scope
	CollectVariables(node *sitter.Node) []*Variable
	// OnNodeEnter is called when the scope builder enters a node
	// for the first time, and hasn't scanned its children decls just yet
	// can be used to handle language specific scoping rules, if any
	// If `node` is smth like a block statement, `currentScope` corresponds
	// to the scope introduced by the block statement.
	OnNodeEnter(node *sitter.Node, currentScope *Scope)
	// OnNodeExit is called when the scope builder exits a node
	// can be used to handle language specific scoping rules, if any
	// If `node` is smth like a block statement, `currentScope` corresponds
	// to the scope introduced by the block statement.
	OnNodeExit(node *sitter.Node, currentScope *Scope)
}

ScopeBuilder is an interface that has to be implemented once for every supported language. Languages that don't implement a `ScopeBuilder` can still have checkers, just not any that require scope resolution.

type ScopeTree added in v0.4.0

type ScopeTree struct {
	Language Language
	// ScopeOfNode maps every scope-having node to its corresponding scope.
	// E.g: a block statement is mapped to the scope it introduces.
	ScopeOfNode map[*sitter.Node]*Scope
	// Root is the top-level scope in the program,
	// usually associated with the `program` or `module` node
	Root *Scope
}

func BuildScopeTree added in v0.4.0

func BuildScopeTree(builder ScopeBuilder, ast *sitter.Node, source []byte) *ScopeTree

BuildScopeTree constructs a scope tree from the AST for a program

func MakeScopeTree added in v0.4.0

func MakeScopeTree(lang Language, ast *sitter.Node, source []byte) *ScopeTree

func (*ScopeTree) GetScope added in v0.4.0

func (st *ScopeTree) GetScope(node *sitter.Node) *Scope

GetScope finds the nearest surrounding scope of an AST node

type Severity

type Severity string
const (
	SeverityCritical Severity = "critical"
	SeverityError    Severity = "error"
	SeverityWarning  Severity = "warning"
	SeverityInfo     Severity = "info"
)

func (Severity) IsValid

func (s Severity) IsValid() bool

type SkipComment added in v0.7.0

type SkipComment struct {
	// the line number for the skipcq comment
	CommentLine int
	// the entire text of the skipcq comment
	CommentText string
	// (optional) name of the checker for targetted skip
	CheckerIds []string
}

for caching the skipcq comments

func GatherSkipInfo added in v0.7.0

func GatherSkipInfo(fileContext *ParseResult) []*SkipComment

cache all the skipcq comments from an ast

type TsScopeBuilder added in v0.4.0

type TsScopeBuilder struct {
	// contains filtered or unexported fields
}

func (*TsScopeBuilder) CollectVariables added in v0.4.0

func (ts *TsScopeBuilder) CollectVariables(node *sitter.Node) []*Variable

func (*TsScopeBuilder) DeclaresVariable added in v0.4.0

func (ts *TsScopeBuilder) DeclaresVariable(node *sitter.Node) bool

func (*TsScopeBuilder) GetLanguage added in v0.4.0

func (j *TsScopeBuilder) GetLanguage() Language

func (*TsScopeBuilder) NodeCreatesScope added in v0.4.0

func (ts *TsScopeBuilder) NodeCreatesScope(node *sitter.Node) bool

func (*TsScopeBuilder) OnNodeEnter added in v0.4.0

func (ts *TsScopeBuilder) OnNodeEnter(node *sitter.Node, scope *Scope)

func (*TsScopeBuilder) OnNodeExit added in v0.4.0

func (ts *TsScopeBuilder) OnNodeExit(node *sitter.Node, scope *Scope)

type UnresolvedRef added in v0.4.0

type UnresolvedRef struct {
	// contains filtered or unexported fields
}

type VarKind added in v0.4.0

type VarKind int32
const (
	VarKindError VarKind = iota
	VarKindImport
	VarKindFunction
	VarKindVariable
	VarKindParameter
	VarKindClass
)

type Variable added in v0.4.0

type Variable struct {
	Kind VarKind
	// Stores the name of the variable
	Name string
	// DeclNode is the AST node that declares this variable
	DeclNode *sitter.Node
	// Refs is a list of references to this variable throughout the file
	Refs []*Reference
	// Exported tracks if the variable is valid to be exported
	Exported bool
}

type Walker added in v0.4.0

type Walker interface {
	// OnEnterNode is called when the walker enters a node.
	// The boolean return value indicates whether the walker should
	// continue walking the sub-tree of this node.
	OnEnterNode(node *sitter.Node) bool
	// OnLeaveNode is called when the walker leaves a node.
	// This is called after all the children of the node have been visited and explored.
	OnLeaveNode(node *sitter.Node)
}

Walker is an interface that dictates what to do when entering and leaving each node during the pre-order traversal of a tree. To traverse post-order, use the `OnLeaveNode` callback.

type Yaml added in v0.7.1

type Yaml struct {
	Language    string          `yaml:"language"`
	Code        string          `yaml:"name"`
	Message     string          `yaml:"message"`
	Category    Category        `yaml:"category"`
	Severity    Severity        `yaml:"severity"`
	Pattern     string          `yaml:"pattern"`
	Patterns    []string        `yaml:"patterns"`
	Description string          `yaml:"description"`
	Exclude     []string        `yaml:"exclude,omitempty"`
	Include     []string        `yaml:"include,omitempty"`
	Filters     []filterYaml    `yaml:"filters,omitempty"`
	PathFilter  *pathFilterYaml `yaml:"path_filter,omitempty"`
}

type YamlAnalyzer added in v0.7.1

type YamlAnalyzer struct {
	Analyzer   *Analyzer
	Patterns   []*sitter.Query
	NodeFilter []NodeFilter
	PathFilter *PathFilter
	Message    string
}

type YamlTestCase added in v0.7.1

type YamlTestCase struct {
	YamlCheckerPath string
	TestFile        string
}

func FindYamlTestFiles added in v0.7.1

func FindYamlTestFiles(testDir string) ([]YamlTestCase, error)

Jump to

Keyboard shortcuts

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