diff --git a/skewc.js b/skewc.js index 75813caa..e0d2bb35 100644 --- a/skewc.js +++ b/skewc.js @@ -9650,6 +9650,22 @@ this._bestMatch = null; }; + Skew.FuzzySymbolMatcher.prototype._isBetterScore = function(score, match) { + if (score < this._bestScore) { + return true; + } + + // Do tie-breaking using a consistent ordering so that language targets + // with unordered maps (C++ for example) can iterate over symbols in an + // unspecified order for speed and still deterministically arrive at the + // same result. + if (score == this._bestScore && (this._bestMatch == null || match.id < this._bestMatch.id)) { + return true; + } + + return false; + }; + Skew.FuzzySymbolMatcher.prototype.include = function(match) { if (this._kind == Skew.FuzzySymbolKind.INSTANCE_ONLY && !Skew.in_SymbolKind.isOnInstances(match.kind) || this._kind == Skew.FuzzySymbolKind.GLOBAL_ONLY && Skew.in_SymbolKind.isOnInstances(match.kind) || this._kind == Skew.FuzzySymbolKind.TYPE_ONLY && !Skew.in_SymbolKind.isType(match.kind) || match.state == Skew.SymbolState.INITIALIZING) { return; @@ -9657,7 +9673,7 @@ var score = Skew.caseAwareLevenshteinEditDistance(this._name, match.name); - if (score <= this._bestScore && score <= match.name.length * 0.5) { + if (score <= match.name.length * 0.5 && this._isBetterScore(score, match)) { this._bestScore = score; this._bestMatch = match; } diff --git a/src/core/symbol.sk b/src/core/symbol.sk index 6fac4c3c..8a084b0d 100644 --- a/src/core/symbol.sk +++ b/src/core/symbol.sk @@ -453,6 +453,22 @@ namespace Skew { _bestMatch = null } + def _isBetterScore(score double, match Symbol) bool { + if score < _bestScore { + return true + } + + # Do tie-breaking using a consistent ordering so that language targets + # with unordered maps (C++ for example) can iterate over symbols in an + # unspecified order for speed and still deterministically arrive at the + # same result. + if score == _bestScore && (_bestMatch == null || match.id < _bestMatch.id) { + return true + } + + return false + } + def include(match Symbol) { if _kind == .INSTANCE_ONLY && !match.kind.isOnInstances || _kind == .GLOBAL_ONLY && match.kind.isOnInstances || @@ -462,7 +478,7 @@ namespace Skew { } var score = caseAwareLevenshteinEditDistance(_name, match.name) - if score <= _bestScore && score <= match.name.count * 0.5 { + if score <= match.name.count * 0.5 && _isBetterScore(score, match) { _bestScore = score _bestMatch = match } diff --git a/tests/ide.sk b/tests/ide.sk index ba9db179..a5072896 100644 --- a/tests/ide.sk +++ b/tests/ide.sk @@ -731,12 +731,12 @@ namespace Foo { var bat = 0 ", 7, 8, " -:8:7: error: \"ba\" is not declared, did you mean \"bat\"? +:8:7: error: \"ba\" is not declared, did you mean \"bar\"? ba ~~ -:21:5: note: \"bat\" is defined here -var bat = 0 - ~~~ +:2:7: note: \"bar\" is defined here + var bar = 0 + ~~~ :8:7: completions: ba ~~