Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions cli/dispatcher/internal/compilecheck/baseline_record.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"strings"

"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/fastcheck"
"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/resultstore"
)

// RecordBaseline records what the next changed-files check of a unit compares against, after a
Expand Down Expand Up @@ -56,9 +57,9 @@ func (runner *fastPathRunner) RecordBaseline(
return err
}

return c.records(plan).recordBaseline(unit.Assembly.AssemblyName, baselineInputs{
return c.records(plan).RecordBaseline(unit.Assembly.AssemblyName, resultstore.BaselineInputs{
InputKey: keyResult.Key,
NonSourceKey: nonSourceKey,
NonSourceKey: resultstore.KeyDigest(nonSourceKey),
WorkerKey: worker.Key,
Files: files,
})
Expand All @@ -67,8 +68,8 @@ func (runner *fastPathRunner) RecordBaseline(
// baselineFiles pairs each source's content hash, as the input key read it, with its fingerprint.
func baselineFiles(
projectRoot string, unit CompileUnit, keyResult inputKeyResult, fingerprints fastcheck.FingerprintResponse,
) (map[string]baselineFile, error) {
files := make(map[string]baselineFile, len(unit.Sources))
) (map[string]resultstore.BaselineFile, error) {
files := make(map[string]resultstore.BaselineFile, len(unit.Sources))
for _, source := range unit.Sources {
absolute := projectPath(projectRoot, source)
fingerprint, hasFingerprint := fingerprints.Fingerprints[absolute]
Expand All @@ -79,7 +80,7 @@ func baselineFiles(
if contentHash != keyResult.SourceHashes[source] {
return nil, fmt.Errorf("source changed during the compile: %s", source)
}
files[source] = baselineFile{ContentHash: contentHash, Fingerprint: fingerprint}
files[source] = resultstore.BaselineFile{ContentHash: contentHash, Fingerprint: fingerprint}
}

return files, nil
Expand Down
5 changes: 3 additions & 2 deletions cli/dispatcher/internal/compilecheck/baseline_record_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"time"

"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/fastcheck"
"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/resultstore"
)

// Verifies that a successful full compile records a baseline whose content hashes are the ones the
Expand Down Expand Up @@ -125,7 +126,7 @@ func TestCompileUnitPassesGeneratedFilesOut(t *testing.T) {
written, _ := compileSecondUnit(t, "", 0)

plan := newCompilerPlan()
want := quoteFlag(generatedFilesOutFlagPrefix, filepath.ToSlash(openRecordStore("", plan.OutputDir).generatedDirectory(plan.Units[1].Assembly.AssemblyName)))
want := quoteFlag(generatedFilesOutFlagPrefix, filepath.ToSlash(resultstore.Open[Diagnostic]("", plan.OutputDir).GeneratedDirectory(plan.Units[1].Assembly.AssemblyName)))
if !strings.Contains(written, want) {
t.Errorf("expected %s in the response file, got:\n%s", want, written)
}
Expand Down Expand Up @@ -217,7 +218,7 @@ func TestCompileUnitCreatesGeneratedFilesOutDirectory(t *testing.T) {
ProjectRoot: projectRoot,
Timeout: time.Minute,
Run: func(_ context.Context, _ *exec.Cmd) (string, string, int, error) {
info, err := os.Stat(filepath.Join(projectRoot, openRecordStore(projectRoot, plan.OutputDir).generatedDirectory(plan.Units[1].Assembly.AssemblyName)))
info, err := os.Stat(filepath.Join(projectRoot, resultstore.Open[Diagnostic](projectRoot, plan.OutputDir).GeneratedDirectory(plan.Units[1].Assembly.AssemblyName)))
existed = err == nil && info.IsDir()
return "", "", 0, nil
},
Expand Down
6 changes: 3 additions & 3 deletions cli/dispatcher/internal/compilecheck/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,15 @@ func (c Compiler) CompileUnit(
// Why the generator output directory is created here: the csc of Roslyn 4.3 (Unity 2022.3) creates
// the folder of each generator under it but not the directory itself, and fails every generated
// file with CS0016 when it is missing. Newer Roslyn creates it either way.
generatedPath := filepath.Join(c.ProjectRoot, c.records(plan).generatedDirectory(unit.Assembly.AssemblyName))
generatedPath := filepath.Join(c.ProjectRoot, c.records(plan).GeneratedDirectory(unit.Assembly.AssemblyName))
if err := os.MkdirAll(generatedPath, outputDirPermissions); err != nil {
return UnitResult{}, fmt.Errorf("failed to create %s: %w", generatedPath, err)
}

// Why the generator output is saved: a later fast check reads it instead of running the generators.
responseFilePath, err := writeRewrittenResponseFile(c.ProjectRoot, plan, unit,
unit.Assembly.AssemblyName+responseFileExtension,
[]string{quoteFlag(generatedFilesOutFlagPrefix, filepath.ToSlash(c.records(plan).generatedDirectory(unit.Assembly.AssemblyName)))})
[]string{quoteFlag(generatedFilesOutFlagPrefix, filepath.ToSlash(c.records(plan).GeneratedDirectory(unit.Assembly.AssemblyName)))})
if err != nil {
return UnitResult{}, err
}
Expand Down Expand Up @@ -168,7 +168,7 @@ func (c Compiler) removeUnitOutputs(plan BuildPlan, unit CompileUnit) error {
}
}

return c.records(plan).forget(unit.Assembly.AssemblyName)
return c.records(plan).Forget(unit.Assembly.AssemblyName)
}

// buildUnitResult turns one compiler invocation's output into the result for its assembly.
Expand Down
31 changes: 31 additions & 0 deletions cli/dispatcher/internal/compilecheck/diagnostic_format_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package compilecheck

import (
"encoding/json"
"testing"
)

// Verifies the JSON form of a diagnostic, field names and order included. The result store records
// diagnostics exactly as it is handed them, so changing this form would change how the records an
// earlier run left are read, without anything marking those records as written by another version.
func TestDiagnosticKeepsTheJSONFormTheResultStoreRecords(t *testing.T) {
diagnostic := Diagnostic{
Severity: severityError,
Code: "CS0103",
Message: "The name 'Missing' does not exist in the current context",
File: "Assets/Alpha/Alpha.cs",
Line: 3,
Column: 9,
}

content, err := json.Marshal(diagnostic)
if err != nil {
t.Fatalf("failed to encode the diagnostic: %v", err)
}

want := `{"Severity":"error","Code":"CS0103","Message":"The name 'Missing' does not exist in the current context",` +
`"File":"Assets/Alpha/Alpha.cs","Line":3,"Column":9}`
if string(content) != want {
t.Errorf("JSON form =\n%s\nwant\n%s", content, want)
}
}
13 changes: 7 additions & 6 deletions cli/dispatcher/internal/compilecheck/fast_path.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"time"

"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/fastcheck"
"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/resultstore"
)

const (
Expand Down Expand Up @@ -78,7 +79,7 @@ func (runner *fastPathRunner) Try(
nonSourceKey nonSourceIdentity,
) fastPathAttempt {
records := c.records(plan)
baseline, reason := records.loadBaseline(unit.Assembly.AssemblyName)
baseline, reason := records.LoadBaseline(unit.Assembly.AssemblyName)
if reason != "" {
return fallBack(reason)
}
Expand All @@ -88,10 +89,10 @@ func (runner *fastPathRunner) Try(
}
if nonSourceKey.Key != baseline.NonSourceKey.Key {
return fallBack("inputs other than source contents changed: " +
strings.Join(changedInputKinds(nonSourceKey, baseline.NonSourceKey), ", "))
strings.Join(changedInputKinds(nonSourceKey, nonSourceIdentity(baseline.NonSourceKey)), ", "))
}

if !records.generatorOutputUnchanged(baseline) {
if !records.GeneratorOutputUnchanged(baseline) {
return fallBack("generator output of the baseline is gone")
}

Expand All @@ -114,7 +115,7 @@ func (runner *fastPathRunner) Try(
// last full compile reported for the files that did not change.
func (runner *fastPathRunner) check(
ctx context.Context, c Compiler, plan BuildPlan, unit CompileUnit,
baseline storedBaseline, changed []string,
baseline resultstore.Baseline[Diagnostic], changed []string,
) fastPathAttempt {
startedAt := time.Now()
worker, err := runner.Worker.Ensure(ctx)
Expand Down Expand Up @@ -174,7 +175,7 @@ func projectRelativeReason(projectRoot string, reason string, changed []string)

// buildCheckRequest names, in absolute paths, what the worker checks and against which baseline.
func buildCheckRequest(
projectRoot string, baseline storedBaseline, responseFilePath string, changed []string,
projectRoot string, baseline resultstore.Baseline[Diagnostic], responseFilePath string, changed []string,
) fastcheck.CheckRequest {
request := fastcheck.CheckRequest{
ProjectRoot: projectRoot,
Expand All @@ -196,7 +197,7 @@ func buildCheckRequest(

// changedSources lists the sources whose content differs from the baseline, using the hashes the
// input key read rather than reading the files again.
func changedSources(unit CompileUnit, keyResult inputKeyResult, files map[string]baselineFile) []string {
func changedSources(unit CompileUnit, keyResult inputKeyResult, files map[string]resultstore.BaselineFile) []string {
changed := []string{}
for _, source := range unit.Sources {
if keyResult.SourceHashes[source] != files[source].ContentHash {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"time"

"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/fastcheck"
"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/resultstore"
)

// fakeDeclarationSeparator splits a fixture source into its declaration part and its body part, so
Expand Down Expand Up @@ -227,9 +228,9 @@ func (project *fastPathProject) hasBaseline() bool {
}

// baseline reads Alpha's baseline through the store and fails the test when there is none to use.
func (project *fastPathProject) baseline(t *testing.T) storedBaseline {
func (project *fastPathProject) baseline(t *testing.T) resultstore.Baseline[Diagnostic] {
t.Helper()
baseline, reason := project.records().loadBaseline("Alpha")
baseline, reason := project.records().LoadBaseline("Alpha")
if reason != "" {
t.Fatalf("expected a usable baseline for Alpha, got %q", reason)
}
Expand All @@ -238,7 +239,7 @@ func (project *fastPathProject) baseline(t *testing.T) storedBaseline {
}

// generatedFileCount counts the files under the generator output a baseline points at.
func (project *fastPathProject) generatedFileCount(t *testing.T, baseline storedBaseline) int {
func (project *fastPathProject) generatedFileCount(t *testing.T, baseline resultstore.Baseline[Diagnostic]) int {
t.Helper()
count := 0
err := filepath.WalkDir(projectPath(project.root, baseline.GeneratedDirectory),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
// matches the baseline, and the check that it is gone could run anywhere in the order unnoticed.
func (project *fastPathProject) recordBaselineWithGeneratorOutput(t *testing.T) string {
t.Helper()
generatedDirectoryPath := project.records().generatedDirectory("Alpha")
generatedDirectoryPath := project.records().GeneratedDirectory("Alpha")
recorder := newCachedSchedulerRecorder("Alpha", "Beta")
recorder.during = func(unit string) {
if unit == "Alpha" {
Expand Down
17 changes: 9 additions & 8 deletions cli/dispatcher/internal/compilecheck/fast_path_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"testing"

"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/fastcheck"
"github.com/hatayama/unity-cli-loop/dispatcher/internal/compilecheck/resultstore"
)

// Verifies that unchanged inputs are reused before the changed-files check is tried.
Expand Down Expand Up @@ -123,8 +124,8 @@ func TestHandCorruptedFailedManifestFallsBack(t *testing.T) {
project.recordBaseline(t)
project.editBody(t, 0, "edited")
baseline := project.baseline(t)
if err := project.records().recordCompile("Alpha", baseline.InputKey,
recordedCompile{Succeeded: false, Diagnostics: baseline.Diagnostics}, unitOutputNames(project.plan.Units[0])); err != nil {
if err := project.records().RecordCompile("Alpha", baseline.InputKey,
resultstore.CompileResult[Diagnostic]{Succeeded: false, Diagnostics: baseline.Diagnostics}, unitOutputNames(project.plan.Units[0])); err != nil {
t.Fatalf("failed to record the failed compile: %v", err)
}
recorder := newCachedSchedulerRecorder("Alpha", "Beta")
Expand Down Expand Up @@ -222,11 +223,11 @@ func TestMissingOrChangedGeneratorOutputFallsBack(t *testing.T) {
} {
t.Run(name, func(t *testing.T) {
project := newFastPathProject(t, fastPathMinimumSources)
generatedPath := filepath.Join(project.root, project.records().generatedDirectory("Alpha"))
generatedPath := filepath.Join(project.root, project.records().GeneratedDirectory("Alpha"))
recorder := newCachedSchedulerRecorder("Alpha", "Beta")
recorder.during = func(unit string) {
if unit == "Alpha" {
project.writeFile(t, filepath.Join(project.records().generatedDirectory("Alpha"), "Gen", "G.g.cs"), "class G { }")
project.writeFile(t, filepath.Join(project.records().GeneratedDirectory("Alpha"), "Gen", "G.g.cs"), "class G { }")
}
}
project.run(t, recorder, false)
Expand Down Expand Up @@ -361,7 +362,7 @@ func TestFastPathCleanResultKeepsBaselineFiles(t *testing.T) {
if recorder.runs["Beta"] != 0 || outcome.Skipped != 1 {
t.Errorf("expected Beta to be skipped, got %d runs and %d skipped", recorder.runs["Beta"], outcome.Skipped)
}
if project.worker.lastCheck.GeneratedDirectory != filepath.Join(project.root, project.records().generatedDirectory("Alpha")) {
if project.worker.lastCheck.GeneratedDirectory != filepath.Join(project.root, project.records().GeneratedDirectory("Alpha")) {
t.Errorf("expected the saved generator output to be passed, got %q", project.worker.lastCheck.GeneratedDirectory)
}
}
Expand Down Expand Up @@ -434,11 +435,11 @@ func TestZeroChangedFilesDropsBaselineAndFallsBack(t *testing.T) {
project.recordBaseline(t)
baseline := project.baseline(t)
records := project.records()
if err := records.recordCompile("Alpha", "tampered",
recordedCompile{Succeeded: true, Diagnostics: baseline.Diagnostics}, unitOutputNames(project.plan.Units[0])); err != nil {
if err := records.RecordCompile("Alpha", "tampered",
resultstore.CompileResult[Diagnostic]{Succeeded: true, Diagnostics: baseline.Diagnostics}, unitOutputNames(project.plan.Units[0])); err != nil {
t.Fatalf("failed to record the tampered compile: %v", err)
}
if err := records.recordBaseline("Alpha", baselineInputs{
if err := records.RecordBaseline("Alpha", resultstore.BaselineInputs{
InputKey: "tampered", NonSourceKey: baseline.NonSourceKey, WorkerKey: baseline.WorkerKey, Files: baseline.Files,
}); err != nil {
t.Fatalf("failed to record the tampered baseline: %v", err)
Expand Down
Loading
Loading