Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions .cursor/rules/clean-code.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
---
description: Guidelines for writing clean, maintainable, and human-readable code. Apply these rules when writing or reviewing code to ensure consistency and quality.
globs:
---
# Clean Code Guidelines

## Constants Over Magic Numbers
- Replace hard-coded values with named constants
- Use descriptive constant names that explain the value's purpose
- Keep constants at the top of the file or in a dedicated constants file

## Meaningful Names
- Variables, functions, and classes should reveal their purpose
- Names should explain why something exists and how it's used
- Avoid abbreviations unless they're universally understood

## Smart Comments
- Don't comment on what the code does - make the code self-documenting
- Use comments to explain why something is done a certain way
- Document APIs, complex algorithms, and non-obvious side effects

## Single Responsibility
- Each function should do exactly one thing
- Functions should be small and focused
- If a function needs a comment to explain what it does, it should be split

## DRY (Don't Repeat Yourself)
- Extract repeated code into reusable functions
- Share common logic through proper abstraction
- Maintain single sources of truth

## Clean Structure
- Keep related code together
- Organize code in a logical hierarchy
- Use consistent file and folder naming conventions

## Encapsulation
- Hide implementation details
- Expose clear interfaces
- Move nested conditionals into well-named functions

## Code Quality Maintenance
- Refactor continuously
- Fix technical debt early
- Leave code cleaner than you found it

## Testing
- Write tests before fixing bugs
- Keep tests readable and maintainable
- Test edge cases and error conditions

## Version Control
- Write clear commit messages
- Make small, focused commits
- Use meaningful branch names
4 changes: 2 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func main() {
},
}

cmdLint.Flags().StringP("rules", "r", "rules", "Path to directory with rules")
cmdLint.Flags().StringP("rules", "r", ".mendix-cache/rules", "Path to directory with rules")
cmdLint.Flags().StringP("modelsource", "m", "modelsource", "Path to directory with exported model")
cmdLint.Flags().StringP("xunit-report", "x", "", "Path to output file for xunit report. If not provided, no xunit report will be generated")
cmdLint.Flags().StringP("json-file", "j", "", "Path to output file for JSON report. If not provided, no JSON file will be generated")
Expand Down Expand Up @@ -111,7 +111,7 @@ func main() {
},
}

cmdRules.Flags().StringP("rules", "r", "rules", "Path to directory with rules")
cmdRules.Flags().StringP("rules", "r", ".mendix-cache/rules", "Path to directory with rules")
cmdRules.Flags().Bool("verbose", false, "Turn on for debug logs")
rootCmd.AddCommand(cmdRules)

Expand Down
49 changes: 31 additions & 18 deletions serve/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ func NewServeCommand() *cobra.Command {
cmd.Flags().StringP("input", "i", ".", "Path to directory or mpr file to export. If it's a directory, all mpr files will be exported")
cmd.Flags().StringP("output", "o", "modelsource", "Path to directory to write the yaml files. If it doesn't exist, it will be created")
cmd.Flags().StringP("mode", "m", "basic", "Export mode. Valid options: basic, advanced")
cmd.Flags().StringP("rules", "r", "rules", "Path to directory with rules")
cmd.Flags().StringP("rules", "r", ".mendix-cache/rules", "Path to directory with rules")
cmd.Flags().IntP("port", "p", 8082, "Port to run the server on")
cmd.Flags().Bool("verbose", false, "Turn on for debug logs")
cmd.Flags().IntP("debounce", "d", 500, "Debounce time in milliseconds for file change events")
Expand Down Expand Up @@ -73,9 +73,12 @@ func runServe(cmd *cobra.Command, args []string) {

// Check if rules directory exists, if not download it
if _, err := os.Stat(rulesDirectory); os.IsNotExist(err) {
log.Infof("Rules directory %s not found. Downloading latest mxlint-rules from GitHub...", rulesDirectory)
if err := DownloadRules(rulesDirectory, log); err != nil {
log.Fatalf("Failed to download rules: %v", err)
}
} else {
log.Infof("Rules directory %s found", rulesDirectory)
}

expandedPath, err := filepath.Abs(inputDirectory)
Expand Down Expand Up @@ -244,6 +247,14 @@ func runServe(cmd *cobra.Command, args []string) {
log.Debugf("Change detected: %s", event)
}

// skip if event is CHMOD
if event.Has(fsnotify.Chmod) {
if verbose {
log.Debugf("Skipping CHMOD event: %s", event)
}
continue
}

timerMutex.Lock()
// Cancel existing timer if it's running
if timer != nil {
Expand Down Expand Up @@ -313,32 +324,34 @@ func addDirsRecursive(watcher *fsnotify.Watcher, root string, excludeDir string,
return err
}

// Skip the exclude directory
// Only process directories
if !info.IsDir() {
return nil
}

// Get absolute path for comparison
absPath, err := filepath.Abs(path)
if err != nil {
return err
}

if absPath == excludePath || strings.HasPrefix(absPath, excludePath+string(os.PathSeparator)) {
if info.IsDir() {
return filepath.SkipDir
}
return nil
// Skip hidden directories (but not "." itself which represents current directory)
baseName := filepath.Base(path)
if strings.HasPrefix(baseName, ".") && baseName != "." {
log.Debugf("Skipping hidden directory: %s", path)
return filepath.SkipDir
}

// Skip hidden files and directories
if strings.HasPrefix(filepath.Base(path), ".") {
if info.IsDir() {
return filepath.SkipDir
}
return nil
// Skip the exclude directory and its subdirectories
if absPath == excludePath || strings.HasPrefix(absPath, excludePath+string(os.PathSeparator)) {
log.Debugf("Skipping exclude directory: %s", path)
return filepath.SkipDir
}

// Only add directories to the watcher
if info.IsDir() {
if err := watcher.Add(path); err != nil {
log.Warnf("Error watching path %s: %v", path, err)
}
// Add directory to the watcher
log.Debugf("Adding directory to watch: %s", path)
if err := watcher.Add(path); err != nil {
log.Warnf("Error watching path %s: %v", path, err)
}

return nil
Expand Down
Loading