@@ -100,7 +100,8 @@ func collectImports(im *Imports, p plan.Plan) {
100100func writeContainer (w io.Writer , im * Imports , p plan.Plan ) error {
101101 name := p .ConstructorName
102102 structName := p .Container .StructName
103- paramSig := formatParams (im , p .Inputs )
103+ ns := assignNames (im , p )
104+ paramSig := formatParams (im , p .Inputs , ns )
104105 retSig := im .QualifyType (p .ReturnType )
105106
106107 fmt .Fprintf (w , "// %s initializes dependencies and constructs %s.\n " , name , structName )
@@ -110,29 +111,86 @@ func writeContainer(w io.Writer, im *Imports, p plan.Plan) error {
110111 fmt .Fprintf (w , "func %s(%s) %s {\n " , name , paramSig , retSig )
111112 }
112113
113- wrote , err := writeSteps (w , im , p , retSig )
114+ wrote , err := writeSteps (w , im , p , ns , retSig )
114115 if err != nil {
115116 return err
116117 }
117118
118- writeStructLiteral (w , p , wrote )
119+ writeStructLiteral (w , p , ns , wrote )
119120 if p .ReturnsError {
120121 fmt .Fprint (w , ", nil" )
121122 }
122123 fmt .Fprint (w , "\n }\n \n " )
123124
124125 if p .EmitMust {
125- writeMustVariant (w , im , p )
126+ writeMustVariant (w , im , p , ns )
126127 }
127128 return nil
128129}
129130
131+ // names holds the final, collision-free identifiers used when rendering one
132+ // plan. Indices line up with plan.Inputs / plan.Steps.
133+ type names struct {
134+ inputs []string
135+ steps []string
136+ }
137+
138+ // assignNames picks variable and parameter names for the plan that do not
139+ // collide with imported package aliases. Each name is derived from the
140+ // plan-level name (Input.Name / Step.VarName) and suffixed with a counter
141+ // when a collision is detected. Steps that reference an input share that
142+ // input's renamed identifier so the function signature and the body stay
143+ // in sync.
144+ func assignNames (im * Imports , p plan.Plan ) names {
145+ taken := make (map [string ]bool , len (im .used )+ 3 )
146+ for a := range im .used {
147+ taken [a ] = true
148+ }
149+ // Reserve identifiers the generated body always uses.
150+ taken ["err" ] = true
151+ taken ["v" ] = true
152+ taken ["_" ] = true
153+
154+ pick := func (base string ) string {
155+ if base == "" || base == "_" {
156+ base = "v"
157+ }
158+ if ! taken [base ] {
159+ taken [base ] = true
160+ return base
161+ }
162+ for i := 2 ; ; i ++ {
163+ try := fmt .Sprintf ("%s%d" , base , i )
164+ if ! taken [try ] {
165+ taken [try ] = true
166+ return try
167+ }
168+ }
169+ }
170+
171+ ns := names {
172+ inputs : make ([]string , len (p .Inputs )),
173+ steps : make ([]string , len (p .Steps )),
174+ }
175+ for i , in := range p .Inputs {
176+ ns .inputs [i ] = pick (in .Name )
177+ }
178+ for i , s := range p .Steps {
179+ if s .Kind == plan .StepKindInput {
180+ ns .steps [i ] = ns .inputs [s .InputIndex ]
181+ continue
182+ }
183+ ns .steps [i ] = pick (s .VarName )
184+ }
185+ return ns
186+ }
187+
130188// writeSteps emits step lines and reports whether any visible code was
131189// written. Pure-input plans (e.g. a container whose only inputs are
132190// non-blank inject:"arg" fields) produce no step lines, and the caller
133191// uses the bool to decide whether to leave a blank line before the
134192// struct literal.
135- func writeSteps (w io.Writer , im * Imports , p plan.Plan , retSig string ) (bool , error ) {
193+ func writeSteps (w io.Writer , im * Imports , p plan.Plan , ns names , retSig string ) (bool , error ) {
136194 zeroExpr := "nil"
137195 if ! isNilable (p .ReturnType ) {
138196 // For non-nilable return types we need an explicit zero value;
@@ -141,30 +199,29 @@ func writeSteps(w io.Writer, im *Imports, p plan.Plan, retSig string) (bool, err
141199 }
142200
143201 wrote := false
144- for _ , s := range p .Steps {
202+ for i , s := range p .Steps {
145203 switch s .Kind {
146204 case plan .StepKindInput :
147205 // The input is already a function parameter — nothing to emit.
148206 case plan .StepKindEmbedField :
149- in := p .Inputs [s .InputIndex ]
150- fmt .Fprintf (w , "\t %s := %s.%s\n " , s .VarName , in .Name , s .EmbedFieldName )
207+ fmt .Fprintf (w , "\t %s := %s.%s\n " , ns .steps [i ], ns .inputs [s .InputIndex ], s .EmbedFieldName )
151208 wrote = true
152209 case plan .StepKindProvider :
153210 if s .Provider == nil {
154211 return wrote , fmt .Errorf ("provider step %q has nil Provider" , s .VarName )
155212 }
156213 args := make ([]string , 0 , len (s .ArgSteps ))
157214 for _ , idx := range s .ArgSteps {
158- args = append (args , p . Steps [idx ]. VarName )
215+ args = append (args , ns . steps [idx ])
159216 }
160217 call := im .QualifyProvider (s .Provider )
161218 if s .Provider .ReturnsError {
162- fmt .Fprintf (w , "\t %s, err := %s(%s)\n " , s . VarName , call , strings .Join (args , ", " ))
219+ fmt .Fprintf (w , "\t %s, err := %s(%s)\n " , ns . steps [ i ] , call , strings .Join (args , ", " ))
163220 fmt .Fprint (w , "\t if err != nil {\n " )
164221 fmt .Fprintf (w , "\t \t return %s, err\n " , zeroExpr )
165222 fmt .Fprint (w , "\t }\n " )
166223 } else {
167- fmt .Fprintf (w , "\t %s := %s(%s)\n " , s . VarName , call , strings .Join (args , ", " ))
224+ fmt .Fprintf (w , "\t %s := %s(%s)\n " , ns . steps [ i ] , call , strings .Join (args , ", " ))
168225 }
169226 wrote = true
170227 }
@@ -189,56 +246,51 @@ func isNilable(t types.Type) bool {
189246 return false
190247}
191248
192- func writeStructLiteral (w io.Writer , p plan.Plan , leadingBlank bool ) {
249+ func writeStructLiteral (w io.Writer , p plan.Plan , ns names , leadingBlank bool ) {
193250 if leadingBlank {
194251 fmt .Fprint (w , "\n " )
195252 }
196253 fmt .Fprintf (w , "\t return &%s{\n " , p .Container .StructName )
197254 for _ , o := range p .Outputs {
198- v := p .Steps [o .StepIndex ].VarName
199- fmt .Fprintf (w , "\t \t %s: %s,\n " , o .FieldName , v )
255+ fmt .Fprintf (w , "\t \t %s: %s,\n " , o .FieldName , ns .steps [o .StepIndex ])
200256 }
201257 fmt .Fprint (w , "\t }" )
202258}
203259
204260// writeMustVariant emits MustNewX, which delegates to NewX and panics on
205261// error.
206- func writeMustVariant (w io.Writer , im * Imports , p plan.Plan ) {
262+ func writeMustVariant (w io.Writer , im * Imports , p plan.Plan , ns names ) {
207263 name := "Must" + p .ConstructorName
208- paramSig := formatParams (im , p .Inputs )
264+ paramSig := formatParams (im , p .Inputs , ns )
209265 retSig := im .QualifyType (p .ReturnType )
210266
211267 fmt .Fprintf (w ,
212268 "// %s initializes dependencies and constructs %s or panics on failure.\n " ,
213269 name , p .Container .StructName )
214270 fmt .Fprintf (w , "func %s(%s) %s {\n " , name , paramSig , retSig )
215271 if p .ReturnsError {
216- fmt .Fprintf (w , "\t v, err := %s(%s)\n " , p .ConstructorName , formatArgs (p . Inputs ))
272+ fmt .Fprintf (w , "\t v, err := %s(%s)\n " , p .ConstructorName , formatArgs (ns ))
217273 fmt .Fprint (w , "\t if err != nil {\n " )
218274 fmt .Fprint (w , "\t \t panic(err)\n " )
219275 fmt .Fprint (w , "\t }\n " )
220276 fmt .Fprint (w , "\t return v\n " )
221277 } else {
222- fmt .Fprintf (w , "\t return %s(%s)\n " , p .ConstructorName , formatArgs (p . Inputs ))
278+ fmt .Fprintf (w , "\t return %s(%s)\n " , p .ConstructorName , formatArgs (ns ))
223279 }
224280 fmt .Fprint (w , "}\n \n " )
225281}
226282
227- func formatParams (im * Imports , inputs []plan.Input ) string {
283+ func formatParams (im * Imports , inputs []plan.Input , ns names ) string {
228284 if len (inputs ) == 0 {
229285 return ""
230286 }
231287 parts := make ([]string , 0 , len (inputs ))
232- for _ , in := range inputs {
233- parts = append (parts , in . Name + " " + im .QualifyType (in .Type ))
288+ for i , in := range inputs {
289+ parts = append (parts , ns . inputs [ i ] + " " + im .QualifyType (in .Type ))
234290 }
235291 return strings .Join (parts , ", " )
236292}
237293
238- func formatArgs (inputs []plan.Input ) string {
239- parts := make ([]string , 0 , len (inputs ))
240- for _ , in := range inputs {
241- parts = append (parts , in .Name )
242- }
243- return strings .Join (parts , ", " )
294+ func formatArgs (ns names ) string {
295+ return strings .Join (ns .inputs , ", " )
244296}
0 commit comments