[K/N] Set mayContainSupplCodepoints flag only when alt is updated
Motivation: Calling AbstractCharClass.setNegative always leads to mayContainSupplCodepoints being `true`, even when `alt` is already equal to the argument. Given that CharClass always calls setNegative with its constructor parameter - `negative`, mayContainSupplCodepoints always gets set. i.e. `[a]` will have mayContainSupplCodepoints set. mayContainSupplCodepoints affects what node (RangeSet or SupplementaryRangeSet) wraps this char class. See Pattern.processRangeSet. RangeSet is better optimized and avoids recursion when it is quantified. Modification: Set `mayContainSupplCodepoints` flag only when `alt` is updated. When `alt` is updated, this char class gets inverted, hence now may contain supplementary code points. Otherwise, content of this char class does not change, i.e. no new supplementary code points is added. Result: Fixes KT-46211.
This commit is contained in:
committed by
Space Team
parent
d7f166eda3
commit
6e50bbee3b
@@ -58,9 +58,12 @@ internal abstract class AbstractCharClass : SpecialToken() {
|
||||
internal var alt: Boolean = false
|
||||
internal var altSurrogates: Boolean = false
|
||||
|
||||
/**
|
||||
* For each unpaired surrogate char indicates whether it is contained in this char class.
|
||||
*/
|
||||
internal val lowHighSurrogates = BitSet(SURROGATE_CARDINALITY) // Bit set for surrogates?
|
||||
|
||||
/*
|
||||
/**
|
||||
* Indicates if this class may contain supplementary Unicode codepoints.
|
||||
* If this flag is specified it doesn't mean that this class contains supplementary characters but may contain.
|
||||
*/
|
||||
@@ -92,6 +95,20 @@ internal abstract class AbstractCharClass : SpecialToken() {
|
||||
|
||||
|
||||
private val surrogates_ = AtomicReference<AbstractCharClass?>(null)
|
||||
/**
|
||||
* Returns a char class that contains only unpaired surrogate chars from this char class.
|
||||
*
|
||||
* Consider the following char class: `[a\uD801\uDC00\uD800]`.
|
||||
* This function returns a char class that contains only `\uD800`: `[\uD800]`.
|
||||
* [classWithoutSurrogates] returns a char class that does not contain `\uD800`: `[a\uD801\uDC00]`.
|
||||
*
|
||||
* The returned char class is used to create [SurrogateRangeSet] node
|
||||
* that matches any unpaired surrogate from this char class. [SurrogateRangeSet]
|
||||
* doesn't match a surrogate that is paired with the char before or after it.
|
||||
* The result of [classWithoutSurrogates] is used to create [SupplementaryRangeSet]
|
||||
* or [RangeSet] depending on [mayContainSupplCodepoints].
|
||||
* The two nodes are then combined in [CompositeRangeSet] node to fully represent this char class.
|
||||
*/
|
||||
fun classWithSurrogates(): AbstractCharClass {
|
||||
surrogates_.value?.let {
|
||||
return it
|
||||
@@ -108,12 +125,19 @@ internal abstract class AbstractCharClass : SpecialToken() {
|
||||
}
|
||||
}
|
||||
}
|
||||
result.setNegative(this.altSurrogates)
|
||||
result.alt = this.alt
|
||||
result.altSurrogates = this.altSurrogates
|
||||
result.mayContainSupplCodepoints = this.mayContainSupplCodepoints
|
||||
surrogates_.compareAndSet(null, result.freeze())
|
||||
return surrogates_.value!!
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a char class that contains all chars from this char class excluding the unpaired surrogate chars.
|
||||
*
|
||||
* See [classWithSurrogates] for details.
|
||||
*/
|
||||
// We cannot cache this class as we've done with surrogates above because
|
||||
// here is a circular reference between it and AbstractCharClass.
|
||||
fun classWithoutSurrogates(): AbstractCharClass {
|
||||
@@ -129,8 +153,9 @@ internal abstract class AbstractCharClass : SpecialToken() {
|
||||
return this@AbstractCharClass.contains(ch) && !containslHS
|
||||
}
|
||||
}
|
||||
result.setNegative(isNegative())
|
||||
result.mayContainSupplCodepoints = mayContainSupplCodepoints
|
||||
result.alt = this.alt
|
||||
result.altSurrogates = this.altSurrogates
|
||||
result.mayContainSupplCodepoints = this.mayContainSupplCodepoints
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -145,9 +170,10 @@ internal abstract class AbstractCharClass : SpecialToken() {
|
||||
if (alt xor value) {
|
||||
alt = !alt
|
||||
altSurrogates = !altSurrogates
|
||||
}
|
||||
if (!mayContainSupplCodepoints) {
|
||||
mayContainSupplCodepoints = true
|
||||
|
||||
if (!mayContainSupplCodepoints) {
|
||||
mayContainSupplCodepoints = true
|
||||
}
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user