-
-
Notifications
You must be signed in to change notification settings - Fork 662
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
rules_go improvement to externalize the nogo fix
- Loading branch information
Showing
17 changed files
with
368 additions
and
236 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,88 @@ | ||
package main | ||
|
||
|
||
import ( | ||
"fmt" | ||
"go/token" | ||
"strings" | ||
"os" | ||
"path/filepath" | ||
|
||
"golang.org/x/tools/go/analysis" | ||
) | ||
|
||
// DiagnosticEntry represents a diagnostic entry with the corresponding analyzer. | ||
type DiagnosticEntry struct { | ||
analysis.Diagnostic | ||
*analysis.Analyzer | ||
} | ||
|
||
// An Edit describes the replacement of a portion of a text file. | ||
type Edit struct { | ||
New string `json:"new"` // the replacement | ||
Start int `json:"start"` // starting byte offset of the region to replace | ||
End int `json:"end"` // ending byte offset of the region to replace | ||
} | ||
|
||
|
||
// Change represents a set of edits to be applied to a set of files. | ||
type Change struct { | ||
AnalysisName string `json:"analysis_name"` | ||
FileToEdits map[string][]Edit `json:"file_to_edits"` | ||
AnalyzerToFileToEdits map[string]map[string][]Edit `json:"analyzer_file_to_edits"` | ||
} | ||
|
||
|
||
|
||
// NewChange creates a new Change object. | ||
func NewChange() *Change { | ||
return &Change{ | ||
FileToEdits: make(map[string][]Edit), | ||
AnalyzerToFileToEdits: make(map[string]map[string][]Edit), | ||
} | ||
} | ||
|
||
// SetAnalysisName sets the name of the analysis that produced the change. | ||
func (c *Change) SetAnalysisName(name string) { | ||
c.AnalysisName = name | ||
} | ||
|
||
// AddEdit adds an edit to the change. | ||
func (c *Change) AddEdit(file string, edit Edit) { | ||
c.FileToEdits[file] = append(c.FileToEdits[file], edit) | ||
} | ||
|
||
// BuildFromDiagnostics builds a Change from a set of diagnostics. | ||
// NewChangeFromDiagnostics builds a Change from a set of diagnostics. | ||
// Unlike Diagnostic, Change is independent of the FileSet given it uses perf-file offsets instead of token.Pos. | ||
// This allows Change to be used in contexts where the FileSet is not available, e.g., it remains applicable after it is saved to disk and loaded back. | ||
// See https://github.com/golang/tools/blob/master/go/analysis/diagnostic.go for details. | ||
func (c *Change) BuildFromDiagnostics(diagnostics []analysis.Diagnostic, fileSet *token.FileSet) error { | ||
for _, diag := range diagnostics { | ||
for _, sf := range diag.SuggestedFixes { | ||
func NewChangeFromDiagnostics(entries []DiagnosticEntry, fileSet *token.FileSet) (*Change, error) { | ||
c := NewChange() | ||
cwd, err := os.Getwd() // workspace root | ||
if err != nil { | ||
return c, fmt.Errorf("Error getting current working directory: (%v)", err) | ||
} | ||
for _, entry := range entries { | ||
analyzer := entry.Analyzer.Name | ||
for _, sf := range entry.Diagnostic.SuggestedFixes { | ||
for _, edit := range sf.TextEdits { | ||
file := fileSet.File(edit.Pos) | ||
|
||
if file == nil { | ||
return fmt.Errorf("invalid fix: missing file info for pos (%v)", edit.Pos) | ||
return c, fmt.Errorf("invalid fix: missing file info for pos (%v)", edit.Pos) | ||
} | ||
if edit.Pos > edit.End { | ||
return fmt.Errorf("invalid fix: pos (%v) > end (%v)", edit.Pos, edit.End) | ||
return c, fmt.Errorf("invalid fix: pos (%v) > end (%v)", edit.Pos, edit.End) | ||
} | ||
if eof := token.Pos(file.Base() + file.Size()); edit.End > eof { | ||
return fmt.Errorf("invalid fix: end (%v) past end of file (%v)", edit.End, eof) | ||
return c, fmt.Errorf("invalid fix: end (%v) past end of file (%v)", edit.End, eof) | ||
} | ||
edit := Edit{Start: file.Offset(edit.Pos), End: file.Offset(edit.End), New: string(edit.NewText)} | ||
fileRelativePath := file.Name() | ||
c.AddEdit(fileRelativePath, edit) | ||
fileRelativePath, err := filepath.Rel(cwd, file.Name()) | ||
if err != nil { | ||
fileRelativePath = file.Name() // fallback logic | ||
} | ||
c.AddEdit(analyzer, fileRelativePath, edit) | ||
} | ||
} | ||
} | ||
return nil | ||
return c, nil | ||
} | ||
|
||
// MergeChanges merges multiple changes into a single change. | ||
func MergeChanges(changes []Change) Change { | ||
mergedChange := NewChange() // Create a new Change object for the result | ||
analysisNames := []string{} // no deduplication needed | ||
|
||
for _, change := range changes { | ||
if change.AnalysisName != "" { | ||
analysisNames = append(analysisNames, change.AnalysisName) | ||
} | ||
for file, edits := range change.FileToEdits { | ||
// If the file already exists in the merged change, append the edits | ||
if existingEdits, found := mergedChange.FileToEdits[file]; found { | ||
// checking the overlapping of edits happens in edit.go during the ApplyEdits function. | ||
// so we don't need to check it here. | ||
mergedChange.FileToEdits[file] = append(existingEdits, edits...) | ||
} else { | ||
// Otherwise, just set the file and edits | ||
mergedChange.FileToEdits[file] = edits | ||
} | ||
} | ||
// AddEdit adds an edit to the change. | ||
func (c *Change) AddEdit(analyzer string, file string, edit Edit) { | ||
// Check if the analyzer exists in the map | ||
if _, ok := c.AnalyzerToFileToEdits[analyzer]; !ok { | ||
// Initialize the map for the analyzer if it doesn't exist | ||
c.AnalyzerToFileToEdits[analyzer] = make(map[string][]Edit) | ||
} | ||
mergedChange.AnalysisName = strings.Join(analysisNames, ",") | ||
return *mergedChange | ||
|
||
// Append the edit to the list of edits for the specific file under the analyzer | ||
c.AnalyzerToFileToEdits[analyzer][file] = append(c.AnalyzerToFileToEdits[analyzer][file], edit) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package main | ||
|
||
import ( | ||
"os" | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestSaveLoad(t *testing.T) { | ||
// Create a temporary file | ||
file, err := os.CreateTemp("", "tmp_file") | ||
if err != nil { | ||
t.Fatal(err) | ||
} | ||
defer os.Remove(file.Name()) | ||
|
||
// Initialize a Change struct with some edits and analyzers | ||
change := *NewChange() | ||
change.AddEdit("AnalyzerA", "file1.txt", Edit{New: "replacement1", Start: 0, End: 5}) | ||
change.AddEdit("AnalyzerA", "file1.txt", Edit{New: "replacement2", Start: 10, End: 15}) | ||
change.AddEdit("AnalyzerB", "file2.txt", Edit{New: "new text", Start: 20, End: 25}) | ||
|
||
// Test saving to file | ||
err = SaveToFile(file.Name(), change) | ||
if err != nil { | ||
t.Fatalf("Failed to save Change struct to file: %v", err) | ||
} | ||
|
||
// Test loading from file | ||
loadedChange, err := LoadFromFile(file.Name()) | ||
if err != nil { | ||
t.Fatalf("Failed to load Change struct from file: %v", err) | ||
} | ||
|
||
// Compare original and loaded Change structs | ||
if !reflect.DeepEqual(change, loadedChange) { | ||
t.Fatalf("Loaded Change struct does not match original.\nOriginal: %+v\nLoaded: %+v", change, loadedChange) | ||
} | ||
} |
Oops, something went wrong.