Files
2026-07-13 13:33:09 +08:00

333 lines
7.4 KiB
Go

package file_map
import (
"fmt"
"strings"
shared "plandex-shared"
)
func isDefinitionNode(node Node, parentNode *Node) bool {
setNodeType(&node)
res := false
config := definitionNodeMap.getConfig(node.Type, node.Lang)
var parentConfig *nodeConfig
if parentNode != nil {
parentConfig = parentNodeMap.getConfig(parentNode.Type, parentNode.Lang)
}
if config == nil {
res = isAssignmentNode(node) || isParentNode(node)
if res && parentConfig != nil && parentConfig.onlyChildren != nil {
res = parentConfig.onlyChildren[nodeType(node.Type)]
}
return res
}
res = !config.ignore
if res {
if parentConfig != nil && parentConfig.onlyChildren != nil {
res = parentConfig.onlyChildren[nodeType(node.Type)]
}
}
return res
}
func isAssignmentNode(node Node) bool {
setNodeType(&node)
config := assignmentNodeMap.getConfig(node.Type, node.Lang)
if config == nil {
return false
}
return !config.ignore
}
func isParentNode(node Node) bool {
setNodeType(&node)
config := parentNodeMap.getConfig(node.Type, node.Lang)
if config == nil {
return false
}
return !config.ignore
}
func isImplBoundaryNode(node Node) bool {
setNodeType(&node)
config := implBoundaryNodeMap.getConfig(node.Type, node.Lang)
if config == nil {
return false
}
return !config.ignore
}
func isAssignmentBoundaryNode(node Node) bool {
setNodeType(&node)
config := assignmentBoundaryNodeMap.getConfig(node.Type, node.Lang)
if config == nil {
return false
}
return !config.ignore
}
func isIdentifierNode(node Node) bool {
setNodeType(&node)
config := identifierNodeMap.getConfig(node.Type, node.Lang)
if config == nil {
return false
}
return !config.ignore
}
func isPassThroughParentNode(node Node) bool {
setNodeType(&node)
config := passThroughParentNodeMap.getConfig(node.Type, node.Lang)
if config == nil {
return false
}
return !config.ignore
}
func isIncludeAndContinueNode(node Node) bool {
setNodeType(&node)
config := includeAndContinueNodeMap.getConfig(node.Type, node.Lang)
if config == nil {
return false
}
return !config.ignore
}
func (m nodeMap) getConfig(t string, lang shared.Language) *nodeConfig {
// first look for exact match
config, ok := m[nodeType(t)]
if ok {
if config.all {
if config.except == nil || !config.except[lang] {
return &config
}
}
if config.languages != nil && config.languages[lang] {
return &config
}
}
// then look for prefix or suffix match
var foundConfig *nodeConfig
for k, config := range m {
var maybeConfig *nodeConfig
if config.nodeMatch == matchTypePrefix && strings.HasPrefix(t, string(k)) {
maybeConfig = &config
} else if config.nodeMatch == matchTypeSuffix && strings.HasSuffix(t, string(k)) {
maybeConfig = &config
}
var wouldSet *nodeConfig
if maybeConfig != nil {
if maybeConfig.all {
if maybeConfig.except == nil || !maybeConfig.except[lang] {
wouldSet = maybeConfig
}
} else if maybeConfig.languages != nil && maybeConfig.languages[lang] {
wouldSet = maybeConfig
}
}
if wouldSet != nil {
if foundConfig != nil {
// ignore takes precedence
if wouldSet.ignore {
foundConfig = wouldSet
}
} else {
foundConfig = wouldSet
}
}
}
return foundConfig
}
func findImplementationBoundary(node Node) *Node {
if isImplBoundaryNode(node) {
return &node
}
for i := 0; i < int(node.TsNode.ChildCount()); i++ {
child := node.TsNode.Child(i)
if verboseLogging {
fmt.Println(" findImplementationBoundary child", child.Type())
}
childNode := Node{
Type: child.Type(),
Lang: node.Lang,
TsNode: child,
Bytes: node.Bytes,
}
if isImplBoundaryNode(childNode) {
return &childNode
} else {
found := findImplementationBoundary(childNode)
if found != nil {
return found
}
}
}
return nil
}
func findIdentifier(node Node) []Node {
if isIdentifierNode(node) {
return []Node{node}
}
nodes := []Node{}
for i := 0; i < int(node.TsNode.ChildCount()); i++ {
child := node.TsNode.Child(i)
childNode := Node{
Type: child.Type(),
Lang: node.Lang,
TsNode: child,
Bytes: node.Bytes,
}
if verboseLogging {
fmt.Println(" child", child.Type())
}
found := findIdentifier(childNode)
if found != nil {
nodes = append(nodes, found...)
}
}
return nodes
}
func firstDefinitionChild(node Node) *Node {
for i := 0; i < int(node.TsNode.ChildCount()); i++ {
child := node.TsNode.Child(i)
if verboseLogging {
fmt.Println(" child", child.Type())
}
childNode := Node{
Type: child.Type(),
Lang: node.Lang,
TsNode: child,
Bytes: node.Bytes,
}
if isDefinitionNode(childNode, &node) && !isIncludeAndContinueNode(childNode) {
return &childNode
}
}
return nil
}
func findAssignmentBoundary(node Node) *Node {
return findAssignmentBoundaryOnly(node, nil)
}
func findAssignmentBoundaryOnly(node Node, only map[nodeType]bool) *Node {
if only != nil {
if _, ok := only[nodeType(node.Type)]; ok {
return &node
}
} else if isAssignmentBoundaryNode(node) {
return skipForwardIfNeeded(node)
}
for i := 0; i < int(node.TsNode.ChildCount()); i++ {
child := node.TsNode.Child(i)
childNode := Node{
Type: child.Type(),
Lang: node.Lang,
TsNode: child,
Bytes: node.Bytes,
}
if verboseLogging {
fmt.Println(" child", child.Type())
}
found := findAssignmentBoundaryOnly(childNode, only)
if found != nil {
return found
}
}
return nil
}
func skipForwardIfNeeded(node Node) *Node {
config := assignmentBoundarySkipForwardNodeMap.getConfig(node.Type, node.Lang)
if config == nil {
return &node
}
if config.skipForward != nil {
tsParent := node.TsNode.Parent()
if tsParent == nil {
return &node
}
parent := Node{
Type: tsParent.Type(),
Lang: node.Lang,
TsNode: tsParent,
Bytes: node.Bytes,
}
skipToNode := findAssignmentBoundaryOnly(parent, config.skipForward)
if skipToNode != nil {
return skipToNode
}
}
return &node
}
func setNodeType(node *Node) {
if node.Lang == shared.LanguageElixir && node.Type == "call" {
content := node.TsNode.Content(node.Bytes)
switch {
case strings.HasPrefix(string(content), "defmodule"):
node.Type = "module_definition"
case strings.HasPrefix(string(content), "defprotocol"):
node.Type = "protocol_definition"
case strings.HasPrefix(string(content), "defimpl"):
node.Type = "protocol_implementation"
case strings.HasPrefix(string(content), "defstruct"):
node.Type = "struct_definition"
case strings.HasPrefix(string(content), "defexception"):
node.Type = "exception_definition"
case strings.HasPrefix(string(content), "defdelegate"):
node.Type = "delegate_definition"
case strings.HasPrefix(string(content), "defoverridable"):
node.Type = "overridable_definition"
case strings.HasPrefix(string(content), "defcallback"):
node.Type = "callback_definition"
case strings.HasPrefix(string(content), "defmacrocallback"):
node.Type = "macro_callback_definition"
case strings.HasPrefix(string(content), "defmacrop"):
node.Type = "private_macro_definition"
case strings.HasPrefix(string(content), "defmacro"):
node.Type = "macro_definition"
case strings.HasPrefix(string(content), "defguardp"):
node.Type = "private_guard_definition"
case strings.HasPrefix(string(content), "defguard"):
node.Type = "guard_definition"
case strings.HasPrefix(string(content), "defp"):
node.Type = "private_function_definition"
case strings.HasPrefix(string(content), "def"):
node.Type = "function_definition"
}
}
}