mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
jsx & html support: Provide proper attr value for actions
fix "insert attribute" quick fix (it must respect the default quote type) fix "=" type handler (it must use the attribute presentation for value) add tests for "insert attribute" quick fix
This commit is contained in:
@@ -35,7 +35,6 @@ import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.text.CharArrayUtil;
|
||||
import com.intellij.xml.XmlNamespaceHelper;
|
||||
import com.intellij.xml.util.HtmlUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -68,7 +67,7 @@ public class XmlAttributeInsertHandler implements InsertHandler<LookupElement> {
|
||||
final PsiFile file = context.getFile();
|
||||
|
||||
final CharSequence chars = document.getCharsSequence();
|
||||
final String quote = XmlEditUtil.getAttributeQuote(HtmlUtil.hasHtml(file) || HtmlUtil.supportsXmlTypedHandlers(file));
|
||||
final String quote = XmlEditUtil.getAttributeQuote(file);
|
||||
final boolean insertQuotes = WebEditorOptions.getInstance().isInsertQuotesForAttributeValue() && StringUtil.isNotEmpty(quote);
|
||||
final boolean hasQuotes = CharArrayUtil.regionMatches(chars, caretOffset, "=\"") ||
|
||||
CharArrayUtil.regionMatches(chars, caretOffset, "='");
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.application.options.editor.WebEditorOptions;
|
||||
import com.intellij.codeInsight.TailType;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.EmptyExpression;
|
||||
import com.intellij.codeInsight.editorActions.XmlEditUtil;
|
||||
import com.intellij.codeInsight.lookup.Lookup;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
@@ -238,7 +239,7 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
|
||||
if (!notRequiredAttributes.contains(attributeName)) {
|
||||
if (!extension.isIndirectSyntax(attributeDecl)) {
|
||||
template.addTextSegment(" " + attributeName + "=" + presenter.getPrefix());
|
||||
template.addVariable(new MacroCallNode(new CompleteMacro()), true);
|
||||
template.addVariable(presenter.showAutoPopup() ? new MacroCallNode(new CompleteMacro()) : new EmptyExpression(), true);
|
||||
template.addTextSegment(presenter.getPostfix());
|
||||
}
|
||||
else {
|
||||
|
||||
+14
-3
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInsight.daemon.impl.analysis;
|
||||
|
||||
import com.intellij.codeInsight.daemon.XmlErrorMessages;
|
||||
import com.intellij.codeInsight.editorActions.XmlEditUtil;
|
||||
import com.intellij.codeInsight.intention.HighPriorityAction;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementBuilder;
|
||||
@@ -35,6 +36,7 @@ import com.intellij.psi.xml.XmlTag;
|
||||
import com.intellij.xml.XmlAttributeDescriptor;
|
||||
import com.intellij.xml.XmlElementDescriptor;
|
||||
import com.intellij.xml.XmlExtension;
|
||||
import com.intellij.xml.XmlExtension.AttributeValuePresentation;
|
||||
import com.intellij.xml.util.HtmlUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -96,11 +98,20 @@ public class InsertRequiredAttributeFix extends LocalQuickFixAndIntentionActionO
|
||||
if (anchor == null) return;
|
||||
|
||||
final Template template = TemplateManager.getInstance(project).createTemplate("", "");
|
||||
String valuePostfix = "\"";
|
||||
if (indirectSyntax) {
|
||||
if (anchorIsEmptyTag) template.addTextSegment(">");
|
||||
template.addTextSegment("<jsp:attribute name=\"" + myAttrName + "\">");
|
||||
} else {
|
||||
template.addTextSegment(" " + myAttrName + (!insertShorthand ? "=\"" : ""));
|
||||
}
|
||||
else {
|
||||
template.addTextSegment(" " + myAttrName);
|
||||
if (!insertShorthand) {
|
||||
String quote = XmlEditUtil.getAttributeQuote(file);
|
||||
AttributeValuePresentation presentation = XmlExtension.getExtension(file).getAttributeValuePresentation(attrDescriptor, quote);
|
||||
|
||||
valuePostfix = presentation.getPostfix();
|
||||
template.addTextSegment("=" + presentation.getPrefix());
|
||||
}
|
||||
}
|
||||
|
||||
Expression expression = new Expression() {
|
||||
@@ -133,7 +144,7 @@ public class InsertRequiredAttributeFix extends LocalQuickFixAndIntentionActionO
|
||||
template.addEndVariable();
|
||||
if (anchorIsEmptyTag) template.addTextSegment("</" + myTag.getName() + ">");
|
||||
} else if (!insertShorthand) {
|
||||
template.addTextSegment("\"");
|
||||
template.addTextSegment(valuePostfix);
|
||||
}
|
||||
|
||||
final PsiElement anchor1 = anchor;
|
||||
|
||||
@@ -22,6 +22,9 @@ import com.intellij.psi.codeStyle.CodeStyleSettings;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.xml.util.HtmlUtil.hasHtml;
|
||||
import static com.intellij.xml.util.HtmlUtil.supportsXmlTypedHandlers;
|
||||
|
||||
public class XmlEditUtil {
|
||||
/**
|
||||
* Calculates quote style to use in a particular file depends on user's settings and injections
|
||||
@@ -39,4 +42,8 @@ public class XmlEditUtil {
|
||||
public static String getAttributeQuote(boolean html) {
|
||||
return html ? CodeStyleSchemes.getInstance().getCurrentScheme().getCodeStyleSettings().HTML_QUOTE_STYLE.quote : "\"";
|
||||
}
|
||||
|
||||
public static String getAttributeQuote(@NotNull PsiFile file) {
|
||||
return getAttributeQuote(hasHtml(file) || supportsXmlTypedHandlers(file));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,8 +24,11 @@ import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.xml.XmlAttribute;
|
||||
import com.intellij.xml.util.HtmlUtil;
|
||||
import com.intellij.xml.XmlAttributeDescriptor;
|
||||
import com.intellij.xml.XmlExtension;
|
||||
import com.intellij.xml.XmlExtension.AttributeValuePresentation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class XmlEqTypedHandler extends TypedHandlerDelegate {
|
||||
private boolean needToInsertQuotes = false;
|
||||
@@ -35,10 +38,9 @@ public class XmlEqTypedHandler extends TypedHandlerDelegate {
|
||||
if (c == '=' && WebEditorOptions.getInstance().isInsertQuotesForAttributeValue()) {
|
||||
if (XmlGtTypedHandler.fileContainsXmlLanguage(file)) {
|
||||
PsiDocumentManager.getInstance(project).commitDocument(editor.getDocument());
|
||||
|
||||
PsiElement at = file.findElementAt(editor.getCaretModel().getOffset() - 1);
|
||||
PsiElement atParent = at != null ? at.getParent() : null;
|
||||
if(atParent instanceof XmlAttribute && ((XmlAttribute)atParent).getValueElement() == null) {
|
||||
|
||||
PsiElement atParent = getAttributeCandidate(editor, file, false);
|
||||
if (atParent instanceof XmlAttribute && ((XmlAttribute)atParent).getValueElement() == null) {
|
||||
needToInsertQuotes = ((XmlAttribute)atParent).getValueElement() == null;
|
||||
}
|
||||
}
|
||||
@@ -47,26 +49,57 @@ public class XmlEqTypedHandler extends TypedHandlerDelegate {
|
||||
return super.beforeCharTyped(c, project, editor, file, fileType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiElement getAttributeCandidate(@NotNull Editor editor, @NotNull PsiFile file, boolean typed) {
|
||||
int newOffset = editor.getCaretModel().getOffset() - (typed ? 2 : 1);
|
||||
if (newOffset < 0) return null;
|
||||
|
||||
PsiElement at = file.findElementAt(newOffset);
|
||||
return at != null ? at.getParent() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Result charTyped(char c, Project project, @NotNull Editor editor, @NotNull PsiFile file) {
|
||||
if (needToInsertQuotes) {
|
||||
int offset = editor.getCaretModel().getOffset();
|
||||
PsiElement fileContext = file.getContext();
|
||||
String toInsert = null;
|
||||
|
||||
if(fileContext != null) {
|
||||
if (fileContext.getText().startsWith("\"")) toInsert = "''";
|
||||
if (fileContext.getText().startsWith("\'")) toInsert = "\"\"";
|
||||
}
|
||||
String toInsert = tryCompleteQuotes(fileContext);
|
||||
boolean showPopup = true;
|
||||
if (toInsert == null) {
|
||||
final String quote = XmlEditUtil.getAttributeQuote(HtmlUtil.hasHtml(file) || HtmlUtil.supportsXmlTypedHandlers(file));
|
||||
toInsert = quote + quote;
|
||||
final String quote = getDefaultQuote(file);
|
||||
AttributeValuePresentation presentation = getValuePresentation(editor, file, quote);
|
||||
toInsert = presentation.getPrefix() + presentation.getPostfix();
|
||||
showPopup = presentation.showAutoPopup();
|
||||
}
|
||||
editor.getDocument().insertString(offset, toInsert);
|
||||
editor.getCaretModel().moveToOffset(offset + toInsert.length() / 2);
|
||||
AutoPopupController.getInstance(project).scheduleAutoPopup(editor);
|
||||
if (showPopup) {
|
||||
AutoPopupController.getInstance(project).scheduleAutoPopup(editor);
|
||||
}
|
||||
needToInsertQuotes = false;
|
||||
}
|
||||
needToInsertQuotes = false;
|
||||
|
||||
return super.charTyped(c, project, editor, file);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static String tryCompleteQuotes(@Nullable PsiElement fileContext) {
|
||||
if (fileContext != null) {
|
||||
if (fileContext.getText().startsWith("\"")) return "''";
|
||||
if (fileContext.getText().startsWith("\'")) return "\"\"";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getDefaultQuote(@NotNull PsiFile file) {
|
||||
return XmlEditUtil.getAttributeQuote(file);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static AttributeValuePresentation getValuePresentation(@NotNull Editor editor, @NotNull PsiFile file, @NotNull String quote) {
|
||||
PsiElement atParent = getAttributeCandidate(editor, file, true);
|
||||
XmlAttributeDescriptor descriptor = atParent instanceof XmlAttribute ? ((XmlAttribute)atParent).getDescriptor() : null;
|
||||
return XmlExtension.getExtension(file).getAttributeValuePresentation(descriptor, quote);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +54,10 @@ public abstract class XmlExtension {
|
||||
|
||||
@NotNull
|
||||
String getPostfix();
|
||||
|
||||
default boolean showAutoPopup() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static XmlExtension calcExtension(PsiFile file) {
|
||||
@@ -168,7 +172,8 @@ public abstract class XmlExtension {
|
||||
return descriptor.isRequired();
|
||||
}
|
||||
|
||||
public AttributeValuePresentation getAttributeValuePresentation(@NotNull XmlAttributeDescriptor descriptor,
|
||||
@NotNull
|
||||
public AttributeValuePresentation getAttributeValuePresentation(@Nullable XmlAttributeDescriptor descriptor,
|
||||
@NotNull String defaultAttributeQuote) {
|
||||
return new AttributeValuePresentation() {
|
||||
@NotNull
|
||||
|
||||
@@ -612,11 +612,11 @@ public class HtmlUtil {
|
||||
return tagName != null && "br".equalsIgnoreCase(tagName);
|
||||
}
|
||||
|
||||
public static boolean hasHtml(PsiFile file) {
|
||||
public static boolean hasHtml(@NotNull PsiFile file) {
|
||||
return isHtmlFile(file) || file.getViewProvider() instanceof TemplateLanguageFileViewProvider;
|
||||
}
|
||||
|
||||
public static boolean supportsXmlTypedHandlers(PsiFile file) {
|
||||
public static boolean supportsXmlTypedHandlers(@NotNull PsiFile file) {
|
||||
Language language = file.getLanguage();
|
||||
while (language != null) {
|
||||
if ("JavaScript".equals(language.getID())) return true;
|
||||
|
||||
Reference in New Issue
Block a user