WEB-8334 Wrong caret position using Emmet inside JS string

This commit is contained in:
Alexander Zolotov
2013-08-06 15:20:38 +04:00
parent ce19f38661
commit 8744e8b2d3
2 changed files with 46 additions and 22 deletions
@@ -16,8 +16,10 @@
package com.intellij.codeInsight.template.emmet.filters;
import com.intellij.codeInsight.template.emmet.nodes.GenerationNode;
import com.intellij.codeInsight.template.emmet.tokens.TemplateToken;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
@@ -32,6 +34,12 @@ public class SingleLineEmmetFilter extends ZenCodingFilter {
return "s";
}
@NotNull
@Override
public String filterText(@NotNull String text, @NotNull TemplateToken token) {
return StringUtil.replace(text, "\n", "");
}
@NotNull
@Override
public GenerationNode filterNode(@NotNull GenerationNode node) {
@@ -26,8 +26,11 @@ import com.intellij.codeInsight.template.emmet.generators.XmlZenCodingGeneratorI
import com.intellij.codeInsight.template.emmet.generators.ZenCodingGenerator;
import com.intellij.codeInsight.template.emmet.tokens.TemplateToken;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.injected.editor.DocumentWindowImpl;
import com.intellij.lang.xml.XMLLanguage;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
@@ -135,23 +138,48 @@ public class GenerationNode extends UserDataHolderBase {
boolean insertSurroundedText) {
myContainsSurroundedTextMarker = !(insertSurroundedText && myInsertSurroundedTextAtTheEnd);
boolean singleLineFilterEnabled = false;
GenerationNode generationNode = this;
if (generationNode != this) {
return generationNode.generate(callback, generator, Collections.<ZenCodingFilter>emptyList(), insertSurroundedText);
}
boolean shouldNotReformatTemplate = false;
boolean oneLineTemplateExpanding = false;
for (ZenCodingFilter filter : filters) {
generationNode = filter.filterNode(generationNode);
if(filter instanceof SingleLineEmmetFilter) {
singleLineFilterEnabled = true;
shouldNotReformatTemplate = true;
oneLineTemplateExpanding = true;
}
}
if (generationNode != this) {
return generationNode.generate(callback, generator, Collections.<ZenCodingFilter>emptyList(), insertSurroundedText);
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(callback.getProject());
String indentStr;
if (callback.isInInjectedFragment()) {
Editor editor = callback.getEditor();
Document document = editor.getDocument();
if(document instanceof DocumentWindowImpl && ((DocumentWindowImpl)document).isOneLine()) {
/*
* If document is one-line that in the moment of inserting text,
* new line chars will be filtered (see DocumentWindowImpl#insertString).
* So in this case we should filter text by SingleLineAvoid in order to avoid
* inconsistency of template segments.
*/
oneLineTemplateExpanding = true;
filters.add(new SingleLineEmmetFilter());
}
indentStr = "";
}
else if (settings.useTabCharacter(callback.getFileType())) {
indentStr = "\t";
}
else {
int tabSize = settings.getTabSize(callback.getFileType());
indentStr = StringUtil.repeatSymbol(' ', tabSize);
}
LiveTemplateBuilder builder = new LiveTemplateBuilder();
int end = -1;
boolean hasChildren = myChildren.size() > 0;
TemplateImpl parentTemplate;
@@ -188,26 +216,14 @@ public class GenerationNode extends UserDataHolderBase {
}
LiveTemplateBuilder.Marker marker = offset < builder.length() ? builder.createMarker(offset) : null;
CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(callback.getProject());
String indentStr;
if (callback.isInInjectedFragment()) {
indentStr = "";
}
else if (settings.useTabCharacter(callback.getFileType())) {
indentStr = "\t";
}
else {
int tabSize = settings.getTabSize(callback.getFileType());
indentStr = StringUtil.repeatSymbol(' ', tabSize);
}
//noinspection ForLoopReplaceableByForEach
for (int i = 0, myChildrenSize = myChildren.size(); i < myChildrenSize; i++) {
GenerationNode child = myChildren.get(i);
TemplateImpl childTemplate = child.generate(callback, generator, filters, !myContainsSurroundedTextMarker);
boolean blockTag = child.isBlockTag();
if (!singleLineFilterEnabled && blockTag && !isNewLineBefore(builder.getText(), offset)) {
if (!oneLineTemplateExpanding && blockTag && !isNewLineBefore(builder.getText(), offset)) {
builder.insertText(offset, "\n" + indentStr, false);
offset += indentStr.length() + 1;
}
@@ -215,7 +231,7 @@ public class GenerationNode extends UserDataHolderBase {
int e = builder.insertTemplate(offset, childTemplate, null);
offset = marker != null ? marker.getEndOffset() : builder.length();
if (!singleLineFilterEnabled && ((blockTag && !isNewLineAfter(builder.getText(), offset)) || myInsertNewLineBetweenNodes)) {
if (!oneLineTemplateExpanding && ((blockTag && !isNewLineAfter(builder.getText(), offset)) || myInsertNewLineBetweenNodes)) {
builder.insertText(offset, "\n" + indentStr, false);
offset += indentStr.length() + 1;
}
@@ -224,7 +240,7 @@ public class GenerationNode extends UserDataHolderBase {
end = e;
}
}
if(singleLineFilterEnabled) {
if(shouldNotReformatTemplate) {
builder.setIsToReformat(false);
}
return builder.buildTemplate();