diff --git a/RegExpSupport/src/org/intellij/lang/regexp/inspection/RegExpReplacementUtil.java b/RegExpSupport/src/org/intellij/lang/regexp/inspection/RegExpReplacementUtil.java index 02ba1d5f439e..191374050de6 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/inspection/RegExpReplacementUtil.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/inspection/RegExpReplacementUtil.java @@ -15,7 +15,10 @@ */ package org.intellij.lang.regexp.inspection; +import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.ElementManipulator; +import com.intellij.psi.ElementManipulators; import com.intellij.psi.PsiElement; import com.intellij.psi.xml.XmlElement; import com.intellij.xml.util.XmlStringUtil; @@ -31,7 +34,17 @@ public class RegExpReplacementUtil { public static String escapeForContext(String text, RegExpElement element) { final PsiElement context = element.getContainingFile().getContext(); - if (RegExpElementImpl.isLiteralExpression(context)) { + ElementManipulator manipulator = context == null ? null : ElementManipulators.getManipulator(context); + if (manipulator != null) { + // use element manipulator to process escape sequences correctly for all supported languages + PsiElement copy = context.copy(); // create a copy to avoid original element modifications + PsiElement newElement = manipulator.handleContentChange(copy, text); + String newElementText = newElement.getText(); + TextRange newRange = manipulator.getRangeInElement(newElement); + return newElementText.substring(newRange.getStartOffset(), newRange.getEndOffset()); + } + else if (RegExpElementImpl.isLiteralExpression(context)) { + // otherwise, just pretend it is a Java-style string return StringUtil.escapeStringCharacters(text); } else if (context instanceof XmlElement) { diff --git a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java index f0befa3c0287..31da24f15bf8 100644 --- a/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java +++ b/RegExpSupport/src/org/intellij/lang/regexp/psi/impl/RegExpElementImpl.java @@ -23,6 +23,7 @@ import com.intellij.lang.ParserDefinition; import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.impl.source.tree.CompositeElement; import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil; import com.intellij.psi.tree.IElementType; import com.intellij.util.IncorrectOperationException; @@ -85,10 +86,15 @@ public abstract class RegExpElementImpl extends ASTWrapperPsiElement implements public static boolean isLiteralExpression(@Nullable PsiElement context) { if (context == null) return false; - final ASTNode astNode = context.getNode(); + ASTNode astNode = context.getNode(); if (astNode == null) { return false; } + if (astNode instanceof CompositeElement) { // in some languages token nodes are wrapped within a single-child composite + ASTNode[] children = astNode.getChildren(null); + if (children.length != 1) return false; + astNode = children[0]; + } final IElementType elementType = astNode.getElementType(); final ParserDefinition parserDefinition = LanguageParserDefinitions.INSTANCE.forLanguage(context.getLanguage()); return parserDefinition.getStringLiteralElements().contains(elementType);