Skip to content

Commit 353573b

Browse files
authored
Merge pull request #11701 from owen-mc/go/count-fields-correctly
Go: Count fields correctly
2 parents cedc9c0 + 3eb419e commit 353573b

File tree

5 files changed

+217
-14
lines changed

5 files changed

+217
-14
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* The predicate `getNumParameter` on `FuncTypeExpr` has been changed to actually give the number of parameters. It previously gave the number of parameter declarations. `getNumParameterDecl` has been introduced to preserve this functionality.

go/ql/lib/semmle/go/AST.qll

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,24 +194,27 @@ class DeclParent extends @declparent, AstNode {
194194
}
195195

196196
/**
197-
* An AST node whose children include fields.
197+
* An AST node whose children include field declarations.
198+
*
199+
* A field declaration can be in a struct, a function (for parameter or result
200+
* variables), or an interface (in which case it is a method or embedding spec).
198201
*/
199202
class FieldParent extends @fieldparent, AstNode {
200203
/**
201-
* Gets the `i`th field of this node.
204+
* Gets the `i`th field declaration of this node.
202205
*
203-
* Note that the precise indices of fields are considered an implementation detail
204-
* and are subject to change without notice.
206+
* Note that the precise indices of field declarations are considered an
207+
* implementation detail and are subject to change without notice.
205208
*/
206209
FieldBase getField(int i) { fields(result, this, i) }
207210

208211
/**
209-
* Gets a child field of this node in the AST.
212+
* Gets a child field declaration of this node in the AST.
210213
*/
211214
FieldBase getAField() { result = this.getField(_) }
212215

213216
/**
214-
* Gets the number of child fields of this node.
217+
* Gets the number of child field declarations of this node.
215218
*/
216219
int getNumFields() { result = count(this.getAField()) }
217220
}

go/ql/lib/semmle/go/Decls.qll

Lines changed: 180 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -416,8 +416,35 @@ class AliasSpec extends @aliasspec, TypeSpec { }
416416
class TypeDefSpec extends @typedefspec, TypeSpec { }
417417

418418
/**
419-
* A field declaration, of a struct, a function (in which case this is a parameter or result variable),
420-
* or an interface (in which case this is a method or embedding spec).
419+
* A field declaration, in a struct, a function (for parameter or result
420+
* variables), or an interface (in which case this is a method or embedding
421+
* spec).
422+
*
423+
* Examples:
424+
*
425+
* ```go
426+
* Name string `json:"name"`
427+
* s string
428+
* x, y int
429+
* p *Point
430+
* Close() error
431+
* io.Reader
432+
* ~int | float32
433+
* ```
434+
* as in the following code:
435+
* ```go
436+
* struct {
437+
* io.Reader
438+
* Name string `json:"name"`
439+
* x, y int
440+
* }
441+
* func (p *Point) f(s string) (x, y int) { }
442+
* type MyInterface interface {
443+
* Close() error
444+
* io.Reader
445+
* ~int32 | float32
446+
* }
447+
* ```
421448
*/
422449
class FieldBase extends @field, ExprParent {
423450
/**
@@ -433,6 +460,22 @@ class FieldBase extends @field, ExprParent {
433460

434461
/**
435462
* A field declaration in a struct type.
463+
*
464+
* Examples:
465+
*
466+
* ```go
467+
* Name string `json:"name"`
468+
* x, y int
469+
* ```
470+
*
471+
* as in the following code:
472+
*
473+
* ```go
474+
* struct {
475+
* Name string `json:"name"`
476+
* x, y int
477+
* }
478+
* ```
436479
*/
437480
class FieldDecl extends FieldBase, Documentable, ExprParent {
438481
StructTypeExpr st;
@@ -464,6 +507,20 @@ class FieldDecl extends FieldBase, Documentable, ExprParent {
464507

465508
/**
466509
* An embedded field declaration in a struct.
510+
*
511+
* Examples:
512+
*
513+
* ```go
514+
* io.Reader
515+
* ```
516+
*
517+
* as in the following code:
518+
*
519+
* ```go
520+
* struct {
521+
* io.Reader
522+
* }
523+
* ```
467524
*/
468525
class EmbeddedFieldDecl extends FieldDecl {
469526
EmbeddedFieldDecl() { not exists(this.getNameExpr(_)) }
@@ -473,6 +530,20 @@ class EmbeddedFieldDecl extends FieldDecl {
473530

474531
/**
475532
* A function parameter or result variable declaration.
533+
*
534+
* Examples:
535+
*
536+
* ```go
537+
* s string
538+
* x, y int
539+
* ```
540+
*
541+
* as in the following code:
542+
*
543+
* ```go
544+
* func f(s string, x, y int) { }
545+
* func g() (s string, x, y int){ return }
546+
* ```
476547
*/
477548
class ParameterOrResultDecl extends FieldBase, Documentable, ExprParent {
478549
int rawIndex;
@@ -507,6 +578,19 @@ class ParameterOrResultDecl extends FieldBase, Documentable, ExprParent {
507578

508579
/**
509580
* A parameter declaration.
581+
*
582+
* Examples:
583+
*
584+
* ```go
585+
* s string
586+
* x, y int
587+
* ```
588+
*
589+
* as in the following code:
590+
*
591+
* ```go
592+
* func f(s string, x, y int) { }
593+
* ```
510594
*/
511595
class ParameterDecl extends ParameterOrResultDecl {
512596
ParameterDecl() { rawIndex >= 0 }
@@ -524,6 +608,20 @@ class ParameterDecl extends ParameterOrResultDecl {
524608

525609
/**
526610
* A receiver declaration in a function declaration.
611+
*
612+
* Examples:
613+
*
614+
* ```go
615+
* p *Point
616+
* r io.Reader
617+
* ```
618+
*
619+
* as in the following code:
620+
*
621+
* ```go
622+
* func (p *Point) f() { }
623+
* func (r io.Reader) g() { }
624+
* ```
527625
*/
528626
class ReceiverDecl extends FieldBase, Documentable, ExprParent {
529627
FuncDecl fd;
@@ -547,6 +645,22 @@ class ReceiverDecl extends FieldBase, Documentable, ExprParent {
547645

548646
/**
549647
* A result variable declaration.
648+
*
649+
* Examples:
650+
*
651+
* ```go
652+
* error
653+
* r io.Reader
654+
* x, y int
655+
* ```
656+
*
657+
* as in the following code:
658+
*
659+
* ```go
660+
* func f(error) { return nil }
661+
* func g(r io.Reader) { return nil }
662+
* func h(x, y int) { return }
663+
* ```
550664
*/
551665
class ResultVariableDecl extends ParameterOrResultDecl {
552666
ResultVariableDecl() { rawIndex < 0 }
@@ -564,6 +678,22 @@ class ResultVariableDecl extends ParameterOrResultDecl {
564678

565679
/**
566680
* A type parameter declaration in a type specification.
681+
*
682+
* Examples:
683+
*
684+
* ```go
685+
* S, T comparable
686+
* U any
687+
* K ~int32 | float32
688+
* _ any
689+
* ```
690+
*
691+
* as in the following code:
692+
*
693+
* ```go
694+
* type GenericStruct[S, T comparable, U any, K ~int32 | float32, _ any] struct { }
695+
* func GenericFunction[S, T comparable, U any, K ~int32 | float32, _ any]() {}
696+
* ```
567697
*/
568698
class TypeParamDecl extends @typeparamdecl, Documentable, ExprParent {
569699
TypeParamDecl() { typeparamdecls(this, _, _) }
@@ -615,6 +745,24 @@ class TypeParamDecl extends @typeparamdecl, Documentable, ExprParent {
615745

616746
/**
617747
* A method or embedding specification in an interface type expression.
748+
*
749+
* Examples:
750+
*
751+
* ```go
752+
* Close() error
753+
* io.Reader
754+
* ~int32 | float32
755+
* ```
756+
*
757+
* as in the following code:
758+
*
759+
* ```go
760+
* type MyInterface interface {
761+
* Close() error
762+
* io.Reader
763+
* ~int32 | float32
764+
* }
765+
* ```
618766
*/
619767
class InterfaceMemberSpec extends FieldBase, Documentable, ExprParent {
620768
InterfaceTypeExpr ite;
@@ -636,6 +784,20 @@ class InterfaceMemberSpec extends FieldBase, Documentable, ExprParent {
636784

637785
/**
638786
* A method specification in an interface.
787+
*
788+
* Examples:
789+
*
790+
* ```go
791+
* Close() error
792+
* ```
793+
*
794+
* as in the following code:
795+
*
796+
* ```go
797+
* type MyInterface interface {
798+
* Close() error
799+
* }
800+
* ```
639801
*/
640802
class MethodSpec extends InterfaceMemberSpec {
641803
Expr name;
@@ -654,6 +816,22 @@ class MethodSpec extends InterfaceMemberSpec {
654816

655817
/**
656818
* An embedding specification in an interface.
819+
*
820+
* Examples:
821+
*
822+
* ```go
823+
* io.Reader
824+
* ~int32 | float32
825+
* ```
826+
*
827+
* as in the following code:
828+
*
829+
* ```go
830+
* type MyInterface interface {
831+
* io.Reader
832+
* ~int32 | float32
833+
* }
834+
* ```
657835
*/
658836
class EmbeddingSpec extends InterfaceMemberSpec {
659837
EmbeddingSpec() { not exists(this.getChildExpr(1)) }

go/ql/lib/semmle/go/Expr.qll

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -980,18 +980,36 @@ class StructTypeExpr extends @structtypeexpr, TypeExpr, FieldParent {
980980
* Examples:
981981
*
982982
* ```go
983-
* func(a, b int, c float32) (float32, bool)
983+
* func(a int, b, c float32) (float32, bool)
984984
* ```
985985
*/
986986
class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
987987
/** Gets the `i`th parameter of this function type (0-based). */
988988
ParameterDecl getParameterDecl(int i) { result = this.getField(i) and i >= 0 }
989989

990-
/** Gets a parameter of this function type. */
990+
/**
991+
* Gets a parameter declaration of this function type.
992+
*
993+
* For example, for `func(a int, b, c float32) (float32, bool)` the result is
994+
* `a int` or `b, c float32`.
995+
*/
991996
ParameterDecl getAParameterDecl() { result = this.getParameterDecl(_) }
992997

993-
/** Gets the number of parameters of this function type. */
994-
int getNumParameter() { result = count(this.getAParameterDecl()) }
998+
/**
999+
* Gets the number of parameter declarations of this function type.
1000+
*
1001+
* For example, for `func(a int, b, c float32) (float32, bool)` the result is 2:
1002+
* `a int` and `b, c float32`.
1003+
*/
1004+
int getNumParameterDecl() { result = count(this.getAParameterDecl()) }
1005+
1006+
/**
1007+
* Gets the number of parameters of this function type.
1008+
*
1009+
* For example, for `func(a int, b, c float32) (float32, bool)` the result is 3:
1010+
* `a`, `b` and `c`.
1011+
*/
1012+
int getNumParameter() { result = count(this.getAParameterDecl().getANameExpr()) }
9951013

9961014
/** Gets the `i`th result of this function type (0-based). */
9971015
ResultVariableDecl getResultDecl(int i) { result = this.getField(-(i + 1)) }
@@ -1011,9 +1029,9 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
10111029

10121030
/** Gets the `i`th child of this node, parameters first followed by results. */
10131031
override AstNode getUniquelyNumberedChild(int i) {
1014-
if i < this.getNumParameter()
1032+
if i < this.getNumParameterDecl()
10151033
then result = this.getParameterDecl(i)
1016-
else result = this.getResultDecl(i - this.getNumParameter())
1034+
else result = this.getResultDecl(i - this.getNumParameterDecl())
10171035
}
10181036
}
10191037

0 commit comments

Comments
 (0)