immosquare-cleaner 0.1.104 → 0.1.105

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fe176ca59627b1693859214bf23eb81860a761401abc4d76ed3412d70b586892
4
- data.tar.gz: c7663e4b3eacacbf4e241bd2896ae714f388805c7c395b02ffa4528ba12f0696
3
+ metadata.gz: 73fae62cc9335a00c4ca43998545d10a0ca0ae7541c5aaa1d2721e03834f26ea
4
+ data.tar.gz: 122bd307b070b742dd7c2e1739503a5437d6feeaa0813bbf8c58eeeca315d7b5
5
5
  SHA512:
6
- metadata.gz: b019065b995fbe5ac11216c458d467aa4ec0c65924afe26d29111953197b99992e1473f88eecfd5813db12211e9d0bfa6e9e6ab78df394a9c185300006e76a7e
7
- data.tar.gz: eaad6f72c1e46688e230a52e2dcf5e040b3af9014f030a92742d0d227e13b25c02e3e57f3e334152c6fdce396f291baa91caf75a49400a72c88f22a5efc7aafa
6
+ metadata.gz: bff5c8d3ef37a3e24b05c262d23a119bd6bae616e84ce3625fd40921e7f5becb69520b7a4c1992e38e2de6ffde20778207c3f7c7c9e2ab846a6a69c3bfb01b8c
7
+ data.tar.gz: 9695564168f28471e05478bf1c8abb5c291704c1f7f60cc714defe46266791537b2d0cce549dcfcb93ea912f8e32d5ded3eb74d664107d6016cbe1a78cefb4eb
@@ -1,3 +1,3 @@
1
1
  module ImmosquareCleaner
2
- VERSION = "0.1.104".freeze
2
+ VERSION = "0.1.105".freeze
3
3
  end
@@ -8,136 +8,144 @@ module RuboCop
8
8
 
9
9
  MSG = "Comments should be normalized with the standard format if start with ##".freeze
10
10
  BORDER_LINE = "###{"=" * 60}##".freeze
11
+ INSIDE_SEPARATOR = "## ---------".freeze
12
+ BLANK_LINE = "##".freeze
13
+ EMPTY_BODY = "## ...".freeze
11
14
  SPACE = " ".freeze
12
- INSIDE_SEPARATOR = "###{SPACE}---------".freeze
15
+
16
+ ##============================================================##
17
+ ## Patterns détectés ligne par ligne dans un bloc :
18
+ ## - STRUCTURED_LINE : puces, citations, listes numérotées
19
+ ## - INDENTED_LINE : indentation explicite (3+ espaces après ##)
20
+ ## - RAW_LINE : ligne préservée telle quelle (## | ...)
21
+ ## - FENCE_LINE : ouverture/fermeture d'un bloc de code (## ```)
22
+ ## - USER_SEPARATOR : séparateur explicite (## ---, ===, ___)
23
+ ##============================================================##
24
+ STRUCTURED_LINE = /\A##\s+([-*+>]|\d+[.)])\s/
25
+ INDENTED_LINE = /\A##\s{3,}\S/
26
+ RAW_LINE = /\A##\s*\|/
27
+ FENCE_LINE = /\A##\s*```/
28
+ USER_SEPARATOR = /\A##\s*[-=_]{3,}\s*\z/
13
29
 
14
30
  def on_new_investigation
15
31
  return if @investigation_in_progress
16
32
 
17
33
  @investigation_in_progress = true
18
34
 
19
- comment_blocks = find_comment_blocks(processed_source.comments)
20
-
21
- comment_blocks.each do |block|
22
- correct_block = normalize_comment_block(block)
23
-
24
-
25
- if needs_correction?(block, correct_block)
26
- ##============================================================##
27
- ## Pour désactiver les cops autres cops qui pourraient être
28
- ## déclenchés par les commentaires
29
- ##============================================================##
30
- buffer = processed_source.buffer
31
- start_pos = buffer.line_range(block.first.location.line).begin_pos
32
- end_pos = buffer.line_range(block.last.location.line).end_pos
33
- range = Parser::Source::Range.new(buffer, start_pos, end_pos)
34
- ignore_node(range)
35
-
36
- ##============================================================##
37
- ## Puis, on ajoute l'offense
38
- ##============================================================##
39
- add_offense(block.first) do |corrector|
40
- corrector.replace(range, normalize_comment_block(block))
41
- end
35
+ find_comment_blocks(processed_source.comments).each do |block|
36
+ normalized = normalize_comment_block(block)
37
+ next if !needs_correction?(block, normalized)
38
+
39
+ range = block_range(block)
40
+ ignore_node(range)
41
+ add_offense(block.first) do |corrector|
42
+ corrector.replace(range, normalized)
42
43
  end
43
44
  end
44
45
  end
45
46
 
46
-
47
-
48
47
  private
49
48
 
50
-
51
49
  ##============================================================##
52
- ## On ne veut traiter que les commentaires ## qui ne sont pas
53
- ## des commentaires de fin de ligne ruby
50
+ ## On ne traite que les commentaires qui commencent en début de
51
+ ## ligne par "##" (pas les commentaires de fin de ligne ruby).
52
+ ## Les blocs sont des suites de lignes contiguës.
54
53
  ##============================================================##
55
54
  def find_comment_blocks(comments)
56
- blocks = []
57
- current_block = []
58
- standalone_comments = comments.select do |comment|
59
- line = processed_source.lines[comment.location.line - 1]
60
- line.strip.start_with?("##")
55
+ standalone = comments.select do |comment|
56
+ processed_source.lines[comment.location.line - 1].lstrip.start_with?("##")
61
57
  end
62
58
 
63
- standalone_comments.each_with_index do |comment, index|
64
- next_comment = standalone_comments[index + 1]
65
- next_line_contiguous = next_comment && next_comment.location.line == comment.location.line + 1
59
+ standalone.slice_when {|prev, nxt| nxt.location.line != prev.location.line + 1 }.to_a
60
+ end
66
61
 
67
- if next_line_contiguous
68
- current_block << comment
69
- else
70
- current_block << comment
71
- blocks << current_block.dup if !current_block.empty?
72
- current_block.clear
73
- end
74
- end
75
- blocks
62
+ def block_range(block)
63
+ buffer = processed_source.buffer
64
+ start_pos = buffer.line_range(block.first.location.line).begin_pos
65
+ end_pos = buffer.line_range(block.last.location.line).end_pos
66
+ Parser::Source::Range.new(buffer, start_pos, end_pos)
76
67
  end
77
68
 
78
69
  ##============================================================##
79
- ## Pour formater correctement le block de commentaires
70
+ ## Encadre le body avec BORDER_LINE et indente toutes les lignes
71
+ ## sur la colonne du bloc original. Le range remplacé démarre en
72
+ ## colonne 0, donc la première ligne doit aussi recevoir le pad.
80
73
  ##============================================================##
81
74
  def normalize_comment_block(block)
82
- indent_level = indent_level(block.first)
83
- first_line_with_text_found = false
75
+ body = build_body(block)
76
+ body = [EMPTY_BODY] if body.empty?
84
77
 
85
- body = block.map do |comment|
86
- text = comment.text.to_s.strip
87
- alphanumercic = text.match?(/[\p{L}0-9]/)
88
- first_line_with_text_found = true if alphanumercic && !first_line_with_text_found
89
- if text == BORDER_LINE
90
- nil
91
- elsif alphanumercic
92
- cleaned_line(text)
93
- elsif !first_line_with_text_found
94
- nil
95
- else
96
- text == "##" ? "##" : INSIDE_SEPARATOR
97
- end
98
- end.compact
78
+ pad = SPACE * indent_level(block.first)
79
+ [BORDER_LINE, *body, BORDER_LINE].map {|line| "#{pad}#{line}" }.join("\n")
80
+ end
99
81
 
82
+ ##============================================================##
83
+ ## Transforme chaque ligne du bloc :
84
+ ## - bordures existantes → ignorées
85
+ ## - lignes vides en tête → ignorées (avant tout contenu)
86
+ ## - fenced code blocks (## ```)→ contenu préservé tel quel
87
+ ## - lignes "raw" (## | ...) → préservées
88
+ ## - listes / indentation 3+ → préservées
89
+ ## - séparateurs (## ---) → INSIDE_SEPARATOR
90
+ ## - lignes "##" seules → conservées comme ligne vide
91
+ ## - texte normal → nettoyé via #cleaned_line
92
+ ##============================================================##
93
+ def build_body(block)
94
+ body = []
95
+ in_code = false
96
+ content_seen = false
100
97
 
101
- body = ["## ..."] if body.empty?
98
+ block.each do |comment|
99
+ text = comment.text.to_s.rstrip
102
100
 
103
- ##============================================================##
104
- ## Le block va être remis à la place du block original sur
105
- ## la colone du block original. Donc la première ligne du block
106
- ## ne doit pas être indentée manuellement. Par contre les autres
107
- ## lignes doivent être indentées sur la même colonne que la première
108
- ##============================================================##
109
- [BORDER_LINE, body, BORDER_LINE].flatten.map.with_index {|line, index| index == 0 ? line : "#{SPACE * indent_level}#{line}" }.join("\n")
110
- end
101
+ if text == BORDER_LINE
102
+ next
103
+ elsif text.match?(FENCE_LINE)
104
+ in_code = !in_code
105
+ body << text
106
+ content_seen = true
107
+ elsif in_code || text.match?(RAW_LINE)
108
+ body << text
109
+ content_seen = true
110
+ elsif text == BLANK_LINE
111
+ body << BLANK_LINE if content_seen
112
+ elsif text.match?(USER_SEPARATOR)
113
+ body << INSIDE_SEPARATOR if content_seen
114
+ elsif text.match?(STRUCTURED_LINE) || text.match?(INDENTED_LINE)
115
+ body << text
116
+ content_seen = true
117
+ else
118
+ body << cleaned_line(text)
119
+ content_seen = true
120
+ end
121
+ end
111
122
 
112
- def indent_level(line)
113
- line_content(line)[/\A */].size
123
+ body
114
124
  end
115
125
 
116
126
  ##============================================================##
117
- ## Pour récupérer le contenu de la ligne courante
127
+ ## Nettoie une ligne de texte standard :
128
+ ## - "### foo" → "## foo" (collapse les # répétés)
129
+ ## - "## foo" → "## foo" (un seul espace après ##)
130
+ ## NB : les lignes avec 3+ espaces volontaires sont déjà
131
+ ## interceptées en amont par INDENTED_LINE.
118
132
  ##============================================================##
119
- def line_content(comment)
120
- processed_source.lines[comment.location.line - 1]
133
+ def cleaned_line(text)
134
+ text.sub(/\A##\s*#+\s*(?=\S)/, "## ").sub(/\A##\s+(?=\S)/, "## ")
121
135
  end
122
136
 
123
- ##============================================================##
124
- ## Expliquons la regex :
125
- ## ##\s*#*\s*(?=[[:alnum:]])
126
- ## ---------
127
- ## ## : match littéralement "##"
128
- ## \s* : match 0 ou plusieurs espaces
129
- ## #* : match 0 ou plusieurs #
130
- ## \s* : match encore 0 ou plusieurs espaces
131
- ## (?=[[:alnum:]]) : lookahead positif qui vérifie qu'on a un caractère alphanumérique après
132
- ##============================================================##
133
- def cleaned_line(line)
134
- return line if line.start_with?("## |")
135
-
136
- line.gsub(/##\s*#*\s*(?=[[:alnum:]])/, "## ")
137
+ def indent_level(comment)
138
+ processed_source.lines[comment.location.line - 1][/\A */].size
137
139
  end
138
140
 
139
- def needs_correction?(block, correct_block)
140
- block.map(&:text).map(&:strip).join("|") != correct_block.split("\n").map(&:strip).join("|")
141
+ ##============================================================##
142
+ ## Compare en strippant chaque ligne : on ignore les différences
143
+ ## d'indentation puisque le range cible déjà la bonne colonne.
144
+ ##============================================================##
145
+ def needs_correction?(block, normalized)
146
+ current_lines = block.map {|c| c.text.to_s.strip }
147
+ normalized_lines = normalized.split("\n").map(&:strip)
148
+ current_lines != normalized_lines
141
149
  end
142
150
 
143
151
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: immosquare-cleaner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.104
4
+ version: 0.1.105
5
5
  platform: ruby
6
6
  authors:
7
7
  - immosquare
@@ -190,7 +190,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
190
190
  - !ruby/object:Gem::Version
191
191
  version: '0'
192
192
  requirements: []
193
- rubygems_version: 4.0.10
193
+ rubygems_version: 4.0.11
194
194
  specification_version: 4
195
195
  summary: A gem to lint and organize files in a Rails application.
196
196
  test_files: []