mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Emmet: performance improvements, add segments limit.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2014 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.
|
||||
@@ -17,6 +17,8 @@ package com.intellij.codeInsight.template;
|
||||
|
||||
import com.intellij.codeInsight.template.impl.TemplateImpl;
|
||||
import com.intellij.codeInsight.template.impl.Variable;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import com.intellij.util.containers.HashSet;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -29,15 +31,27 @@ import java.util.*;
|
||||
*/
|
||||
public class LiveTemplateBuilder {
|
||||
@NonNls private static final String END_PREFIX = "____END";
|
||||
private static final Logger LOGGER = Logger.getInstance(LiveTemplateBuilder.class);
|
||||
|
||||
private final StringBuilder myText = new StringBuilder();
|
||||
private final List<Variable> myVariables = new ArrayList<Variable>();
|
||||
private final Set<String> myVarNames = new HashSet<String>();
|
||||
private final List<VarOccurence> myVariableOccurences = new ArrayList<VarOccurence>();
|
||||
private final List<Marker> myMarkers = new ArrayList<Marker>();
|
||||
private final int mySegmentLimit;
|
||||
private String myLastEndVarName;
|
||||
private boolean myIsToReformat = false;
|
||||
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public LiveTemplateBuilder() {
|
||||
this(Registry.intValue("emmet.segments.limit"));
|
||||
}
|
||||
|
||||
public LiveTemplateBuilder(int segmentLimit) {
|
||||
mySegmentLimit = segmentLimit;
|
||||
}
|
||||
|
||||
public void setIsToReformat(boolean isToReformat) {
|
||||
myIsToReformat = isToReformat;
|
||||
}
|
||||
@@ -71,9 +85,10 @@ public class LiveTemplateBuilder {
|
||||
|
||||
@NotNull
|
||||
public TemplateImpl buildTemplate() {
|
||||
List<Variable> variables = getListWithLimit(myVariables);
|
||||
if (!findVarOccurence(TemplateImpl.END)) {
|
||||
if (myLastEndVarName == null) {
|
||||
for (Variable variable : myVariables) {
|
||||
for (Variable variable : variables) {
|
||||
if (isEndVariable(variable.getName())) {
|
||||
myLastEndVarName = variable.getName();
|
||||
break;
|
||||
@@ -91,7 +106,7 @@ public class LiveTemplateBuilder {
|
||||
}
|
||||
}
|
||||
if (endOffset >= 0) {
|
||||
for (Iterator<Variable> it1 = myVariables.iterator(); it1.hasNext();) {
|
||||
for (Iterator<Variable> it1 = variables.iterator(); it1.hasNext(); ) {
|
||||
Variable variable = it1.next();
|
||||
if (myLastEndVarName.equals(variable.getName()) && variable.isAlwaysStopAt()) {
|
||||
it.remove();
|
||||
@@ -103,10 +118,12 @@ public class LiveTemplateBuilder {
|
||||
}
|
||||
}
|
||||
TemplateImpl template = new TemplateImpl("", "");
|
||||
for (Variable variable : myVariables) {
|
||||
for (Variable variable : variables) {
|
||||
template.addVariable(variable.getName(), variable.getExpressionString(), variable.getDefaultValueString(), variable.isAlwaysStopAt());
|
||||
}
|
||||
Collections.sort(myVariableOccurences, new Comparator<VarOccurence>() {
|
||||
|
||||
List<VarOccurence> variableOccurrences = getListWithLimit(myVariableOccurences);
|
||||
Collections.sort(variableOccurrences, new Comparator<VarOccurence>() {
|
||||
@Override
|
||||
public int compare(VarOccurence o1, VarOccurence o2) {
|
||||
if (o1.myOffset < o2.myOffset) {
|
||||
@@ -119,7 +136,7 @@ public class LiveTemplateBuilder {
|
||||
}
|
||||
});
|
||||
int last = 0;
|
||||
for (VarOccurence occurence : myVariableOccurences) {
|
||||
for (VarOccurence occurence : variableOccurrences) {
|
||||
template.addTextSegment(myText.substring(last, occurence.myOffset));
|
||||
template.addVariableSegment(occurence.myName);
|
||||
last = occurence.myOffset;
|
||||
@@ -129,25 +146,13 @@ public class LiveTemplateBuilder {
|
||||
return template;
|
||||
}
|
||||
|
||||
/*private void addEndPlaceholders() {
|
||||
int[] endOffsets = myEndOffsets.toArray();
|
||||
Arrays.sort(endOffsets);
|
||||
for (int i = 0, n = endOffsets.length; i < n; i++) {
|
||||
int offset = endOffsets[i];
|
||||
if (offset < 0 || myText.length() == 0 || offset == myText.length() - 1 || hasVarAtOffset(offset)) {
|
||||
continue;
|
||||
}
|
||||
if (i < n - 1) {
|
||||
String varName = generateUniqueVarName(myVarNames);
|
||||
myVarNames.add(varName);
|
||||
myVariables.add(new Variable(varName, "", "", true));
|
||||
myVariableOccurences.add(new VarOccurence(varName, offset));
|
||||
}
|
||||
else {
|
||||
insertVariableSegment(offset, TemplateImpl.END);
|
||||
}
|
||||
private <T> List<T> getListWithLimit(List<T> list) {
|
||||
if (mySegmentLimit > 0 && list.size() > mySegmentLimit) {
|
||||
LOGGER.warn("Template with more than 100 segments had been build. Text: " + myText);
|
||||
return list.subList(0, Math.min(list.size(), mySegmentLimit));
|
||||
}
|
||||
}*/
|
||||
return list;
|
||||
}
|
||||
|
||||
public void insertText(int offset, String text, boolean disableEndVariable) {
|
||||
if (disableEndVariable) {
|
||||
@@ -205,18 +210,6 @@ public class LiveTemplateBuilder {
|
||||
return prefix + i;
|
||||
}
|
||||
|
||||
/*private static String preslashQuotes(String s) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
char c = s.charAt(i);
|
||||
if (c == '"') {
|
||||
builder.append('\\');
|
||||
}
|
||||
builder.append(c);
|
||||
}
|
||||
return builder.toString();
|
||||
}*/
|
||||
|
||||
public int insertTemplate(int offset, TemplateImpl template, Map<String, String> predefinedVarValues) {
|
||||
myIsToReformat = myText.length() > 0 || template.isToReformat();
|
||||
removeEndVarAtOffset(offset);
|
||||
|
||||
@@ -398,3 +398,4 @@ focus.fix.lost.cursor.description=See IDEA-79312
|
||||
ide.inertial.mouse.fix=false
|
||||
ide.inertial.mouse.fix.description=See IDEA-71508
|
||||
|
||||
emmet.segments.limit=50
|
||||
|
||||
@@ -112,7 +112,7 @@ public class EmmetPreviewTypedHandler extends TypedHandlerDelegate {
|
||||
|
||||
if (!regularTemplateWithSamePrefixExists) {
|
||||
// exclude perfect matches with existing templates because LiveTemplateCompletionContributor handles it
|
||||
ZenCodingTemplate.expand(templatePrefix, callback, null, generator, Collections.<ZenCodingFilter>emptyList(), false);
|
||||
ZenCodingTemplate.expand(templatePrefix, callback, null, generator, Collections.<ZenCodingFilter>emptyList(), false, 0);
|
||||
TemplateImpl template = generatedTemplate.get();
|
||||
String templateText = template != null ? template.getTemplateText() : null;
|
||||
if (!StringUtil.isEmpty(templateText)) {
|
||||
|
||||
@@ -48,6 +48,7 @@ import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.wm.IdeFocusManager;
|
||||
import com.intellij.patterns.StandardPatterns;
|
||||
@@ -125,7 +126,7 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
|
||||
public void expand(@NotNull String key, @NotNull CustomTemplateCallback callback) {
|
||||
ZenCodingGenerator defaultGenerator = findApplicableDefaultGenerator(callback.getContext(), false);
|
||||
assert defaultGenerator != null;
|
||||
expand(key, callback, null, defaultGenerator, Collections.<ZenCodingFilter>emptyList(), true);
|
||||
expand(key, callback, null, defaultGenerator, Collections.<ZenCodingFilter>emptyList(), true, Registry.intValue("emmet.segments.limit"));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -183,7 +184,7 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
|
||||
public static void expand(@NotNull String key, @NotNull CustomTemplateCallback callback, @Nullable String surroundedText,
|
||||
@NotNull ZenCodingGenerator defaultGenerator,
|
||||
@NotNull Collection<? extends ZenCodingFilter> extraFilters,
|
||||
boolean expandPrimitiveAbbreviations) {
|
||||
boolean expandPrimitiveAbbreviations, int segmentsLimit) {
|
||||
final ZenCodingNode node = parse(key, callback, defaultGenerator, surroundedText);
|
||||
if (node == null) {
|
||||
return;
|
||||
@@ -211,14 +212,14 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
|
||||
// commit is required. otherwise injections placed after caret will be broken
|
||||
PsiDocumentManager.getInstance(callback.getProject()).commitDocument(callback.getEditor().getDocument());
|
||||
}
|
||||
expand(node, generator, filters, surroundedText, callback, expandPrimitiveAbbreviations);
|
||||
expand(node, generator, filters, surroundedText, callback, expandPrimitiveAbbreviations, segmentsLimit);
|
||||
}
|
||||
|
||||
private static void expand(ZenCodingNode node,
|
||||
ZenCodingGenerator generator,
|
||||
List<ZenCodingFilter> filters,
|
||||
String surroundedText,
|
||||
CustomTemplateCallback callback, boolean expandPrimitiveAbbreviations) {
|
||||
CustomTemplateCallback callback, boolean expandPrimitiveAbbreviations, int segmentsLimit) {
|
||||
if (surroundedText != null) {
|
||||
surroundedText = surroundedText.trim();
|
||||
}
|
||||
@@ -233,11 +234,11 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
|
||||
}
|
||||
|
||||
List<GenerationNode> genNodes = fakeParentNode.getChildren();
|
||||
LiveTemplateBuilder builder = new LiveTemplateBuilder();
|
||||
LiveTemplateBuilder builder = new LiveTemplateBuilder(segmentsLimit);
|
||||
int end = -1;
|
||||
for (int i = 0, genNodesSize = genNodes.size(); i < genNodesSize; i++) {
|
||||
GenerationNode genNode = genNodes.get(i);
|
||||
TemplateImpl template = genNode.generate(callback, generator, filters, true);
|
||||
TemplateImpl template = genNode.generate(callback, generator, filters, true, segmentsLimit);
|
||||
int e = builder.insertTemplate(builder.length(), template, null);
|
||||
if (i < genNodesSize - 1 && genNode.isInsertNewLineBetweenNodes()) {
|
||||
builder.insertText(e, "\n", false);
|
||||
@@ -435,7 +436,7 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
|
||||
EditorModificationUtil.deleteSelectedText(callback.getEditor());
|
||||
PsiDocumentManager.getInstance(callback.getProject()).commitAllDocuments();
|
||||
|
||||
expand(node, generator, filters, selection, callback, true);
|
||||
expand(node, generator, filters, selection, callback, true, Registry.intValue("emmet.segments.limit"));
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -504,7 +505,7 @@ public class ZenCodingTemplate extends CustomLiveTemplateBase {
|
||||
if (!regularTemplateWithSamePrefixExists) {
|
||||
// exclude perfect matches with existing templates because LiveTemplateCompletionContributor handles it
|
||||
final Collection<SingleLineEmmetFilter> extraFilters = ContainerUtil.newLinkedList(new SingleLineEmmetFilter());
|
||||
expand(templatePrefix, callback, null, generator, extraFilters, false);
|
||||
expand(templatePrefix, callback, null, generator, extraFilters, false, 0);
|
||||
if (!generatedTemplate.isNull()) {
|
||||
final TemplateImpl template = generatedTemplate.get();
|
||||
template.setKey(templatePrefix);
|
||||
|
||||
@@ -134,14 +134,14 @@ public class GenerationNode extends UserDataHolderBase {
|
||||
|
||||
@NotNull
|
||||
public TemplateImpl generate(@NotNull CustomTemplateCallback callback,
|
||||
@Nullable ZenCodingGenerator generator,
|
||||
@NotNull Collection<ZenCodingFilter> filters,
|
||||
boolean insertSurroundedText) {
|
||||
@Nullable ZenCodingGenerator generator,
|
||||
@NotNull Collection<ZenCodingFilter> filters,
|
||||
boolean insertSurroundedText, int segmentsLimit) {
|
||||
myContainsSurroundedTextMarker = !(insertSurroundedText && myInsertSurroundedTextAtTheEnd);
|
||||
|
||||
GenerationNode generationNode = this;
|
||||
if (generationNode != this) {
|
||||
return generationNode.generate(callback, generator, Collections.<ZenCodingFilter>emptyList(), insertSurroundedText);
|
||||
return generationNode.generate(callback, generator, Collections.<ZenCodingFilter>emptyList(), insertSurroundedText, segmentsLimit);
|
||||
}
|
||||
|
||||
boolean shouldNotReformatTemplate = false;
|
||||
@@ -179,7 +179,7 @@ public class GenerationNode extends UserDataHolderBase {
|
||||
indentStr = StringUtil.repeatSymbol(' ', tabSize);
|
||||
}
|
||||
|
||||
LiveTemplateBuilder builder = new LiveTemplateBuilder();
|
||||
LiveTemplateBuilder builder = new LiveTemplateBuilder(segmentsLimit);
|
||||
int end = -1;
|
||||
boolean hasChildren = myChildren.size() > 0;
|
||||
|
||||
@@ -204,7 +204,7 @@ public class GenerationNode extends UserDataHolderBase {
|
||||
parentTemplate.setString(s);
|
||||
|
||||
final String txt = hasChildren || myContainsSurroundedTextMarker ? null : mySurroundedText;
|
||||
parentTemplate = expandTemplate(parentTemplate, predefinedValues, txt);
|
||||
parentTemplate = expandTemplate(parentTemplate, predefinedValues, txt, segmentsLimit);
|
||||
|
||||
int offset = builder.insertTemplate(0, parentTemplate, null);
|
||||
int newOffset = gotoChild(callback.getProject(), builder.getText(), offset, 0, builder.length());
|
||||
@@ -220,7 +220,7 @@ public class GenerationNode extends UserDataHolderBase {
|
||||
//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);
|
||||
TemplateImpl childTemplate = child.generate(callback, generator, filters, !myContainsSurroundedTextMarker, segmentsLimit);
|
||||
|
||||
boolean blockTag = child.isBlockTag();
|
||||
|
||||
@@ -305,8 +305,9 @@ public class GenerationNode extends UserDataHolderBase {
|
||||
@NotNull
|
||||
private static TemplateImpl expandTemplate(@NotNull TemplateImpl template,
|
||||
Map<String, String> predefinedVarValues,
|
||||
String surroundedText) {
|
||||
LiveTemplateBuilder builder = new LiveTemplateBuilder();
|
||||
String surroundedText,
|
||||
int segmentsLimit) {
|
||||
LiveTemplateBuilder builder = new LiveTemplateBuilder(segmentsLimit);
|
||||
if (predefinedVarValues == null && surroundedText == null) {
|
||||
return template;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user