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
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ module github.com/moderneinc/recipes-go

go 1.25.0

require github.com/openrewrite/rewrite/rewrite-go v0.0.29
require github.com/openrewrite/rewrite/rewrite-go v0.0.30

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/google/uuid v1.6.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.11.1 // indirect
golang.org/x/mod v0.35.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
14 changes: 12 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/openrewrite/rewrite/rewrite-go v0.0.29 h1:Fo6ECB7n1ylCqO1FvFM5aAvxd8PEcpAvykShJukKiSE=
github.com/openrewrite/rewrite/rewrite-go v0.0.29/go.mod h1:YquZz5hJMNrl7quFsOhlgyc5+UTV05XyFBSLJITdtvw=
github.com/openrewrite/rewrite/rewrite-go v0.0.30 h1:jAliVCxsa9IwQt+ZdDuHAXwNDDh0+CsOdnOLwcvJvCY=
github.com/openrewrite/rewrite/rewrite-go v0.0.30/go.mod h1:6fC3xnUD4/MGZsuWVcEwWlaBsxZTP1ueCWf69rKLeQQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM=
golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
12 changes: 6 additions & 6 deletions recipes/errorhandling/use_errors_as.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,8 @@ func matchCommaOkTypeAssert(swi *golang.StatementWithInit) (string, java.Express
return "", nil, nil
}

// The value must be a TypeCast (type assertion)
tc, ok := ma.Values[0].Element.(*java.TypeCast)
// The value must be a type assertion
ta, ok := ma.Values[0].Element.(*golang.TypeAssertion)
if !ok {
return "", nil, nil
}
Expand Down Expand Up @@ -153,17 +153,17 @@ func matchCommaOkTypeAssert(swi *golang.StatementWithInit) (string, java.Express

// The expression being asserted must be an error.
// Check type info first; fall back to name heuristic.
if !looksLikeError(tc.Expr) {
if !looksLikeError(ta.Left.Element) {
return "", nil, nil
}

// Extract the type from the type assertion (inside the ControlParentheses)
if tc.Clazz == nil {
if ta.AssertedType == nil {
return "", nil, nil
}
typeExpr := tc.Clazz.Tree.Element
typeExpr := ta.AssertedType.Tree.Element

return targetIdent.Name, typeExpr, tc.Expr
return targetIdent.Name, typeExpr, ta.Left.Element
}

// Reports whether the expression is assignable to error, deciding from the
Expand Down
42 changes: 41 additions & 1 deletion recipes/migration/jsonv2/relocate_raw_message.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ func (v *relocateRawMessageVisitor) VisitCompilationUnit(cu *golang.CompilationU
return drainQueuedImports(v, cu, p)
}

// The type the rewritten nodes carry.
var jsontextValueType = &java.JavaTypeClass{FullyQualifiedName: "encoding/json/jsontext.Value", Kind: "Class"}

// Rewrites a json.RawMessage type reference to jsontext.Value, keeping the
// original whitespace.
func (v *relocateRawMessageVisitor) VisitFieldAccess(fa *java.FieldAccess, p any) java.J {
Expand All @@ -95,10 +98,46 @@ func (v *relocateRawMessageVisitor) VisitFieldAccess(fa *java.FieldAccess, p any
Before: fa.Name.Before,
Element: &java.Identifier{Prefix: fa.Name.Element.Prefix, Name: "Value"},
}
c.Type = nil
c.Type = jsontextValueType
return &c
}

// A field keeps the type it was attributed at parse, so the declaration has to
// be re-attributed too: left alone it still reads as encoding/json.RawMessage,
// and RemoveImport rightly keeps an import the tree says is in use.
func (v *relocateRawMessageVisitor) VisitVariableDeclarations(vd *java.VariableDeclarations, p any) java.J {
vd = v.GoVisitor.VisitVariableDeclarations(vd, p).(*java.VariableDeclarations)
if !isJsontextValue(vd.TypeExpr) {
return vd
}
c := *vd
c.Variables = make([]java.RightPadded[*java.VariableDeclarator], len(vd.Variables))
copy(c.Variables, vd.Variables)
for i, rp := range c.Variables {
if rp.Element == nil || rp.Element.Name == nil || rp.Element.Name.Type == jsontextValueType {
continue
}
declarator := *rp.Element
name := *declarator.Name
name.Type = jsontextValueType
declarator.Name = &name
c.Variables[i] = java.RightPadded[*java.VariableDeclarator]{
Element: &declarator, After: rp.After, Markers: rp.Markers,
}
}
return &c
}

// isJsontextValue reports whether expr is the `jsontext.Value` this recipe writes.
func isJsontextValue(expr java.Expression) bool {
fa, ok := expr.(*java.FieldAccess)
if !ok || fa.Name.Element == nil || fa.Name.Element.Name != "Value" {
return false
}
target, ok := fa.Target.(*java.Identifier)
return ok && target.Name == "jsontext"
}

// Rewrites a json.RawMessage(x) conversion to jsontext.Value(x).
func (v *relocateRawMessageVisitor) VisitMethodInvocation(mi *java.MethodInvocation, p any) java.J {
mi = v.GoVisitor.VisitMethodInvocation(mi, p).(*java.MethodInvocation)
Expand All @@ -116,6 +155,7 @@ func (v *relocateRawMessageVisitor) VisitMethodInvocation(mi *java.MethodInvocat
After: mi.Select.After,
}
c.Name = &java.Identifier{Prefix: mi.Name.Prefix, Name: "Value"}
c.MethodType = nil
return &c
}

Expand Down
20 changes: 10 additions & 10 deletions recipes/redundancy/remove_redundant_interface_assertion.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,14 @@ type removeRedundantInterfaceAssertionVisitor struct {
visitor.GoVisitor
}

func (v *removeRedundantInterfaceAssertionVisitor) VisitTypeCast(tc *java.TypeCast, p any) java.J {
tc = v.GoVisitor.VisitTypeCast(tc, p).(*java.TypeCast)
func (v *removeRedundantInterfaceAssertionVisitor) VisitTypeAssertion(ta *golang.TypeAssertion, p any) java.J {
ta = v.GoVisitor.VisitTypeAssertion(ta, p).(*golang.TypeAssertion)

if tc.Clazz == nil {
return tc
if ta.AssertedType == nil {
return ta
}

inner := tc.Clazz.Tree.Element
inner := ta.AssertedType.Tree.Element

isRedundant := false

Expand All @@ -70,14 +70,14 @@ func (v *removeRedundantInterfaceAssertionVisitor) VisitTypeCast(tc *java.TypeCa
}

if !isRedundant {
return tc
return ta
}

// Replace the type assertion with just the inner expression.
// The Expr already carries the correct prefix (the space between the
// Replace the type assertion with just the asserted expression.
// That expression already carries the correct prefix (the space between the
// preceding token and the expression, e.g. the space after "=" in "_ = x.(any)").
// We prepend tc.Prefix whitespace in case the TypeCast itself had leading space.
return prependExprPrefix(tc.Expr, tc.Prefix)
// We prepend ta.Prefix whitespace in case the assertion itself had leading space.
return prependExprPrefix(ta.Left.Element, ta.Prefix)
}

// prependExprPrefix prepends extra whitespace to an expression's existing prefix.
Expand Down
3 changes: 2 additions & 1 deletion recipes/redundancy/remove_redundant_sprintf.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/openrewrite/rewrite/rewrite-go/pkg/recipe"
recipegolang "github.com/openrewrite/rewrite/rewrite-go/pkg/recipe/golang"
"github.com/openrewrite/rewrite/rewrite-go/pkg/template"
"github.com/openrewrite/rewrite/rewrite-go/pkg/tree/golang"
"github.com/openrewrite/rewrite/rewrite-go/pkg/tree/java"
"github.com/openrewrite/rewrite/rewrite-go/pkg/visitor"
)
Expand Down Expand Up @@ -88,7 +89,7 @@ func withLeadingPrefix(e java.Expression, p java.Space) java.Expression {
return n.WithPrefix(p)
case *java.ArrayAccess:
return n.WithPrefix(p)
case *java.TypeCast:
case *golang.TypeAssertion:
return n.WithPrefix(p)
}
return e
Expand Down
10 changes: 7 additions & 3 deletions recipes/style/check_template_execute_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,13 @@ func buildIfInitErrCheck(mi *java.MethodInvocation) *golang.StatementWithInit {
}

return &golang.StatementWithInit{
ID: uuid.New(),
Prefix: prefix,
Init: java.RightPadded[java.Statement]{Element: initAssign},
ID: uuid.New(),
Prefix: prefix,
Init: java.RightPadded[java.Statement]{
Element: initAssign,
// The printer emits the `;` between init and condition from this marker.
Markers: java.Markers{ID: uuid.New(), Entries: []java.Marker{golang.NewSemicolon()}},
},
Statement: innerIf,
}
}
Expand Down
6 changes: 3 additions & 3 deletions recipes/style/use_comma_ok_type_assertion.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,9 @@ func (v *useCommaOkTypeAssertionVisitor) VisitBlock(block *java.Block, p any) ja
continue
}

// RHS must be a TypeCast (type assertion)
_, isCast := assign.Value.Element.(*java.TypeCast)
if !isCast {
// RHS must be a type assertion
_, isAssertion := assign.Value.Element.(*golang.TypeAssertion)
if !isAssertion {
newStmts = append(newStmts, rp)
continue
}
Expand Down
Loading