From 9511494da7c7412aaded3115384eabad70ca3eee Mon Sep 17 00:00:00 2001 From: Nikkel Mollenhauer <57323886+NikkelM@users.noreply.github.com> Date: Thu, 22 Feb 2024 23:50:07 +0100 Subject: [PATCH] Added functionality for multiple line comment characters (#55) --- .github/config.yml | 8 +++--- CHANGELOG.md | 1 + README.md | 4 +-- app.rb | 53 ++++++++++++++++++++++++--------------- validation/validation.css | 7 ++++++ validation/validation.php | 17 +++++++++++++ 6 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 validation/validation.css create mode 100644 validation/validation.php diff --git a/.github/config.yml b/.github/config.yml index 191d9f3..04706a7 100644 --- a/.github/config.yml +++ b/.github/config.yml @@ -5,11 +5,13 @@ todo-pr-checker: ignore_files: null # What action items should be looked for (setting this will the overwrite default values) action_items: ['TODO', 'FIXME', 'BUG'] - # Languages/file types to add. At least either the line comment or both block comment definitions are required. - # If there are no line comments in the language, you may set the value to null. + # Languages/file types to add. At least either the line comment or both block comment definitions are required + # If there are no line comments in the language, you may set the value to null + # The languages shown here are examples and already included in the default configuration add_languages: [ ['js', '//', '/*', '*/'], ['css', null, '/*', '*/'], + ['php', ['//', '#'], '/*', '*/'], ['.py', '#'] ] # Whether or not searching for action items should be case sensitive @@ -19,7 +21,7 @@ todo-pr-checker: multiline_comments: false # How many lines below found action items should be shown in the embedded code snippet # If there are no more lines below the action item before the file ends, the code snippet will not be able to render - additional_lines: 0 + additional_lines: 1 # Whether or not each action item should always be rendered in a separate code snippet # If disabled, action items that are located close to each other will be rendered in the same code snippet always_split_snippets: false diff --git a/CHANGELOG.md b/CHANGELOG.md index 33ffd92..016dbf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ - Added a new `additional_lines` configuration option to control how many lines below action items are rendered in code snippets. - Added a new `always_split_snippets` configuration option to control whether or not action items should always be rendered in seperate code snippets, even when they are located close to each other in code. +- The app now supports multiple line comment types for languages that have them, such as `//` and `#` for PHP. ## v1.3.2 diff --git a/README.md b/README.md index 0fd63eb..1372a63 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,10 @@ To get started, you can copy the `.github/config.yml` file from this repository | `post_comment` | `items_found`, `always`, `never` | Controls when the app should post a comment. By default, a comment is only posted if an action item has been found. If set to `never`, the check will still fail. If set to `always`, the app will post a comment that all action items have been resolved if none are found. | `items_found` | | `ignore_files` | `string[]`, maximum 7 entries | A list of glob patterns to specify files that should be ignored during the check. You may specify up to 7 patterns. The pattern matching logic used is the same as for `.gitignore` files. | `null` | | `action_items` | `string[]`, maximum 15 entries | A list of action items to look for in code comments. If you set this option, the default values will be overwritten, so you must include them in your list to use them. By default, action items are case insensitive. You may specify up to 15 items. | `['TODO', 'FIXME', 'BUG']` | -| `add_languages` | `[string[file_type, line_start, block_start, block_end]]`
Example: `[['js', '//', '/*', '*,'], ['css', null, '/*', '*/'], ['.py', '#']]`, maximum 10 entries | A list of a list of programming languages to add support for. This list will be added to the already supported languages. If you define a language that is already supported, the default values will be overwritten. `file_type` must be the extension of the file (e.g. `js`) and may start with a `.`. You may omit the block comment definitions if the file type does not support block comments. If you want to omit the definition of a line comment, you must set `line_start` to `null`. If defining `block_start`, `block_end` must also be defined. You may specify up to 10 new file types. *The file types shown in the example are already natively supported by the app.* | `null` | +| `add_languages` | `[string[file_type, line_start, block_start, block_end]]`
Example: `[['js', '//', '/*', '*,'], ['php', ['//', '#'], '/*', '*/'], ['css', null, '/*', '*/'], ['.py', '#']]`, maximum 10 entries | A list of a list of programming languages to add support for. This list will be added to the already supported languages. If you define a language that is already supported, the default values will be overwritten. `file_type` must be the extension of the file (e.g. `js`) and may start with a `.`. If the file type you are adding supports mulitple line comment types, you may define an `array` of `strings` instead of just a `string`. You may omit the block comment definitions if the file type does not support block comments. If you want to omit the definition of a line comment, you may set `line_start` to `null` or omit it. If defining `block_start`, `block_end` must also be defined. You may specify up to 10 new file types. *The file types shown in the example are already natively supported by the app.* | `null` | | `case_sensitive` | `true`, `false` | Controls whether the app should look for action items in a case-sensitive manner. | `false` | | `multiline_comments` | `true`, `false` | Whether or not looking for action items in multiline block comments is enabled or not. When enabled, the app *may* incorrectly mark action items in your Pull Request if at least one of the opening or closing line of the block comment (e.g. `*/` and `/*` in JavaScript) are not included in the Pull Request diff, which causes them to not be found by the app. For multiline comments to always work, you must ensure that both the opening and closing characters are included in the diff. Action items located on the first line of a block comment will always be detected, even if this option is disabled. | `false` | -| `additional_lines` | `integer` between `0` and `10` | The number of additional lines to include below found action items in embedded code snippets. The default of `0` shows only the line with the action item. This setting does not influence the behaviour of showing multiple action items in one snippet if they are located close to each other. *Note that if there are not enough lines left in the file to display, the embedded code snippet will not be able to render at all and will display as a link only.* | `0` | +| `additional_lines` | `integer` between `0` and `10` | The number of additional lines to include below found action items in embedded code snippets. If set to `0`, the code snippet shows only the line with the action item. This setting does not influence the behaviour of showing multiple action items in one snippet if they are located close to each other. *Note that if there are not enough lines left in the file to display, the embedded code snippet will not be able to render at all and will display as a link only.* | `1` | | `always_split_snippets` | `true`, `false` | Whether or not action items should always be rendered in separate code snippets, even when they are located close to each other in code. | `false` |
diff --git a/app.rb b/app.rb index 975b8b8..f2ff5c7 100644 --- a/app.rb +++ b/app.rb @@ -181,7 +181,18 @@ def get_app_options(full_repo_name, head_sha) 'multiline_comments' => ->(value) { [true, false].include?(value) }, 'action_items' => ->(value) { value.is_a?(Array) && (0..15).include?(value.size) }, 'case_sensitive' => ->(value) { [true, false].include?(value) }, - 'add_languages' => ->(value) { value.is_a?(Array) && (1..10).include?(value.size) && value.all? { |v| v.is_a?(Array) && (2..4).include?(v.size) && v.all? { |i| i.is_a?(String) || i.nil? } } }, + # A language may have multiple line characters, defined as an array of strings in second place, or just a string + 'add_languages' => lambda do |value| + value.is_a?(Array) && + (1..10).include?(value.size) && + value.all? do |v| + v.is_a?(Array) && + (2..4).include?(v.size) && + v[0].is_a?(String) && + (v.size == 2 || v.size == 4 ? (v[1].is_a?(Array) && v[1].all? { |i| i.is_a?(String) }) || v[1].is_a?(String) : v[1].is_a?(String)) && + (v[2..] || []).all? { |i| i.is_a?(String) || i.nil? } + end + end, # The regex checks if the given input is a valid .gitignore pattern 'ignore_files' => ->(value) { value.is_a?(Array) && (1..7).include?(value.size) && value.all? { |v| v.is_a?(String) && %r{\A(/?(\*\*/)?[\w*\[\]{}?\.\/-]+(/\*\*)?/?)\Z}.match?(v) } }, 'additional_lines' => ->(value) { value.is_a?(Integer) && (0..10).include?(value) }, @@ -221,7 +232,6 @@ def get_pull_request_changes(full_repo_name, pull_number, ignore_files_regex) current_file = '' line_number = 0 changes = {} - print diff diff_enum = diff.each_line line = diff_enum.next rescue nil @@ -291,7 +301,7 @@ def check_for_todos(changes, options) on_block_comment_starting_line = comment_char[1][:block_start] && text.start_with?(comment_char[1][:block_start]) # If the line is a comment and contains any action item, add it to the output collection - file_todos << line if (text.start_with?(comment_char[1][:line]) || on_block_comment_starting_line || in_multiline_comment) && regexes.any? { |regex| text.match(regex) } + file_todos << line if (comment_char[1][:line].any? { |char| text.start_with?(char) } || on_block_comment_starting_line || in_multiline_comment) && regexes.any? { |regex| text.match(regex) } # Reset the flag if the line ends a block comment in_multiline_comment = false if !multiline_comments || (comment_char[1][:block_end] && text.end_with?(comment_char[1][:block_end])) @@ -307,20 +317,21 @@ def check_for_todos(changes, options) # (6) Retrieves the file types and comment characters for the app's supported languages, and user defined values def get_comment_chars(added_languages) default_comment_chars = { - %w[md html xml] => { line: '' }, - %w[astro] => { line: '//', block_start: '' }, - %w[js java ts c cpp cs php swift go kt rs dart sc groovy less sass scss] => { line: '//', block_start: '/*', block_end: '*/' }, - %w[css] => { line: '/*', block_start: '/*', block_end: '*/' }, - %w[r gitignore sh bash yml yaml] => { line: '#', block_start: nil, block_end: nil }, - %w[rb] => { line: '#', block_start: '=begin', block_end: '=end' }, - %w[pl] => { line: '#', block_start: '=', block_end: '=cut' }, - %w[py] => { line: '#', block_start: "'''", block_end: "'''" }, - %w[ps1] => { line: '#', block_start: '<#', block_end: '#>' }, - %w[sql] => { line: '--', block_start: '/*', block_end: '*/' }, - %w[hs] => { line: '--', block_start: '{-', block_end: '-}' }, - %w[lua] => { line: '--', block_start: '--[[', block_end: ']]' }, - %w[m] => { line: '%', block_start: '%{', block_end: '%}' }, - %w[tex] => { line: '%', block_start: nil, block_end: nil } + %w[md html xml] => { line: ['' }, + %w[astro] => { line: ['//'], block_start: '' }, + %w[js java ts c cpp cs swift go kt rs dart sc groovy less sass scss] => { line: ['//'], block_start: '/*', block_end: '*/' }, + %w[php] => { line: ['//', '#'], block_start: '/*', block_end: '*/' }, + %w[css] => { line: ['/*'], block_start: '/*', block_end: '*/' }, + %w[r gitignore sh bash yml yaml] => { line: ['#'], block_start: nil, block_end: nil }, + %w[rb] => { line: ['#'], block_start: '=begin', block_end: '=end' }, + %w[pl] => { line: ['#'], block_start: '=', block_end: '=cut' }, + %w[py] => { line: ['#'], block_start: "'''", block_end: "'''" }, + %w[ps1] => { line: ['#'], block_start: '<#', block_end: '#>' }, + %w[sql] => { line: ['--'], block_start: '/*', block_end: '*/' }, + %w[hs] => { line: ['--'], block_start: '{-', block_end: '-}' }, + %w[lua] => { line: ['--'], block_start: '--[[', block_end: ']]' }, + %w[m] => { line: ['%'], block_start: '%{', block_end: '%}' }, + %w[tex] => { line: ['%'], block_start: nil, block_end: nil } } unwrapped_comment_chars = {} @@ -332,15 +343,17 @@ def get_comment_chars(added_languages) added_languages.each do |lang| file_type = lang[0].sub(/^\./, '') + line_chars = lang[1].is_a?(Array) ? lang[1] : [lang[1]] # The length of lang defines which permutation is given by the user # Users may overwrite the default comment characters for a file type case lang.length when 2 - unwrapped_comment_chars[file_type] = { line: lang[1], block_start: nil, block_end: nil } + unwrapped_comment_chars[file_type] = { line: line_chars, block_start: nil, block_end: nil } when 3 - unwrapped_comment_chars[file_type] = { line: lang[1], block_start: lang[1], block_end: lang[2] } + # If only the block comment was defined, we need to extract the character from the array entry when setting the block start character, as it was parsed to an array earlier + unwrapped_comment_chars[file_type] = { line: line_chars, block_start: line_chars[0], block_end: lang[2] } when 4 - unwrapped_comment_chars[file_type] = { line: lang[1], block_start: lang[2], block_end: lang[3] } + unwrapped_comment_chars[file_type] = { line: line_chars, block_start: lang[2], block_end: lang[3] } end end diff --git a/validation/validation.css b/validation/validation.css new file mode 100644 index 0000000..ffe27c5 --- /dev/null +++ b/validation/validation.css @@ -0,0 +1,7 @@ +/* TODO: Alerts in this file: 3 if multiline comments, 2 else */ +/* TODO */ + + + +/* This is +TODO Number 2 */ \ No newline at end of file diff --git a/validation/validation.php b/validation/validation.php new file mode 100644 index 0000000..516a538 --- /dev/null +++ b/validation/validation.php @@ -0,0 +1,17 @@ + \ No newline at end of file