Skip to content

Commit 66877cf

Browse files
authored
Merge pull request #205 from gofiber/codex/2025-09-03-12-12-29
2 parents ef273a3 + b1e9bfe commit 66877cf

File tree

2 files changed

+102
-63
lines changed

2 files changed

+102
-63
lines changed

cmd/internal/migrations/v3/context_methods.go

Lines changed: 56 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,51 @@ func MigrateContextMethods(cmd *cobra.Command, cwd string, _, _ *semver.Version)
2020
changed, err := internal.ChangeFileContent(cwd, func(content string) string {
2121
orig := content
2222

23-
// UserContext() removed - Ctx implements context.Context
23+
// old Context() returned fasthttp.RequestCtx
24+
if !strings.Contains(orig, ".SetContext(") {
25+
fset := token.NewFileSet()
26+
file, err := parser.ParseFile(fset, "", content, parser.ParseComments)
27+
if err == nil {
28+
modified := false
29+
baseIdent := func(expr ast.Expr) *ast.Ident {
30+
for {
31+
switch e := expr.(type) {
32+
case *ast.Ident:
33+
return e
34+
case *ast.SelectorExpr:
35+
expr = e.X
36+
case *ast.CallExpr:
37+
expr = e.Fun
38+
default:
39+
return nil
40+
}
41+
}
42+
}
43+
ast.Inspect(file, func(n ast.Node) bool {
44+
call, ok := n.(*ast.CallExpr)
45+
if !ok {
46+
return true
47+
}
48+
sel, ok := call.Fun.(*ast.SelectorExpr)
49+
if !ok || sel.Sel.Name != "Context" || len(call.Args) != 0 {
50+
return true
51+
}
52+
if ident := baseIdent(sel.X); ident != nil && isFiberCtx(orig, ident.Name) {
53+
sel.Sel.Name = "RequestCtx"
54+
modified = true
55+
}
56+
return true
57+
})
58+
if modified {
59+
var buf bytes.Buffer
60+
if err := format.Node(&buf, fset, file); err == nil {
61+
content = buf.String()
62+
}
63+
}
64+
}
65+
}
66+
67+
// UserContext() replaced by Context()
2468
reUserCtx := regexp.MustCompile(`(\w+)\.UserContext\(\)`)
2569
content = reUserCtx.ReplaceAllStringFunc(content, func(match string) string {
2670
parts := reUserCtx.FindStringSubmatch(match)
@@ -29,68 +73,23 @@ func MigrateContextMethods(cmd *cobra.Command, cwd string, _, _ *semver.Version)
2973
}
3074
ident := parts[1]
3175
if isFiberCtx(orig, ident) {
32-
return ident
76+
return ident + ".Context()"
3377
}
3478
return match
3579
})
3680

37-
// old Context() returned fasthttp.RequestCtx
38-
fset := token.NewFileSet()
39-
file, err := parser.ParseFile(fset, "", content, parser.ParseComments)
40-
if err == nil {
41-
modified := false
42-
baseIdent := func(expr ast.Expr) *ast.Ident {
43-
for {
44-
switch e := expr.(type) {
45-
case *ast.Ident:
46-
return e
47-
case *ast.SelectorExpr:
48-
expr = e.X
49-
case *ast.CallExpr:
50-
expr = e.Fun
51-
default:
52-
return nil
53-
}
54-
}
55-
}
56-
ast.Inspect(file, func(n ast.Node) bool {
57-
call, ok := n.(*ast.CallExpr)
58-
if !ok {
59-
return true
60-
}
61-
sel, ok := call.Fun.(*ast.SelectorExpr)
62-
if !ok || sel.Sel.Name != "Context" || len(call.Args) != 0 {
63-
return true
64-
}
65-
if ident := baseIdent(sel.X); ident != nil && isFiberCtx(orig, ident.Name) {
66-
sel.Sel.Name = "RequestCtx"
67-
modified = true
68-
}
69-
return true
70-
})
71-
if modified {
72-
var buf bytes.Buffer
73-
if err := format.Node(&buf, fset, file); err == nil {
74-
content = buf.String()
75-
}
76-
}
77-
}
78-
79-
// SetUserContext removed - comment out the call
80-
reSetUserCtx := regexp.MustCompile(`(?m)^(\s*)(.*?\b(\w+)\.SetUserContext\([^\n]*\).*)$`)
81-
content = reSetUserCtx.ReplaceAllStringFunc(content, func(line string) string {
82-
if strings.Contains(line, "TODO: SetUserContext was removed") {
83-
return line
84-
}
85-
parts := reSetUserCtx.FindStringSubmatch(line)
86-
if len(parts) != 4 {
87-
return line
81+
// SetUserContext renamed to SetContext
82+
reSetUserCtx := regexp.MustCompile(`(\w+)\.SetUserContext\(`)
83+
content = reSetUserCtx.ReplaceAllStringFunc(content, func(match string) string {
84+
parts := reSetUserCtx.FindStringSubmatch(match)
85+
if len(parts) != 2 {
86+
return match
8887
}
89-
ident := parts[3]
90-
if !isFiberCtx(orig, ident) {
91-
return line
88+
ident := parts[1]
89+
if isFiberCtx(orig, ident) {
90+
return ident + ".SetContext("
9291
}
93-
return fmt.Sprintf("%s// TODO: SetUserContext was removed, please migrate manually: %s", parts[1], parts[2])
92+
return match
9493
})
9594

9695
return content

cmd/internal/migrations/v3/context_methods_test.go

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,11 @@ func handler(c fiber.Ctx) error {
3535
require.NoError(t, v3.MigrateContextMethods(cmd, dir, nil, nil))
3636

3737
content := readFile(t, file)
38-
assert.Contains(t, content, ".RequestCtx()")
39-
assert.NotContains(t, content, ".Context()")
40-
assert.Contains(t, content, `// TODO: SetUserContext was removed, please migrate manually: c.SetUserContext(ctx)`)
41-
assert.Contains(t, content, "uc := c")
38+
assert.Contains(t, content, "ctx := c.RequestCtx()")
39+
assert.Contains(t, content, "uc := c.Context()")
40+
assert.Contains(t, content, "c.SetContext(ctx)")
41+
assert.NotContains(t, content, ".UserContext()")
42+
assert.NotContains(t, content, "SetUserContext")
4243
assert.Contains(t, buf.String(), "Migrating context methods")
4344
}
4445

@@ -62,8 +63,9 @@ func handler(ctx fiber.Ctx) error {
6263
require.NoError(t, v3.MigrateContextMethods(cmd, dir, nil, nil))
6364

6465
content := readFile(t, file)
65-
assert.Contains(t, content, `// TODO: SetUserContext was removed, please migrate manually: res := ctx.SetUserContext(ctx.RequestCtx())`)
66+
assert.Contains(t, content, `res := ctx.SetContext(ctx.RequestCtx())`)
6667
assert.NotContains(t, content, `.UserContext()`)
68+
assert.NotContains(t, content, "SetUserContext")
6769
assert.Contains(t, buf.String(), "Migrating context methods")
6870
}
6971

@@ -88,7 +90,45 @@ func handler(c fiber.Ctx) error {
8890
require.NoError(t, v3.MigrateContextMethods(cmd, dir, nil, nil))
8991
second := readFile(t, file)
9092
assert.Equal(t, first, second)
91-
assert.Equal(t, 1, strings.Count(second, "TODO: SetUserContext was removed"))
93+
assert.Equal(t, 1, strings.Count(second, "SetContext("))
94+
}
95+
96+
func Test_MigrateContextMethods_MultipleRuns(t *testing.T) {
97+
t.Parallel()
98+
99+
dir, err := os.MkdirTemp("", "mcmtestmulti2")
100+
require.NoError(t, err)
101+
defer func() { require.NoError(t, os.RemoveAll(dir)) }()
102+
103+
file := writeTempFile(t, dir, `package main
104+
import "github.com/gofiber/fiber/v2"
105+
func handler(c fiber.Ctx) error {
106+
ctx := c.Context()
107+
uc := c.UserContext()
108+
c.SetUserContext(ctx)
109+
c.SetUserContext(c.Context())
110+
_ = uc
111+
return nil
112+
}`)
113+
114+
var buf bytes.Buffer
115+
cmd := newCmd(&buf)
116+
require.NoError(t, v3.MigrateContextMethods(cmd, dir, nil, nil))
117+
first := readFile(t, file)
118+
119+
require.Contains(t, first, "ctx := c.RequestCtx()")
120+
require.Contains(t, first, "uc := c.Context()")
121+
require.Contains(t, first, "c.SetContext(ctx)")
122+
require.Contains(t, first, "c.SetContext(c.RequestCtx())")
123+
require.NotContains(t, first, ".UserContext()")
124+
require.NotContains(t, first, "SetUserContext")
125+
126+
require.NoError(t, v3.MigrateContextMethods(cmd, dir, nil, nil))
127+
second := readFile(t, file)
128+
assert.Equal(t, first, second)
129+
assert.Equal(t, 1, strings.Count(second, "uc := c.Context()"))
130+
assert.Equal(t, 2, strings.Count(second, ".RequestCtx()"))
131+
assert.Equal(t, 2, strings.Count(second, "SetContext("))
92132
}
93133

94134
func Test_MigrateContextMethods_SkipNonFiber(t *testing.T) {

0 commit comments

Comments
 (0)