ccru 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.github/workflows/main.yml +27 -0
- data/.gitignore +9 -0
- data/.rubocop.yml +13 -0
- data/CHANGELOG.md +79 -0
- data/Gemfile +8 -0
- data/Gemfile.lock +55 -0
- data/README.md +88 -0
- data/Rakefile +8 -0
- data/bin/console +11 -0
- data/bin/setup +8 -0
- data/ccru.gemspec +39 -0
- data/exe/ccru +5 -0
- data/lib/ccru/cli.rb +84 -0
- data/lib/ccru/erb_linter.rb +83 -0
- data/lib/ccru/erb_linter_runner.rb +37 -0
- data/lib/ccru/file_handler.rb +12 -0
- data/lib/ccru/file_type_detector.rb +27 -0
- data/lib/ccru/git_diff.rb +141 -0
- data/lib/ccru/javascript_linter.rb +282 -0
- data/lib/ccru/javascript_linter_runner.rb +32 -0
- data/lib/ccru/linter_runner.rb +40 -0
- data/lib/ccru/offense_printer.rb +45 -0
- data/lib/ccru/rubocop_runner.rb +65 -0
- data/lib/ccru/usual_linter.rb +57 -0
- data/lib/ccru/version.rb +5 -0
- data/lib/ccru.rb +8 -0
- data/sig/ccru.rbs +4 -0
- metadata +98 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 66fdeba1e23df9b584d0b8f8f8ea2624497a2c570fce20b135a1b6f70babd39d
|
|
4
|
+
data.tar.gz: ec06b11b0728bf84c00f49770829b345ce62f7d95748885e82a54d418160b748
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: d06a3bcb1bad991407f3b367bc9ccdd7fa7bbd5d329c148c1524d5434847c572cfcc1a65e790a0465e14da5c1367c9a6ed5d0eaa5d7f18286d3b4bb2a3df509a
|
|
7
|
+
data.tar.gz: 46298743b4620789e3a3452f12994dd4e69ba5492145dcee2101372b7a599fe1fa9c892a209f6d5e26f1302b71ce35c8f0987f3a2dcbc95b738555c8ac4895cf
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Ruby
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
|
|
8
|
+
pull_request:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
build:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
name: Ruby ${{ matrix.ruby }}
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
ruby:
|
|
17
|
+
- '3.3.0'
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v4
|
|
21
|
+
- name: Set up Ruby
|
|
22
|
+
uses: ruby/setup-ruby@v1
|
|
23
|
+
with:
|
|
24
|
+
ruby-version: ${{ matrix.ruby }}
|
|
25
|
+
bundler-cache: true
|
|
26
|
+
- name: Run the default task
|
|
27
|
+
run: bundle exec rake
|
data/.gitignore
ADDED
data/.rubocop.yml
ADDED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
## [0.1.0] - 2025-08-29
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **JavaScript ES6 Syntax Checking**: New feature to detect ES6+ syntax violations in JavaScript files
|
|
9
|
+
- **Multi-language Support**: Now supports both Ruby (.rb) and JavaScript (.js) files
|
|
10
|
+
- **File Type Detection**: Automatic detection of file types and appropriate linter selection
|
|
11
|
+
- **ES6 Violation Rules**: Built-in detection for:
|
|
12
|
+
- Arrow functions (`=>`)
|
|
13
|
+
- const/let declarations
|
|
14
|
+
- Template literals (`` `string ${var}` ``)
|
|
15
|
+
- Destructuring assignments
|
|
16
|
+
- Spread operator (`...`)
|
|
17
|
+
- ES6 classes
|
|
18
|
+
- ES6 modules (import/export)
|
|
19
|
+
- Default parameters
|
|
20
|
+
- Rest parameters
|
|
21
|
+
- **JavaScript Code Quality Rules**: Comprehensive code quality checking including:
|
|
22
|
+
- **Code Style & Formatting**:
|
|
23
|
+
- Trailing whitespace detection
|
|
24
|
+
- Missing final newline detection
|
|
25
|
+
- Line length checking (120 characters)
|
|
26
|
+
- **Best Practices**:
|
|
27
|
+
- Console statement warnings (console.log, console.debug, etc.)
|
|
28
|
+
- Eval usage errors (security risk)
|
|
29
|
+
- With statement errors (deprecated)
|
|
30
|
+
- Document write warnings (performance/security)
|
|
31
|
+
- **Potential Bug Detection**:
|
|
32
|
+
- Loose equality warnings (== vs ===, allows == null/undefined)
|
|
33
|
+
- Loose inequality warnings (!= vs !==)
|
|
34
|
+
- Unused variable detection
|
|
35
|
+
- Missing semicolon detection (with smart detection)
|
|
36
|
+
- Inline comment warnings
|
|
37
|
+
- **Performance & Security**:
|
|
38
|
+
- innerHTML usage warnings (XSS risk)
|
|
39
|
+
- Global variable pollution warnings
|
|
40
|
+
- **ERB Template Support**: Custom ERB linter for convention checking:
|
|
41
|
+
- Proper spacing validation (`<% code %>` vs `<%code%>`)
|
|
42
|
+
- Comment format validation (`<%# comment %>` vs `<% # comment %>`)
|
|
43
|
+
- Output spacing validation (`<%= code %>` vs `<%=code%>`)
|
|
44
|
+
- **Enhanced CLI Options**: Support for RuboCop options via `--` separator
|
|
45
|
+
- **Improved Output Format**: Consistent violation reporting across all linters
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
- **Architecture Refactor**: Restructured code to support multiple linters
|
|
49
|
+
- **Module Organization**: Clean separation of concerns with dedicated modules:
|
|
50
|
+
- `LinterRunner`: Main orchestration module
|
|
51
|
+
- `RuboCopRunner`: Ruby file processing
|
|
52
|
+
- `JavaScriptLinterRunner`: JavaScript file processing
|
|
53
|
+
- `ErbLinterRunner`: ERB template processing
|
|
54
|
+
- **Git Diff Enhancement**: Extended to detect and process multiple file types
|
|
55
|
+
- **Violation Formatting**: Unified output format for all linter types
|
|
56
|
+
|
|
57
|
+
### Technical Improvements
|
|
58
|
+
- **Modular Design**: Clean separation of concerns with dedicated modules
|
|
59
|
+
- **Extensible Architecture**: Easy to add support for new file types and linters
|
|
60
|
+
- **Backward Compatibility**: Existing Ruby-only functionality preserved
|
|
61
|
+
- **Performance**: Maintains the same fast git-diff-based approach
|
|
62
|
+
- **Error Handling**: Improved error handling and file reading safety
|
|
63
|
+
|
|
64
|
+
### New Command Line Options
|
|
65
|
+
- Support for passing RuboCop options: `bundle exec ccru -- --auto-correct`
|
|
66
|
+
|
|
67
|
+
### Notes
|
|
68
|
+
- Staged changes support is implemented in the code but not exposed via command line options
|
|
69
|
+
- Base branch can only be specified via environment variable `CCRU_BASE`
|
|
70
|
+
|
|
71
|
+
## [0.1.0] - 2024-12-19
|
|
72
|
+
|
|
73
|
+
### Added
|
|
74
|
+
- Initial release
|
|
75
|
+
- RuboCop integration for Ruby files
|
|
76
|
+
- Git diff-based change detection
|
|
77
|
+
- Line-level filtering for modified files
|
|
78
|
+
- Base branch specification via environment variable
|
|
79
|
+
- Basic file handling and offense printing
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
ccru (0.1.0)
|
|
5
|
+
rubocop (>= 0.5, < 2.0)
|
|
6
|
+
|
|
7
|
+
GEM
|
|
8
|
+
remote: https://rubygems.org/
|
|
9
|
+
specs:
|
|
10
|
+
ast (2.4.3)
|
|
11
|
+
coderay (1.1.3)
|
|
12
|
+
json (2.13.2)
|
|
13
|
+
language_server-protocol (3.17.0.5)
|
|
14
|
+
lint_roller (1.1.0)
|
|
15
|
+
method_source (1.1.0)
|
|
16
|
+
parallel (1.27.0)
|
|
17
|
+
parser (3.3.9.0)
|
|
18
|
+
ast (~> 2.4.1)
|
|
19
|
+
racc
|
|
20
|
+
prism (1.4.0)
|
|
21
|
+
pry (0.15.2)
|
|
22
|
+
coderay (~> 1.1)
|
|
23
|
+
method_source (~> 1.0)
|
|
24
|
+
racc (1.8.1)
|
|
25
|
+
rainbow (3.1.1)
|
|
26
|
+
regexp_parser (2.11.2)
|
|
27
|
+
rubocop (1.79.2)
|
|
28
|
+
json (~> 2.3)
|
|
29
|
+
language_server-protocol (~> 3.17.0.2)
|
|
30
|
+
lint_roller (~> 1.1.0)
|
|
31
|
+
parallel (~> 1.10)
|
|
32
|
+
parser (>= 3.3.0.2)
|
|
33
|
+
rainbow (>= 2.2.2, < 4.0)
|
|
34
|
+
regexp_parser (>= 2.9.3, < 3.0)
|
|
35
|
+
rubocop-ast (>= 1.46.0, < 2.0)
|
|
36
|
+
ruby-progressbar (~> 1.7)
|
|
37
|
+
unicode-display_width (>= 2.4.0, < 4.0)
|
|
38
|
+
rubocop-ast (1.46.0)
|
|
39
|
+
parser (>= 3.3.7.2)
|
|
40
|
+
prism (~> 1.4)
|
|
41
|
+
ruby-progressbar (1.13.0)
|
|
42
|
+
unicode-display_width (3.1.5)
|
|
43
|
+
unicode-emoji (~> 4.0, >= 4.0.4)
|
|
44
|
+
unicode-emoji (4.0.4)
|
|
45
|
+
|
|
46
|
+
PLATFORMS
|
|
47
|
+
arm64-darwin-24
|
|
48
|
+
ruby
|
|
49
|
+
|
|
50
|
+
DEPENDENCIES
|
|
51
|
+
ccru!
|
|
52
|
+
pry (= 0.15.2)
|
|
53
|
+
|
|
54
|
+
BUNDLED WITH
|
|
55
|
+
2.5.22
|
data/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# ccru – Code Changed Rules (RuboCop + ES6 Syntax + ERB Checker)
|
|
2
|
+
|
|
3
|
+
RuboCop on diff for Ruby files + ES6 syntax checker for JavaScript files + ERB template support: lint only what's new/changed
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```ruby
|
|
8
|
+
group :development, :test
|
|
9
|
+
gem 'ccru', require: false
|
|
10
|
+
end
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
### Basic Usage
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Check changed Ruby, JavaScript, and ERB files in git diff (compared to merge-base)
|
|
19
|
+
bundle exec ccru
|
|
20
|
+
|
|
21
|
+
# Check specific files
|
|
22
|
+
bundle exec ccru path/to/file.rb path/to/script.js path/to/template.erb
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Environment Variables
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Set default base branch for git diff comparison
|
|
29
|
+
export CCRU_BASE=develop
|
|
30
|
+
bundle exec ccru
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Supported File Types
|
|
34
|
+
|
|
35
|
+
- **Ruby files**: `.rb` - Checked with RuboCop
|
|
36
|
+
- **JavaScript files**: `.js` - Checked for ES6 syntax violations + code quality
|
|
37
|
+
- **ERB templates**: `.erb` - Checked with custom ERB linter for conventions
|
|
38
|
+
|
|
39
|
+
## ERB Template Support
|
|
40
|
+
|
|
41
|
+
### Ruby ERB Templates (`.erb`)
|
|
42
|
+
- Automatically checks ERB conventions and formatting
|
|
43
|
+
- Validates proper spacing: `<% code %>` instead of `<%code%>`
|
|
44
|
+
- Checks comment format: `<%# comment %>` instead of `<% # comment %>`
|
|
45
|
+
- Ensures proper output spacing: `<%= code %>` instead of `<%=code%>`
|
|
46
|
+
- Maps violations back to original ERB line numbers
|
|
47
|
+
|
|
48
|
+
## JavaScript ES6 Violations Checked
|
|
49
|
+
|
|
50
|
+
The following ES6+ syntax patterns are detected and flagged as errors:
|
|
51
|
+
|
|
52
|
+
- **Arrow functions**: `=>` syntax
|
|
53
|
+
- **const/let**: `const` and `let` declarations
|
|
54
|
+
- **Template literals**: `` `string ${variable}` ``
|
|
55
|
+
- **Destructuring**: `{ prop } = obj` assignments
|
|
56
|
+
- **Spread operator**: `...` syntax
|
|
57
|
+
- **ES6 classes**: `class` declarations
|
|
58
|
+
- **ES6 modules**: `import`/`export` statements
|
|
59
|
+
- **Default parameters**: `function(param = value)`
|
|
60
|
+
- **Rest parameters**: `function(...args)`
|
|
61
|
+
|
|
62
|
+
## JavaScript Code Quality Rules
|
|
63
|
+
|
|
64
|
+
### Code Style & Formatting
|
|
65
|
+
- **Trailing whitespace**: Detects spaces at end of lines
|
|
66
|
+
- **Missing final newline**: Ensures files end with newline
|
|
67
|
+
- **Line length**: Maximum line length checking (120 characters)
|
|
68
|
+
|
|
69
|
+
### Best Practices
|
|
70
|
+
- **Console statements**: Warns about `console.log`, `console.debug`, etc.
|
|
71
|
+
- **Eval usage**: Errors on dangerous `eval()` calls
|
|
72
|
+
- **With statement**: Errors on deprecated `with` statements
|
|
73
|
+
- **Document write**: Warns about `document.write()` usage
|
|
74
|
+
|
|
75
|
+
### Potential Bugs
|
|
76
|
+
- **Loose equality**: Warns about `==` vs `===` usage (allows `== null` and `== undefined`)
|
|
77
|
+
- **Loose inequality**: Warns about `!=` vs `!==` usage
|
|
78
|
+
- **Unused variables**: Detects potentially unused variable declarations
|
|
79
|
+
- **Missing semicolons**: Identifies missing semicolons (with smart detection)
|
|
80
|
+
- **Inline comments**: Warns about inline comments at end of code lines
|
|
81
|
+
|
|
82
|
+
### Performance Issues
|
|
83
|
+
- **innerHTML usage**: Warns about potential XSS vulnerabilities
|
|
84
|
+
- **Global variables**: Warns about global scope pollution
|
|
85
|
+
|
|
86
|
+
## License
|
|
87
|
+
|
|
88
|
+
This project is licensed under the MIT License.
|
data/Rakefile
ADDED
data/bin/console
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require "bundler/setup"
|
|
5
|
+
require "ccru"
|
|
6
|
+
|
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
+
|
|
10
|
+
require "irb"
|
|
11
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
data/ccru.gemspec
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "lib/ccru/version"
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = "ccru"
|
|
7
|
+
spec.version = Ccru::VERSION
|
|
8
|
+
spec.authors = ["thucpt"]
|
|
9
|
+
spec.email = ["thucpt@zigexn.vn"]
|
|
10
|
+
|
|
11
|
+
spec.summary = "Multi-language linter wrapper that checks only changed lines/files (Ruby, JavaScript, ERB)"
|
|
12
|
+
spec.description = "Checks only new files fully and modified files only for changed lines based on git diff.\
|
|
13
|
+
Supports Ruby (RuboCop), JavaScript (ES6 syntax + code quality), and ERB templates (conventions)."
|
|
14
|
+
spec.homepage = "https://github.com/thuczige/ccru"
|
|
15
|
+
spec.required_ruby_version = ">= 2.0"
|
|
16
|
+
|
|
17
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
|
18
|
+
|
|
19
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
20
|
+
spec.metadata["source_code_uri"] = "https://github.com/thuczige/ccru"
|
|
21
|
+
spec.metadata["changelog_uri"] = "https://github.com/thuczige/ccru/blob/main/CHANGELOG.md"
|
|
22
|
+
spec.metadata["rubygems_mfa_required"] = "true"
|
|
23
|
+
|
|
24
|
+
# Specify which files should be added to the gem when it is released.
|
|
25
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
26
|
+
File.basename(__FILE__)
|
|
27
|
+
spec.files = Dir.chdir(__dir__) { `git ls-files -z`.split("\x0") }
|
|
28
|
+
spec.bindir = "exe"
|
|
29
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
30
|
+
spec.require_paths = ["lib"]
|
|
31
|
+
|
|
32
|
+
# Uncomment to register a new dependency of your gem
|
|
33
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
|
34
|
+
|
|
35
|
+
spec.add_dependency "rubocop", ">= 0.5", "< 2.0"
|
|
36
|
+
|
|
37
|
+
# For more information and examples about making a new gem, check out our
|
|
38
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
|
39
|
+
end
|
data/exe/ccru
ADDED
data/lib/ccru/cli.rb
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "git_diff"
|
|
4
|
+
require_relative "linter_runner"
|
|
5
|
+
|
|
6
|
+
require "pry"
|
|
7
|
+
|
|
8
|
+
module Ccru
|
|
9
|
+
# Command-line interface for ccru
|
|
10
|
+
class CLI
|
|
11
|
+
def run(argv)
|
|
12
|
+
puts "\n[START] #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}\n\n"
|
|
13
|
+
opts = { base: ENV.fetch("CCRU_BASE", nil), staged: false, files: argv }
|
|
14
|
+
|
|
15
|
+
# Check if there are specific files provided
|
|
16
|
+
return run_on_specific_files(opts[:files]) if opts[:files] && opts[:files].any?
|
|
17
|
+
|
|
18
|
+
files = Ccru::GitDiff.changed_files(opts[:base], opts[:staged])
|
|
19
|
+
return no_changes if files.empty?
|
|
20
|
+
|
|
21
|
+
run_on_files(files)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
include LinterRunner
|
|
27
|
+
|
|
28
|
+
def run_on_specific_files(file_paths)
|
|
29
|
+
has_errors = false
|
|
30
|
+
|
|
31
|
+
file_paths.each do |path|
|
|
32
|
+
result = process_specific_file(path)
|
|
33
|
+
has_errors = true if result == 1
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
return 1 if has_errors
|
|
37
|
+
|
|
38
|
+
puts_all_ok
|
|
39
|
+
0
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def process_specific_file(path)
|
|
43
|
+
return 0 unless valid_file?(path)
|
|
44
|
+
|
|
45
|
+
file_type = FileTypeDetector.file_type(path)
|
|
46
|
+
meta = { type: :new, lines: nil, file_type: file_type }
|
|
47
|
+
|
|
48
|
+
run_linter_file(path, meta)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def valid_file?(path)
|
|
52
|
+
File.exist?(path) && FileTypeDetector.supported_file?(path)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def no_changes
|
|
56
|
+
puts_all_ok
|
|
57
|
+
0
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def run_on_files(files)
|
|
61
|
+
has_errors = false
|
|
62
|
+
|
|
63
|
+
files.each do |path, meta|
|
|
64
|
+
result = process_file(path, meta)
|
|
65
|
+
has_errors = true if result == 1
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
return 1 if has_errors
|
|
69
|
+
|
|
70
|
+
puts_all_ok
|
|
71
|
+
0
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def process_file(path, meta)
|
|
75
|
+
return run_linter_file(path, meta) if meta[:type] == :new
|
|
76
|
+
|
|
77
|
+
run_linter_filtered(path, meta)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def puts_all_ok
|
|
81
|
+
puts "ccru: All OK - No violations found\n\n"
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "usual_linter"
|
|
4
|
+
|
|
5
|
+
module Ccru
|
|
6
|
+
# ERB linter that checks basic ERB conventions
|
|
7
|
+
class ErbLinter
|
|
8
|
+
include UsualLinter
|
|
9
|
+
|
|
10
|
+
def initialize
|
|
11
|
+
@offenses = []
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# ERB convention violations
|
|
15
|
+
ERB_VIOLATIONS = {
|
|
16
|
+
# Bad comment format: <% # comment %> instead of <%# comment %>
|
|
17
|
+
bad_comment_format: {
|
|
18
|
+
pattern: /<%\s+#[^%]*%>/,
|
|
19
|
+
message: "Use <%# comment %> instead of <% # comment %> for ERB comments",
|
|
20
|
+
cop_name: "BadCommentFormat",
|
|
21
|
+
severity: "error"
|
|
22
|
+
},
|
|
23
|
+
# Bad spacing: <%foo%> instead of <% foo %>
|
|
24
|
+
bad_spacing: {
|
|
25
|
+
pattern: /<%(?!=)[^\s#][^%]*%>/,
|
|
26
|
+
message: "<% your_code %> for better readability",
|
|
27
|
+
cop_name: "BadSpacing",
|
|
28
|
+
severity: "warning"
|
|
29
|
+
},
|
|
30
|
+
# Bad output spacing: <%=foo%> instead of <%= foo %>
|
|
31
|
+
bad_output_spacing: {
|
|
32
|
+
pattern: /<%=[^\s][^%]*%>/,
|
|
33
|
+
message: "<%= your_code %> for better readability",
|
|
34
|
+
cop_name: "BadOutputSpacing",
|
|
35
|
+
severity: "warning"
|
|
36
|
+
},
|
|
37
|
+
# Bad comment spacing: <%#foo%> instead of <%# foo %>
|
|
38
|
+
bad_comment_spacing: {
|
|
39
|
+
pattern: /<%#[^\s][^%]*%>/,
|
|
40
|
+
message: "<%# your_comment %> for better readability",
|
|
41
|
+
cop_name: "BadCommentSpacing",
|
|
42
|
+
severity: "warning"
|
|
43
|
+
}
|
|
44
|
+
}.freeze
|
|
45
|
+
|
|
46
|
+
def lint_file(content)
|
|
47
|
+
check_final_newline(content)
|
|
48
|
+
check_erb_conventions(content)
|
|
49
|
+
check_trailing_whitespace(content)
|
|
50
|
+
|
|
51
|
+
@offenses
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def lint_filtered(content, changed_lines)
|
|
55
|
+
changed_lines.each do |line_number|
|
|
56
|
+
line_content = content.lines[line_number - 1]
|
|
57
|
+
next unless line_content
|
|
58
|
+
|
|
59
|
+
check_line_conventions(line_content, line_number)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
@offenses
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def check_erb_conventions(content)
|
|
66
|
+
content.lines.each_with_index do |line_content, index|
|
|
67
|
+
next if line_content.strip.empty?
|
|
68
|
+
|
|
69
|
+
line_number = index + 1
|
|
70
|
+
check_line_conventions(line_content, line_number)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def check_line_conventions(line_content, line_number)
|
|
75
|
+
ERB_VIOLATIONS.each do |rule_name, rule|
|
|
76
|
+
next if line_content.match(rule[:pattern]).nil?
|
|
77
|
+
|
|
78
|
+
add_offense(rule_name, rule, line_content, line_number)
|
|
79
|
+
break
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "erb_linter"
|
|
4
|
+
require_relative "file_handler"
|
|
5
|
+
require_relative "offense_printer"
|
|
6
|
+
|
|
7
|
+
module Ccru
|
|
8
|
+
# ERB linter runner methods
|
|
9
|
+
module ErbLinterRunner
|
|
10
|
+
include FileHandler
|
|
11
|
+
include OffensePrinter
|
|
12
|
+
|
|
13
|
+
def run_erb_linter_file(path)
|
|
14
|
+
content = safe_read_file(path)
|
|
15
|
+
return 0 unless content
|
|
16
|
+
|
|
17
|
+
erb_linter = ErbLinter.new
|
|
18
|
+
offenses = erb_linter.lint_file(content)
|
|
19
|
+
return 0 if offenses.empty?
|
|
20
|
+
|
|
21
|
+
print_offenses(path, offenses)
|
|
22
|
+
1
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def run_erb_linter_filtered(path, meta)
|
|
26
|
+
content = safe_read_file(path)
|
|
27
|
+
return 0 unless content && meta[:lines].any?
|
|
28
|
+
|
|
29
|
+
erb_linter = ErbLinter.new
|
|
30
|
+
offenses = erb_linter.lint_filtered(content, meta[:lines])
|
|
31
|
+
return 0 if offenses.empty?
|
|
32
|
+
|
|
33
|
+
print_offenses(path, offenses)
|
|
34
|
+
1
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ccru
|
|
4
|
+
# Detects file types and determines which linter to use
|
|
5
|
+
module FileTypeDetector
|
|
6
|
+
SUPPORTED_EXTENSIONS = {
|
|
7
|
+
".rb" => :ruby,
|
|
8
|
+
".js" => :javascript,
|
|
9
|
+
".erb" => :erb
|
|
10
|
+
}.freeze
|
|
11
|
+
|
|
12
|
+
class << self
|
|
13
|
+
def supported_file?(path)
|
|
14
|
+
SUPPORTED_EXTENSIONS.key?(File.extname(path))
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def file_type(path)
|
|
18
|
+
extension = File.extname(path)
|
|
19
|
+
SUPPORTED_EXTENSIONS[extension]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def ruby_file?(path)
|
|
23
|
+
file_type(path) == :ruby
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|