Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ANN: fix infinite loop when invoking a quick fix on an element with a syntax error #7841

Merged
merged 1 commit into from Sep 15, 2021

Conversation

Kobzol
Copy link
Member

@Kobzol Kobzol commented Sep 13, 2021

This issue produced an interesting situation. In the following code (which has a syntax error in the reference lifetime):

fn foo(a: &u32) {}

fn main() {
    let a = 1;
    foo(&'static a);
}

the foo call is parsed as having two arguments. Therefore the RemoveRedundantFunctionArgumentsFix shows up, which tries to remove the argument a, along with its surrounding whitespace and comments. The code that handles this is RsElement.deleteWithSurroundingCommaAndWhitespace in RsElement.kt:

fun RsElement.deleteWithSurroundingCommaAndWhitespace() {
    while (nextSibling?.isWhitespaceOrComment == true) {
        nextSibling?.delete()
    }
    while (prevSibling?.isWhitespaceOrComment == true) {
        prevSibling?.delete()
    }
    deleteWithSurroundingComma()
}

The problem is that when the whitespace before a in &'static a gets removed, the plugin somehow automatically adds it back again (maybe because it's preceded by an error element?). This caused the above function to end in an infinite loop. To resolve this pathetic case, I introduced a simple infinite loop guard, which will run the removal at most five times (this should be enough to remove successive whitespace/comments in most situations).

The bug was pretty nasty, as it immediately deadlocked the whole IDE.

Fixes: #7830

changelog: Avoid IDE freeze in certain situations when invoking quick fixes or intentions on elements with syntax errors.

@Kobzol Kobzol added the fix Pull requests that fix some bug(s) label Sep 13, 2021
@Kobzol Kobzol requested a review from Undin September 13, 2021 21:32
@Kobzol Kobzol added this to In Progress in To test via automation Sep 13, 2021
@vlad20012
Copy link
Member

LGTM as a hotfix, but I think it's better to do either

  1. Check for PsiErrorElement there
  2. Split collect and removal steps. Collect using PsiElement.rightSiblings and PsiElement.leftSiblings sequences

bors r+

@Kobzol
Copy link
Member Author

Kobzol commented Sep 15, 2021

Hmm, but if we collect the siblings first, isn't it possible that one of the siblings will be invalidated if we remove another sibling? E.g. I first collect [S1, S2, S3], then remove S3, isn't it possible that it will invalidate S2/S1?

@bors
Copy link
Contributor

bors bot commented Sep 15, 2021

Build succeeded:

@bors bors bot merged commit cb346f0 into intellij-rust:master Sep 15, 2021
To test automation moved this from In Progress to Test Sep 15, 2021
@Kobzol Kobzol deleted the fix-infinite-loop branch September 15, 2021 15:37
@vlad20012
Copy link
Member

vlad20012 commented Sep 15, 2021

Hmm, but if we collect the siblings first, isn't it possible that one of the siblings will be invalidated if we remove another sibling? E.g. I first collect [S1, S2, S3], then remove S3, isn't it possible that it will invalidate S2/S1?

HmmMMMmm, as far as I know, no, it's impossible. You can even construct an invalid PSI like remove a very essential keyword. The PSI will be invalidated only after a reparse that will be performed after the end of an intention action invocation (or in doPostponedOperationsAndUnblockDocument/forcePsiPostprocessAndRestoreElement)

@github-actions github-actions bot added this to the v156 milestone Sep 15, 2021
@mili-l mili-l self-assigned this Sep 17, 2021
@mili-l mili-l moved this from Test to Done in To test Sep 17, 2021
bors bot added a commit that referenced this pull request Nov 19, 2021
7855: Collect surrounding whitespace and comments before deleting them in `deleteWithSurroundingCommaAndWhitespace` r=dima74 a=Kobzol

Discussed in #7841.

Co-authored-by: Jakub Beránek <berykubik@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
fix Pull requests that fix some bug(s)
Projects
To test
  
Done
Development

Successfully merging this pull request may close these issues.

AWT thread freezes when performing editing
3 participants