mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[astro] WEB-76003 Improve attribute insert handling for Astro
Space-RevId: 89d349e837e10f77861ac1b0fd3534dfab7474cb GitOrigin-RevId: e61ff48a5fc55575dd3acdeda14ccbfc2e852374
This commit is contained in:
committed by
intellij-monorepo-bot
parent
38c3ee874d
commit
6201848e37
@@ -0,0 +1,81 @@
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion
|
||||
|
||||
import com.intellij.application.options.editor.WebEditorOptions
|
||||
import com.intellij.codeInsight.AutoPopupController
|
||||
import com.intellij.codeInsight.editorActions.TabOutScopesTracker
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.openapi.editor.ScrollType
|
||||
import com.intellij.util.text.CharArrayUtil
|
||||
|
||||
class XmlAttributeValueQuotationHandler(private val myStyle: AttributeValueQuotationStyle) : InsertHandler<LookupElement> {
|
||||
|
||||
enum class AttributeValueQuotationStyle { QUOTES, BRACES, EQUAL_ONLY }
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
val QUOTES: XmlAttributeValueQuotationHandler = XmlAttributeValueQuotationHandler(AttributeValueQuotationStyle.QUOTES)
|
||||
@JvmField
|
||||
val BRACES: XmlAttributeValueQuotationHandler = XmlAttributeValueQuotationHandler(AttributeValueQuotationStyle.BRACES)
|
||||
@JvmField
|
||||
val EQUAL_ONLY: XmlAttributeValueQuotationHandler = XmlAttributeValueQuotationHandler(AttributeValueQuotationStyle.EQUAL_ONLY)
|
||||
}
|
||||
|
||||
override fun handleInsert(context: InsertionContext, item: LookupElement) {
|
||||
val editor = context.editor
|
||||
val document = editor.document
|
||||
val caretOffset = editor.caretModel.offset
|
||||
|
||||
val chars = document.charsSequence
|
||||
val hasQuotes = CharArrayUtil.regionMatches(chars, caretOffset, "=\"") ||
|
||||
CharArrayUtil.regionMatches(chars, caretOffset, "='")
|
||||
val hasBraces = CharArrayUtil.regionMatches(chars, caretOffset, "={")
|
||||
val hasValue = hasQuotes || hasBraces
|
||||
|
||||
if (!hasValue && CharArrayUtil.regionMatches(chars, caretOffset, "=")) {
|
||||
document.deleteString(caretOffset, caretOffset + 1)
|
||||
}
|
||||
|
||||
var effective = myStyle
|
||||
val insertQuotes = WebEditorOptions.getInstance().isInsertQuotesForAttributeValue
|
||||
if (!insertQuotes && effective == AttributeValueQuotationStyle.QUOTES) {
|
||||
effective = AttributeValueQuotationStyle.EQUAL_ONLY
|
||||
}
|
||||
|
||||
if (!hasValue) {
|
||||
val toInsert = when (effective) {
|
||||
AttributeValueQuotationStyle.BRACES -> "={}"
|
||||
AttributeValueQuotationStyle.QUOTES -> "=\"\""
|
||||
AttributeValueQuotationStyle.EQUAL_ONLY -> "="
|
||||
}
|
||||
|
||||
if (caretOffset < document.textLength && "/> \n\t\r".indexOf(chars[caretOffset]) < 0) {
|
||||
document.insertString(caretOffset, "$toInsert ")
|
||||
}
|
||||
else {
|
||||
document.insertString(caretOffset, toInsert)
|
||||
}
|
||||
|
||||
if ('=' == context.completionChar) {
|
||||
context.setAddCompletionChar(false)
|
||||
}
|
||||
}
|
||||
|
||||
val move = when (effective) {
|
||||
AttributeValueQuotationStyle.BRACES, AttributeValueQuotationStyle.QUOTES -> 2
|
||||
AttributeValueQuotationStyle.EQUAL_ONLY -> 1
|
||||
}
|
||||
editor.caretModel.moveToOffset(caretOffset + move)
|
||||
if (effective != AttributeValueQuotationStyle.EQUAL_ONLY || hasValue) {
|
||||
TabOutScopesTracker.getInstance().registerEmptyScopeAtCaret(editor)
|
||||
}
|
||||
editor.scrollingModel.scrollToCaret(ScrollType.RELATIVE)
|
||||
editor.selectionModel.removeSelection()
|
||||
|
||||
if (effective == AttributeValueQuotationStyle.BRACES) {
|
||||
AutoPopupController.getInstance(context.project).autoPopupParameterInfo(editor, null)
|
||||
} else {
|
||||
AutoPopupController.getInstance(context.project).scheduleAutoPopup(editor)
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-3
@@ -20,7 +20,11 @@ import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.psi.xml.XmlAttribute
|
||||
|
||||
class HtmlAttributeSymbolsCompletionProvider : PolySymbolsCompletionProviderBase<XmlAttribute>() {
|
||||
import com.intellij.codeInsight.completion.InsertHandler
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
|
||||
|
||||
open class HtmlAttributeSymbolsCompletionProvider : PolySymbolsCompletionProviderBase<XmlAttribute>() {
|
||||
|
||||
override fun getContext(position: PsiElement): XmlAttribute? =
|
||||
PsiTreeUtil.getParentOfType(position, XmlAttribute::class.java)
|
||||
@@ -81,8 +85,9 @@ class HtmlAttributeSymbolsCompletionProvider : PolySymbolsCompletionProviderBase
|
||||
.asSingleSymbol() ?: return@runWithTimeoutOrNull null
|
||||
HtmlAttributeSymbolInfo.create(fullName, freshRegistry, match, insertionContext.file)
|
||||
}
|
||||
if (info != null && info.acceptsValue && !info.acceptsNoValue) {
|
||||
XmlAttributeInsertHandler.INSTANCE.handleInsert(insertionContext, lookupItem)
|
||||
if (info != null && shouldInsertValue(parameters, item, info)) {
|
||||
val handler = selectInsertHandler(parameters, item, info)
|
||||
handler.handleInsert(insertionContext, lookupItem)
|
||||
}
|
||||
}
|
||||
).addToResult(parameters, patchedResultSet)
|
||||
@@ -102,4 +107,22 @@ class HtmlAttributeSymbolsCompletionProvider : PolySymbolsCompletionProviderBase
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected open fun selectInsertHandler(
|
||||
parameters: CompletionParameters,
|
||||
item: PolySymbolCodeCompletionItem,
|
||||
info: HtmlAttributeSymbolInfo
|
||||
): InsertHandler<LookupElement> {
|
||||
val framework = HtmlFrameworkSymbolsSupport.get(info.symbol)
|
||||
return framework.createAttributeInsertHandler(parameters, item, info) ?: XmlAttributeInsertHandler.INSTANCE
|
||||
}
|
||||
|
||||
protected open fun shouldInsertValue(
|
||||
parameters: CompletionParameters,
|
||||
item: PolySymbolCodeCompletionItem,
|
||||
info: HtmlAttributeSymbolInfo
|
||||
): Boolean {
|
||||
val framework = HtmlFrameworkSymbolsSupport.get(info.symbol)
|
||||
return framework.shouldInsertAttributeValue(parameters, item, info)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,12 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.polySymbols.html
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionParameters
|
||||
import com.intellij.codeInsight.completion.InsertHandler
|
||||
import com.intellij.codeInsight.lookup.LookupElement
|
||||
import com.intellij.polySymbols.PolySymbol
|
||||
import com.intellij.polySymbols.PolySymbolProperty
|
||||
import com.intellij.polySymbols.completion.PolySymbolCodeCompletionItem
|
||||
import com.intellij.polySymbols.framework.FrameworkId
|
||||
import com.intellij.polySymbols.framework.PolySymbolFramework
|
||||
import com.intellij.polySymbols.html.attributes.HtmlAttributeSymbolDescriptor
|
||||
@@ -22,6 +26,28 @@ interface HtmlFrameworkSymbolsSupport {
|
||||
|
||||
fun getAttributeNameCodeCompletionFilter(tag: XmlTag): Predicate<String> = Predicate { true }
|
||||
|
||||
/**
|
||||
* Creates an insert handler for the given attribute completion item.
|
||||
* Override this method to provide framework-specific insert handlers (e.g., braces for JSX-like syntax).
|
||||
*
|
||||
* Default implementation returns null, which will use the standard XML attribute insert handler.
|
||||
*/
|
||||
fun createAttributeInsertHandler(
|
||||
parameters: CompletionParameters,
|
||||
item: PolySymbolCodeCompletionItem,
|
||||
info: HtmlAttributeSymbolInfo
|
||||
): InsertHandler<LookupElement>? = null
|
||||
|
||||
/**
|
||||
* Determines whether to insert a value (quotes/braces) after the attribute name.
|
||||
* Override this method to customize when values should be inserted (e.g., always insert for directives).
|
||||
*/
|
||||
fun shouldInsertAttributeValue(
|
||||
parameters: CompletionParameters,
|
||||
item: PolySymbolCodeCompletionItem,
|
||||
info: HtmlAttributeSymbolInfo
|
||||
): Boolean = info.acceptsValue && !info.acceptsNoValue
|
||||
|
||||
companion object {
|
||||
/**
|
||||
* Provides id of the Symbol's framework, e.g. vue, angular, react, etc.
|
||||
|
||||
Reference in New Issue
Block a user