Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into document-symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
jackielii committed Oct 20, 2024
2 parents fcc0770 + bb5e41b commit 90c3f99
Show file tree
Hide file tree
Showing 116 changed files with 2,864 additions and 1,267 deletions.
2 changes: 1 addition & 1 deletion .version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.2.766
0.2.786
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ See user documentation at https://templ.guide
<a href="https://pkg.go.dev/github.com/a-h/templ"><img src="https://pkg.go.dev/badge/github.com/a-h/templ.svg" alt="Go Reference" /></a>
<a href="https://xcfile.dev"><img src="https://xcfile.dev/badge.svg" alt="xc compatible" /></a>
<a href="https://raw.githack.com/wiki/a-h/templ/coverage.html"><img src="https://github.com/a-h/templ/wiki/coverage.svg" alt="Go Coverage" /></a>
<a href="https://goreportcard.com/report/github.com/a-h/templ"><img src="https://goreportcard.com/badge/github.com/a-h/templ" alt="Go Report Card" /></a<
<a href="https://goreportcard.com/report/github.com/a-h/templ"><img src="https://goreportcard.com/badge/github.com/a-h/templ" alt="Go Report Card" /></a>
</p>

## Tasks
Expand Down
3 changes: 3 additions & 0 deletions benchmarks/templ/template_templ.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 2 additions & 7 deletions cfg/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,7 @@ import (
"strings"
)

type Flags struct {
// RawGo will enable the support of arbibrary Go code in templates.
RawGo bool
}
type Flags struct{}

var Experiment = parse()

Expand All @@ -19,7 +16,5 @@ func parse() *Flags {
m[strings.ToLower(f)] = true
}

return &Flags{
RawGo: m["rawgo"],
}
return &Flags{}
}
61 changes: 40 additions & 21 deletions cmd/templ/fmtcmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
)

type Arguments struct {
FailIfChanged bool
ToStdout bool
StdinFilepath string
Files []string
Expand All @@ -26,9 +27,10 @@ type Arguments struct {
func Run(log *slog.Logger, stdin io.Reader, stdout io.Writer, args Arguments) (err error) {
// If no files are provided, read from stdin and write to stdout.
if len(args.Files) == 0 {
return format(writeToWriter(stdout), readFromReader(stdin, args.StdinFilepath), true)
out, _ := format(writeToWriter(stdout), readFromReader(stdin, args.StdinFilepath), true)
return out
}
process := func(fileName string) error {
process := func(fileName string) (error, bool) {
read := readFromFile(fileName)
write := writeToFile
if args.ToStdout {
Expand All @@ -38,22 +40,24 @@ func Run(log *slog.Logger, stdin io.Reader, stdout io.Writer, args Arguments) (e
return format(write, read, writeIfUnchanged)
}
dir := args.Files[0]
return NewFormatter(log, dir, process, args.WorkerCount).Run()
return NewFormatter(log, dir, process, args.WorkerCount, args.FailIfChanged).Run()
}

type Formatter struct {
Log *slog.Logger
Dir string
Process func(fileName string) error
WorkerCount int
Log *slog.Logger
Dir string
Process func(fileName string) (error, bool)
WorkerCount int
FailIfChange bool
}

func NewFormatter(log *slog.Logger, dir string, process func(fileName string) error, workerCount int) *Formatter {
func NewFormatter(log *slog.Logger, dir string, process func(fileName string) (error, bool), workerCount int, failIfChange bool) *Formatter {
f := &Formatter{
Log: log,
Dir: dir,
Process: process,
WorkerCount: workerCount,
Log: log,
Dir: dir,
Process: process,
WorkerCount: workerCount,
FailIfChange: failIfChange,
}
if f.WorkerCount == 0 {
f.WorkerCount = runtime.NumCPU()
Expand All @@ -62,12 +66,16 @@ func NewFormatter(log *slog.Logger, dir string, process func(fileName string) er
}

func (f *Formatter) Run() (err error) {
changesMade := 0
start := time.Now()
results := make(chan processor.Result)
f.Log.Debug("Walking directory", slog.String("path", f.Dir))
go processor.Process(f.Dir, f.Process, f.WorkerCount, results)
var successCount, errorCount int
for r := range results {
if r.ChangesMade {
changesMade += 1
}
if r.Error != nil {
f.Log.Error(r.FileName, slog.Any("error", r.Error))
errorCount++
Expand All @@ -76,10 +84,18 @@ func (f *Formatter) Run() (err error) {
f.Log.Debug(r.FileName, slog.Duration("duration", r.Duration))
successCount++
}
f.Log.Info("Format complete", slog.Int("count", successCount+errorCount), slog.Int("errors", errorCount), slog.Duration("duration", time.Since(start)))

if f.FailIfChange && changesMade > 0 {
f.Log.Error("Templates were valid but not properly formatted", slog.Int("count", successCount+errorCount), slog.Int("changed", changesMade), slog.Int("errors", errorCount), slog.Duration("duration", time.Since(start)))
return fmt.Errorf("templates were not formatted properly")
}

f.Log.Info("Format Complete", slog.Int("count", successCount+errorCount), slog.Int("errors", errorCount), slog.Int("changed", changesMade), slog.Duration("duration", time.Since(start)))

if errorCount > 0 {
return fmt.Errorf("formatting failed")
}

return
}

Expand Down Expand Up @@ -122,26 +138,29 @@ func writeToFile(fileName, tgt string) error {
return atomic.WriteFile(fileName, bytes.NewBufferString(tgt))
}

func format(write writer, read reader, writeIfUnchanged bool) (err error) {
func format(write writer, read reader, writeIfUnchanged bool) (err error, fileChanged bool) {
fileName, src, err := read()
if err != nil {
return err
return err, false
}
t, err := parser.ParseString(src)
if err != nil {
return err
return err, false
}
t.Filepath = fileName
t, err = imports.Process(t)
if err != nil {
return err
return err, false
}
w := new(bytes.Buffer)
if err = t.Write(w); err != nil {
return fmt.Errorf("formatting error: %w", err)
return fmt.Errorf("formatting error: %w", err), false
}
if !writeIfUnchanged && src == w.String() {
return nil

fileChanged = (src != w.String())

if !writeIfUnchanged && !fileChanged {
return nil, fileChanged
}
return write(fileName, w.String())
return write(fileName, w.String()), fileChanged
}
48 changes: 48 additions & 0 deletions cmd/templ/fmtcmd/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ func TestFormat(t *testing.T) {
Files: []string{
tp.testFiles["a.templ"].name,
},
FailIfChanged: false,
}); err != nil {
t.Fatalf("failed to run format command: %v", err)
}
Expand All @@ -101,6 +102,7 @@ func TestFormat(t *testing.T) {
Files: []string{
tp.testFiles["a.templ"].name,
},
FailIfChanged: false,
}); err != nil {
t.Fatalf("failed to run format command: %v", err)
}
Expand All @@ -112,4 +114,50 @@ func TestFormat(t *testing.T) {
t.Error(diff)
}
})

t.Run("fails when fail flag used and change occurs", func(t *testing.T) {
tp, err := setupProjectDir()
if err != nil {
t.Fatalf("failed to setup project dir: %v", err)
}
defer tp.cleanup()
if err = Run(log, nil, nil, Arguments{
Files: []string{
tp.testFiles["a.templ"].name,
},
FailIfChanged: true,
}); err == nil {
t.Fatal("command should have exited with an error and did not")
}
data, err := os.ReadFile(tp.testFiles["a.templ"].name)
if err != nil {
t.Fatalf("failed to read file: %v", err)
}
if diff := cmp.Diff(tp.testFiles["a.templ"].expected, string(data)); diff != "" {
t.Error(diff)
}
})

t.Run("passes when fail flag used and no change occurs", func(t *testing.T) {
tp, err := setupProjectDir()
if err != nil {
t.Fatalf("failed to setup project dir: %v", err)
}
defer tp.cleanup()
if err = Run(log, nil, nil, Arguments{
Files: []string{
tp.testFiles["c.templ"].name,
},
FailIfChanged: true,
}); err != nil {
t.Fatalf("failed to run format command: %v", err)
}
data, err := os.ReadFile(tp.testFiles["c.templ"].name)
if err != nil {
t.Fatalf("failed to read file: %v", err)
}
if diff := cmp.Diff(tp.testFiles["c.templ"].expected, string(data)); diff != "" {
t.Error(diff)
}
})
}
22 changes: 21 additions & 1 deletion cmd/templ/fmtcmd/testdata.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ templ b() {
<div><p>B
</p></div>
}
-- a.templ --
-- b.templ --
package test

templ b() {
Expand All @@ -32,3 +32,23 @@ templ b() {
</p>
</div>
}
-- c.templ --
package test

templ c() {
<div>
<p>
C
</p>
</div>
}
-- c.templ --
package test

templ c() {
<div>
<p>
C
</p>
</div>
}
108 changes: 108 additions & 0 deletions cmd/templ/generatecmd/run/run_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package run_test

import (
"context"
"embed"
"io"
"net/http"
"os"
"path/filepath"
"syscall"
"testing"
"time"

"github.com/a-h/templ/cmd/templ/generatecmd/run"
)

//go:embed testprogram/*
var testprogram embed.FS

func TestGoRun(t *testing.T) {
if testing.Short() {
t.Skip("Skipping test in short mode.")
}

// Copy testprogram to a temporary directory.
dir, err := os.MkdirTemp("", "testprogram")
if err != nil {
t.Fatalf("failed to make test dir: %v", err)
}
files, err := testprogram.ReadDir("testprogram")
if err != nil {
t.Fatalf("failed to read embedded dir: %v", err)
}
for _, file := range files {
srcFileName := "testprogram/" + file.Name()
srcData, err := testprogram.ReadFile(srcFileName)
if err != nil {
t.Fatalf("failed to read src file %q: %v", srcFileName, err)
}
tgtFileName := filepath.Join(dir, file.Name())
tgtFile, err := os.Create(tgtFileName)
if err != nil {
t.Fatalf("failed to create tgt file %q: %v", tgtFileName, err)
}
defer tgtFile.Close()
if _, err := tgtFile.Write(srcData); err != nil {
t.Fatalf("failed to write to tgt file %q: %v", tgtFileName, err)
}
}
// Rename the go.mod.embed file to go.mod.
if err := os.Rename(filepath.Join(dir, "go.mod.embed"), filepath.Join(dir, "go.mod")); err != nil {
t.Fatalf("failed to rename go.mod.embed: %v", err)
}

tests := []struct {
name string
cmd string
}{
{
name: "Well behaved programs get shut down",
cmd: "go run .",
},
{
name: "Badly behaved programs get shut down",
cmd: "go run . -badly-behaved",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
cmd, err := run.Run(ctx, dir, tt.cmd)
if err != nil {
t.Fatalf("failed to run program: %v", err)
}

time.Sleep(1 * time.Second)

pid := cmd.Process.Pid

if err := run.KillAll(); err != nil {
t.Fatalf("failed to kill all: %v", err)
}

// Check the parent process is no longer running.
if err := cmd.Process.Signal(os.Signal(syscall.Signal(0))); err == nil {
t.Fatalf("process %d is still running", pid)
}
// Check that the child was stopped.
body, err := readResponse("http://localhost:7777")
if err == nil {
t.Fatalf("child process is still running: %s", body)
}
})
}
}

func readResponse(url string) (body string, err error) {
resp, err := http.Get(url)
if err != nil {
return body, err
}
defer resp.Body.Close()
b, err := io.ReadAll(resp.Body)
if err != nil {
return body, err
}
return string(b), nil
}
Loading

0 comments on commit 90c3f99

Please sign in to comment.