Skip to content

Commit

Permalink
Add static.FromDir().
Browse files Browse the repository at this point in the history
  • Loading branch information
jmalloc committed Aug 16, 2024
1 parent a765c9c commit cb13e28
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 192 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,17 @@ The format is based on [Keep a Changelog], and this project adheres to

## [0.13.5] - 2024-08-16

### Added

- Added `static.PackagesLoadMode` as a convenience for using Go's built-in
`packages.Load()` with a mode suitable for static analysis.
- Added `static.FromDir()` as a convenience for analyzing packages recursively
from a directory.

### Fixed

- Fixed panicking when handling type aliases in static analysis.
- Handle alias types under Go v1.23 (or when using `GODEBUG=gotypealias=1`), which
previously caused a panic.

## [0.13.4] - 2024-08-16

Expand Down
10 changes: 1 addition & 9 deletions static/adaptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,12 @@ import (
. "github.com/dogmatiq/configkit/static"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"golang.org/x/tools/go/packages"
)

var _ = Describe("func FromPackages() (adaptor function)", func() {
When("the the handler is created by adapting a partial handler implementation", func() {
It("builds the configuration from the adapted type", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/adaptor",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/adaptor")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))
Expect(apps[0].Handlers().Processes()).To(HaveLen(1))
Expand Down
79 changes: 9 additions & 70 deletions static/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,12 @@ import (
. "github.com/dogmatiq/configkit/static"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"golang.org/x/tools/go/packages"
)

var _ = Describe("func FromPackages() (application detection)", func() {
When("a package contains a single application", func() {
It("returns the application configuration", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/apps/single-app",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/apps/single-app")
Expect(apps).To(HaveLen(1))

Expect(apps[0].Identity()).To(
Expand All @@ -44,14 +36,7 @@ var _ = Describe("func FromPackages() (application detection)", func() {

When("multiple packages contain applications", func() {
It("returns all of the application configurations", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/apps/multiple-apps-in-pkgs",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/apps/multiple-apps-in-pkgs")
Expect(apps).To(HaveLen(2))

Expect(
Expand All @@ -76,14 +61,7 @@ var _ = Describe("func FromPackages() (application detection)", func() {

When("a single package contains multiple applications", func() {
It("returns all of the application configurations", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/apps/multiple-apps-in-single-pkg/apps",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/apps/multiple-apps-in-single-pkg/apps")
Expect(apps).To(HaveLen(2))

Expect(
Expand All @@ -108,16 +86,9 @@ var _ = Describe("func FromPackages() (application detection)", func() {

When("a package contains an application implemented with pointer receivers", func() {
It("returns the application configuration", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/apps/pointer-receiver-app",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)

apps := FromDir("testdata/apps/pointer-receiver-app")
Expect(apps).To(HaveLen(1))

Expect(apps[0].Identity()).To(
Equal(
configkit.Identity{
Expand All @@ -131,30 +102,16 @@ var _ = Describe("func FromPackages() (application detection)", func() {

When("none of the packages contain any applications", func() {
It("returns an empty slice", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/apps/no-app",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)

apps := FromDir("testdata/apps/no-app")
Expect(apps).To(BeEmpty())
})
})

When("a field within the application type is registered as a handler", func() {
It("includes the handler in the application configuration", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/apps/handler-from-field",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/apps/handler-from-field")
Expect(apps).To(HaveLen(1))

Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))

a := apps[0].Handlers().Aggregates()[0]
Expand All @@ -171,14 +128,7 @@ var _ = Describe("func FromPackages() (application detection)", func() {

When("an application in the package has multiple handlers", func() {
It("returns all messages consumed or produced by all handlers", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/apps/app-level-messages",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/apps/app-level-messages")
Expect(apps).To(HaveLen(1))

Expect(apps[0].MessageNames()).To(Equal(
Expand All @@ -200,14 +150,3 @@ var _ = Describe("func FromPackages() (application detection)", func() {
})
})
})

func loadPackages(cfg packages.Config) []*packages.Package {
pkgs, err := packages.Load(&cfg, "./...")
Expect(err).NotTo(HaveOccurred())

for _, pkg := range pkgs {
ExpectWithOffset(1, pkg.Errors).To(BeEmpty())
}

return pkgs
}
10 changes: 1 addition & 9 deletions static/constructor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,12 @@ import (
. "github.com/dogmatiq/configkit/static"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"golang.org/x/tools/go/packages"
)

var _ = Describe("func FromPackages() (constructor function)", func() {
When("the handler is created by a call to a 'constructor' function", func() {
It("builds the configuration from the adapted type", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/constructor",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/constructor")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))
Expect(apps[0].Handlers().Processes()).To(HaveLen(1))
Expand Down
82 changes: 9 additions & 73 deletions static/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
. "github.com/dogmatiq/configkit/static"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"golang.org/x/tools/go/packages"
)

// matchIdentities matches the given identities to those of the handlers in the
Expand All @@ -27,14 +26,7 @@ func matchIdentities(
var _ = Describe("func FromPackages() (handler analysis)", func() {
When("the application contains a single handler of each type", func() {
It("returns a single configuration for each handler type", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/single",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/single")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))
Expect(apps[0].Handlers().Processes()).To(HaveLen(1))
Expand Down Expand Up @@ -176,14 +168,7 @@ var _ = Describe("func FromPackages() (handler analysis)", func() {
})

It("returns a single configuration for each handler type", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/typealias",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/typealias")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))
Expect(apps[0].Handlers().Processes()).To(HaveLen(1))
Expand Down Expand Up @@ -311,14 +296,7 @@ var _ = Describe("func FromPackages() (handler analysis)", func() {

When("messages are passed to the *Configurer.Routes() method", func() {
It("includes messages passed as args to *Configurer.Routes() method only", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/only-routes-args",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/only-routes-args")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))
Expect(apps[0].Handlers().Processes()).To(HaveLen(1))
Expand Down Expand Up @@ -446,14 +424,7 @@ var _ = Describe("func FromPackages() (handler analysis)", func() {

When("messages are passed to the *Configurer.Routes() method as a dynamically populated splice", func() {
It("returns a single configuration for each handler type", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/dynamic-routes",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/dynamic-routes")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))
Expect(apps[0].Handlers().Processes()).To(HaveLen(1))
Expand Down Expand Up @@ -581,14 +552,7 @@ var _ = Describe("func FromPackages() (handler analysis)", func() {

When("messages are passed to the *Configurer.Routes() method in conditional branches", func() {
It("returns messages populated in every conditional branch", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/conditional-branches",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/conditional-branches")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))
Expect(apps[0].Handlers().Processes()).To(HaveLen(1))
Expand Down Expand Up @@ -716,14 +680,7 @@ var _ = Describe("func FromPackages() (handler analysis)", func() {

When("nil is passed to a call of *Configurer.Routes() methods", func() {
It("does not populate messages", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/nil-routes",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/nil-routes")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))
Expect(apps[0].Handlers().Processes()).To(HaveLen(1))
Expand Down Expand Up @@ -827,14 +784,7 @@ var _ = Describe("func FromPackages() (handler analysis)", func() {

When("the application multiple handlers of each type", func() {
It("returns all of the handler configurations", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/multiple",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/multiple")
Expect(apps).To(HaveLen(1))

matchIdentities(
Expand Down Expand Up @@ -877,29 +827,15 @@ var _ = Describe("func FromPackages() (handler analysis)", func() {

When("a nil value is passed as a handler", func() {
It("does not add a handler to the application configuration", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/nil-handler",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/nil-handler")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers()).To(Equal(configkit.HandlerSet{}))
})
})

When("a handler with a non-pointer methodset is registered as a pointer", func() {
It("includes the handler in the application configuration", func() {
cfg := packages.Config{
Mode: LoadPackagesConfigMode,
Dir: "testdata/handlers/pointer-handler-with-non-pointer-methodset",
}

pkgs := loadPackages(cfg)

apps := FromPackages(pkgs)
apps := FromDir("testdata/handlers/pointer-handler-with-non-pointer-methodset")
Expect(apps).To(HaveLen(1))
Expect(apps[0].Handlers().Aggregates()).To(HaveLen(1))
Expect(apps[0].Handlers().Processes()).To(HaveLen(1))
Expand Down
Loading

0 comments on commit cb13e28

Please sign in to comment.