1
0
mirror of https://github.com/golang/go synced 2024-09-30 22:58:34 -06:00

internal/lsp/source: optimize computeFixEdits

In the common case that a file has imports, we're going to diff just the
import block. That means that ApplyFixes doesn't need to produce the
whole formatted file, which is a huge speedup. We will do more work twice
for files with no imports, but those are presumably pretty short.

Hat tip to Muir for pointing towards this in
https://go-review.googlesource.com/c/tools/+/209579/2/internal/imports/imports.go#87
even if I didn't catch it.

Updates golang/go#36001.

Change-Id: Ibbeb4d88c6505eac26a36994de514813606c8c79
Reviewed-on: https://go-review.googlesource.com/c/tools/+/210200
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Heschi Kreinick 2019-12-05 19:49:14 -05:00
parent 330b9f1384
commit 6d582d504c
3 changed files with 15 additions and 7 deletions

View File

@ -83,8 +83,9 @@ func FixImports(filename string, src []byte, opt *Options) (fixes []*ImportFix,
return getFixes(fileSet, file, filename, opt.Env)
}
// ApplyFix will apply all of the fixes to the file and format it.
func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options) (formatted []byte, err error) {
// ApplyFixes applies all of the fixes to the file and formats it. extraMode
// is added in when parsing the file.
func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, extraMode parser.Mode) (formatted []byte, err error) {
src, opt, err = initialize(filename, src, opt)
if err != nil {
return nil, err
@ -100,6 +101,8 @@ func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options) (
if opt.AllErrors {
parserMode |= parser.AllErrors
}
parserMode |= extraMode
file, err := parser.ParseFile(fileSet, filename, src, parserMode)
if file == nil {
return nil, err

View File

@ -71,7 +71,7 @@ func _() {
t.Errorf("%s: %s", test.name, err.Error())
}
got, err = ApplyFixes(fixes, "", []byte(input), test.opt)
got, err = ApplyFixes(fixes, "", []byte(input), test.opt, 0)
if err != nil {
t.Errorf("%s: %s", test.name, err.Error())
}

View File

@ -93,7 +93,7 @@ func AllImportsFixes(ctx context.Context, snapshot Snapshot, f File) (allFixEdit
pkg, pgh, err := getParsedFile(ctx, snapshot, f, NarrowestCheckPackageHandle)
if err != nil {
return nil, nil, fmt.Errorf("getting file for AllImportsFixes: %v", err)
return nil, nil, errors.Errorf("getting file for AllImportsFixes: %v", err)
}
if hasListErrors(pkg) {
return nil, nil, errors.Errorf("%s has list errors, not running goimports", f.URI())
@ -112,7 +112,7 @@ func AllImportsFixes(ctx context.Context, snapshot Snapshot, f File) (allFixEdit
return err
}, options)
if err != nil {
return nil, nil, err
return nil, nil, errors.Errorf("computing fix edits: %v", err)
}
return allFixEdits, editsPerFix, nil
@ -186,7 +186,8 @@ func computeFixEdits(view View, ph ParseGoHandle, options *imports.Options, orig
filename := ph.File().Identity().URI.Filename()
// Apply the fixes and re-parse the file so that we can locate the
// new imports.
fixedData, err := imports.ApplyFixes(fixes, filename, origData, options)
fixedData, err := imports.ApplyFixes(fixes, filename, origData, options, parser.ImportsOnly)
fixedData = append(fixedData, '\n') // ApplyFixes comes out missing the newline, go figure.
if err != nil {
return nil, err
}
@ -211,7 +212,11 @@ func computeFixEdits(view View, ph ParseGoHandle, options *imports.Options, orig
// somewhere before that.
if origImportOffset == 0 || fixedImportsOffset == 0 {
left, _ = trimToFirstNonImport(view.Session().Cache().FileSet(), origAST, origData, nil)
// We need the whole AST here, not just the ImportsOnly AST we parsed above.
fixedData, err = imports.ApplyFixes(fixes, filename, origData, options, 0)
if err != nil {
return nil, err
}
// We need the whole file here, not just the ImportsOnly versions we made above.
fixedAST, err = parser.ParseFile(fixedFset, filename, fixedData, 0)
if fixedAST == nil {
return nil, err