support for filter suffixes

This commit is contained in:
Eugene.Kudelevsky
2010-05-11 06:03:14 +04:00
parent 7482f3fc39
commit a318dff295
7 changed files with 135 additions and 22 deletions
@@ -0,0 +1,31 @@
/*
* Copyright 2000-2010 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.template.zencoding;
/**
* @author Eugene.Kudelevsky
*/
public class FilterToken extends Token {
private final String mySuffix;
public FilterToken(String suffix) {
mySuffix = suffix;
}
public String getSuffix() {
return mySuffix;
}
}
@@ -0,0 +1,43 @@
/*
* Copyright 2000-2010 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.template.zencoding;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* @author Eugene.Kudelevsky
*/
public abstract class XmlZenCodingFilter implements ZenCodingFilter {
@NotNull
public String toString(@NotNull TemplateToken token, @NotNull PsiElement context) {
if (!(token instanceof XmlTemplateToken)) {
throw new IllegalArgumentException();
}
return toString(((XmlTemplateToken)token).getTag(), context);
}
protected abstract String toString(@NotNull XmlTag tag, @NotNull PsiElement context);
@NotNull
public abstract String buildAttributesString(@NotNull List<Pair<String, String>> attribute2value, int numberInIteration);
public abstract boolean isMyContext(@NotNull PsiElement context);
}
@@ -35,7 +35,7 @@ import java.util.List;
/**
* @author Eugene.Kudelevsky
*/
public class ZenCodingFilterImpl implements ZenCodingFilter {
public class XmlZenCodingFilterImpl extends XmlZenCodingFilter {
@NotNull
public String toString(@NotNull XmlTag tag, @NotNull PsiElement context) {
FileType fileType = context.getContainingFile().getFileType();
@@ -64,6 +64,14 @@ public class ZenCodingFilterImpl implements ZenCodingFilter {
return true;
}
public String getSuffix() {
return null;
}
public boolean isDefaultFilter() {
return true;
}
private static String getAttributeString(String name, String value) {
return name + "=\"" + value + '"';
}
@@ -104,6 +104,15 @@ class XmlZenCodingInterpreter {
}
private void invoke(int startIndex) {
String filter = null;
if (myTokens.size() > 0) {
Token lastToken = myTokens.get(myTokens.size() - 1);
if (lastToken instanceof FilterToken) {
filter = ((FilterToken)lastToken).getSuffix();
}
}
final int n = myTokens.size();
TemplateToken templateToken = null;
int number = -1;
@@ -117,7 +126,7 @@ class XmlZenCodingInterpreter {
if (sign == '+' || (mySurroundedText == null && sign == ZenCodingTemplate.MARKER)) {
final Object key = new Object();
myCallback.fixStartOfTemplate(key);
invokeTemplate(templateToken, myCallback, 0);
invokeTemplate(templateToken, myCallback, 0, filter);
myState = State.WORD;
if (myCallback.getOffset() != myCallback.getEndOfTemplate(key)) {
myCallback.fixEndOffset();
@@ -128,7 +137,7 @@ class XmlZenCodingInterpreter {
templateToken = null;
}
else if (sign == '>' || (mySurroundedText != null && sign == ZenCodingTemplate.MARKER)) {
startTemplateAndGotoChild(templateToken);
startTemplateAndGotoChild(templateToken, filter);
templateToken = null;
}
else if (sign == '*') {
@@ -162,16 +171,16 @@ class XmlZenCodingInterpreter {
if (token instanceof MarkerToken || token instanceof OperationToken) {
char sign = token instanceof OperationToken ? ((OperationToken)token).getSign() : ZenCodingTemplate.MARKER;
if (sign == '+' || (mySurroundedText == null && sign == ZenCodingTemplate.MARKER)) {
invokeTemplateSeveralTimes(templateToken, 0, number);
invokeTemplateSeveralTimes(templateToken, 0, number, filter);
templateToken = null;
}
else if (number > 1) {
invokeTemplateAndProcessTail(templateToken, 0, number, i + 1);
invokeTemplateAndProcessTail(templateToken, 0, number, i + 1, filter);
return;
}
else {
assert number == 1;
startTemplateAndGotoChild(templateToken);
startTemplateAndGotoChild(templateToken, filter);
templateToken = null;
}
myState = State.WORD;
@@ -188,21 +197,22 @@ class XmlZenCodingInterpreter {
finish();
}
private void startTemplateAndGotoChild(TemplateToken templateToken) {
private void startTemplateAndGotoChild(TemplateToken templateToken, String filter) {
final Object key = new Object();
myCallback.fixStartOfTemplate(key);
invokeTemplate(templateToken, myCallback, 0);
invokeTemplate(templateToken, myCallback, 0, filter);
myState = State.WORD;
gotoChild(key);
}
private void invokeTemplateSeveralTimes(final TemplateToken templateToken,
final int startIndex,
final int count) {
final int count,
String filter) {
final Object key = new Object();
myCallback.fixStartOfTemplate(key);
for (int i = startIndex; i < count; i++) {
invokeTemplate(templateToken, myCallback, i);
invokeTemplate(templateToken, myCallback, i, filter);
myState = State.WORD;
if (myCallback.getOffset() != myCallback.getEndOfTemplate(key)) {
myCallback.fixEndOffset();
@@ -219,13 +229,14 @@ class XmlZenCodingInterpreter {
private void invokeTemplateAndProcessTail(final TemplateToken templateToken,
final int startIndex,
final int count,
final int tailStart) {
final int tailStart,
String filter) {
final Object key = new Object();
myCallback.fixStartOfTemplate(key);
for (int i = startIndex; i < count; i++) {
Object iterKey = new Object();
myCallback.fixStartOfTemplate(iterKey);
invokeTemplate(templateToken, myCallback, i);
invokeTemplate(templateToken, myCallback, i, filter);
gotoChild(iterKey);
interpret(myTokens, tailStart, myCallback, State.WORD, mySurroundedText);
if (myCallback.getOffset() != myCallback.getEndOfTemplate(key)) {
@@ -288,13 +299,14 @@ class XmlZenCodingInterpreter {
return filter.buildAttributesString(attribute2value, numberInIteration);
}
}
return new ZenCodingFilterImpl().buildAttributesString(attribute2value, numberInIteration);
return new XmlZenCodingFilterImpl().buildAttributesString(attribute2value, numberInIteration);
}
private static void invokeTemplate(TemplateToken token,
final CustomTemplateCallback callback,
int numberInIteration) {
int numberInIteration,
String filter) {
if (token instanceof XmlTemplateToken && token.getTemplate() != null) {
XmlTemplateToken xmlTemplateToken = (XmlTemplateToken)token;
List<Pair<String, String>> attr2value = new ArrayList<Pair<String, String>>(xmlTemplateToken.getAttribute2Value());
@@ -309,7 +321,7 @@ class XmlZenCodingInterpreter {
iterator.remove();
}
}
String s = filter(tag, callback);
String s = filterXml(tag, callback, filter);
assert s != null;
modifiedTemplate.setString(s);
removeVariablesWhichHasNoSegment(modifiedTemplate);
@@ -327,14 +339,16 @@ class XmlZenCodingInterpreter {
}
@Nullable
private static String filter(XmlTag tag, CustomTemplateCallback callback) {
private static String filterXml(XmlTag tag, CustomTemplateCallback callback, String filterSuffix) {
PsiElement context = callback.getContext();
for (ZenCodingFilter filter : ZenCodingFilter.EP_NAME.getExtensions()) {
if (filter.isMyContext(context)) {
return filter.toString(tag, context);
if ((filterSuffix == null && filter.isDefaultFilter()) || (filterSuffix != null && filterSuffix.equals(filter.getSuffix()))) {
if (filter instanceof XmlZenCodingFilter && filter.isDefaultFilter() && filter.isMyContext(context)) {
return ((XmlZenCodingFilter)filter).toString(tag, context);
}
}
}
return new ZenCodingFilterImpl().toString(tag, context);
return new XmlZenCodingFilterImpl().toString(tag, context);
}
private static void fail() {
@@ -282,7 +282,7 @@ public class XmlZenCodingTemplate extends ZenCodingTemplate {
return true;
}
}
return new ZenCodingFilterImpl().isMyContext(context);
return new XmlZenCodingFilterImpl().isMyContext(context);
}
public static boolean startZenCoding(Editor editor, PsiFile file, String abbreviation) {
@@ -18,8 +18,8 @@ package com.intellij.codeInsight.template.zencoding;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.psi.xml.XmlTag;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -30,10 +30,15 @@ public interface ZenCodingFilter {
ExtensionPointName<ZenCodingFilter> EP_NAME = new ExtensionPointName<ZenCodingFilter>("com.intellij.xml.zenCodingFilter");
@NotNull
String toString(@NotNull XmlTag tag, @NotNull PsiElement context);
String toString(@NotNull TemplateToken token, @NotNull PsiElement context);
@NotNull
String buildAttributesString(@NotNull List<Pair<String, String>> attribute2value, int numberInIteration);
boolean isMyContext(@NotNull PsiElement context);
@Nullable
String getSuffix();
boolean isDefaultFilter();
}
@@ -55,6 +55,14 @@ public abstract class ZenCodingTemplate implements CustomLiveTemplate {
@Nullable
private List<Token> parse(@NotNull String text, @NotNull CustomTemplateCallback callback) {
String filter = null;
int filterDelim = text.indexOf('|');
if (filterDelim >= 0 && filterDelim < text.length() - 1) {
filter = text.substring(filterDelim + 1);
text = text.substring(0, filterDelim);
}
text += MARKER;
StringBuilder templateKeyBuilder = new StringBuilder();
List<Token> result = new ArrayList<Token>();
@@ -81,6 +89,10 @@ public abstract class ZenCodingTemplate implements CustomLiveTemplate {
return null;
}
}
if (filter != null) {
result.add(new FilterToken(filter));
}
return result;
}