Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
peng3141 committed Oct 2, 2024
1 parent 615c816 commit 106467d
Show file tree
Hide file tree
Showing 14 changed files with 332 additions and 13 deletions.
Binary file added go/.DS_Store
Binary file not shown.
5 changes: 5 additions & 0 deletions go/private/actions/archive.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,12 @@ def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_d
out_facts = go.declare_file(go, name = source.library.name, ext = pre_ext + ".facts")
out_nogo_log = go.declare_file(go, name = source.library.name, ext = pre_ext + ".nogo.log")
out_nogo_validation = go.declare_file(go, name = source.library.name, ext = pre_ext + ".nogo")
out_nogo_fix = go.declare_file(go, name = source.library.name, ext = pre_ext + ".nogo.fix")
else:
out_facts = None
out_nogo_log = None
out_nogo_validation = None
out_nogo_fix = None

direct = source.deps

Expand Down Expand Up @@ -113,6 +115,7 @@ def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_d
out_facts = out_facts,
out_nogo_log = out_nogo_log,
out_nogo_validation = out_nogo_validation,
out_nogo_fix = out_nogo_fix,
nogo = nogo,
out_cgo_export_h = out_cgo_export_h,
gc_goopts = source.gc_goopts,
Expand Down Expand Up @@ -142,6 +145,7 @@ def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_d
out_facts = out_facts,
out_nogo_log = out_nogo_log,
out_nogo_validation = out_nogo_validation,
out_nogo_fix = out_nogo_fix,
nogo = nogo,
gc_goopts = source.gc_goopts,
cgo = False,
Expand Down Expand Up @@ -187,6 +191,7 @@ def emit_archive(go, source = None, _recompile_suffix = "", recompile_internal_d
facts_file = out_facts,
runfiles = source.runfiles,
_validation_output = out_nogo_validation,
_out_nogo_fix = out_nogo_fix,
_cgo_deps = cgo_deps,
)
x_defs = dict(source.x_defs)
Expand Down
9 changes: 7 additions & 2 deletions go/private/actions/compilepkg.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ def emit_compilepkg(
out_facts = None,
out_nogo_log = None,
out_nogo_validation = None,
out_nogo_fix = None,
nogo = None,
out_cgo_export_h = None,
gc_goopts = [],
Expand All @@ -87,7 +88,8 @@ def emit_compilepkg(
fail("nogo must be specified if and only if out_nogo_log is specified")
if bool(nogo) != bool(out_nogo_validation):
fail("nogo must be specified if and only if out_nogo_validation is specified")

if bool(nogo) != bool(out_nogo_fix):
fail("nogo must be specified if and only if out_nogo_fix is specified")
if cover and go.coverdata:
archives = archives + [go.coverdata]

Expand Down Expand Up @@ -221,6 +223,7 @@ def emit_compilepkg(
out_facts = out_facts,
out_log = out_nogo_log,
out_validation = out_nogo_validation,
out_nogo_fix = out_nogo_fix,
nogo = nogo,
)

Expand All @@ -238,6 +241,7 @@ def _run_nogo(
out_facts,
out_log,
out_validation,
out_nogo_fix,
nogo):
"""Runs nogo on Go source files, including those generated by cgo."""
sdk = go.sdk
Expand All @@ -246,7 +250,7 @@ def _run_nogo(
[archive.data.facts_file for archive in archives if archive.data.facts_file] +
[archive.data.export_file for archive in archives])
inputs_transitive = [sdk.tools, sdk.headers, go.stdlib.libs]
outputs = [out_facts, out_log]
outputs = [out_facts, out_log, out_nogo_fix]

args = go.builder_args(go, "nogo", use_path_mapping = True)
args.add_all(sources, before_each = "-src")
Expand All @@ -271,6 +275,7 @@ def _run_nogo(
args.add_all(archives, before_each = "-facts", map_each = _facts)
args.add("-out_facts", out_facts)
args.add("-out_log", out_log)
args.add("-fixpath", out_nogo_fix)
args.add("-nogo", nogo)

# This action runs nogo and produces the facts files for downstream nogo actions.
Expand Down
2 changes: 2 additions & 0 deletions go/private/rules/library.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def _go_library_impl(ctx):
source = go.library_to_source(go, ctx.attr, library, ctx.coverage_instrumented())
archive = go.archive(go, source)
validation_output = archive.data._validation_output
nogo_fix_output = archive.data._out_nogo_fix

return [
library,
Expand All @@ -65,6 +66,7 @@ def _go_library_impl(ctx):
OutputGroupInfo(
cgo_exports = archive.cgo_exports,
compilation_outputs = [archive.data.file],
out_nogo_fix = [nogo_fix_output] if nogo_fix_output else [],
_validation = [validation_output] if validation_output else [],
),
]
Expand Down
1 change: 0 additions & 1 deletion go/private/sdk.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ def _go_download_sdk_impl(ctx):
)

data = ctx.read("versions.json")
ctx.delete("versions.json")
sdks_by_version = _parse_versions_json(data)

if not version:
Expand Down
3 changes: 3 additions & 0 deletions go/tools/builders/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ go_source(
"constants.go",
"env.go",
"flags.go",
"nogo_change.go",
"nogo_change_serialization.go",
"nogo_edit.go",
"nogo_main.go",
"nogo_typeparams_go117.go",
"nogo_typeparams_go118.go",
Expand Down
2 changes: 1 addition & 1 deletion go/tools/builders/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ func main() {
log.SetPrefix(verb + ": ")

if err := action(rest); err != nil {
log.Fatal(err)
log.Fatalf("\n$$$$$$$$$$$$$$$$$$$$$$$$ fatal: %+v", err)
}
}
13 changes: 10 additions & 3 deletions go/tools/builders/nogo.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ func nogo(args []string) error {
var importPath, packagePath, nogoPath, packageListPath string
var testFilter string
var outFactsPath, outLogPath string
var nogoFixPath string
var coverMode string
fs.Var(&unfilteredSrcs, "src", ".go, .c, .cc, .m, .mm, .s, or .S file to be filtered and checked")
fs.Var(&ignoreSrcs, "ignore_src", ".go, .c, .cc, .m, .mm, .s, or .S file to be filtered and checked, but with its diagnostics ignored")
Expand All @@ -39,6 +40,9 @@ func nogo(args []string) error {
fs.StringVar(&nogoPath, "nogo", "", "The nogo binary")
fs.StringVar(&outFactsPath, "out_facts", "", "The file to emit serialized nogo facts to")
fs.StringVar(&outLogPath, "out_log", "", "The file to emit nogo logs into")

fs.StringVar(&nogoFixPath, "fixpath", "", "The fix path")

if err := fs.Parse(args); err != nil {
return err
}
Expand Down Expand Up @@ -82,10 +86,10 @@ func nogo(args []string) error {
return err
}

return runNogo(workDir, nogoPath, goSrcs, ignoreSrcs, facts, importPath, importcfgPath, outFactsPath, outLogPath)
return runNogo(workDir, nogoPath, goSrcs, ignoreSrcs, facts, importPath, importcfgPath, outFactsPath, outLogPath, nogoFixPath)
}

func runNogo(workDir string, nogoPath string, srcs, ignores []string, facts []archive, packagePath, importcfgPath, outFactsPath string, outLogPath string) error {
func runNogo(workDir string, nogoPath string, srcs, ignores []string, facts []archive, packagePath, importcfgPath, outFactsPath string, outLogPath string, nogoFixPath string) error {
if len(srcs) == 0 {
// emit_compilepkg expects a nogo facts file, even if it's empty.
// We also need to write the validation output log.
Expand All @@ -101,6 +105,10 @@ func runNogo(workDir string, nogoPath string, srcs, ignores []string, facts []ar
}
args := []string{nogoPath}
args = append(args, "-p", packagePath)
args = append(args, "-fixpath", nogoFixPath)


// args = append(args, "-json")
args = append(args, "-importcfg", importcfgPath)
for _, fact := range facts {
args = append(args, "-fact", fmt.Sprintf("%s=%s", fact.importPath, fact.file))
Expand Down Expand Up @@ -148,4 +156,3 @@ func runNogo(workDir string, nogoPath string, srcs, ignores []string, facts []ar
}
return nil
}

85 changes: 85 additions & 0 deletions go/tools/builders/nogo_change.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package main

import (
"fmt"
"go/token"
"strings"

"golang.org/x/tools/go/analysis"
)

// 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"`
}

// NewChange creates a new Change object.
func NewChange() *Change {
return &Change{
FileToEdits: make(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.
// 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 {
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)
}
if edit.Pos > edit.End {
return 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)
}
edit := Edit{Start: file.Offset(edit.Pos), End: file.Offset(edit.End), New: string(edit.NewText)}
fileRelativePath := file.Name()
c.AddEdit(fileRelativePath, edit)
}
}
}
return 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
}
}
}
mergedChange.AnalysisName = strings.Join(analysisNames, ",")
return *mergedChange
}
44 changes: 44 additions & 0 deletions go/tools/builders/nogo_change_serialization.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package main

import (
"encoding/json"
"fmt"
"io/ioutil"
// "log"
)

// SaveToFile saves the Change struct to a JSON file.
func SaveToFile(filename string, change Change) error {
// Serialize Change to JSON
jsonData, err := json.MarshalIndent(change, "", " ")
if err != nil {
return fmt.Errorf("error serializing to JSON: %v", err)
}
// log.Fatalf("!!!!: %v", change)
// Write the JSON data to the file
err = ioutil.WriteFile(filename, jsonData, 0644)
if err != nil {
return fmt.Errorf("error writing to file: %v", err)
}

return nil
}

// LoadFromFile loads the Change struct from a JSON file.
func LoadFromFile(filename string) (Change, error) {
var change Change

// Read the JSON file
jsonData, err := ioutil.ReadFile(filename)
if err != nil {
return change, fmt.Errorf("error reading file: %v", err)
}

// Deserialize JSON data into the Change struct
err = json.Unmarshal(jsonData, &change)
if err != nil {
return change, fmt.Errorf("error deserializing JSON: %v", err)
}

return change, nil
}
Loading

0 comments on commit 106467d

Please sign in to comment.