| 
					
				 | 
			
			
				@@ -9,8 +9,11 @@ import ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	"github.com/gogo/protobuf/proto" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	"github.com/sergi/go-diff/diffmatchpatch" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"gopkg.in/bblfsh/client-go.v2/tools" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	"gopkg.in/bblfsh/sdk.v1/uast" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"gopkg.in/bblfsh/client-go.v3/tools" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"gopkg.in/bblfsh/sdk.v2/uast" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	uast_nodes "gopkg.in/bblfsh/sdk.v2/uast/nodes" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"gopkg.in/bblfsh/sdk.v2/uast/query" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	"gopkg.in/bblfsh/sdk.v2/uast/role" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	"gopkg.in/src-d/go-git.v4" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	"gopkg.in/src-d/go-git.v4/plumbing/object" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	"gopkg.in/src-d/hercules.v7/internal/core" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -42,10 +45,10 @@ const ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// DefaultShotnessXpathStruct is the default UAST XPath to choose the analysed nodes. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// It extracts functions. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	DefaultShotnessXpathStruct = "//*[@roleFunction and @roleDeclaration]" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	DefaultShotnessXpathStruct = "//*[@role='Function' and @role='Declaration']" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// DefaultShotnessXpathName is the default UAST XPath to choose the names of the analysed nodes. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// It looks at the current tree level and at the immediate children. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	DefaultShotnessXpathName = "/*[@roleFunction and @roleIdentifier and @roleName] | /*/*[@roleFunction and @roleIdentifier and @roleName]" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	DefaultShotnessXpathName = "/*[1]/*/*[@role='Function' and @role='Identifier' and @role='Name'] | /*[1]" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type nodeShotness struct { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -58,7 +61,7 @@ type nodeShotness struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 // These attributes are supposed to uniquely identify each node. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 type NodeSummary struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	InternalRole string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	Roles        []uast.Role 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	Roles        []role.Role 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	Name         string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	File         string 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -167,10 +170,10 @@ func (shotness *ShotnessAnalysis) Consume(deps map[string]interface{}) (map[stri 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	diffs := deps[items.DependencyFileDiff].(map[string]items.FileDiffData) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	allNodes := map[string]bool{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	addNode := func(name string, node *uast.Node, fileName string) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	addNode := func(name string, node uast_nodes.Node, fileName string) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		nodeSummary := NodeSummary{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			InternalRole: node.InternalType, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			Roles:        node.Roles, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			InternalRole: uast.TypeOf(node), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			Roles:        uast.RolesOf(node.(uast_nodes.Object)), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			Name:         name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			File:         fileName, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -260,23 +263,25 @@ func (shotness *ShotnessAnalysis) Consume(deps map[string]interface{}) (map[stri 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		reversedNodesAfter := reverseNodeMap(nodesAfter) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		genLine2Node := func(nodes map[string]*uast.Node, linesNum int) [][]*uast.Node { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			res := make([][]*uast.Node, linesNum) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		genLine2Node := func(nodes map[string]uast_nodes.Node, linesNum int) [][]uast_nodes.Node { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			res := make([][]uast_nodes.Node, linesNum) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			for _, node := range nodes { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				if node.StartPosition == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				pos := uast.PositionsOf(node.(uast_nodes.Object)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if pos.Start() == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				startLine := node.StartPosition.Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				endLine := node.StartPosition.Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				if node.EndPosition != nil && node.EndPosition.Line > node.StartPosition.Line { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					endLine = node.EndPosition.Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				startLine := pos.Start().Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				endLine := pos.Start().Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				if pos.End() != nil && pos.End().Line > pos.Start().Line { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					endLine = pos.End().Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				} else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					// we need to determine node.EndPosition.Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-					uast_items.VisitEachNode(node, func(child *uast.Node) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						if child.StartPosition != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							candidate := child.StartPosition.Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-							if child.EndPosition != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-								candidate = child.EndPosition.Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					// we need to determine pos.End().Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+					uast_items.VisitEachNode(node, func(child uast_nodes.Node) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						childPos := uast.PositionsOf(child.(uast_nodes.Object)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						if childPos.Start() != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							candidate := childPos.Start().Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+							if childPos.End() != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+								candidate = childPos.End().Line 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 							if candidate > endLine { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 								endLine = candidate 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -287,7 +292,7 @@ func (shotness *ShotnessAnalysis) Consume(deps map[string]interface{}) (map[stri 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				for l := startLine; l <= endLine; l++ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					lineNodes := res[l-1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					if lineNodes == nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						lineNodes = []*uast.Node{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						lineNodes = []uast_nodes.Node{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					lineNodes = append(lineNodes, node) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					res[l-1] = lineNodes 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -309,7 +314,7 @@ func (shotness *ShotnessAnalysis) Consume(deps map[string]interface{}) (map[stri 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					nodes := line2nodeBefore[l] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					for _, node := range nodes { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 						// toName because we handled a possible rename before 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						addNode(reversedNodesBefore[node], node, toName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						addNode(reversedNodesBefore[uast_nodes.UniqueKey(node)], node, toName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				lineNumBefore += size 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -317,7 +322,7 @@ func (shotness *ShotnessAnalysis) Consume(deps map[string]interface{}) (map[stri 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				for l := lineNumAfter; l < lineNumAfter+size; l++ { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					nodes := line2nodeAfter[l] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					for _, node := range nodes { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-						addNode(reversedNodesAfter[node], node, toName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+						addNode(reversedNodesAfter[uast_nodes.UniqueKey(node)], node, toName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 					} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 				lineNumAfter += size 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -443,49 +448,54 @@ func (shotness *ShotnessAnalysis) serializeBinary(result *ShotnessResult, writer 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	return err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func (shotness *ShotnessAnalysis) extractNodes(root *uast.Node) (map[string]*uast.Node, error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	structs, err := tools.Filter(root, shotness.XpathStruct) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func (shotness *ShotnessAnalysis) extractNodes(root uast_nodes.Node) (map[string]uast_nodes.Node, error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	it, err := tools.Filter(root, shotness.XpathStruct) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		return nil, err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	structs := query.AllNodes(it) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// some structs may be inside other structs; we pick the outermost 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	// otherwise due to UAST quirks there may be false positives 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	internal := map[*uast.Node]bool{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for _, mainNode := range structs { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if internal[mainNode] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	internal := map[uast_nodes.Comparable]bool{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for _, ext := range structs { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		mainNode := ext.(uast_nodes.Node) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if internal[uast_nodes.UniqueKey(mainNode)] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		subs, err := tools.Filter(mainNode, shotness.XpathStruct) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return nil, err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		for _, sub := range subs { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-			if sub != mainNode { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-				internal[sub] = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		for subs.Next() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			sub := subs.Node().(uast_nodes.Node) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+			if uast_nodes.UniqueKey(sub) != uast_nodes.UniqueKey(mainNode) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+				internal[uast_nodes.UniqueKey(sub)] = true 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	res := map[string]*uast.Node{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	for _, node := range structs { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		if internal[node] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	res := map[string]uast_nodes.Node{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	for _, ext := range structs { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		node := ext.(uast_nodes.Node) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		if internal[uast_nodes.UniqueKey(node)] { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		nodeNames, err := tools.Filter(node, shotness.XpathName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		it, err := tools.Filter(node, shotness.XpathName) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if err != nil { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			return nil, err 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		nodeNames := query.AllNodes(it) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		if len(nodeNames) == 0 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 			continue 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 		} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		res[nodeNames[0].Token] = node 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		res[uast.TokenOf(nodeNames[0].(uast_nodes.Object))] = node 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	return res, nil 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-func reverseNodeMap(nodes map[string]*uast.Node) map[*uast.Node]string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-	res := map[*uast.Node]string{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+func reverseNodeMap(nodes map[string]uast_nodes.Node) map[uast_nodes.Comparable]string { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+	res := map[uast_nodes.Comparable]string{} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	for key, node := range nodes { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-		res[node] = key 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+		res[uast_nodes.UniqueKey(node)] = key 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 	return res 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |