diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/spellchecker/GroovySpellcheckingStrategy.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/spellchecker/GroovySpellcheckingStrategy.java index 2a8f9ea95690..b47f57eacd05 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/spellchecker/GroovySpellcheckingStrategy.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/codeInspection/spellchecker/GroovySpellcheckingStrategy.java @@ -16,10 +16,10 @@ package org.jetbrains.plugins.groovy.codeInspection.spellchecker; import com.intellij.codeInspection.SuppressIntentionAction; -import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.spellchecker.inspections.PlainTextSplitter; +import com.intellij.spellchecker.tokenizer.EscapeSequenceTokenizer; import com.intellij.spellchecker.tokenizer.SuppressibleSpellcheckingStrategy; import com.intellij.spellchecker.tokenizer.TokenConsumer; import com.intellij.spellchecker.tokenizer.Tokenizer; @@ -27,31 +27,43 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.groovy.codeInspection.GroovySuppressableInspectionTool; import org.jetbrains.plugins.groovy.lang.lexer.TokenSets; import org.jetbrains.plugins.groovy.lang.psi.GrNamedElement; -import org.jetbrains.plugins.groovy.lang.resolve.GroovyStringLiteralManipulator; +import org.jetbrains.plugins.groovy.lang.psi.util.GrStringUtil; /** * @author peter */ public class GroovySpellcheckingStrategy extends SuppressibleSpellcheckingStrategy { private final GrDocCommentTokenizer myDocCommentTokenizer = new GrDocCommentTokenizer(); + private Tokenizer myStringTokenizer = new Tokenizer() { + @Override + public void tokenize(@NotNull PsiElement literal, TokenConsumer consumer) { + String text = GrStringUtil.removeQuotes(literal.getText()); + if (!text.contains("\\")) { + consumer.consumeToken(literal, PlainTextSplitter.getInstance()); + } + else { + StringBuilder unescapedText = new StringBuilder(); + int[] offsets = new int[text.length() + 1]; + GrStringUtil.parseStringCharacters(text, unescapedText, offsets); + EscapeSequenceTokenizer.processTextWithOffsets(literal, consumer, unescapedText, offsets, GrStringUtil.getStartQuote(literal.getText()).length()); + } + } + }; @NotNull @Override public Tokenizer getTokenizer(PsiElement element) { + if (TokenSets.STRING_LITERAL_SET.contains(element.getNode().getElementType())) { + return myStringTokenizer; + } if (element instanceof GrNamedElement) { final PsiElement name = ((GrNamedElement)element).getNameIdentifierGroovy(); if (TokenSets.STRING_LITERAL_SET.contains(name.getNode().getElementType())) { - return new Tokenizer() { - @Override - public void tokenize(@NotNull GrNamedElement element, TokenConsumer consumer) { - String text = name.getText(); - TextRange range = GroovyStringLiteralManipulator.getLiteralRange(text); - consumer.consumeToken(name, text, false, 0, range, PlainTextSplitter.getInstance()); - } - }; + return EMPTY_TOKENIZER; } } if (element instanceof PsiDocComment) return myDocCommentTokenizer; + //if (element instanceof GrLiteralImpl && ((GrLiteralImpl)element).isStringLiteral()) return myStringTokenizer; return super.getTokenizer(element); } diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovySpellcheckerTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovySpellcheckerTest.groovy index 6af89920d7b7..e16eac955c3e 100644 --- a/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovySpellcheckerTest.groovy +++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/lang/GroovySpellcheckerTest.groovy @@ -45,5 +45,15 @@ class SpockTest { ''' checkTypos() } - + + public void testStringEscapes() { + myFixture.configureByText 'a.groovy', ''' +def foo = "\\ntest \\ndddd" +def foo1 = '\\ntest \\ndddd' +def bar = """\\ntest \\ndddd""" +def bar1 = \'''\\ntest \\ndddd\''' +''' + checkTypos() + } + } diff --git a/plugins/java-i18n/src/com/intellij/spellchecker/LiteralExpressionTokenizer.java b/plugins/java-i18n/src/com/intellij/spellchecker/LiteralExpressionTokenizer.java index bb603058649d..be421176d366 100644 --- a/plugins/java-i18n/src/com/intellij/spellchecker/LiteralExpressionTokenizer.java +++ b/plugins/java-i18n/src/com/intellij/spellchecker/LiteralExpressionTokenizer.java @@ -64,6 +64,6 @@ public class LiteralExpressionTokenizer extends Tokenizer int[] offsets = new int[text.length()+1]; PsiLiteralExpressionImpl.parseStringCharacters(text, unescapedText, offsets); - EscapeSequenceTokenizer.processTextWithOffsets(element, consumer, unescapedText, offsets); + EscapeSequenceTokenizer.processTextWithOffsets(element, consumer, unescapedText, offsets, 1); } } diff --git a/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/EscapeSequenceTokenizer.java b/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/EscapeSequenceTokenizer.java index 5402f0032707..b9ab65389aed 100644 --- a/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/EscapeSequenceTokenizer.java +++ b/plugins/spellchecker/src/com/intellij/spellchecker/tokenizer/EscapeSequenceTokenizer.java @@ -24,13 +24,13 @@ import com.intellij.spellchecker.inspections.PlainTextSplitter; */ public class EscapeSequenceTokenizer { public static void processTextWithOffsets(PsiElement element, TokenConsumer consumer, StringBuilder unescapedText, - int[] offsets) { + int[] offsets, int startOffset) { StringBuilder currentToken = new StringBuilder(); - int currentTokenStart = 0; + int currentTokenStart = startOffset; for (int i = 0; i < unescapedText.length(); i++) { if (offsets[i+1]-offsets[i] == 1) { if (currentToken.length() == 0) { - currentTokenStart = offsets[i]; + currentTokenStart = offsets[i] + startOffset; } currentToken.append(unescapedText.charAt(i)); } @@ -51,6 +51,6 @@ public class EscapeSequenceTokenizer { int currentTokenStart, TokenConsumer consumer) { final String token = currentToken.toString(); // +1 for the starting quote of the string literal - consumer.consumeToken(element, token, false, currentTokenStart+1, TextRange.allOf(token), PlainTextSplitter.getInstance()); + consumer.consumeToken(element, token, false, currentTokenStart, TextRange.allOf(token), PlainTextSplitter.getInstance()); } }