Skip to content

Commit

Permalink
base solution
Browse files Browse the repository at this point in the history
  • Loading branch information
Hidanio committed Oct 22, 2024
1 parent 326d6be commit b1fe2ef
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 0 deletions.
84 changes: 84 additions & 0 deletions src/linter/conf.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package linter

import (
"path/filepath"
"regexp"
"runtime"
"strings"
"time"

"github.com/VKCOM/php-parser/pkg/version"
Expand Down Expand Up @@ -38,8 +40,13 @@ type Config struct {
// Rules is a set of dynamically loaded linter diagnostics.
Rules *rules.Set

// PathRules is a set of specific rules for paths.
PathRules *RuleNode

// settings

ProjectPath string

StubsDir string
Debug bool

Expand Down Expand Up @@ -68,6 +75,82 @@ type Config struct {
StrictMixed bool
}

type RuleNode struct {
Children map[string]*RuleNode // Child nodes (subdirectories and files)
Enable map[string]bool // Rules enabled at this level
Disable map[string]bool // Disabled rules at this level
}

func NewRuleNode() *RuleNode {
return &RuleNode{
Children: make(map[string]*RuleNode),
Enable: make(map[string]bool),
Disable: make(map[string]bool),
}
}

type PathRuleSet struct {
Enable map[string]bool // Rules that are enabled for this path
Disable map[string]bool // Rules that are disabled for this path
}

func BuildRuleTree(pathRules map[string]*PathRuleSet) *RuleNode {
root := NewRuleNode()

for path, ruleSet := range pathRules {
normalizedPath := filepath.ToSlash(filepath.Clean(path))
parts := strings.Split(normalizedPath, "/")
currentNode := root

for _, part := range parts {
if part == "" {
continue
}
if _, exists := currentNode.Children[part]; !exists {
currentNode.Children[part] = NewRuleNode()
}
currentNode = currentNode.Children[part]
}

for rule := range ruleSet.Enable {
currentNode.Enable[rule] = true
}
for rule := range ruleSet.Disable {
currentNode.Disable[rule] = true
}
}

return root
}

func IsRuleEnabled(root *RuleNode, filePath string, checkRule string) bool {
normalizedPath := filepath.ToSlash(filepath.Clean(filePath))
parts := strings.Split(normalizedPath, "/")
currentNode := root

// Starting with global state. We have guarantee while parsing config that rule is `on` and exist
ruleState := true

for _, part := range parts {
if part == "" {
continue
}
if node, exists := currentNode.Children[part]; exists {
if node.Disable[checkRule] {
ruleState = false // Disable on this path
}
if node.Enable[checkRule] {
ruleState = true // Enable on this path
}
currentNode = node
} else {
break
}
}

return ruleState
}

func NewConfig(ver string) *Config {
reg := &CheckersRegistry{
info: map[string]CheckerInfo{},
Expand All @@ -79,6 +162,7 @@ func NewConfig(ver string) *Config {
return &Config{
SrcInput: inputs.NewDefaultSourceInput(),
Rules: rules.NewSet(),
PathRules: NewRuleNode(),
MaxConcurrency: runtime.NumCPU(),
IsDiscardVar: isUnderscore,
Checkers: reg,
Expand Down
19 changes: 19 additions & 0 deletions src/linter/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -1556,6 +1556,25 @@ func (d *rootWalker) Report(n ir.Node, level int, checkName, msg string, args ..
}
}

var rootNode = d.config.PathRules

filePath := d.file.Name()

if d.config.ProjectPath != "" {
// Convert absolute path to relative to the project root

relativePath, err := filepath.Rel(d.config.ProjectPath, filePath)
if err != nil {
d.ReportLocation(loc, level, checkName, msg, args...)
return
}
filePath = relativePath
}

if !IsRuleEnabled(rootNode, filePath, checkName) {
return
}

d.ReportLocation(loc, level, checkName, msg, args...)
}

Expand Down

0 comments on commit b1fe2ef

Please sign in to comment.