internal/analysisinternal: move FindBestMatch to internal/lsp/fuzzy

This is used by internal/lsp/analysis/fillreturns and
internal/lsp/analysis/fillstruct. This doesn't need to be in this
analysisinternal package.

This removes the dependency path

  go/analysis/internal/checker ->
    internal/analysisinternal ->
      internal/lsp/fuzzy

Change-Id: I5db674ca30eb06ae6ce7021397cf5530a695af4e
Reviewed-on: https://go-review.googlesource.com/c/tools/+/417418
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Hyang-Ah Hana Kim <hyangah@gmail.com>
This commit is contained in:
Hana (Hyang-Ah) Kim 2022-07-13 17:10:18 -04:00 committed by Hyang-Ah Hana Kim
parent 9b6c01892a
commit a7c53b59a6
4 changed files with 32 additions and 31 deletions

View File

@ -12,8 +12,6 @@ import (
"go/token"
"go/types"
"strconv"
"golang.org/x/tools/internal/lsp/fuzzy"
)
// Flag to gate diagnostics for fuzz tests in 1.18.
@ -397,30 +395,3 @@ func equivalentTypes(want, got types.Type) bool {
}
return types.AssignableTo(want, got)
}
// FindBestMatch employs fuzzy matching to evaluate the similarity of each given identifier to the
// given pattern. We return the identifier whose name is most similar to the pattern.
func FindBestMatch(pattern string, idents []*ast.Ident) ast.Expr {
fuzz := fuzzy.NewMatcher(pattern)
var bestFuzz ast.Expr
highScore := float32(0) // minimum score is 0 (no match)
for _, ident := range idents {
// TODO: Improve scoring algorithm.
score := fuzz.Score(ident.Name)
if score > highScore {
highScore = score
bestFuzz = ident
} else if score == 0 {
// Order matters in the fuzzy matching algorithm. If we find no match
// when matching the target to the identifier, try matching the identifier
// to the target.
revFuzz := fuzzy.NewMatcher(ident.Name)
revScore := revFuzz.Score(pattern)
if revScore > highScore {
highScore = revScore
bestFuzz = ident
}
}
}
return bestFuzz
}

View File

@ -19,6 +19,7 @@ import (
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/internal/analysisinternal"
"golang.org/x/tools/internal/lsp/fuzzy"
"golang.org/x/tools/internal/typeparams"
)
@ -191,7 +192,7 @@ outer:
// Find the identifier whose name is most similar to the return type.
// If we do not find any identifier that matches the pattern,
// generate a zero value.
value := analysisinternal.FindBestMatch(retTyp.String(), idents)
value := fuzzy.FindBestMatch(retTyp.String(), idents)
if value == nil {
value = analysisinternal.ZeroValue(file, pass.Pkg, retTyp)
}

View File

@ -21,6 +21,7 @@ import (
"golang.org/x/tools/go/ast/astutil"
"golang.org/x/tools/go/ast/inspector"
"golang.org/x/tools/internal/analysisinternal"
"golang.org/x/tools/internal/lsp/fuzzy"
"golang.org/x/tools/internal/span"
"golang.org/x/tools/internal/typeparams"
)
@ -254,7 +255,7 @@ func SuggestedFix(fset *token.FileSet, rng span.Range, content []byte, file *ast
// Find the identifier whose name is most similar to the name of the field's key.
// If we do not find any identifier that matches the pattern, generate a new value.
// NOTE: We currently match on the name of the field key rather than the field type.
value := analysisinternal.FindBestMatch(obj.Field(i).Name(), idents)
value := fuzzy.FindBestMatch(obj.Field(i).Name(), idents)
if value == nil {
value = populateValue(file, pkg, fieldTyp)
}

View File

@ -8,6 +8,7 @@ package fuzzy
import (
"bytes"
"fmt"
"go/ast"
)
const (
@ -405,3 +406,30 @@ func (m *Matcher) poorMatch() bool {
}
return false
}
// FindBestMatch employs fuzzy matching to evaluate the similarity of each given identifier to the
// given pattern. We return the identifier whose name is most similar to the pattern.
func FindBestMatch(pattern string, idents []*ast.Ident) ast.Expr {
fuzz := NewMatcher(pattern)
var bestFuzz ast.Expr
highScore := float32(0) // minimum score is 0 (no match)
for _, ident := range idents {
// TODO: Improve scoring algorithm.
score := fuzz.Score(ident.Name)
if score > highScore {
highScore = score
bestFuzz = ident
} else if score == 0 {
// Order matters in the fuzzy matching algorithm. If we find no match
// when matching the target to the identifier, try matching the identifier
// to the target.
revFuzz := NewMatcher(ident.Name)
revScore := revFuzz.Score(pattern)
if revScore > highScore {
highScore = revScore
bestFuzz = ident
}
}
}
return bestFuzz
}