mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
[java-completion] IDEA-246986 Fixes according to review IDEA-CR-65611
1. Honor SPACE_WITHIN_PARENTHESES setting 2. Some cheap lexer checks to avoid document commit when unnecessary GitOrigin-RevId: 168e521a4f59d294d09098a05d7fa276501cf2ba
This commit is contained in:
committed by
intellij-monorepo-bot
parent
22bf433b63
commit
ec21ef9436
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.editorActions;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
import com.intellij.codeInsight.AutoPopupController;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.CompletionType;
|
||||
@@ -136,8 +137,9 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
|
||||
}
|
||||
|
||||
if (c == '?') {
|
||||
handleQuestionMark(project, editor, file, offsetBefore);
|
||||
return Result.STOP;
|
||||
if (handleQuestionMark(project, editor, file, offsetBefore)) {
|
||||
return Result.STOP;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '=') {
|
||||
@@ -192,9 +194,29 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
|
||||
Document doc = editor.getDocument();
|
||||
char prevChar = doc.getCharsSequence().charAt(offsetBefore - 1);
|
||||
if (prevChar != '=' && prevChar != '!') return false;
|
||||
|
||||
HighlighterIterator it = ((EditorEx)editor).getHighlighter().createIterator(offsetBefore - 1);
|
||||
IElementType curToken = it.getTokenType();
|
||||
if (curToken != JavaTokenType.EQ && curToken != JavaTokenType.EXCL) return false;
|
||||
int lineStart = doc.getLineStartOffset(doc.getLineNumber(offsetBefore));
|
||||
do {
|
||||
it.retreat();
|
||||
curToken = it.getTokenType();
|
||||
}
|
||||
while (curToken == TokenType.WHITE_SPACE || curToken == JavaTokenType.C_STYLE_COMMENT || curToken == JavaTokenType.END_OF_LINE_COMMENT);
|
||||
// ) == or ) != : definitely no need to add parentheses
|
||||
if (curToken == JavaTokenType.RPARENTH) return false;
|
||||
while (true) {
|
||||
if (it.getStart() < lineStart) return false;
|
||||
it.retreat();
|
||||
if (it.atEnd()) return false;
|
||||
curToken = it.getTokenType();
|
||||
if (curToken == JavaTokenType.AND || curToken == JavaTokenType.OR || curToken == JavaTokenType.XOR) break;
|
||||
}
|
||||
|
||||
doc.insertString(offsetBefore, "=");
|
||||
// a&b== => (a&b)==
|
||||
editor.getCaretModel().moveToOffset(offsetBefore + 1);
|
||||
// a&b== => (a&b)==
|
||||
PsiDocumentManager.getInstance(project).commitDocument(doc);
|
||||
PsiJavaToken token = ObjectUtils.tryCast(file.findElementAt(offsetBefore), PsiJavaToken.class);
|
||||
if (token == null) return true;
|
||||
@@ -211,23 +233,67 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
|
||||
if (!TypeConversionUtil.isIntegralNumberType(left.getType()) || !TypeConversionUtil.isIntegralNumberType(right.getType())) {
|
||||
return true;
|
||||
}
|
||||
doc.insertString(right.getTextRange().getEndOffset(), ")");
|
||||
doc.insertString(left.getTextRange().getStartOffset(), "(");
|
||||
editor.getCaretModel().moveToOffset(offsetBefore + 3);
|
||||
int openingOffset = left.getTextRange().getStartOffset();
|
||||
int closingOffset = right.getTextRange().getEndOffset();
|
||||
wrapWithParentheses(file, doc, openingOffset, closingOffset);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void handleQuestionMark(Project project, Editor editor, PsiFile file, int offsetBefore) {
|
||||
private static final TokenSet UNWANTED_TOKEN_AT_QUESTION =
|
||||
TokenSet.create(JavaTokenType.C_STYLE_COMMENT, JavaTokenType.END_OF_LINE_COMMENT, JavaTokenType.CHARACTER_LITERAL,
|
||||
JavaTokenType.STRING_LITERAL, JavaTokenType.TEXT_BLOCK_LITERAL);
|
||||
|
||||
private static final TokenSet UNWANTED_TOKEN_BEFORE_QUESTION =
|
||||
TokenSet.create(
|
||||
// inside assignment
|
||||
JavaTokenType.EQ, JavaTokenType.ASTERISKEQ, JavaTokenType.DIVEQ, JavaTokenType.PERCEQ, JavaTokenType.PLUSEQ, JavaTokenType.MINUSEQ,
|
||||
JavaTokenType.LTLTEQ, JavaTokenType.GTGTEQ, JavaTokenType.GTGTGTEQ, JavaTokenType.ANDEQ, JavaTokenType.OREQ, JavaTokenType.XOREQ,
|
||||
// inside another ?:
|
||||
JavaTokenType.QUEST, JavaTokenType.COLON);
|
||||
|
||||
private static final TokenSet WANTED_TOKEN_BEFORE_QUESTION =
|
||||
TokenSet.create(
|
||||
// Tokens that may appear before ?: in void context
|
||||
JavaTokenType.ARROW, JavaTokenType.SEMICOLON, JavaTokenType.LBRACE, JavaTokenType.RBRACE,
|
||||
// Tokens that may appear before ?: in polyadic expression that may have non-boolean result
|
||||
JavaTokenType.OR, JavaTokenType.XOR, JavaTokenType.AND, JavaTokenType.LTLT, JavaTokenType.GTGT,
|
||||
JavaTokenType.GTGTGT, JavaTokenType.PLUS, JavaTokenType.MINUS, JavaTokenType.ASTERISK, JavaTokenType.DIV,
|
||||
JavaTokenType.PERC);
|
||||
|
||||
private static boolean handleQuestionMark(Project project, Editor editor, PsiFile file, int offsetBefore) {
|
||||
if (offsetBefore == 0) return false;
|
||||
HighlighterIterator it = ((EditorEx)editor).getHighlighter().createIterator(offsetBefore);
|
||||
if (it.atEnd()) return false;
|
||||
IElementType curToken = it.getTokenType();
|
||||
if (UNWANTED_TOKEN_AT_QUESTION.contains(curToken)) return false;
|
||||
int nesting = 0;
|
||||
while (true) {
|
||||
it.retreat();
|
||||
if (it.atEnd()) return false;
|
||||
curToken = it.getTokenType();
|
||||
if (curToken == JavaTokenType.LPARENTH || curToken == JavaTokenType.LBRACKET) {
|
||||
nesting--;
|
||||
if (nesting < 0) return false;
|
||||
}
|
||||
else if (curToken == JavaTokenType.RPARENTH || curToken == JavaTokenType.RBRACKET) {
|
||||
nesting++;
|
||||
}
|
||||
else if (nesting == 0) {
|
||||
if (UNWANTED_TOKEN_BEFORE_QUESTION.contains(curToken)) return false;
|
||||
if (WANTED_TOKEN_BEFORE_QUESTION.contains(curToken)) break;
|
||||
}
|
||||
}
|
||||
|
||||
Document doc = editor.getDocument();
|
||||
doc.insertString(offsetBefore, "?");
|
||||
editor.getCaretModel().moveToOffset(offsetBefore + 1);
|
||||
PsiDocumentManager.getInstance(project).commitDocument(doc);
|
||||
PsiElement element = file.findElementAt(offsetBefore);
|
||||
if (!(element instanceof PsiJavaToken) || !((PsiJavaToken)element).getTokenType().equals(JavaTokenType.QUEST)) return;
|
||||
if (!(element instanceof PsiJavaToken) || !((PsiJavaToken)element).getTokenType().equals(JavaTokenType.QUEST)) return true;
|
||||
PsiConditionalExpression cond = ObjectUtils.tryCast(element.getParent(), PsiConditionalExpression.class);
|
||||
if (cond == null || cond.getThenExpression() != null || cond.getElseExpression() != null) return;
|
||||
if (cond == null || cond.getThenExpression() != null || cond.getElseExpression() != null) return true;
|
||||
PsiExpression condition = cond.getCondition();
|
||||
if (PsiUtilCore.hasErrorElementChild(condition)) return;
|
||||
if (PsiUtilCore.hasErrorElementChild(condition)) return true;
|
||||
PsiExpression parenthesisStart = null;
|
||||
// intVal+bool? => intVal+(bool?)
|
||||
if (condition instanceof PsiPolyadicExpression && !PsiType.BOOLEAN.equals(condition.getType())) {
|
||||
@@ -241,11 +307,17 @@ public class JavaTypedHandler extends TypedHandlerDelegate {
|
||||
parenthesisStart = cond;
|
||||
}
|
||||
if (parenthesisStart != null) {
|
||||
int offset = parenthesisStart.getTextRange().getStartOffset();
|
||||
doc.insertString(offsetBefore + 1, ")");
|
||||
doc.insertString(offset, "(");
|
||||
editor.getCaretModel().moveToOffset(offsetBefore + 2);
|
||||
int openingOffset = parenthesisStart.getTextRange().getStartOffset();
|
||||
int closingOffset = cond.getTextRange().getEndOffset();
|
||||
wrapWithParentheses(file, doc, openingOffset, closingOffset);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void wrapWithParentheses(PsiFile file, Document doc, int openingOffset, int closingOffset) {
|
||||
String space = CodeStyle.getLanguageSettings(file).SPACE_WITHIN_PARENTHESES ? " " : "";
|
||||
doc.insertString(closingOffset, space + ")");
|
||||
doc.insertString(openingOffset, "(" + space);
|
||||
}
|
||||
|
||||
private static boolean shouldInsertPairedBrace(@NotNull PsiElement leaf) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
public class Foo {
|
||||
void test(int x) {
|
||||
if((x|0x1F)!=0x1F && (x|0x38)!=<caret>)
|
||||
if((x|0x1F)!=0x1F && ( x|0x38 )!=<caret>)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
public class Foo {
|
||||
void test(int x, String s) {
|
||||
System.out.println(x+(!s.trim().substring(new int[] {1,2,3}.length).isEmpty()?<caret>));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
public class Foo {
|
||||
void test(int x, String s) {
|
||||
System.out.println(x+!s.trim().substring(new int[] {1,2,3}.length).isEmpty()<caret>);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.java.codeInsight;
|
||||
|
||||
import com.intellij.application.options.CodeStyle;
|
||||
import com.intellij.openapi.command.undo.UndoManager;
|
||||
import com.intellij.openapi.editor.ex.EditorEx;
|
||||
import com.intellij.openapi.fileEditor.TextEditor;
|
||||
import com.intellij.openapi.fileEditor.impl.text.TextEditorProvider;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.testFramework.fixtures.BasePlatformTestCase;
|
||||
@@ -141,16 +143,28 @@ public class JavaTypingTest extends BasePlatformTestCase {
|
||||
}
|
||||
|
||||
public void testCommaInDefaultAnnotationStringArgumentWhenArrayIsExpected() { doTest(','); }
|
||||
|
||||
|
||||
public void testQuestionAfterPolyadic() { doTest('?'); }
|
||||
|
||||
public void testQuestionAfterPolyadic2() { doTest('?'); }
|
||||
|
||||
public void testQuestionAfterPolyadicBoolean() { doTest('?'); }
|
||||
|
||||
|
||||
public void testQuestionInVoidContext() { doTest('?'); }
|
||||
|
||||
|
||||
public void testEqualAfterBitwiseOp() { doTest('='); }
|
||||
|
||||
public void testEqualAfterBitwiseOp2() { doTest('='); }
|
||||
|
||||
public void testEqualAfterBitwiseOp2() {
|
||||
myFixture.configureByFile(getTestName(true) + "_before.java");
|
||||
CommonCodeStyleSettings settings = CodeStyle.getLanguageSettings(myFixture.getFile());
|
||||
settings.SPACE_WITHIN_PARENTHESES = true;
|
||||
try {
|
||||
myFixture.type('=');
|
||||
myFixture.checkResultByFile(getTestName(true) + "_after.java");
|
||||
}
|
||||
finally {
|
||||
settings.SPACE_WITHIN_PARENTHESES = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void doTest(char c) {
|
||||
myFixture.configureByFile(getTestName(true) + "_before.java");
|
||||
|
||||
@@ -25,8 +25,20 @@ public interface HighlighterIterator {
|
||||
TextAttributes getTextAttributes();
|
||||
int getStart();
|
||||
int getEnd();
|
||||
|
||||
/**
|
||||
* @return type if the current token
|
||||
*/
|
||||
IElementType getTokenType();
|
||||
|
||||
/**
|
||||
* Move iterator to the next segment
|
||||
*/
|
||||
void advance();
|
||||
|
||||
/**
|
||||
* Move iterator to the previous segment
|
||||
*/
|
||||
void retreat();
|
||||
boolean atEnd();
|
||||
Document getDocument();
|
||||
|
||||
Reference in New Issue
Block a user