From 581e22430a0f9d8a000e4b7956dc30ab9197c931 Mon Sep 17 00:00:00 2001 From: sebthom Date: Tue, 7 Nov 2023 04:59:22 +0100 Subject: [PATCH] fix: disable broken handling of surrounding quotes pairs --- ...uageConfigurationCharacterPairMatcher.java | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationCharacterPairMatcher.java b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationCharacterPairMatcher.java index 25cb639ab..d69052ff0 100644 --- a/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationCharacterPairMatcher.java +++ b/org.eclipse.tm4e.languageconfiguration/src/main/java/org/eclipse/tm4e/languageconfiguration/internal/LanguageConfigurationCharacterPairMatcher.java @@ -11,6 +11,8 @@ */ package org.eclipse.tm4e.languageconfiguration.internal; +import java.util.Objects; + import org.eclipse.core.runtime.content.IContentType; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.jface.text.IDocument; @@ -18,6 +20,7 @@ import org.eclipse.jface.text.source.DefaultCharacterPairMatcher; import org.eclipse.jface.text.source.ICharacterPairMatcher; import org.eclipse.jface.text.source.ICharacterPairMatcherExtension; +import org.eclipse.tm4e.languageconfiguration.internal.model.AutoClosingPair; import org.eclipse.tm4e.languageconfiguration.internal.registry.LanguageConfigurationRegistryManager; import org.eclipse.tm4e.ui.internal.utils.ContentTypeHelper; import org.eclipse.tm4e.ui.internal.utils.ContentTypeInfo; @@ -28,6 +31,8 @@ public class LanguageConfigurationCharacterPairMatcher implements ICharacterPairMatcher, ICharacterPairMatcherExtension { + private static DefaultCharacterPairMatcher NOOP_MATCHER = new DefaultCharacterPairMatcher(new char[0]); + @Nullable private DefaultCharacterPairMatcher matcher; @@ -111,25 +116,37 @@ private DefaultCharacterPairMatcher getMatcher(final IDocument document) { this.document = document; // initialize a DefaultCharacterPairMatcher by using character pairs of the language configuration. - final var sb = new StringBuilder(); final ContentTypeInfo info = ContentTypeHelper.findContentTypes(document); final IContentType[] contentTypes = info == null ? null : info.getContentTypes(); - if (contentTypes != null) { + + if (contentTypes == null || contentTypes.length == 0) { + this.matcher = matcher = NOOP_MATCHER; + } else { + final var surroundingBracketsChars = new StringBuilder(); + final var surroundingQuotesChars = new StringBuilder(); final var registry = LanguageConfigurationRegistryManager.getInstance(); for (final IContentType contentType : contentTypes) { - if (!registry.shouldSurroundingPairs(contentType)) { - continue; - } - final var surroundingPairs = registry.getSurroundingPairs(contentType); - for (final var surroundingPair : surroundingPairs) { - sb.append(surroundingPair.open); - sb.append(surroundingPair.close); + if (registry.shouldSurroundingPairs(contentType)) { + for (final AutoClosingPair surroundingPair : registry.getSurroundingPairs(contentType)) { + if (Objects.equals(surroundingPair.open, surroundingPair.close)) { + surroundingQuotesChars.append(surroundingPair.open); + } else { + surroundingBracketsChars.append(surroundingPair.open); + surroundingBracketsChars.append(surroundingPair.close); + } + } } } + if (surroundingBracketsChars.isEmpty() && surroundingQuotesChars.isEmpty()) { + this.matcher = matcher = NOOP_MATCHER; + } else { + final var bracketsChars = new char[surroundingBracketsChars.length()]; + surroundingBracketsChars.getChars(0, surroundingBracketsChars.length(), bracketsChars, 0); + // TODO handle surroundingQuotesChars, DefaultCharacterPairMatcher cannot handle pairs correctly when open and close chars + // are identically, see https://github.com/eclipse/tm4e/issues/470 + this.matcher = matcher = new DefaultCharacterPairMatcher(bracketsChars); + } } - final var chars = new char[sb.length()]; - sb.getChars(0, sb.length(), chars, 0); - this.matcher = matcher = new DefaultCharacterPairMatcher(chars); } return matcher; }