Merge pull request #228 from rgalonso/bug-fixes

numerous bug fixes
This commit is contained in:
Alastair Mooney 2024-11-11 13:16:30 +00:00 committed by GitHub
commit 5aa95f6c12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 375 additions and 210 deletions

177
main.py
View File

@ -8,6 +8,7 @@ from io import StringIO
import itertools import itertools
import operator import operator
from collections import defaultdict from collections import defaultdict
import sys
from Client import Client from Client import Client
from GitHubClient import GitHubClient from GitHubClient import GitHubClient
@ -15,6 +16,98 @@ from LineStatus import LineStatus
from LocalClient import LocalClient from LocalClient import LocalClient
from TodoParser import TodoParser from TodoParser import TodoParser
def process_diff(diff, client=Client(), insert_issue_urls=False, parser=TodoParser(), output=sys.stdout):
# Parse the diff for TODOs and create an Issue object for each.
raw_issues = parser.parse(diff)
# This is a simple, non-perfect check to filter out any TODOs that have just been moved.
# It looks for items that appear in the diff as both an addition and deletion.
# It is based on the assumption that TODOs will not have identical titles in identical files.
# That is about as good as we can do for TODOs without issue URLs.
issues_to_process = []
for values, similar_issues_iter in itertools.groupby(raw_issues, key=operator.attrgetter('title', 'file_name',
'markdown_language')):
similar_issues = list(similar_issues_iter)
if (len(similar_issues) == 2 and all(issue.issue_url is None for issue in similar_issues)
and ((similar_issues[0].status == LineStatus.ADDED
and similar_issues[1].status == LineStatus.DELETED)
or (similar_issues[1].status == LineStatus.ADDED
and similar_issues[0].status == LineStatus.DELETED))):
print(f'Issue "{values[0]}" appears as both addition and deletion. '
f'Assuming this issue has been moved so skipping.', file=output)
continue
issues_to_process.extend(similar_issues)
# If a TODO with an issue URL is updated, it may appear as both an addition and a deletion.
# We need to ignore the deletion so it doesn't update then immediately close the issue.
# First store TODOs based on their status.
todos_status = defaultdict(lambda: {'added': False, 'deleted': False})
# Populate the status dictionary based on the issue URL.
for raw_issue in issues_to_process:
if raw_issue.issue_url: # Ensuring we're dealing with TODOs that have an issue URL.
if raw_issue.status == LineStatus.ADDED:
todos_status[raw_issue.issue_url]['added'] = True
elif raw_issue.status == LineStatus.DELETED:
todos_status[raw_issue.issue_url]['deleted'] = True
# Determine which issues are both added and deleted.
update_and_close_issues = set()
for _issue_url, _status in todos_status.items():
if _status['added'] and _status['deleted']:
update_and_close_issues.add(_issue_url)
# Remove issues from issues_to_process if they are both to be updated and closed (i.e., ignore deletions).
issues_to_process = [issue for issue in issues_to_process if
not (issue.issue_url in update_and_close_issues and issue.status == LineStatus.DELETED)]
# Cycle through the Issue objects and create or close a corresponding GitHub issue for each.
for j, raw_issue in enumerate(sorted(reversed(sorted(issues_to_process, key = operator.attrgetter('start_line'))), key = operator.attrgetter('file_name'))):
print(f"Processing issue {j + 1} of {len(issues_to_process)}: '{raw_issue.title}' @ {raw_issue.file_name}:{raw_issue.start_line}", file=output)
if raw_issue.status == LineStatus.ADDED:
status_code, new_issue_number = client.create_issue(raw_issue)
if status_code == 201:
print(f'Issue created: #{new_issue_number} @ {client.get_issue_url(new_issue_number)}', file=output)
# Don't insert URLs for comments. Comments do not get updated.
if insert_issue_urls and not (raw_issue.ref and raw_issue.ref.startswith('#')):
line_number = raw_issue.start_line - 1
with open(raw_issue.file_name, 'r') as issue_file:
file_lines = issue_file.readlines()
if line_number < len(file_lines):
# Duplicate the line to retain the comment syntax.
old_line = file_lines[line_number]
remove = fr'(?i:{raw_issue.identifier}).*{re.escape(raw_issue.title)}'
insert = f'Issue URL: {client.get_issue_url(new_issue_number)}'
new_line = re.sub(remove, insert, old_line)
# make sure the above operation worked as intended
if new_line != old_line:
# Check if the URL line already exists, if so abort.
if line_number == len(file_lines) - 1 or file_lines[line_number + 1] != new_line:
file_lines.insert(line_number + 1, new_line)
with open(raw_issue.file_name, 'w') as issue_file:
issue_file.writelines(file_lines)
print('Issue URL successfully inserted', file=output)
else:
print('ERROR: Issue URL was NOT successfully inserted', file=output)
elif status_code == 200:
print(f'Issue updated: #{new_issue_number} @ {client.get_issue_url(new_issue_number)}', file=output)
else:
print('Issue could not be created', file=output)
elif raw_issue.status == LineStatus.DELETED and os.getenv('INPUT_CLOSE_ISSUES', 'true') == 'true':
if raw_issue.ref and raw_issue.ref.startswith('#'):
print('Issue looks like a comment, will not attempt to close.', file=output)
continue
status_code = client.close_issue(raw_issue)
if status_code in [200, 201]:
print('Issue closed', file=output)
else:
print('Issue could not be closed', file=output)
# Stagger the requests to be on the safe side.
sleep(1)
return raw_issues
if __name__ == "__main__": if __name__ == "__main__":
client: Client | None = None client: Client | None = None
# Try to create a basic client for communicating with the remote version control server, automatically initialised with environment variables. # Try to create a basic client for communicating with the remote version control server, automatically initialised with environment variables.
@ -30,89 +123,9 @@ if __name__ == "__main__":
# Get the diff from the last pushed commit. # Get the diff from the last pushed commit.
last_diff = client.get_last_diff() last_diff = client.get_last_diff()
# process the diff
if last_diff: if last_diff:
# Parse the diff for TODOs and create an Issue object for each.
raw_issues = TodoParser().parse(StringIO(last_diff))
# This is a simple, non-perfect check to filter out any TODOs that have just been moved.
# It looks for items that appear in the diff as both an addition and deletion.
# It is based on the assumption that TODOs will not have identical titles in identical files.
# That is about as good as we can do for TODOs without issue URLs.
issues_to_process = []
for values, similar_issues_iter in itertools.groupby(raw_issues, key=operator.attrgetter('title', 'file_name',
'markdown_language')):
similar_issues = list(similar_issues_iter)
if (len(similar_issues) == 2 and all(issue.issue_url is None for issue in similar_issues)
and ((similar_issues[0].status == LineStatus.ADDED
and similar_issues[1].status == LineStatus.DELETED)
or (similar_issues[1].status == LineStatus.ADDED
and similar_issues[0].status == LineStatus.DELETED))):
print(f'Issue "{values[0]}" appears as both addition and deletion. '
f'Assuming this issue has been moved so skipping.')
continue
issues_to_process.extend(similar_issues)
# If a TODO with an issue URL is updated, it may appear as both an addition and a deletion.
# We need to ignore the deletion so it doesn't update then immediately close the issue.
# First store TODOs based on their status.
todos_status = defaultdict(lambda: {'added': False, 'deleted': False})
# Populate the status dictionary based on the issue URL.
for raw_issue in issues_to_process:
if raw_issue.issue_url: # Ensuring we're dealing with TODOs that have an issue URL.
if raw_issue.status == LineStatus.ADDED:
todos_status[raw_issue.issue_url]['added'] = True
elif raw_issue.status == LineStatus.DELETED:
todos_status[raw_issue.issue_url]['deleted'] = True
# Determine which issues are both added and deleted.
update_and_close_issues = set()
for _issue_url, _status in todos_status.items():
if _status['added'] and _status['deleted']:
update_and_close_issues.add(_issue_url)
# Remove issues from issues_to_process if they are both to be updated and closed (i.e., ignore deletions).
issues_to_process = [issue for issue in issues_to_process if
not (issue.issue_url in update_and_close_issues and issue.status == LineStatus.DELETED)]
# Check to see if we should insert the issue URL back into the linked TODO. # Check to see if we should insert the issue URL back into the linked TODO.
insert_issue_urls = os.getenv('INPUT_INSERT_ISSUE_URLS', 'false') == 'true' insert_issue_urls = os.getenv('INPUT_INSERT_ISSUE_URLS', 'false') == 'true'
# Cycle through the Issue objects and create or close a corresponding GitHub issue for each. process_diff(StringIO(last_diff), client, insert_issue_urls)
for j, raw_issue in enumerate(issues_to_process):
print(f"Processing issue {j + 1} of {len(issues_to_process)}: '{raw_issue.title}' @ {raw_issue.file_name}:{raw_issue.start_line}")
if raw_issue.status == LineStatus.ADDED:
status_code, new_issue_number = client.create_issue(raw_issue)
if status_code == 201:
print(f'Issue created: : #{new_issue_number} @ {client.get_issue_url(new_issue_number)}')
# Don't insert URLs for comments. Comments do not get updated.
if insert_issue_urls and not (raw_issue.ref and raw_issue.ref.startswith('#')):
line_number = raw_issue.start_line - 1
with open(raw_issue.file_name, 'r') as issue_file:
file_lines = issue_file.readlines()
if line_number < len(file_lines):
# Duplicate the line to retain the comment syntax.
new_line = file_lines[line_number]
remove = fr'{raw_issue.identifier}.*{raw_issue.title}'
insert = f'Issue URL: {client.get_issue_url(new_issue_number)}'
new_line = re.sub(remove, insert, new_line)
# Check if the URL line already exists, if so abort.
if line_number == len(file_lines) - 1 or file_lines[line_number + 1] != new_line:
file_lines.insert(line_number + 1, new_line)
with open(raw_issue.file_name, 'w') as issue_file:
issue_file.writelines(file_lines)
elif status_code == 200:
print(f'Issue updated: : #{new_issue_number} @ {client.get_issue_url(new_issue_number)}')
else:
print('Issue could not be created')
elif raw_issue.status == LineStatus.DELETED and os.getenv('INPUT_CLOSE_ISSUES', 'true') == 'true':
if raw_issue.ref and raw_issue.ref.startswith('#'):
print('Issue looks like a comment, will not attempt to close.')
continue
status_code = client.close_issue(raw_issue)
if status_code in [200, 201]:
print('Issue closed')
else:
print('Issue could not be closed')
# Stagger the requests to be on the safe side.
sleep(1)

View File

@ -0,0 +1,10 @@
diff --git a/comment_suffix_after_source_line.c b/comment_suffix_after_source_line.c
new file mode 100644
index 0000000..d340f6a
--- /dev/null
+++ b/comment_suffix_after_source_line.c
@@ -0,0 +1,4 @@
+void some_func() {
+ int x = 0; // TODO: give this a better name
+ x++;
+}

14
tests/test_edit.diff Normal file
View File

@ -0,0 +1,14 @@
diff --git a/tests/example.bas b/tests/example.bas
index 6b0c6cf..b37e70a 100644
--- a/tests/example.bas
+++ b/tests/example.bas
@@ -1,1 +1,2 @@
+' TODO: simplify
Public Sub MakeThingsComplicated()
diff --git a/tests/example.frm b/tests/example.frm
index 6b0c6cf..b37e70a 100644
--- a/tests/example.frm
+++ b/tests/example.frm
@@ -1,1 +1,2 @@
+' TODO: remove feature to prevent legal issues
Public Sub Plagiarize()

View File

@ -1,8 +1,8 @@
diff --git a/tests/ExampleFile.java b/tests/ExampleFile.java diff --git a/ExampleFile.java b/ExampleFile.java
new file mode 100644 new file mode 100644
index 0000000..d340f6a index 0000000..d340f6a
--- /dev/null --- /dev/null
+++ b/tests/ExampleFile.java +++ b/ExampleFile.java
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
+package com.mydomain.myapp; +package com.mydomain.myapp;
+ +
@ -18,11 +18,11 @@ index 0000000..d340f6a
+ */ + */
+} +}
\ No newline at end of file \ No newline at end of file
diff --git a/tests/example-file.php b/tests/example-file.php diff --git a/example-file.php b/example-file.php
new file mode 100644 new file mode 100644
index 0000000..063bb80 index 0000000..063bb80
--- /dev/null --- /dev/null
+++ b/tests/example-file.php +++ b/example-file.php
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
+<!DOCTYPE html> +<!DOCTYPE html>
+<html> +<html>
@ -48,11 +48,11 @@ index 0000000..063bb80
+</body> +</body>
+</html> +</html>
\ No newline at end of file \ No newline at end of file
diff --git a/tests/example_file.py b/tests/example_file.py diff --git a/example_file.py b/example_file.py
new file mode 100644 new file mode 100644
index 0000000..525e25d index 0000000..525e25d
--- /dev/null --- /dev/null
+++ b/tests/example_file.py +++ b/example_file.py
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
+def hello_world(): +def hello_world():
+ # TODO: Come up with a more imaginative greeting + # TODO: Come up with a more imaginative greeting
@ -78,11 +78,11 @@ index 0000000..525e25d
+ ''' + '''
+ pass + pass
\ No newline at end of file \ No newline at end of file
diff --git a/src/Swarm/Game/example.hs b/src/Swarm/Game/example.hs diff --git a/example.hs b/example.hs
new file mode 100644 new file mode 100644
index 0000000..0ce9b1a index 0000000..0ce9b1a
--- /dev/null --- /dev/null
+++ b/src/Swarm/Game/example.hs +++ b/example.hs
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
+-- | Standard devices that are always installed. +-- | Standard devices that are always installed.
+-- +--
@ -98,23 +98,23 @@ index 0000000..0ce9b1a
+TODO: Create an issue for TODO +TODO: Create an issue for TODO
+-} +-}
+sum a b = a + b +sum a b = a + b
diff --git a/tests/example_file.cr b/tests/example_file.cr diff --git a/example_file.cr b/example_file.cr
new file mode 100644 new file mode 100644
index 0000000..e6da2ec index 0000000..e6da2ec
--- /dev/null --- /dev/null
+++ b/tests/example_file.cr +++ b/example_file.cr
@@ -0,0 +1,14 @@ @@ -0,0 +1,6 @@
+# TODO: Come up with a more imaginative greeting +# TODO: Come up with a more imaginative greeting
+puts "Greetings" +puts "Greetings"
+ +
+# TODO: Do even more stuff +# TODO: Do even more stuff
+# This function should probably do something more interesting +# This function should probably do something more interesting
+# labels: help wanted +# labels: help wanted
diff --git a/tests/example_file.rb b/tests/example_file.rb diff --git a/example_file.rb b/example_file.rb
new file mode 100644 new file mode 100644
index 0000000..e6da2ec index 0000000..e6da2ec
--- /dev/null --- /dev/null
+++ b/tests/example_file.rb +++ b/example_file.rb
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
+#!/usr/bin/ruby -w +#!/usr/bin/ruby -w
+ +
@ -130,11 +130,11 @@ index 0000000..e6da2ec
+# TODO: Do even more stuff +# TODO: Do even more stuff
+# This function should probably do something more interesting +# This function should probably do something more interesting
+# labels: help wanted +# labels: help wanted
diff --git a/tests/example_file.yaml b/tests/example_file.yaml diff --git a/example_file.yaml b/example_file.yaml
new file mode 100644 new file mode 100644
index 0000000..6397789 index 0000000..6397789
--- /dev/null --- /dev/null
+++ b/tests/example_file.yaml +++ b/example_file.yaml
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
+name: "TODO to Issue" +name: "TODO to Issue"
+# TODO: Write a more interesting description +# TODO: Write a more interesting description
@ -143,11 +143,11 @@ index 0000000..6397789
+# TODO: Define inputs +# TODO: Define inputs
+# Need to do this before the action is released +# Need to do this before the action is released
+# labels: urgent +# labels: urgent
diff --git a/tests/example_file.toml b/tests/example_file.toml diff --git a/example_file.toml b/example_file.toml
new file mode 100644 new file mode 100644
index 0000000..6397789 index 0000000..6397789
--- /dev/null --- /dev/null
+++ b/tests/example_file.toml +++ b/example_file.toml
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
+name = "TODO to Issue" +name = "TODO to Issue"
+# TODO: Write a more interesting description +# TODO: Write a more interesting description
@ -156,31 +156,31 @@ index 0000000..6397789
+# TODO: Define inputs +# TODO: Define inputs
+# Need to do this before the action is released +# Need to do this before the action is released
+# labels: urgent +# labels: urgent
diff --git a/tests/example_file.prog.abap b/src/tests/example_file.prog.abap diff --git a/example_file.prog.abap b/example_file.prog.abap
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/tests/example_file.prog.abap +++ b/example_file.prog.abap
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
+REPORT ztest_todo_2. +REPORT ztest_todo_2.
+ +
+DATA moo TYPE i VALUE 2. +DATA moo TYPE i VALUE 2.
+WRITE moo. " TODO This is an end-of-line to-do +WRITE moo. " TODO This is an end-of-line to-do
+moo = 4. * TODO This is another end-of-line to-do +moo = 4. * TODO This is another end-of-line to-do
diff --git a/tests/example_file.sql b/src/tests/example_file.sql diff --git a/example_file.sql b/example_file.sql
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.sql +++ b/example_file.sql
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
+-- TODO Select all: +-- TODO Select all:
+SELECT * FROM Products; +SELECT * FROM Products;
diff --git a/tests/example_file.tex b/src/tests/example_file.tex diff --git a/example_file.tex b/example_file.tex
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.tex +++ b/example_file.tex
@@ -0,0 +1,2 @@ @@ -0,0 +1,7 @@
+% TODO Add in preamble details +% TODO Add in preamble details
+\begin{document} +\begin{document}
+ \begin{comment} + \begin{comment}
@ -188,24 +188,24 @@ index 0000000..7cccc5b
+ label: urgent + label: urgent
+ \end{comment} + \end{comment}
+\end{document} +\end{document}
diff --git a/tests/example_file.jl b/src/tests/example_file.jl diff --git a/example_file.jl b/example_file.jl
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.jl +++ b/example_file.jl
@@ -0,0 +1,2 @@ @@ -0,0 +1,6 @@
+ # TODO: Hopefully this comment turns into an issue + # TODO: Hopefully this comment turns into an issue
+ print("Hello World") + print("Hello World")
+ #= TODO: Multiline comments + #= TODO: Multiline comments
+ also need to be turned into task, and hopefully + also need to be turned into task, and hopefully
+ kept together as one. + kept together as one.
+ =# + =#
diff --git a/tests/defs.bzl b/tests/defs.bzl diff --git a/defs.bzl b/defs.bzl
new file mode 100644 new file mode 100644
index 0000000..525e25d index 0000000..525e25d
--- /dev/null --- /dev/null
+++ b/tests/defs.bzl +++ b/defs.bzl
@@ -0,0 +1,23 @@ @@ -0,0 +1,8 @@
+def hello_world(): +def hello_world():
+ # TODO: Come up with a more imaginative greeting + # TODO: Come up with a more imaginative greeting
+ print('Hello world') + print('Hello world')
@ -214,12 +214,12 @@ index 0000000..525e25d
+ # This function should probably do something more interesting + # This function should probably do something more interesting
+ # labels: help wanted + # labels: help wanted
+ pass + pass
diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel diff --git a/BUILD.bazel b/BUILD.bazel
new file mode 100644 new file mode 100644
index 0000000..525e25d index 0000000..525e25d
--- /dev/null --- /dev/null
+++ b/tests/BUILD.bazel +++ b/BUILD.bazel
@@ -0,0 +1,23 @@ @@ -0,0 +1,8 @@
+def hello_world(): +def hello_world():
+ # TODO: Come up with a more imaginative greeting + # TODO: Come up with a more imaginative greeting
+ print('Hello world') + print('Hello world')
@ -228,33 +228,33 @@ index 0000000..525e25d
+ # This function should probably do something more interesting + # This function should probably do something more interesting
+ # labels: help wanted + # labels: help wanted
+ pass + pass
diff --git a/tests/example_file.ahk b/src/tests/example_file.ahk diff --git a/example_file.ahk b/example_file.ahk
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.ahk +++ b/example_file.ahk
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
+ ; TODO: Find a better way to manage hotkeys + ; TODO: Find a better way to manage hotkeys
+ ; Maybe just switch to vim?? + ; Maybe just switch to vim??
+ #h:: + #h::
+ RegRead, HiddenFiles_Status, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced, Hidden + RegRead, HiddenFiles_Status, HKEY_CURRENT_USER, Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced, Hidden
diff --git a/tests/example_file.hbs b/src/tests/example_file.hbs diff --git a/example_file.hbs b/example_file.hbs
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.hbs +++ b/example_file.hbs
@@ -0,0 +1,2 @@ @@ -0,0 +1,5 @@
+ <!-- TODO: Hopefully this comment turns into a todo issue --> + <!-- TODO: Hopefully this comment turns into a todo issue -->
+ {{! + {{!
+ TODO: Make a handlebar templtate + TODO: Make a handlebar templtate
+ This is really just a test, but hopefully this works~! + This is really just a test, but hopefully this works~!
+ }} + }}
diff --git a/tests/example_file.org b/src/tests/example_file.org diff --git a/example_file.org b/example_file.org
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.org +++ b/example_file.org
@@ -0,0 +1,2 @@ @@ -0,0 +1,9 @@
+ # TODO: Hopefully this comment turns into a todo issue + # TODO: Hopefully this comment turns into a todo issue
+ #+begin_src python + #+begin_src python
+ print("Hello World") + print("Hello World")
@ -264,11 +264,11 @@ index 0000000..7cccc5b
+ also need to be turned into todos, and hopefully + also need to be turned into todos, and hopefully
+ kept together as one todo + kept together as one todo
+ #+end_comment + #+end_comment
diff --git a/tests/example_file.scss b/src/tests/example_file.scss diff --git a/example_file.scss b/example_file.scss
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.scss +++ b/example_file.scss
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
+// TODO: Hopefully this comment turns into a todo issue +// TODO: Hopefully this comment turns into a todo issue
+.my-class { +.my-class {
@ -281,11 +281,11 @@ index 0000000..7cccc5b
+ text-align: center; + text-align: center;
+ } + }
+} +}
diff --git a/tests/example_file.twig b/src/tests/example_file.twig diff --git a/example_file.twig b/example_file.twig
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.twig +++ b/example_file.twig
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
+ {# TODO: Hopefully this comment turns into a todo issue #} + {# TODO: Hopefully this comment turns into a todo issue #}
+ {# + {#
@ -293,11 +293,11 @@ index 0000000..7cccc5b
+ also need to be turned into todos, and hopefully + also need to be turned into todos, and hopefully
+ kept together as one todo + kept together as one todo
+ #} + #}
diff --git a/tests/example_file.md b/src/tests/example_file.md diff --git a/example_file.md b/example_file.md
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.md +++ b/example_file.md
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
+ {/* TODO: Hopefully this comment turns into a todo issue */} + {/* TODO: Hopefully this comment turns into a todo issue */}
+ {/* + {/*
@ -306,11 +306,11 @@ index 0000000..7cccc5b
+ kept together as one todo + kept together as one todo
+ */} + */}
+ - [ ] TODO: An inline todo that's NOT a comment (what) + - [ ] TODO: An inline todo that's NOT a comment (what)
diff --git a/tests/example_file.mdx b/src/tests/example_file.mdx diff --git a/example_file.mdx b/example_file.mdx
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.mdx +++ b/example_file.mdx
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
+ {/* TODO: Hopefully this comment turns into a todo issue */} + {/* TODO: Hopefully this comment turns into a todo issue */}
+ {/* + {/*
@ -319,12 +319,12 @@ index 0000000..7cccc5b
+ kept together as one todo + kept together as one todo
+ */} + */}
+ - [ ] TODO: An inline todo that's NOT a comment (what) + - [ ] TODO: An inline todo that's NOT a comment (what)
diff --git a/tests/example_file.r b/tests/example_file.r diff --git a/example_file.r b/example_file.r
new file mode 100644 new file mode 100644
index 0000000..525e25d index 0000000..525e25d
--- /dev/null --- /dev/null
+++ b/tests/example_file.r +++ b/example_file.r
@@ -0,0 +1,23 @@ @@ -0,0 +1,8 @@
+hello_world <- function() { +hello_world <- function() {
+ # TODO: Come up with a more imaginative greeting + # TODO: Come up with a more imaginative greeting
+ message("Hello world") + message("Hello world")
@ -333,56 +333,25 @@ index 0000000..525e25d
+ # This function should probably do something more interesting + # This function should probably do something more interesting
+ # labels: help wanted + # labels: help wanted
+} +}
diff --git a/tests/example_file.rmd b/src/tests/example_file.rmd diff --git a/example_file.rmd b/example_file.rmd
new file mode 100644 new file mode 100644
index 0000000..525e25d index 0000000..525e25d
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.rmd +++ b/example_file.rmd
@@ -0,0 +0,1 @@ @@ -0,0 +0,1 @@
+<!-- TODO: Check RMarkdown comments work --> +<!-- TODO: Check RMarkdown comments work -->
diff --git a/tests/example_file.qmd b/src/tests/example_file.qmd diff --git a/example_file.qmd b/example_file.qmd
new file mode 100644 new file mode 100644
index 0000000..525e25d index 0000000..525e25d
--- /dev/null --- /dev/null
+++ b/src/tests/example_file.qmd +++ b/example_file.qmd
@@ -0,0 +0,1 @@ @@ -0,0 +0,1 @@
+<!-- TODO: Check RMarkdown comments work --> +<!-- TODO: Check RMarkdown comments work -->
diff --git a/tests/config.jsonc b/tests/config.jsonc diff --git a/example.clj b/example.clj
new file mode 100644 new file mode 100644
index 0000000..525e25d index 0000000..525e25d
--- /dev/null --- /dev/null
+++ b/tests/config.jsonc +++ b/example.clj
@@ -0,0 +0,11 @@
+{
+ "myConfig": [
+ /*
+ GitRepository where 'Git release/tag'
+ matches 'Helm' version
+ */
+ "itIsWonderful",
+ // TODO: Delete this line from the codebase
+ "butItHasSomePendingActivities"
+ ]
+}
diff --git a/tests/config.json5 b/tests/config.json5
new file mode 100644
index 0000000..525e25d
--- /dev/null
+++ b/tests/config.json5
@@ -0,0 +0,8 @@
+{
+ "myConfig": [
+ // GitRepository where 'Git release/tag' matches 'Helm' version
+ "itIsWonderful",
+ // TODO: Delete this line from the codebase
+ "butItHasSomePendingActivities"
+ ]
+}
diff --git a/tests/example.clj b/tests/example.clj
new file mode 100644
index 0000000..525e25d
--- /dev/null
+++ b/tests/example.clj
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
+(ns example) +(ns example)
+ +
@ -392,22 +361,22 @@ index 0000000..525e25d
+ ;; TODO: todo with description (sub-level) + ;; TODO: todo with description (sub-level)
+ ;; Body of the issue should stay here + ;; Body of the issue should stay here
+ (str "hello" name)) + (str "hello" name))
diff --git a/tests/example.gd b/tests/example.gd diff --git a/example.gd b/example.gd
new file mode 100644 new file mode 100644
index 0000000..525e25d index 0000000..525e25d
--- /dev/null --- /dev/null
+++ b/tests/example.gd +++ b/example.gd
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
+# TODO Store all the players here +# TODO Store all the players here
+var _players: = [] +var _players: = []
+ +
+# TODO Play the level music +# TODO Play the level music
+export: var music_path: String +export: var music_path: String
diff --git a/tests/example.nix b/tests/example.nix diff --git a/example.nix b/example.nix
new file mode 100644 new file mode 100644
index 0000000..a6c6cb0 index 0000000..a6c6cb0
--- /dev/null --- /dev/null
+++ b/tests/example.nix +++ b/example.nix
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
+{ +{
+ # TODO add missing devices + # TODO add missing devices
@ -420,36 +389,22 @@ index 0000000..a6c6cb0
+ */ + */
+ sum = a: b: a + b; + sum = a: b: a + b;
+} +}
diff --git a/tests/example.xaml b/tests/example.xaml diff --git a/example.xaml b/example.xaml
new file mode 100644 new file mode 100644
index 0000000..a6c6cb0 index 0000000..a6c6cb0
--- /dev/null --- /dev/null
+++ b/tests/example.xaml +++ b/example.xaml
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
+<!-- TODO: Add xaml support --> +<!-- TODO: Add xaml support -->
+<Label Text="why"/> +<Label Text="why"/>
+<!-- TODO: please --> +<!-- TODO: please -->
+<Label Text="ok"/> +<Label Text="ok"/>
diff --git a/tests/example.bas b/tests/example.bas diff --git a/example.cu b/example.cu
index 6b0c6cf..b37e70a 100644
--- a/tests/example.bas
+++ b/tests/example.bas
@@ -1,1 +1,2 @@
+' TODO: simplify
Public Sub MakeThingsComplicated()
diff --git a/tests/example.frm b/tests/example.frm
index 6b0c6cf..b37e70a 100644
--- a/tests/example.frm
+++ b/tests/example.frm
@@ -1,1 +1,2 @@
+' TODO: remove feature to prevent legal issues
Public Sub Plagiarize()
diff --git a/tests/example.cu b/tests/example.cu
new file mode 100644 new file mode 100644
index 0000000..a6c6cb0 index 0000000..a6c6cb0
--- /dev/null --- /dev/null
+++ b/tests/example.cu +++ b/example.cu
@@ -1,3 +1,11 @@ @@ -0,0 +1,8 @@
+ +
+// TODO rename this function +// TODO rename this function
+__global__ void test() { +__global__ void test() {
@ -458,11 +413,11 @@ index 0000000..a6c6cb0
+ */ + */
+} +}
+ +
diff --git a/tests/Makefile b/tests/Makefile diff --git a/Makefile b/Makefile
new file mode 100644 new file mode 100644
index 0000000..2996176 index 0000000..2996176
--- /dev/null --- /dev/null
+++ b/tests/Makefile +++ b/Makefile
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
+# TODO change name. +# TODO change name.
+NAME = asm +NAME = asm
@ -476,11 +431,11 @@ index 0000000..2996176
+ # TODO create the directory. + # TODO create the directory.
+ $(AR) rc $@ $(OBJ) + $(AR) rc $@ $(OBJ)
+ +
diff --git a/tests/example_file.liquid b/tests/example_file.liquid diff --git a/example_file.liquid b/example_file.liquid
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/tests/example_file.liquid +++ b/example_file.liquid
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
+{% comment %} TODO: remove loop logic {% endcomment %} +{% comment %} TODO: remove loop logic {% endcomment %}
+{% for i in (1..3) -%} +{% for i in (1..3) -%}
@ -493,11 +448,11 @@ index 0000000..7cccc5b
+{% assign featured_product = all_products["product_handle"] %} +{% assign featured_product = all_products["product_handle"] %}
+{% render "product", product: featured_product %} +{% render "product", product: featured_product %}
+{% endcomment %} +{% endcomment %}
diff --git a/tests/example_file.tsx b/tests/example_file.tsx diff --git a/example_file.tsx b/example_file.tsx
new file mode 100644 new file mode 100644
index 0000000..7cccc5b index 0000000..7cccc5b
--- /dev/null --- /dev/null
+++ b/tests/example_file.tsx +++ b/example_file.tsx
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
+// TODO: rename component +// TODO: rename component
+export default async function Component() { +export default async function Component() {
@ -512,11 +467,11 @@ index 0000000..7cccc5b
+ </div> + </div>
+ ); + );
+} +}
diff --git a/src/Swarm/Game/example.purs b/src/Swarm/Game/example.purs diff --git a/example.purs b/example.purs
new file mode 100644 new file mode 100644
index 0000000..0ce9b1a index 0000000..0ce9b1a
--- /dev/null --- /dev/null
+++ b/src/Swarm/Game/example.purs +++ b/example.purs
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
+-- | Standard devices that are always installed. +-- | Standard devices that are always installed.
+-- +--
@ -532,11 +487,11 @@ index 0000000..0ce9b1a
+TODO: Create an issue for TODO +TODO: Create an issue for TODO
+-} +-}
+sum a b = a + b +sum a b = a + b
diff --git a/src/Swarm/Game/example.agda b/src/Swarm/Game/example.agda diff --git a/example.agda b/example.agda
new file mode 100644 new file mode 100644
index 0000000..0ce9b1a index 0000000..0ce9b1a
--- /dev/null --- /dev/null
+++ b/src/Swarm/Game/example.agda +++ b/example.agda
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
+-- | Standard devices that are always installed. +-- | Standard devices that are always installed.
+-- +--
@ -569,17 +524,17 @@ index 0000000..0ce9b1a
+ labels: urgent + labels: urgent
+--]] +--]]
+local b = 2 +local b = 2
diff --git a/tests/Counter.sol b/tests/Counter.sol diff --git a/Counter.sol b/Counter.sol
new file mode 100644 new file mode 100644
index 0000000..d340f6a index 0000000..d340f6a
--- /dev/null --- /dev/null
+++ b/src/Counter.sol +++ b/Counter.sol
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
+contract Counter { +contract Counter {
+ // TODO: Test this + // TODO: Test this
+ // Do it + // Do it
+ // labels: urgent + // labels: urgent
+
+ /// TODO: Natspec comment + /// TODO: Natspec comment
+ /// Do it + /// Do it
+ /// labels: urgent + /// labels: urgent
@ -589,7 +544,7 @@ index 0000000..d340f6a
+ Do it ASAP + Do it ASAP
+ labels: urgent + labels: urgent
+ */ + */
+
+ /** + /**
+ * TODO: And this too + * TODO: And this too
+ * labels: urgent + * labels: urgent

31
tests/test_new2.diff Normal file
View File

@ -0,0 +1,31 @@
diff --git a/config.jsonc b/config.jsonc
new file mode 100644
index 0000000..525e25d
--- /dev/null
+++ b/config.jsonc
@@ -0,0 +0,11 @@
+{
+ "myConfig": [
+ /*
+ GitRepository where 'Git release/tag'
+ matches 'Helm' version
+ */
+ "itIsWonderful",
+ // TODO: Delete this line from the codebase
+ "butItHasSomePendingActivities"
+ ]
+}
diff --git a/config.json5 b/config.json5
new file mode 100644
index 0000000..525e25d
--- /dev/null
+++ b/config.json5
@@ -0,0 +0,8 @@
+{
+ "myConfig": [
+ // GitRepository where 'Git release/tag' matches 'Helm' version
+ "itIsWonderful",
+ // TODO: Delete this line from the codebase
+ "butItHasSomePendingActivities"
+ ]
+}

110
tests/test_process_diff.py Normal file
View File

@ -0,0 +1,110 @@
import json
import os
import unittest
import tempfile
import subprocess
import io
import re
from TodoParser import TodoParser
from main import process_diff
class IssueUrlInsertionTest(unittest.TestCase):
orig_cwd = None
tempdir = None
diff_file = None
parser = None
def _setUp(self, diff_file):
# get current working directory
self.orig_cwd = os.getcwd()
# Create temporary directory to hold simulated filesystem.
self.tempdir = tempfile.TemporaryDirectory()
# run patch against the diff file to generate the simulated filesystem
subprocess.run(['patch', '-d', self.tempdir.name,
'-i', f'{os.getcwd()}/tests/{diff_file}'],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=True)
self.diff_file = open(f'tests/{diff_file}', 'r')
self.parser = TodoParser()
with open('syntax.json', 'r') as syntax_json:
self.parser.syntax_dict = json.load(syntax_json)
# change to the simulated filesystem directory
os.chdir(self.tempdir.name)
def _standardTest(self, expected_count):
# create object to hold output
output = io.StringIO()
# process the diffs
self.raw_issues = process_diff(diff=self.diff_file, insert_issue_urls=True, parser=self.parser, output=output)
# make sure the number of issue URL comments inserted is as expected
self.assertEqual(output.getvalue().count('Issue URL successfully inserted'),
expected_count,
msg='\nProcessing log\n--------------\n'+output.getvalue())
# this test can take a while and, as far as TodoParser is concerned,
# redundant with the tests of test_todo_parser, so enable the means
# to skip it if desired
@unittest.skipIf(os.getenv('SKIP_PROCESS_DIFF_TEST', 'false') == 'true',
"Skipping because 'SKIP_PROCESS_DIFF_TEST' is 'true'")
def test_url_insertion(self):
self._setUp('test_new.diff')
self._standardTest(80)
# There is a known bug related to this issue, so until it's resolved
# this is an expected failure.
# See #225 and #224
@unittest.expectedFailure
def test_same_title_in_same_file(self):
self._setUp('test_same_title_in_same_file.diff')
self._standardTest(5)
# There is a known bug related to this issue, so until it's resolved
# this is an expected failure.
# See #229
@unittest.expectedFailure
def test_comment_suffix_after_source_line(self):
self._setUp('test_comment_suffix_after_source_line.diff')
self._standardTest(1)
# get details about the issue and source file
issue = self.raw_issues[0]
markers, _ = self.parser._get_file_details(issue.file_name)
with open(f'{self.tempdir.name}/{issue.file_name}', 'r') as source_file:
lines = source_file.read().splitlines()
# regex search the TODO comment and issue URL lines, such that groups are:
# 2: everything from start of line up to (but excluding) comment marker
# 3: comment marker
# 4: anything after comment marker and before identifier
# 1: encompasses all of the above
source_and_todo_line = re.search(fr'^((.*?)({markers[0]["pattern"]})(.*?))(?i:{issue.identifier}).*?{issue.title}',
lines[issue.start_line-1]).groups()
issue_url_line = re.search(fr'^((.*?)({markers[0]["pattern"]})(\s*))Issue URL: N/A$',
lines[issue.start_line]).groups()
# ensure Issue URL is aligned with the TODO above it by verifying
# that length of first group is equal for both lines
self.assertEqual(len(source_and_todo_line[0]), len(issue_url_line[0]), msg='\n'
+ f'Issue URL mis-alignment. {issue.identifier} begins at column '
+ f'{len(source_and_todo_line[0])+1} but\nissue URL begins at column '
+ f'{len(issue_url_line[0])+1}.\n'
+ '-------------------------------------------------------------------\n'
+ f'{lines[issue.start_line-1]}\n'
+ f'{lines[issue.start_line]}\n')
# ensure Issue URL line has only whitespace before the comment marker
self.assertRegex(issue_url_line[1], r'^\s*$', msg='\n'
+ 'Non-whitespace detected prior to comment marker for issue URL line!\n'
+ '-------------------------------------------------------------------\n'
+ f'{lines[issue.start_line]}\n')
def tearDown(self):
# return to original working directory to ensure we don't mess up other tests
os.chdir(self.orig_cwd)
# explicitly cleanup to avoid warning being printed about implicit cleanup
self.tempdir.cleanup()
self.tempdir = None

View File

@ -0,0 +1,27 @@
diff --git a/Counter.sol b/Counter.sol
new file mode 100644
index 0000000..d340f6a
--- /dev/null
+++ b/Counter.sol
@@ -0,0 +1,21 @@
+contract Counter {
+ // TODO: Test this
+ // Do it
+ // labels: urgent
+
+ /// TODO: Natspec comment
+ /// Do it
+ /// labels: urgent
+
+ /*
+ TODO: Test this too
+ Do it ASAP
+ labels: urgent
+ */
+
+ // TODO: Test this
+ /**
+ * TODO: Test this too
+ * labels: urgent
+ */
+}

View File

@ -16,11 +16,16 @@ def count_issues_for_file_type(raw_issues, file_type):
class NewIssueTest(unittest.TestCase): class NewIssueTest(unittest.TestCase):
# Check for newly added TODOs across the files specified. # Check for newly added TODOs across the files specified.
def setUp(self): def setUp(self):
diff_file = open('tests/test_new.diff', 'r')
parser = TodoParser() parser = TodoParser()
self.raw_issues = []
with open('syntax.json', 'r') as syntax_json: with open('syntax.json', 'r') as syntax_json:
parser.syntax_dict = json.load(syntax_json) parser.syntax_dict = json.load(syntax_json)
self.raw_issues = parser.parse(diff_file) with open('tests/test_new.diff', 'r') as diff_file:
self.raw_issues.extend(parser.parse(diff_file))
with open('tests/test_new2.diff', 'r') as diff_file:
self.raw_issues.extend(parser.parse(diff_file))
with open('tests/test_edit.diff', 'r') as diff_file:
self.raw_issues.extend(parser.parse(diff_file))
def test_python_issues(self): def test_python_issues(self):
# Includes 4 tests for Starlark. # Includes 4 tests for Starlark.