Skip to content
This repository has been archived by the owner on Jul 15, 2023. It is now read-only.

Code coverage removal fix for single line comments #1996

Merged
merged 11 commits into from
Jan 15, 2019
Merged

Code coverage removal fix for single line comments #1996

merged 11 commits into from
Jan 15, 2019

Conversation

karthikraobr
Copy link
Contributor

This pull request partially fixes #1852.

@msftclas
Copy link

msftclas commented Oct 12, 2018

CLA assistant check
All CLA requirements met.

@karthikraobr karthikraobr changed the title Fix for single line comments Code coverage removal fix for single line comments Oct 12, 2018
src/goCover.ts Outdated
export function isPartOfComment(e: vscode.TextDocumentChangeEvent): boolean {
let result = false
e.contentChanges.every(function(change, index){
let line = e.document.lineAt(change.range.start)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about the case when the range spans multiple lines and only the first line was part of a comment? In that case, isPartOfComment would return true instead of false

Copy link
Contributor Author

@karthikraobr karthikraobr Oct 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For block comments of the form /* .... *,. I was thinking of the following solution

  • Scan backwards from current change until start of the document or until / is found to find /. This would be necessary in cases where the block comment starts on a line after the code and changes are made to the code. In this case we would have to clear the coverage. Example

return 0, err /* one two three. */

  • Scan forwards until */ is found or end of the document.
  • Check if change is within the above range.

Seems very inefficient to me. Is there a better way of doing it? Perhaps a vscode API to identify block comments?

Copy link
Contributor

@ramya-rao-a ramya-rao-a Oct 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here I wasnt referring to block comments. Let's scope this PR to just line comments for now. Take the below case

// I am a comment
var a = 1
var b = 2

Now if I start selecting from the word comment and continue till the next line and delete the selected text, then the line variable in your code will have // I am a and isPartOfComment will return true even though some code was deleted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have updated the PR to resolve this issue.

src/goCover.ts Outdated
let line = e.document.lineAt(change.range.start)
let text = e.document.getText(line.rangeIncludingLineBreak)
// Exit the loop as soon as one of the changes is not part of a comment.
if (!text.startsWith('//')){
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about a case like the below?

var a = 1 // this is a comment

Here when the comment is edited, isPartOfComment returns false instead of true

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Will update the PR once I have fixed the block comment issue.

src/goCover.ts Outdated
let text = e.document.getText(line.rangeIncludingLineBreak)
// Exit the loop as soon as one of the changes is not part of a comment.
if (!text.startsWith('//')){
result = false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We dont need to use the result variable here. Instead, we can do the below

return e.contentChanges.every(change => {
// Just return true or false based on your logic here
}

The .every on an array stops looping over the array items the moment one of them returns false in the callback

Copy link
Contributor Author

@karthikraobr karthikraobr Oct 15, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it would be a good idea not to return as soon as we find that the change is a part of a comment. If another change which is not a part of a comment is found in a later iteration, then we would have to anyway remove the highlighting right?

@karthikraobr
Copy link
Contributor Author

Apologies for the multiple lint commits. Go dev here :) Hence the missing semi-colons.

src/goCover.ts Outdated
export function isPartOfComment(e: vscode.TextDocumentChangeEvent): boolean {
let result = false;
e.contentChanges.every(function (change, index) {
let line = e.document.lineAt(change.range.start);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return e.contentChanges.every(change => {
// Just return true or false based on your logic here
}

I guess it would be a good idea not to return as soon as we find that the change is a part of a comment. If another change which is not a part of a comment is found in a later iteration, then we would have to anyway remove the highlighting right?

A return statement in the callback passed to the .every doesnt cause a return from isPartOfComment.
A return true statement in the callback passed to the .every cause the iteration to continue;
A return false statement in the callback passed to the .every cause the iteration to stop;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the detailed explanation.

src/goCover.ts Outdated
let text = e.document.getText(line.range);
let idx = text.search('//');
let changeIdx = change.range.start.character;
if (idx === -1 || idx > changeIdx || !change.range.isSingleLine || change.text.includes('\n')) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add some tests to cover these cases?

Copy link
Contributor Author

@karthikraobr karthikraobr Oct 16, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure! Could you please point me to the tests currently present for unit test coverage? I am assuming that I would have to add some test fixtures here and then perform some assertions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please give me some pointers on how to write tests. I ran the tests and seems like currently there are no tests for code coverage. I am assuming these would be the steps I would have to follow :

  • Create a go file with code and comments to cover all scenarios.
  • Write some tests for the above file and run them. (use testCurrentFile function).
  • Select some part of the code and delete/add (based on the scenarios in the if condition using applyUsingTextEditorEdit ).
  • And check if coverage highlights have been removed or retained. (How do I achieve this?)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there are no tests for code coverage right now :(

For this PR, testing just the isPartOfComment function would be enough. I would suggest to

  • Update the signature of isPartOfComment so that it takes 2 parameters document and ranges.
  • Create a go file in the fixtures folder with some comments to cover all scenarios
  • Use vscode.workspace.openTextDocument and vscode.window.showTextDocument just like the other tests to get the document object.
  • Then for each case, create the ranges and pass it to isPartOfComment

@karthikraobr
Copy link
Contributor Author

karthikraobr commented Oct 17, 2018

In case of a deletion, the changed text is always "". Also, the TextDocument object contains the text after the deletion has been performed. Is there a way to get the deleted text, rather than an empty string? This is necessary in cases where multiple lines are deleted. How would I differentiate between deleting lines 1&2 and deleting lines 2&3.

1.// hello world
2.// hello again
3.func sayHello()

@ramya-rao-a
Copy link
Contributor

This will need some more time from my side to look into, I'll get back to this next week.

@karthikraobr
Copy link
Contributor Author

This will need some more time from my side to look into, I'll get back to this next week.

@ramya-rao-a could you please let me know if there has been an update on this?

@ramya-rao-a
Copy link
Contributor

@karthikraobr Thanks for your patience, I'll get right back to this as soon as I release the current update which should be sometime this week.

@karthikraobr
Copy link
Contributor Author

hi @ramya-rao-a , any update on this? Thanks and sorry for the repeated reminders :)

@karthikraobr
Copy link
Contributor Author

@ramya-rao-a any update on this and I apologise in advance :)

@ramya-rao-a
Copy link
Contributor

@karthikraobr No apologies needed :) You have every right to give the reminders.

I have been a little busy at work from my end, and so couldnt get back sooner. I'll definitely take a look soon

@ramya-rao-a
Copy link
Contributor

I have refactored the code a bit to avoid checking for comments when there is no coverage applied in the first place and also the code for isPartOfComment as well

@ramya-rao-a ramya-rao-a merged commit a7b0fb7 into microsoft:master Jan 15, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Coverage UI not updating upon writing comments in the source code
3 participants