Open aaaayush-n opened 1 month ago
Hi @aaaayush-n,
It sounds like you're doing the right thing, but it's a bit hard to make suggestions with seeing the query code you currently have. Would you be able to share the current version of your query?
@jketema
/**
* @id go/get-location
* @kind problem
* @problem.severity recommendation
*/
import go
class MyFunc extends Decl{
TypeDecl typeDecl;
Ident ident;
TypeDecl getObject(string objectName,string objDirPath){
ident.getAPrimaryQlClass()="TypeName"
and ident.toString()=objectName
and ident.getParent().getParent()=typeDecl
and typeDecl.getFile().toString().replaceAll(typeDecl.getFile().getBaseName().toString(), "").substring(0, typeDecl.getFile().toString().replaceAll(typeDecl.getFile().getBaseName().toString(), "").length()-1)=objDirPath
and
result=typeDecl
}
}
from string objectName
, MyFunc func
,TypeDecl object
,string objDirPath
,FieldDecl fieldDecl
where objectName="MyStruct"
and objDirPath="path/to/src/directory"
and object=func.getObject(objectName,objDirPath)
select object,"MyObject"
Now I want to find the nested objects inside TypeDecl object
I was thinking of adding
ident.getAPrimaryQLClass()="TypeName"
and ident.getEnclosingTypeDecl()=object
select ident,"MyNestedObjects"
but there is no such getEnclosingTypeDecl()
predicate, I can't do ident.getParent()=object
because idk how deep in AST my ident will be.
Suggest me some way to find out how to figure this out.
Hi @aaaayush-n 👋
Thanks for sharing your query! What you have written looks a bit unusual and I am guessing you are coming from a background of object-oriented and imperative programming languages. If you haven't seen our documentation for the QL language yet, I'd recommend having a look for lots of advice for how to write good QL. In particular, you may find the section on recursion relevant to your question.
The getAPrimaryQLClass
predicate is mainly intended for debugging, not for actual queries. For example, you don't need the MyFunc
class and your getObject
predicate could be simplified to:
TypeDecl getObject(string objectName,string objDirPath){
exists(TypeName tn |
tn.toString()=objectName and
tn.getParent().getParent()=result and
result.getFile().toString().replaceAll(result.getFile().getBaseName().toString(), "").substring(0, result.getFile().toString().replaceAll(result.getFile().getBaseName().toString(), "").length()-1)=objDirPath
)
}
Use concrete types rather than strings whenever possible. This can probably be further simplified as well, particularly the last line.
In any case, the way I would break this problem down is to start with a predicate which, given some TypeDecl
, finds all the TypeName
s you are interested in. Something like:
predicate isUsedInTypeDecl(TypeDecl decl, TypeName ty) {
result = ty.getParent()
}
You can then extend/modify this to find all TypeName
s with a corresponding TypeDecl
of their own. From there, you can apply the predicate recursively.
@mbg
predicate isUsedInTypeDecl(TypeDecl decl, TypeName ty) { result = ty.getParent() }
This would only give me the
statusCode
in field9 in context of example struct I gave above (that too on having ty.getParent().getParent().getParent() as the AST structure is TypeName>FieldDecl>StructTypeExpr>TypeDecl) I fail to see, how I would call this recursively to get the other types. Please help me with this.
The definition I gave for isUsedInTypeDecl
is just an example. You can tweak it to suit your needs. You can use the resulting TypeName
s for the initial TypeDecl
to find TypeName
s that have corresponding TypeDecls
, which you can then recurse on.
Description of the issue
I want to write a query to find the nested structs in an struct in Golang. Let's say my struct is something like:
and I want to write a query that gives me all the nested types in this struct ie.
statusCode,Response,Category,Time,Header,NewStruct
etc. The field types can be more complex than what is mentioned here. My main problem statement is to find the declarations of these nested structs, which I will continue my query by finding alltypedecl
with theiridents
matching with the above mentionedidents
while matching the import path and the filepath for nested objects from different packages likedto.NewStruct
. If there is some better approach please suggest. Please suggest me an approach.