@@ -17,6 +17,7 @@ package python
1717import  (
1818	"context" 
1919	"fmt" 
20+ 	"log" 
2021	"os" 
2122	"path/filepath" 
2223	"strings" 
@@ -55,7 +56,10 @@ func NewFileParser() *FileParser {
5556	return  & FileParser {}
5657}
5758
58- func  ParseCode (code  []byte ) (* sitter.Node , error ) {
59+ // ParseCode instantiates a new tree-sitter Parser and parses the python code, returning 
60+ // the tree-sitter RootNode. 
61+ // It prints a warning if parsing fails. 
62+ func  ParseCode (code  []byte , path  string ) (* sitter.Node , error ) {
5963	parser  :=  sitter .NewParser ()
6064	parser .SetLanguage (python .GetLanguage ())
6165
@@ -64,9 +68,27 @@ func ParseCode(code []byte) (*sitter.Node, error) {
6468		return  nil , err 
6569	}
6670
67- 	return  tree .RootNode (), nil 
71+ 	root  :=  tree .RootNode ()
72+ 	if  root .HasError () {
73+ 		log .Printf ("WARNING: failed to parse %q. The resulting BUILD target may be incorrect." , path )
74+ 
75+ 		verbose , envExists  :=  os .LookupEnv ("GAZELLE_VERBOSE" )
76+ 		if  envExists  &&  verbose  ==  "1"  {
77+ 			for  i  :=  0 ; i  <  int (root .ChildCount ()); i ++  {
78+ 				child  :=  root .Child (i )
79+ 				if  child .IsError () {
80+ 					log .Printf ("Parse error at %+v:\n %+v" , child .StartPoint (), child .Content (code ))
81+ 					log .Printf ("The above was parsed as: %v" , child .String ())
82+ 				}
83+ 			}
84+ 		}
85+ 	}
86+ 
87+ 	return  root , nil 
6888}
6989
90+ // parseMain returns true if the python file has an `if __name__ == "__main__":` block, 
91+ // which is a common idiom for python scripts/binaries. 
7092func  (p  * FileParser ) parseMain (ctx  context.Context , node  * sitter.Node ) bool  {
7193	for  i  :=  0 ; i  <  int (node .ChildCount ()); i ++  {
7294		if  err  :=  ctx .Err (); err  !=  nil  {
@@ -94,6 +116,8 @@ func (p *FileParser) parseMain(ctx context.Context, node *sitter.Node) bool {
94116	return  false 
95117}
96118
119+ // parseImportStatement parses a node for an import statement, returning a `module` and a boolean 
120+ // representing if the parse was OK or not. 
97121func  parseImportStatement (node  * sitter.Node , code  []byte ) (module , bool ) {
98122	switch  node .Type () {
99123	case  sitterNodeTypeDottedName :
@@ -112,6 +136,9 @@ func parseImportStatement(node *sitter.Node, code []byte) (module, bool) {
112136	return  module {}, false 
113137}
114138
139+ // parseImportStatements parses a node for import statements, returning true if the node is 
140+ // an import statement. It updates FileParser.output.Modules with the `module` that the 
141+ // import represents. 
115142func  (p  * FileParser ) parseImportStatements (node  * sitter.Node ) bool  {
116143	if  node .Type () ==  sitterNodeTypeImportStatement  {
117144		for  j  :=  1 ; j  <  int (node .ChildCount ()); j ++  {
@@ -146,6 +173,8 @@ func (p *FileParser) parseImportStatements(node *sitter.Node) bool {
146173	return  true 
147174}
148175
176+ // parseComments parses a node for comments, returning true if the node is a comment. 
177+ // It updates FileParser.output.Comments with the parsed comment. 
149178func  (p  * FileParser ) parseComments (node  * sitter.Node ) bool  {
150179	if  node .Type () ==  sitterNodeTypeComment  {
151180		p .output .Comments  =  append (p .output .Comments , comment (node .Content (p .code )))
@@ -180,7 +209,7 @@ func (p *FileParser) parse(ctx context.Context, node *sitter.Node) {
180209}
181210
182211func  (p  * FileParser ) Parse (ctx  context.Context ) (* ParserOutput , error ) {
183- 	rootNode , err  :=  ParseCode (p .code )
212+ 	rootNode , err  :=  ParseCode (p .code ,  p . relFilepath )
184213	if  err  !=  nil  {
185214		return  nil , err 
186215	}
0 commit comments