IDEA-74979 (quick fix for "Too many characters in character literal" error)

This commit is contained in:
Roman Shevchenko
2011-10-28 10:05:18 +02:00
parent 1684773504
commit ca544948e9
10 changed files with 187 additions and 10 deletions
@@ -33,10 +33,7 @@ import com.intellij.lang.java.JavaLanguage;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.*;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
@@ -52,6 +49,7 @@ import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.StringBuilderSpinAllocator;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.xml.util.XmlStringUtil;
import gnu.trove.THashMap;
@@ -883,6 +881,8 @@ public class HighlightUtil {
return null;
}
private static final Key<Boolean> TOO_BIG_CHAR_LITERAL_KEY = Key.create("too.big.char.literal");
public static String getLiteralExpressionParsingError(final PsiLiteralExpression expression) {
final Object value = expression.getValue();
final PsiElement literal = expression.getFirstChild();
@@ -959,13 +959,18 @@ public class HighlightUtil {
else {
return JavaErrorMessages.message("illegal.line.end.in.character.literal");
}
StringBuilder chars = new StringBuilder();
boolean success = PsiLiteralExpressionImpl.parseStringCharacters(text, chars, null);
final StringBuilder chars = StringBuilderSpinAllocator.alloc();
final boolean success = PsiLiteralExpressionImpl.parseStringCharacters(text, chars, null);
if (!success) return JavaErrorMessages.message("illegal.escape.character.in.character.literal");
if (chars.length() > 1) {
final int length = chars.length();
StringBuilderSpinAllocator.dispose(chars);
if (length > 1) {
literal.putUserData(TOO_BIG_CHAR_LITERAL_KEY, Boolean.TRUE);
return JavaErrorMessages.message("too.many.characters.in.character.literal");
}
else if (chars.length() == 0) return JavaErrorMessages.message("empty.character.literal");
else if (length == 0) {
return JavaErrorMessages.message("empty.character.literal");
}
}
}
else if (type == JavaTokenType.STRING_LITERAL) {
@@ -1023,12 +1028,17 @@ public class HighlightUtil {
if (PsiLiteralExpressionImpl.REAL_LITERALS.contains(type)) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_5) && text.startsWith(PsiLiteralExpressionImpl.HEX_PREFIX)) {
return Arrays.asList(new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
return Collections.singletonList(new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_5));
}
}
if (PsiLiteralExpressionImpl.NUMERIC_LITERALS.contains(type)) {
if (!languageLevel.isAtLeast(LanguageLevel.JDK_1_7) && (text.startsWith(PsiLiteralExpressionImpl.BIN_PREFIX) || text.contains("_"))) {
return Arrays.asList(new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_7));
return Collections.singletonList(new IncreaseLanguageLevelFix(LanguageLevel.JDK_1_7));
}
}
if (type == JavaTokenType.CHARACTER_LITERAL) {
if (Boolean.TRUE.equals(literal.getUserData(TOO_BIG_CHAR_LITERAL_KEY))) {
return Collections.singletonList(new ConvertToStringLiteralAction());
}
}
@@ -0,0 +1,69 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
public class ConvertToStringLiteralAction implements IntentionAction {
@NotNull
@Override
public String getText() {
return QuickFixBundle.message("convert.to.string.text");
}
@NotNull
@Override
public String getFamilyName() {
return QuickFixBundle.message("convert.to.string.family");
}
@Override
public boolean isAvailable(@NotNull final Project project, final Editor editor, final PsiFile file) {
final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
return PsiUtil.isJavaToken(element, JavaTokenType.CHARACTER_LITERAL);
}
@Override
public void invoke(@NotNull final Project project, final Editor editor, final PsiFile file) throws IncorrectOperationException {
final PsiElement element = file.findElementAt(editor.getCaretModel().getOffset());
if (element != null && PsiUtil.isJavaToken(element, JavaTokenType.CHARACTER_LITERAL)) {
final String text = element.getText();
final int length = text.length();
if (length > 1 && text.charAt(0) == '\'' && text.charAt(length - 1) == '\'') {
final StringBuilder sb = new StringBuilder(text);
sb.replace(0, 1, "\"");
sb.replace(length - 1, length, "\"");
final PsiExpression expression = JavaPsiFacade.getElementFactory(project).createExpressionFromText(sb.toString(), null);
final PsiElement literal = expression.getFirstChild();
if (literal != null && PsiUtil.isJavaToken(literal, JavaTokenType.STRING_LITERAL)) {
element.replace(literal);
}
}
}
}
@Override
public boolean startInWriteAction() {
return true;
}
}
@@ -0,0 +1,20 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class C {
{
System.out.println('<caret>aaa');
}
}
@@ -0,0 +1,20 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
class C {
{
System.out.println("aaa");
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.intention;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.daemon.QuickFixBundle;
import com.intellij.testFramework.fixtures.CodeInsightTestUtil;
import com.intellij.testFramework.fixtures.JavaCodeInsightFixtureTestCase;
public class ConvertToStringLiteralTest extends JavaCodeInsightFixtureTestCase {
private String myIntention;
@Override
public void setUp() throws Exception {
super.setUp();
myIntention = QuickFixBundle.message("convert.to.string.text");
}
public void testSimple() throws Exception {
CodeInsightTestUtil.doIntentionTest(myFixture, myIntention, "Simple.java", "Simple_after.java");
}
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath() + "/codeInsight/convertToStringLiteral/";
}
}
@@ -0,0 +1 @@
String s = <spot>"</spot>literal<spot>"</spot>;
@@ -0,0 +1 @@
String s = <spot>'</spot>literal<spot>'</spot>;
@@ -0,0 +1,6 @@
<html>
<body>
This intention converts invalid character literal (with too many characters)
into string literal.
</body>
</html>
@@ -258,3 +258,6 @@ create.writable.property.with.field=Create setter and field for ''{0}''
change.to.append.family=Fix StringBuilder append
change.to.append.text=Change to ''{0}.append({1})''
convert.to.string.family=Fix Character Literal
convert.to.string.text=Convert to String Literal
+5
View File
@@ -675,6 +675,11 @@
<category>Numbers</category>
</intentionAction>
<intentionAction>
<className>com.intellij.codeInsight.daemon.impl.quickfix.ConvertToStringLiteralAction</className>
<category>Strings</category>
</intentionAction>
<lang.parserDefinition language="JAVA" implementationClass="com.intellij.lang.java.JavaParserDefinition"/>
<lang.refactoringSupport language="JAVA" implementationClass="com.intellij.lang.java.JavaRefactoringSupportProvider"/>