vim-doge icon indicating copy to clipboard operation
vim-doge copied to clipboard

Update of existing documentation

Open gbcreation opened this issue 4 years ago • 21 comments

Is your feature request related to a problem? Please describe. DoGe is great to generate the docblock for a function that doesn't have already one. But when the signature of the function changes then (for example adding or removing parameters), the docblock cannot be automatically updated.

Describe the solution you'd like It would be very useful to hit <c-d> again on the function to update the existing docblock. Missing parameters would be added at the right position in the docblock depending on their order in the signature of the function, and parameters removed from the function would be deleted in the docblock.

gbcreation avatar Jul 19 '19 08:07 gbcreation

Hi,

I did have this version before I released DoGe publically and it worked well, yet there is no possibility to support every language I am currently supporting. The problem here is that languages like Lua has -- as a comment, so there is no differentiation between the start or end of a comment block. They basically use single-line comments.

Assume you have this initially:

-- This is my additional description
--
-- This is my new_function.
-- @param p1 This is p1.
-- @param p2 This is p2.
function new_function(p1, p2)
end

So the actual comment here that is generated by DoGe is this part:

-- This is my new_function.
-- @param p1 This is p1.
-- @param p2 This is p2.

But if you open op a buffer containing this it will replace the whole comment again. Also, if you've added descriptions the only thing I should replace is the things that have been added, deleted or changed and doing this is close to impossible for now, there are too many use-cases to take into account, so I won't fix this by myself since I wasn't able to support every language.

If there is someone who has a suggestion and a pull request I am happy to think with them, but for now it won't happen. Thanks for your submission.

kkoomen avatar Jul 19 '19 09:07 kkoomen

Thank you very for your detailed answer.

That's great news to know that you already developed this feature before. It think it is a must have feature to make DoGe even better. I understand that it could not be supported for a few languages. But as it would perfectly work for other ones, I think it would be a real shame to penalize them just because a few languages could not be supported. I strongly encourage you to think about it. You could specify in the doc which languages are supported for this feature and explain quickly why a few languages are not.

Hope you change your mind :wink: :crossed_fingers:

gbcreation avatar Jul 21 '19 17:07 gbcreation

Hi @kkoomen, is this feature supported for python ? As python docstrings are delimited by """, the problem you mentionned above seems not to apply (as delimiters are explicits). I would be really great if it is ! Something like this :

def my_func(arg1, arg2):
    """
    A useful docstring
    """
    print("That's useful")

Turns into that :

def my_func(arg1, arg2):
    """
    A useful docstring

    :param arg1: [TODO:description]
    :type arg1: [TODO:type]
    :param arg2: [TODO:description]
    :type arg2: [TODO:type]
    """
    print("That's useful")

vigoux avatar Jul 23 '19 12:07 vigoux

Sorry that this is still not fixed. The problem I'm having is that I should be able to merge two multiline strings (doc blocks) together using a history algorithm that git has, but this is difficult to implement. I am trying to get this to work with git, since it's probably the best out there to merge anything. I've made a stackoverflow question as well.

If anyone could help out, feel free to.

kkoomen avatar Aug 16 '19 08:08 kkoomen

I am hesitant to answer at stackoverflow. So here's my two cents -

  • git diff --patch --word-diff=porcelain file2 file1 > temp
  • python script.py temp file3

This is the best that I can do. What is basically does is, it does a word-diff using gitand outputs it to temp. script.py parses that word-diff from temp, and the output is written to file3. file3 is created/overwritten.

Here's script.py -

import sys

print(sys.argv)
if not len(sys.argv) == 3:
    print("Please mention only two files, in-file and out-file")
    sys.exit(1)

with open(sys.argv[1]) as file:
    text = file.read()


text = text[text.index("@@", text.index("@@") + 2) + 2 :]
out_lines = []
split = text.split("~")

for index, string in enumerate(split):
    _splitline = string.split("\n")
    _splitline = _splitline[1:-1]
    if len(_splitline) == 1:
        out_lines.append(_splitline[0][1:])
    else:
        for _line in _splitline[1:]:
            if _line.startswith("+"):
                out_lines.append(_splitline[0][1:] + _line[1:])


for index, string in enumerate(out_lines):
    out_lines[index] = string + "\n"

out_string = ""
for string in out_lines:
    out_string += string

with open(sys.argv[2], "w+") as writefile:
    writefile.write(out_string)

subnut avatar Nov 11 '20 07:11 subnut

@subnut Thanks for your effort. I'll see what I can do this weekend. If this works for one case then I expect this to work for most or perhaps even all cases.

kkoomen avatar Nov 11 '20 08:11 kkoomen

@subnut Right now I do have file1 and file2 like this (php files):

file1
/**
 * [TODO:description]
 *
 * @param [TODO:type] $user [TODO:description]
 *
 * @return [TODO:type] [TODO:description]
 */
function test($user) {}
file2
/**
 * Lorem ipsum dor sit amet lorem ipsum dor sit amet lorem ipsum dor sit amet
 * lorem ipsum dor sit amet lorem ipsum dor sit amet lorem ipsum dor sit amet
 * lorem ipsum dor sit amet lorem ipsum.
 *
 * @param User $user The user object.
 *
 * @return void
 */
function test($user) {}

When I run git diff --patch --word-diff=porcelain file2 file1 it outputs nothing.

kkoomen avatar Nov 15 '20 10:11 kkoomen

When I run git diff --patch --word-diff=porcelain file2 file1 it outputs nothing.

Cannot reproduce. See my GIF -

gifcast_201115180421

subnut avatar Nov 15 '20 12:11 subnut

An updated script -

# new script
# only replaces [TODO:
import sys

print(sys.argv)
if not len(sys.argv) == 3:
    print("Please mention only two files, in-file and out-file")
    sys.exit(1)

with open(sys.argv[1]) as file:
    text = file.read()


text = text[text.index("@@", text.index("@@") + 2) + 2 :]
out_lines = []
split = text.split("~")

for index, string in enumerate(split):
    _splitline = string.split("\n")
    _splitline = _splitline[1:-1]
    if len(_splitline) == 1:
        out_lines.append(_splitline[0][1:])
    elif len(_splitline) == 2:
        _line = _splitline[1]
        if _line.startswith("+"):
            out_lines.append(_splitline[0][1:] + _line[1:])
    elif len(_splitline) == 3:
        if _splitline[2].startswith("+[TODO:"):
            out_lines.append(_splitline[0][1:] + _splitline[2][1:])
        else:
            for _line in _splitline[1:]:
                out_lines.append(_splitline[0][1:] + _line[1:])


for index, string in enumerate(out_lines):
    out_lines[index] = string + "\n"

out_string = ""
for string in out_lines:
    out_string += string

with open(sys.argv[2], "w+") as writefile:
    writefile.write(out_string)

I am going to explain the difference between the old script and the new script below....

subnut avatar Nov 15 '20 13:11 subnut

For reference, here are the files -

file1

/**
 * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis sem ut
 * felis imperdiet elementum. Etiam eu consequat felis. Suspendisse ac lectus
 * vel lacus blandit sollicitudin at ac sapien. Donec scelerisque nisl id tellus
 * faucibus tempor. Praesent accumsan turpis nisi.
 *
 * @param array $p1 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Duis gravida nisi eget mollis semper. Class aptent taciti sociosqu ad litora.
 * @param float $p2 Lorem ipsum dor sit amet.
 * @param string $p3 (optional) Lorem ipsum dor sit amet.
 * @param \Drupal\core\Entity\Node $p4 Lorem ipsum dolor sit amet, consectetur
 * adipiscing elit. Mauris pharetra commodo dolor.
 * @return mixed [TODO:description]
 */

file2

/**
 * [TODO:description]
 *
 * @param array $myVar [TODO:description]
 * @param float $p2 [TODO:description]
 * @param [TODO:type] $p3 (optional) [TODO:description]
 * @param \Drupal\core\Entity\Node $p4 [TODO:description]
 * @param [TODO:type] $p5 [TODO:description]
 * @return [TODO:type] [TODO:description]
 */

temp (ie. output of the diff)

diff --git a/file2 b/file1
index 04acf1d..712d4a2 100644
--- a/file2
+++ b/file1
@@ -1,10 +1,14 @@
 /**
~
  * 
-[TODO:description]
+Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis sem ut
~
+ * felis imperdiet elementum. Etiam eu consequat felis. Suspendisse ac lectus
~
+ * vel lacus blandit sollicitudin at ac sapien. Donec scelerisque nisl id tellus
~
+ * faucibus tempor. Praesent accumsan turpis nisi.
~
  *
~
  * @param array 
-$myVar [TODO:description]
+$p1 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
~
+ * Duis gravida nisi eget mollis semper. Class aptent taciti sociosqu ad litora.
~
  * @param float $p2 
-[TODO:description]
+Lorem ipsum dor sit amet.
~
  * @param 
-[TODO:type]
+string
  $p3 (optional) 
-[TODO:description]
+Lorem ipsum dor sit amet.
~
  * @param \Drupal\core\Entity\Node $p4 
-[TODO:description]
+Lorem ipsum dolor sit amet, consectetur
~
  * 
-@param [TODO:type] $p5 [TODO:description]
+adipiscing elit. Mauris pharetra commodo dolor.
~
  * @return 
-[TODO:type]
+mixed
  [TODO:description]
~
  */
~

subnut avatar Nov 15 '20 13:11 subnut

Now here's file3 , i.e. output of the scripts -

Old script output

/**
 * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis sem ut
 * felis imperdiet elementum. Etiam eu consequat felis. Suspendisse ac lectus
 * vel lacus blandit sollicitudin at ac sapien. Donec scelerisque nisl id tellus
 * faucibus tempor. Praesent accumsan turpis nisi.
 *
 * @param array $p1 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Duis gravida nisi eget mollis semper. Class aptent taciti sociosqu ad litora.
 * @param float $p2 Lorem ipsum dor sit amet.
 * @param string
 * @param Lorem ipsum dor sit amet.
 * @param \Drupal\core\Entity\Node $p4 Lorem ipsum dolor sit amet, consectetur
 * adipiscing elit. Mauris pharetra commodo dolor.
 * @return mixed
 */

New script output

/**
 * [TODO:description]
 * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis sem ut
 * felis imperdiet elementum. Etiam eu consequat felis. Suspendisse ac lectus
 * vel lacus blandit sollicitudin at ac sapien. Donec scelerisque nisl id tellus
 * faucibus tempor. Praesent accumsan turpis nisi.
 *
 * @param array $myVar [TODO:description]
 * @param array $p1 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
 * Duis gravida nisi eget mollis semper. Class aptent taciti sociosqu ad litora.
 * @param float $p2 [TODO:description]
 * @param float $p2 Lorem ipsum dor sit amet.
 * @param \Drupal\core\Entity\Node $p4 [TODO:description]
 * @param \Drupal\core\Entity\Node $p4 Lorem ipsum dolor sit amet, consectetur
 * @param [TODO:type] $p5 [TODO:description]
 * adipiscing elit. Mauris pharetra commodo dolor.
 */

Difference

diff --git a/file3.old b/file3
index 78a1bbd..5d4e80e 100644
--- a/file3.old
+++ b/file3
@@ -1,15 +1,17 @@
 /**
+ * [TODO:description]
  * Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec quis sem ut
  * felis imperdiet elementum. Etiam eu consequat felis. Suspendisse ac lectus
  * vel lacus blandit sollicitudin at ac sapien. Donec scelerisque nisl id tellus
  * faucibus tempor. Praesent accumsan turpis nisi.
  *
+ * @param array $myVar [TODO:description]
  * @param array $p1 Lorem ipsum dolor sit amet, consectetur adipiscing elit.
  * Duis gravida nisi eget mollis semper. Class aptent taciti sociosqu ad litora.
+ * @param float $p2 [TODO:description]
  * @param float $p2 Lorem ipsum dor sit amet.
- * @param string
- * @param Lorem ipsum dor sit amet.
+ * @param \Drupal\core\Entity\Node $p4 [TODO:description]
  * @param \Drupal\core\Entity\Node $p4 Lorem ipsum dolor sit amet, consectetur
+ * @param [TODO:type] $p5 [TODO:description]
  * adipiscing elit. Mauris pharetra commodo dolor.
- * @return mixed
  */

subnut avatar Nov 15 '20 14:11 subnut

Sorry, there's a mistake in the updated script, please wait...

subnut avatar Nov 15 '20 14:11 subnut

When I run git diff --patch --word-diff=porcelain file2 file1 it outputs nothing.

Cannot reproduce. See my GIF -

gifcast_201115180421

You're showing me here file1.php and file2.php but the actual command is using file1 and file2 instead of file1.php and file2.php.

Besides that part, I can get the diff if I am running git inside a folder without a .git folder. I used to run this in my vim-doge repo but that doesn't work. Can this be fixed?

kkoomen avatar Nov 16 '20 12:11 kkoomen

Adding --no-index fixes it and thus can be run in existing repo: git diff --patch --no-index --word-diff=porcelain file2 file1

kkoomen avatar Nov 16 '20 12:11 kkoomen

@subnut Perhaps git merge-file might be useful. I really prefer to use the git merging algorithm. The logic I'm looking for is like this:

When generating a comment, replace the current one with the new one. When there's a conflict, just generate a new comment and insert the new comment, leaving the current one unchanged.

kkoomen avatar Nov 16 '20 13:11 kkoomen

@kkoomen Give me some examples in this format -

  • old_file contents
  • new_file contents
  • expected result

subnut avatar Nov 16 '20 13:11 subnut

One example is in StackOverflow, I just need another example

subnut avatar Nov 16 '20 14:11 subnut

You can test against this heavy python example:

file1 (current docblock)

def myFunc(p1: Callable[[int], None] = False, p2: Callable[[int, Exception], None] = {}) -> Callable[[int, Exception], None]:
    """
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec pulvinar eros. Aliquam erat volutpat. Praesent odio ligula, viverra ac imperdiet quis, vestibulum nec urna. Praesent rhoncus libero in purus.

    :param p1 Callable[[int], None]: Lorem ipsum dolor sit amet, consectetur
        adipiscing elit. Sed nec pulvinar eros. Aliquam erat volutpat. Praesent
        odio ligula, viverra ac imperdiet quis, vestibulum nec urna. Praesent
        rhoncus libero in purus.
    :param p2 Callable[[int, Exception], None]: Something short.
    :rtype Callable[[int, Exception], None]: Something that's a bit longer but
        still expands over 2 lines or more, lorem ipsum dor sit amet.
    """
    pass

file2 (updated version, aka incoming change)

def myFunc(newVarName: int) -> int:
    """
    [TODO:description]

    :param newVarName int: [TODO:description]
    :rtype int: [TODO:description]
    """

Expected result:

def myFunc(newVarName: int) -> int:
    """
    Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed nec pulvinar eros. Aliquam erat volutpat. Praesent odio ligula, viverra ac imperdiet quis, vestibulum nec urna. Praesent rhoncus libero in purus.

    :param newVarName int: Lorem ipsum dolor sit amet, consectetur
        adipiscing elit. Sed nec pulvinar eros. Aliquam erat volutpat. Praesent
        odio ligula, viverra ac imperdiet quis, vestibulum nec urna. Praesent
        rhoncus libero in purus.
    :rtype int: Something that's a bit longer but still expands over 2 lines or
        more, lorem ipsum dor sit amet.
    """
    pass

I'm doing this "expected result" based on how merging works. Ideally, to me, it should only preserve documentation if the p1 is still named p1. If it's a different name then it should be a new [TODO: ...] again, but that's something that could be thought about later (if possible)

kkoomen avatar Nov 16 '20 14:11 kkoomen

Also show me your ideal result (for both, this example and the example in StackOverflow)

subnut avatar Nov 16 '20 14:11 subnut

Perhaps the example I showed above is the ideal result for the majority. I am not sure about the most ideal behavior personally. It's something me and others have to experience and feel overtime. Let's do as above for now and if needed, we can make adjustments later. Being able to merge would be really nice already.

kkoomen avatar Nov 16 '20 14:11 kkoomen

Hmm... let me see.... I may need upto a month to get something usable... I am going to be busy for 2 weeks. Feel free to consider alternatives.

subnut avatar Nov 16 '20 17:11 subnut