Skip to content

Go: Improve two class names and add some helper predicates #19677

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
category: deprecated
---
* The class `BuiltinType` is now deprecated. Use the new replacement `BuiltinTypeEntity` instead.
* The class `DeclaredType` is now deprecated. Use the new replacement `DeclaredTypeEntity` instead.
30 changes: 27 additions & 3 deletions go/ql/lib/semmle/go/Decls.qll
Original file line number Diff line number Diff line change
Expand Up @@ -381,10 +381,20 @@ class TypeSpec extends @typespec, Spec, TypeParamDeclParent {
string getName() { result = this.getNameExpr().getName() }

/**
* Gets the expression denoting the underlying type to which the newly declared type is bound.
* Gets the declared type of this specifier.
*
* Note that for alias types this will give the underlying type.
*/
Type getDeclaredType() { result = this.getNameExpr().getType() }

/**
* Gets the expression denoting the underlying type to which the declared type is bound.
*/
Expr getTypeExpr() { result = this.getChildExpr(1) }

/** Gets the underlying type to which the declared type is bound. */
Type getRhsType() { result = this.getTypeExpr().getType() }

override string toString() { result = "type declaration specifier" }

override string getAPrimaryQlClass() { result = "TypeSpec" }
Expand Down Expand Up @@ -461,6 +471,7 @@ class FieldBase extends @field, ExprParent {
* Examples:
*
* ```go
* io.Reader
* Name string `json:"name"`
* x, y int
* ```
Expand All @@ -469,8 +480,9 @@ class FieldBase extends @field, ExprParent {
*
* ```go
* struct {
* Name string `json:"name"`
* x, y int
* io.Reader // embedded field
* Name string `json:"name"` // field with tag
* x, y int // declares two fields with the same type
* }
* ```
*/
Expand All @@ -482,12 +494,24 @@ class FieldDecl extends FieldBase, Documentable, ExprParent {
/**
* Gets the expression representing the name of the `i`th field declared in this declaration
* (0-based).
*
* This is not defined for embedded fields.
*/
Expr getNameExpr(int i) {
i >= 0 and
result = this.getChildExpr(i + 1)
}

/**
* Gets the `i`th field declared in this declaration (0-based).
*
* This is not defined for embedded fields.
*/
Field getField(int i) { this.getNameExpr(i).(Ident).declares(result) }

/** Holds if this field declaration declares an embedded type. */
predicate isEmbedded() { not exists(this.getNameExpr(_)) }

/** Gets the tag expression of this field declaration, if any. */
Expr getTag() { result = this.getChildExpr(-1) }

Expand Down
50 changes: 28 additions & 22 deletions go/ql/lib/semmle/go/Scopes.qll
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,19 @@ class TypeEntity extends Entity, @typeobject { }
class TypeParamParentEntity extends Entity, @typeparamparentobject { }

/** A named type which has a declaration. */
class DeclaredType extends TypeEntity, DeclaredEntity, TypeParamParentEntity, @decltypeobject {
class DeclaredTypeEntity extends TypeEntity, DeclaredEntity, TypeParamParentEntity, @decltypeobject {
/** Gets the declaration specifier declaring this type. */
TypeSpec getSpec() { result.getNameExpr() = this.getDeclaration() }
}

/** DEPRECATED: Use `DeclaredTypeEntity` instead. */
deprecated class DeclaredType = DeclaredTypeEntity;

/** A built-in type. */
class BuiltinType extends TypeEntity, BuiltinEntity, @builtintypeobject { }
class BuiltinTypeEntity extends TypeEntity, BuiltinEntity, @builtintypeobject { }

/** DEPRECATED: Use `BuiltinTypeEntity` instead. */
deprecated class BuiltinType = BuiltinTypeEntity;

/** A built-in or declared constant, variable, field, method or function. */
class ValueEntity extends Entity, @valueobject {
Expand Down Expand Up @@ -754,64 +760,64 @@ private predicate builtinFunction(
module Builtin {
// built-in types
/** Gets the built-in type `bool`. */
BuiltinType bool() { result.getName() = "bool" }
BuiltinTypeEntity bool() { result.getName() = "bool" }

/** Gets the built-in type `byte`. */
BuiltinType byte() { result.getName() = "byte" }
BuiltinTypeEntity byte() { result.getName() = "byte" }

/** Gets the built-in type `complex64`. */
BuiltinType complex64() { result.getName() = "complex64" }
BuiltinTypeEntity complex64() { result.getName() = "complex64" }

/** Gets the built-in type `complex128`. */
BuiltinType complex128() { result.getName() = "complex128" }
BuiltinTypeEntity complex128() { result.getName() = "complex128" }

/** Gets the built-in type `error`. */
BuiltinType error() { result.getName() = "error" }
BuiltinTypeEntity error() { result.getName() = "error" }

/** Gets the built-in type `float32`. */
BuiltinType float32() { result.getName() = "float32" }
BuiltinTypeEntity float32() { result.getName() = "float32" }

/** Gets the built-in type `float64`. */
BuiltinType float64() { result.getName() = "float64" }
BuiltinTypeEntity float64() { result.getName() = "float64" }

/** Gets the built-in type `int`. */
BuiltinType int_() { result.getName() = "int" }
BuiltinTypeEntity int_() { result.getName() = "int" }

/** Gets the built-in type `int8`. */
BuiltinType int8() { result.getName() = "int8" }
BuiltinTypeEntity int8() { result.getName() = "int8" }

/** Gets the built-in type `int16`. */
BuiltinType int16() { result.getName() = "int16" }
BuiltinTypeEntity int16() { result.getName() = "int16" }

/** Gets the built-in type `int32`. */
BuiltinType int32() { result.getName() = "int32" }
BuiltinTypeEntity int32() { result.getName() = "int32" }

/** Gets the built-in type `int64`. */
BuiltinType int64() { result.getName() = "int64" }
BuiltinTypeEntity int64() { result.getName() = "int64" }

/** Gets the built-in type `rune`. */
BuiltinType rune() { result.getName() = "rune" }
BuiltinTypeEntity rune() { result.getName() = "rune" }

/** Gets the built-in type `string`. */
BuiltinType string_() { result.getName() = "string" }
BuiltinTypeEntity string_() { result.getName() = "string" }

/** Gets the built-in type `uint`. */
BuiltinType uint() { result.getName() = "uint" }
BuiltinTypeEntity uint() { result.getName() = "uint" }

/** Gets the built-in type `uint8`. */
BuiltinType uint8() { result.getName() = "uint8" }
BuiltinTypeEntity uint8() { result.getName() = "uint8" }

/** Gets the built-in type `uint16`. */
BuiltinType uint16() { result.getName() = "uint16" }
BuiltinTypeEntity uint16() { result.getName() = "uint16" }

/** Gets the built-in type `uint32`. */
BuiltinType uint32() { result.getName() = "uint32" }
BuiltinTypeEntity uint32() { result.getName() = "uint32" }

/** Gets the built-in type `uint64`. */
BuiltinType uint64() { result.getName() = "uint64" }
BuiltinTypeEntity uint64() { result.getName() = "uint64" }

/** Gets the built-in type `uintptr`. */
BuiltinType uintptr() { result.getName() = "uintptr" }
BuiltinTypeEntity uintptr() { result.getName() = "uintptr" }

// built-in constants
/** Gets the built-in constant `true`. */
Expand Down
4 changes: 2 additions & 2 deletions go/ql/test/library-tests/semmle/go/Decl/TypeSpec.expected
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
| main.go:3:6:3:15 | type declaration specifier | status | int | def |
| main.go:5:6:5:20 | type declaration specifier | intlist | []int | alias |
| main.go:3:6:3:15 | type declaration specifier | status | status | main.go:3:13:3:15 | int | int | def |
| main.go:5:6:5:20 | type declaration specifier | intlist | []int | main.go:5:16:5:20 | array type | []int | alias |
2 changes: 1 addition & 1 deletion go/ql/test/library-tests/semmle/go/Decl/TypeSpec.ql
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ import go

from TypeSpec ts, string kind
where if ts instanceof AliasSpec then kind = "alias" else kind = "def"
select ts, ts.getName(), ts.getTypeExpr().getType().pp(), kind
select ts, ts.getName(), ts.getDeclaredType().pp(), ts.getTypeExpr(), ts.getRhsType().pp(), kind
70 changes: 70 additions & 0 deletions go/ql/test/library-tests/semmle/go/Types/FieldDecl.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
fieldDeclWithNamedFields
| aliases.go:6:26:6:35 | field declaration | 0 | aliases.go:6:26:6:26 | x |
| aliases.go:6:26:6:35 | field declaration | 0 | aliases.go:8:26:8:26 | x |
| aliases.go:6:26:6:35 | field declaration | 0 | aliases.go:19:17:19:17 | x |
| aliases.go:8:26:8:35 | field declaration | 0 | aliases.go:6:26:6:26 | x |
| aliases.go:8:26:8:35 | field declaration | 0 | aliases.go:8:26:8:26 | x |
| aliases.go:8:26:8:35 | field declaration | 0 | aliases.go:19:17:19:17 | x |
| aliases.go:19:17:19:21 | field declaration | 0 | aliases.go:6:26:6:26 | x |
| aliases.go:19:17:19:21 | field declaration | 0 | aliases.go:8:26:8:26 | x |
| aliases.go:19:17:19:21 | field declaration | 0 | aliases.go:19:17:19:17 | x |
| aliases.go:29:34:29:42 | field declaration | 0 | aliases.go:29:34:29:34 | x |
| cyclic.go:9:2:9:6 | field declaration | 0 | cyclic.go:9:2:9:2 | f |
| depth.go:11:2:11:6 | field declaration | 0 | depth.go:11:2:11:2 | f |
| depth.go:19:2:19:9 | field declaration | 0 | depth.go:19:2:19:2 | f |
| embedded.go:4:2:4:9 | field declaration | 0 | embedded.go:4:2:4:2 | A |
| embedded.go:13:2:13:11 | field declaration | 0 | embedded.go:13:2:13:4 | Baz |
| generic.go:4:2:4:15 | field declaration | 0 | generic.go:4:2:4:11 | valueField |
| generic.go:5:2:5:16 | field declaration | 0 | generic.go:5:2:5:13 | pointerField |
| generic.go:6:2:6:19 | field declaration | 0 | generic.go:6:2:6:11 | arrayField |
| generic.go:7:2:7:17 | field declaration | 0 | generic.go:7:2:7:11 | sliceField |
| generic.go:8:2:8:26 | field declaration | 0 | generic.go:8:2:8:9 | mapField |
| generic.go:12:2:12:40 | field declaration | 0 | generic.go:12:2:12:13 | pointerField |
| generic.go:16:2:16:31 | field declaration | 0 | generic.go:16:2:16:5 | root |
| generic.go:20:2:20:30 | field declaration | 0 | generic.go:20:2:20:12 | structField |
| generic.go:21:2:21:20 | field declaration | 0 | generic.go:21:2:21:9 | mapField |
| generic.go:25:2:25:33 | field declaration | 0 | generic.go:25:2:25:12 | structField |
| generic.go:29:2:29:43 | field declaration | 0 | generic.go:29:2:29:13 | pointerField |
| pkg1/embedding.go:37:2:37:6 | field declaration | 0 | pkg1/embedding.go:37:2:37:2 | f |
| pkg1/promotedStructs.go:5:2:5:14 | field declaration | 0 | pkg1/promotedStructs.go:5:2:5:7 | SField |
| pkg1/promotedStructs.go:14:2:14:14 | field declaration | 0 | pkg1/promotedStructs.go:14:2:14:7 | PField |
| pkg1/tst.go:6:2:6:6 | field declaration | 0 | pkg1/tst.go:6:2:6:2 | f |
| pkg1/tst.go:12:2:12:8 | field declaration | 0 | pkg1/tst.go:12:2:12:4 | Foo |
| pkg1/tst.go:23:2:23:8 | field declaration | 0 | pkg1/tst.go:23:2:23:4 | Bar |
| pkg1/tst.go:27:2:27:9 | field declaration | 0 | pkg1/tst.go:27:2:27:4 | val |
| pkg1/tst.go:28:2:28:10 | field declaration | 0 | pkg1/tst.go:28:2:28:5 | flag |
| pkg1/tst.go:32:2:32:10 | field declaration | 0 | pkg1/tst.go:32:2:32:5 | flag |
| pkg2/tst.go:4:2:4:6 | field declaration | 0 | pkg2/tst.go:4:2:4:2 | g |
| pkg2/tst.go:4:2:4:6 | field declaration | 0 | pkg2/tst.go:8:2:8:2 | g |
| pkg2/tst.go:8:2:8:6 | field declaration | 0 | pkg2/tst.go:4:2:4:2 | g |
| pkg2/tst.go:8:2:8:6 | field declaration | 0 | pkg2/tst.go:8:2:8:2 | g |
| pkg2/tst.go:17:2:17:15 | field declaration | 0 | pkg2/tst.go:17:2:17:8 | NCField |
| struct_tags.go:4:2:4:19 | field declaration | 0 | struct_tags.go:4:2:4:7 | field1 |
| struct_tags.go:5:2:5:19 | field declaration | 0 | struct_tags.go:5:2:5:7 | field2 |
| struct_tags.go:9:2:9:19 | field declaration | 0 | struct_tags.go:9:2:9:7 | field1 |
| struct_tags.go:10:2:10:19 | field declaration | 0 | struct_tags.go:10:2:10:7 | field2 |
fieldDeclWithEmbeddedField
| cyclic.go:4:2:4:3 | field declaration | * s |
| cyclic.go:8:2:8:3 | field declaration | * u |
| cyclic.go:13:2:13:2 | field declaration | t |
| cyclic.go:17:2:17:2 | field declaration | s |
| depth.go:6:2:6:2 | field declaration | b |
| depth.go:7:2:7:2 | field declaration | c |
| depth.go:15:2:15:2 | field declaration | d |
| embedded.go:8:2:8:5 | field declaration | * Baz |
| embedded.go:12:2:12:4 | field declaration | Qux |
| main.go:18:2:18:15 | field declaration | NameClash |
| pkg1/embedding.go:19:23:19:26 | field declaration | base |
| pkg1/embedding.go:22:26:22:30 | field declaration | * base |
| pkg1/embedding.go:25:24:25:31 | field declaration | embedder |
| pkg1/embedding.go:28:24:28:31 | field declaration | embedder |
| pkg1/embedding.go:36:2:36:5 | field declaration | base |
| pkg1/promotedStructs.go:22:22:22:22 | field declaration | S |
| pkg1/promotedStructs.go:25:22:25:22 | field declaration | P |
| pkg1/tst.go:7:2:7:4 | field declaration | Foo |
| pkg1/tst.go:8:2:8:4 | field declaration | Bar |
| pkg1/tst.go:13:2:13:4 | field declaration | Bar |
| pkg1/tst.go:17:2:17:5 | field declaration | * Foo |
| pkg1/tst.go:18:2:18:5 | field declaration | * Bar |
| pkg1/tst.go:22:2:22:5 | field declaration | * Foo |
| pkg1/tst.go:62:2:62:15 | field declaration | NameClash |
7 changes: 7 additions & 0 deletions go/ql/test/library-tests/semmle/go/Types/FieldDecl.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import go

query predicate fieldDeclWithNamedFields(FieldDecl fd, int i, Field f) { fd.getField(i) = f }

query predicate fieldDeclWithEmbeddedField(FieldDecl fd, string tp) {
fd.isEmbedded() and tp = fd.getType().pp()
}