mirror of
https://github.com/github/codeql.git
synced 2026-01-29 14:23:03 +01:00
Add libraries for go.mod expressions
This commit is contained in:
@@ -9,6 +9,7 @@ import semmle.go.Concepts
|
||||
import semmle.go.Decls
|
||||
import semmle.go.Expr
|
||||
import semmle.go.Files
|
||||
import semmle.go.GoModExpr
|
||||
import semmle.go.Locations
|
||||
import semmle.go.Packages
|
||||
import semmle.go.Scopes
|
||||
|
||||
@@ -16,6 +16,7 @@ class AstNode extends @node, Locatable {
|
||||
*/
|
||||
AstNode getChild(int i) {
|
||||
result = this.(ExprParent).getChildExpr(i) or
|
||||
result = this.(GoModExprParent).getChildGoModExpr(i) or
|
||||
result = this.(StmtParent).getChildStmt(i) or
|
||||
result = this.(DeclParent).getDecl(i) or
|
||||
result = this.(GenDecl).getSpec(i) or
|
||||
@@ -70,6 +71,29 @@ class ExprParent extends @exprparent, AstNode {
|
||||
int getNumChildExpr() { result = count(getAChildExpr()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An AST node whose children include go.mod expressions.
|
||||
*/
|
||||
class GoModExprParent extends @modexprparent, AstNode {
|
||||
/**
|
||||
* Gets the `i`th child expression of this node.
|
||||
*
|
||||
* Note that the precise indices of child expressions are considered an implementation detail
|
||||
* and are subject to change without notice.
|
||||
*/
|
||||
GoModExpr getChildGoModExpr(int i) { modexprs(result, _, this, i) }
|
||||
|
||||
/**
|
||||
* Gets an expression that is a child node of this node in the AST.
|
||||
*/
|
||||
GoModExpr getAChildGoModExpr() { result = getChildGoModExpr(_) }
|
||||
|
||||
/**
|
||||
* Gets the number of child expressions of this node.
|
||||
*/
|
||||
int getNumChildGoModExpr() { result = count(getAChildGoModExpr()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An AST node whose children include statements.
|
||||
*/
|
||||
|
||||
@@ -178,7 +178,8 @@ class Folder extends Container, @folder {
|
||||
}
|
||||
|
||||
/** A file. */
|
||||
class File extends Container, @file, Documentable, ExprParent, DeclParent, ScopeNode {
|
||||
class File extends Container, @file, Documentable, ExprParent, GoModExprParent, DeclParent,
|
||||
ScopeNode {
|
||||
override Location getLocation() { has_location(this, result) }
|
||||
|
||||
override string getAbsolutePath() { files(this, result, _, _, _) }
|
||||
|
||||
167
ql/src/semmle/go/GoModExpr.qll
Normal file
167
ql/src/semmle/go/GoModExpr.qll
Normal file
@@ -0,0 +1,167 @@
|
||||
/**
|
||||
* Provides classes for working with go.mod expressions.
|
||||
*/
|
||||
|
||||
import go
|
||||
|
||||
/**
|
||||
* A go.mod expression.
|
||||
*/
|
||||
class GoModExpr extends @modexpr, GoModExprParent {
|
||||
/**
|
||||
* Gets the kind of this expression, which is an integer value representing the expression's
|
||||
* node type.
|
||||
*
|
||||
* Note that the mapping from node types to integer kinds is considered an implementation detail
|
||||
* and subject to change without notice.
|
||||
*/
|
||||
int getKind() { modexprs(this, result, _, _) }
|
||||
|
||||
/**
|
||||
* Get the comment group associated with this expression.
|
||||
*/
|
||||
DocComment getComments() { result.getDocumentedElement() = this }
|
||||
|
||||
override string toString() { result = "go.mod expression" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A top-level block of comments separate from any rule.
|
||||
*/
|
||||
class GoModCommentBlock extends @modcommentblock, GoModExpr { }
|
||||
|
||||
/**
|
||||
* A single line of tokens.
|
||||
*/
|
||||
class GoModLine extends @modline, GoModExpr {
|
||||
/**
|
||||
* Gets the `i`th token on this line.
|
||||
*/
|
||||
string getToken(int i) { modtokens(result, this, i) }
|
||||
|
||||
override string toString() { result = "go.mod line" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A line that contains the module information
|
||||
*/
|
||||
class GoModModuleLine extends GoModLine {
|
||||
GoModModuleLine() {
|
||||
this.getParent().(GoModLineBlock).getToken(0) = "module"
|
||||
or
|
||||
not this.getParent() instanceof GoModLineBlock and
|
||||
this.getToken(0) = "module"
|
||||
}
|
||||
|
||||
string getPath() {
|
||||
if this.getParent() instanceof GoModLineBlock
|
||||
then result = this.getToken(1)
|
||||
else result = this.getToken(0)
|
||||
}
|
||||
|
||||
override string toString() { result = "go.mod module line" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A factored block of lines, for example `require ( "path" )`.
|
||||
*/
|
||||
class GoModLineBlock extends @modlineblock, GoModExpr {
|
||||
/**
|
||||
* Gets the `i`th token of this line block.
|
||||
*/
|
||||
string getToken(int i) { modtokens(result, this, i) }
|
||||
|
||||
override string toString() { result = "go.mod line block" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A line that declares the Go version to be used, for example `go 1.14`.
|
||||
*/
|
||||
class GoModGoLine extends GoModLine {
|
||||
GoModGoLine() { this.getToken(0) = "go" }
|
||||
|
||||
/** Gets the Go version declared. */
|
||||
string getVer() { result = this.getToken(1) }
|
||||
|
||||
override string toString() { result = "go.mod go line" }
|
||||
}
|
||||
|
||||
private string getOffsetToken(GoModLine line, int i) {
|
||||
if line.getParent() instanceof GoModLineBlock
|
||||
then result = line.getToken(i - 1)
|
||||
else result = line.getToken(i)
|
||||
}
|
||||
|
||||
/**
|
||||
* A line that declares a requirement, for example `require "path"`.
|
||||
*/
|
||||
class GoModRequireLine extends GoModLine {
|
||||
GoModRequireLine() {
|
||||
this.getParent().(GoModLineBlock).getToken(0) = "require"
|
||||
or
|
||||
not this.getParent() instanceof GoModLineBlock and
|
||||
this.getToken(0) = "require"
|
||||
}
|
||||
|
||||
/** Gets the path of the dependency. */
|
||||
string getPath() { result = getOffsetToken(this, 1) }
|
||||
|
||||
/** Gets the version of the dependency. */
|
||||
string getVer() { result = getOffsetToken(this, 2) }
|
||||
|
||||
override string toString() { result = "go.mod require line" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A line that declares a dependency version to exclude, for example `exclude "ver"`.
|
||||
*/
|
||||
class GoModExcludeLine extends GoModLine {
|
||||
GoModExcludeLine() {
|
||||
this.getParent().(GoModLineBlock).getToken(0) = "exclude"
|
||||
or
|
||||
not this.getParent() instanceof GoModLineBlock and
|
||||
this.getToken(0) = "exclude"
|
||||
}
|
||||
|
||||
/** Gets the path of the dependency to exclude a version of. */
|
||||
string getPath() { result = getOffsetToken(this, 1) }
|
||||
|
||||
/** Gets the excluded version. */
|
||||
string getVer() { result = getOffsetToken(this, 2) }
|
||||
|
||||
override string toString() { result = "go.mod exclude line" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A line that specifies a dependency to use instead of another one, for example
|
||||
* `replace "a" => "b" ver`.
|
||||
*/
|
||||
class GoModReplaceLine extends GoModLine {
|
||||
GoModReplaceLine() {
|
||||
this.getParent().(GoModLineBlock).getToken(0) = "replace"
|
||||
or
|
||||
not this.getParent() instanceof GoModLineBlock and
|
||||
this.getToken(0) = "replace"
|
||||
}
|
||||
|
||||
/** Gets the path of the dependency to be replaced. */
|
||||
string getOriginalPath() { result = getOffsetToken(this, 1) }
|
||||
|
||||
/** Gets the path of the replacement dependency. */
|
||||
string getReplacementPath() { result = getOffsetToken(this, 3) }
|
||||
|
||||
/** Gets the version of the replacement dependency. */
|
||||
string getReplacementVer() { result = getOffsetToken(this, 4) }
|
||||
|
||||
override string toString() { result = "go.mod replace line" }
|
||||
}
|
||||
|
||||
/** A left parenthesis for a line block. */
|
||||
class GoModLParen extends @modlparen, GoModExpr {
|
||||
override string toString() { result = "go.mod (" }
|
||||
}
|
||||
|
||||
/** A right parenthesis for a line block. */
|
||||
class GoModRParen extends @modrparen, GoModExpr {
|
||||
override string toString() { result = "go.mod )" }
|
||||
}
|
||||
Reference in New Issue
Block a user