Documentation
¶
Overview ¶
scope resolution implementation for JS and TS files
Index ¶
- Variables
- func ChildWithFieldName(node *sitter.Node, fieldName string) *sitter.Node
- func ChildrenOfType(node *sitter.Node, nodeType string) []*sitter.Node
- func ChildrenWithFieldName(node *sitter.Node, fieldName string) []*sitter.Node
- func FindMatchingChild(node *sitter.Node, predicate func(*sitter.Node) bool) *sitter.Node
- func FirstChildOfType(node *sitter.Node, nodeType string) *sitter.Node
- func GetExtFromLanguage(lang Language) string
- func WalkTree(node *sitter.Node, walker Walker)
- type Analyzer
- type Issue
- type Language
- type NodeFilter
- type ParseResult
- type PathFilter
- type PatternRuleFile
- type Reference
- type Rule
- type Scope
- type ScopeBuilder
- type ScopeTree
- type TsScopeBuilder
- func (ts *TsScopeBuilder) CollectVariables(node *sitter.Node) []*Variable
- func (ts *TsScopeBuilder) DeclaresVariable(node *sitter.Node) bool
- func (j *TsScopeBuilder) GetLanguage() Language
- func (ts *TsScopeBuilder) NodeCreatesScope(node *sitter.Node) bool
- func (ts *TsScopeBuilder) OnNodeEnter(node *sitter.Node, scope *Scope)
- func (ts *TsScopeBuilder) OnNodeExit(node *sitter.Node, scope *Scope)
- type UnresolvedRef
- type VarKind
- type Variable
- type VisitFn
- type Walker
- type YmlRule
Constants ¶
This section is empty.
Variables ¶
var ScopeNodes = []string{
"statement_block",
"function_declaration",
"function_expression",
"for_statement",
"for_in_statement",
"for_of_statement",
}
Functions ¶
func ChildrenWithFieldName ¶
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 FindMatchingChild ¶
FindMatchingChild iterates over all children of a node—both named and unnamed—and returns the first child that matches the predicate function.
func GetExtFromLanguage ¶
Types ¶
type Analyzer ¶
type Analyzer struct { Language Language // WorkDir is the directory in which the analysis is being run. WorkDir string // ParseResult is the result of parsing a file with a tree-sitter parser, // along with some extra appendages (e.g: scope information). ParseResult *ParseResult // patternRules is a list of all rules that run after a query is run on the AST. // Usually, these are written in a DSL (which, for now, is the tree-sitter S-Expression query language) YmlRules []YmlRule // contains filtered or unexported fields }
func NewAnalyzer ¶
func NewAnalyzer(file *ParseResult, rules []Rule) *Analyzer
func (*Analyzer) OnLeaveNode ¶
type Issue ¶
type Issue struct { // The category of the issue Category config.Category // The severity of the issue Severity config.Severity // The message to display to the user Message string // The file path of the file that the issue was found in Filepath string // The range of the issue in the source code Range sitter.Range // (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 }
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 ¶
DecodeLanguage converts a stringified language name to its corresponding Language enum
func LanguageFromFilePath ¶
LanguageFromFilePath returns the Language of the file at the given path returns `LangUnkown` if the language is not recognized (e.g: `.txt` files).
type NodeFilter ¶
type NodeFilter struct {
// contains filtered or unexported fields
}
NodeFilter is a filter that can be applied to a PatternRule to restrict the the nodes that the rule is applied to. The rule 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 ParseFile ¶
func ParseFile(filePath string) (*ParseResult, error)
ParseFile parses the file at the given path using the appropriate tree-sitter grammar.
type PathFilter ¶
PathFilter is a glob that can be applied to a PatternRule to restrict the files that the rule is applied to.
type PatternRuleFile ¶
type PatternRuleFile struct { Language string `yaml:"language"` Code string `yaml:"name"` Message string `yaml:"message"` Category config.Category `yaml:"category"` Severity config.Severity `yaml:"severity"` // Pattern is a single pattern in the form of: // pattern: (some_pattern) // in the YAML file Pattern string `yaml:"pattern,omitempty"` // Patterns are ultiple patterns in the form of: // pattern: (something) // in the YAML file Patterns []string `yaml:"patterns,omitempty"` Description string `yaml:"description,omitempty"` Filters []filterYAML `yaml:"filters,omitempty"` Exclude []string `yaml:"exclude,omitempty"` Include []string `yaml:"include,omitempty"` }
type Reference ¶
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 rules like "unused-variable", but is safe to use for rules like "unused-import"
type Rule ¶
type Scope ¶
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 }
type ScopeBuilder ¶
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 lints, just not any that require scope resolution.
type ScopeTree ¶
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 ¶
func BuildScopeTree(builder ScopeBuilder, ast *sitter.Node, source []byte) *ScopeTree
BuildScopeTree constructs a scope tree from the AST for a program
type TsScopeBuilder ¶
type TsScopeBuilder struct {
// contains filtered or unexported fields
}
func (*TsScopeBuilder) CollectVariables ¶
func (ts *TsScopeBuilder) CollectVariables(node *sitter.Node) []*Variable
func (*TsScopeBuilder) DeclaresVariable ¶
func (ts *TsScopeBuilder) DeclaresVariable(node *sitter.Node) bool
func (*TsScopeBuilder) GetLanguage ¶
func (j *TsScopeBuilder) GetLanguage() Language
func (*TsScopeBuilder) NodeCreatesScope ¶
func (ts *TsScopeBuilder) NodeCreatesScope(node *sitter.Node) bool
func (*TsScopeBuilder) OnNodeEnter ¶
func (ts *TsScopeBuilder) OnNodeEnter(node *sitter.Node, scope *Scope)
func (*TsScopeBuilder) OnNodeExit ¶
func (ts *TsScopeBuilder) OnNodeExit(node *sitter.Node, scope *Scope)
type UnresolvedRef ¶
type UnresolvedRef struct {
// contains filtered or unexported fields
}
type Walker ¶
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 YmlRule ¶
type YmlRule interface { Name() string Patterns() []*sitter.Query Language() Language Category() config.Category Severity() config.Severity OnMatch( ana *Analyzer, matchedQuery *sitter.Query, matchedNode *sitter.Node, captures []sitter.QueryCapture, ) PathFilter() *PathFilter NodeFilters() []NodeFilter }
A YmlRule is a rule that matches a tree-sitter query pattern and reports an issue when the pattern is found. Unlike regular issues, PatternRules are not associated with a specific node type, rather they are invoked for *every* node that matches the pattern.
func CreatePatternRule ¶
func ReadFromBytes ¶
ReadFromBytes reads a pattern rule definition from bytes array
func ReadFromFile ¶
ReadFromFile reads a pattern rule definition from a YAML config file.