[html] WEB-70082 Additional fix for XmlTagInsertHandler

(cherry picked from commit 91f1abe007d55340b1e6c233fe50b139c213d480)

IJ-CR-157802

GitOrigin-RevId: 9bc901bb647318f54951cfdce7af4e807933df37
This commit is contained in:
Piotr Tomiak
2025-03-14 16:39:50 +01:00
committed by intellij-monorepo-bot
parent 6b04c400ee
commit dda02655d5
2 changed files with 30 additions and 33 deletions

View File

@@ -29,6 +29,7 @@ import com.intellij.openapi.editor.RangeMarker;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.progress.util.ProgressIndicatorUtils;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.profile.codeInspection.InspectionProjectProfileManager;
@@ -212,14 +213,7 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
}
}
XmlAttributeDescriptor[] attributes;
if (ApplicationManager.getApplication().isHeadlessEnvironment() || ApplicationManager.getApplication().isUnitTestMode()) {
attributes = descriptor.getAttributesDescriptors(tag);
}
else {
// Try not to block EDT for a long time
attributes = ProgressIndicatorUtils.withTimeout(500, () -> descriptor.getAttributesDescriptors(tag));
}
XmlAttributeDescriptor[] attributes = getAttributesDescriptors(descriptor, tag);
if (attributes == null || attributes.length == 0) {
return null;
@@ -289,14 +283,14 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
}
else if (completionChar == ' ' && template.getSegmentsCount() == 0) {
if (WebEditorOptions.getInstance().isAutomaticallyStartAttribute() &&
(descriptor.getAttributesDescriptors(tag).length > 0 || isTagFromHtml(tag) && !HtmlUtil.isTagWithoutAttributes(tag.getName()))) {
(getAttributesDescriptors(descriptor, tag).length > 0 || isTagFromHtml(tag) && !HtmlUtil.isTagWithoutAttributes(tag.getName()))) {
completeAttribute(tag.getContainingFile(), template);
return true;
}
}
else if (completionChar == Lookup.AUTO_INSERT_SELECT_CHAR || completionChar == Lookup.NORMAL_SELECT_CHAR || completionChar == Lookup.REPLACE_SELECT_CHAR) {
if (WebEditorOptions.getInstance().isAutomaticallyInsertClosingTag() && isHtmlCode && HtmlUtil.isSingleHtmlTag(tag, true)) {
if (hasOwnAttributes(descriptor, tag)) {
if (runWithTimeoutOrNull(() -> hasOwnAttributes(descriptor, tag)) == Boolean.TRUE) {
template.addEndVariable();
}
template.addTextSegment(HtmlUtil.isHtmlTag(tag) ? ">" : closeTag(tag));
@@ -410,12 +404,12 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
}
private static boolean hasOwnAttributes(XmlElementDescriptor descriptor, XmlTag tag) {
return ContainerUtil.find(descriptor.getAttributesDescriptors(tag),
return ContainerUtil.find(getAttributesDescriptors(descriptor, tag),
attr -> attr instanceof HtmlAttributeDescriptorImpl && HtmlUtil.isOwnHtmlAttribute(attr)) != null;
}
private static boolean canHaveAttributes(XmlElementDescriptor descriptor, XmlTag context) {
XmlAttributeDescriptor[] attributes = descriptor.getAttributesDescriptors(context);
XmlAttributeDescriptor[] attributes = getAttributesDescriptors(descriptor, context);
int required = WebEditorOptions.getInstance().isAutomaticallyInsertRequiredAttributes() ?
ArraysKt.count(attributes, (attribute) -> attribute.isRequired() && context.getAttribute(attribute.getName()) == null) :
0;
@@ -430,4 +424,17 @@ public class XmlTagInsertHandler implements InsertHandler<LookupElement> {
final String ns = tag.getNamespace();
return XmlUtil.XHTML_URI.equals(ns) || XmlUtil.HTML_URI.equals(ns);
}
private static XmlAttributeDescriptor[] getAttributesDescriptors(XmlElementDescriptor descriptor, XmlTag tag) {
var result = runWithTimeoutOrNull(() -> descriptor.getAttributesDescriptors( tag));
return result != null ? result : XmlAttributeDescriptor.EMPTY;
}
public static <T> @Nullable T runWithTimeoutOrNull(Computable<@NotNull T> block) {
if (ApplicationManager.getApplication().isHeadlessEnvironment() || ApplicationManager.getApplication().isUnitTestMode())
return block.get();
else
return ProgressIndicatorUtils.withTimeout(250, block);
}
}

View File

@@ -4,12 +4,10 @@ package com.intellij.html.webSymbols.attributes
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.completion.XmlAttributeInsertHandler
import com.intellij.codeInsight.completion.XmlTagInsertHandler
import com.intellij.html.webSymbols.HtmlDescriptorUtils.getStandardHtmlAttributeDescriptors
import com.intellij.html.webSymbols.WebSymbolsFrameworkHtmlSupport
import com.intellij.html.webSymbols.WebSymbolsHtmlQueryConfigurator
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.progress.runBlockingMaybeCancellable
import com.intellij.openapi.progress.util.ProgressIndicatorUtils
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import com.intellij.psi.xml.XmlAttribute
@@ -21,20 +19,20 @@ import com.intellij.webSymbols.completion.WebSymbolsCompletionProviderBase
import com.intellij.webSymbols.query.WebSymbolsQueryExecutor
import com.intellij.webSymbols.query.WebSymbolsQueryExecutorFactory
import com.intellij.webSymbols.utils.asSingleSymbol
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeoutOrNull
class WebSymbolAttributeNameCompletionProvider : WebSymbolsCompletionProviderBase<XmlAttribute>() {
override fun getContext(position: PsiElement): XmlAttribute? =
PsiTreeUtil.getParentOfType(position, XmlAttribute::class.java)
override fun addCompletions(parameters: CompletionParameters,
result: CompletionResultSet,
position: Int,
name: String,
queryExecutor: WebSymbolsQueryExecutor,
context: XmlAttribute) {
override fun addCompletions(
parameters: CompletionParameters,
result: CompletionResultSet,
position: Int,
name: String,
queryExecutor: WebSymbolsQueryExecutor,
context: XmlAttribute,
) {
val tag = context.parent ?: return
val patchedResultSet = result.withPrefixMatcher(
AsteriskAwarePrefixMatcher(result.prefixMatcher.cloneWithPrefix(name)))
@@ -78,8 +76,8 @@ class WebSymbolAttributeNameCompletionProvider : WebSymbolsCompletionProviderBas
val fullName = name.substring(0, item.offset) + item.name
val match = freshRegistry.runNameMatchQuery(NAMESPACE_HTML, KIND_HTML_ATTRIBUTES, fullName)
.asSingleSymbol() ?: return@withInsertHandlerAdded
val info = runWithTimeoutOrNull {
WebSymbolHtmlAttributeInfo.create(fullName, freshRegistry, match, insertionContext.file)
val info = XmlTagInsertHandler.runWithTimeoutOrNull {
WebSymbolHtmlAttributeInfo.create(fullName, freshRegistry, match, insertionContext.file)
}
if (info != null && info.acceptsValue && !info.acceptsNoValue) {
XmlAttributeInsertHandler.INSTANCE.handleInsert(insertionContext, lookupItem)
@@ -102,12 +100,4 @@ class WebSymbolAttributeNameCompletionProvider : WebSymbolsCompletionProviderBas
}
}
@Suppress("UsagesOfObsoleteApi")
private fun <T> runWithTimeoutOrNull(block: () -> T): T? =
if (ApplicationManager.getApplication().isHeadlessEnvironment() || ApplicationManager.getApplication().isUnitTestMode())
block()
else
ProgressIndicatorUtils.withTimeout(250, block)
}