-
Notifications
You must be signed in to change notification settings - Fork 21
/
doc.go
368 lines (367 loc) · 10.9 KB
/
doc.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Rf refactors Go programs.
//
// Usage:
//
// rf [-diff] script
//
// Rf applies a script of refactoring commands to the package in the current directory.
// For example, to unexport a field in a struct by renaming it:
//
// rf 'mv T.Field T.field'
//
// By default, rf writes changes back to the disk.
// The -diff flag causes rf to print a diff of the intended changes instead.
//
// A script is a sequence of commands, one per line.
// Comments are introduced by # and extend to the end of the line.
// Commands may be broken across lines by ending all but the last
// with a trailing backslash (before any comment), as in:
//
// rf '
// # command
// mv T.Field \ # source
// T.field # destination
// '
//
// Commands that take { } blocks need not backslash-escape line breaks inside the braces, as in:
//
// rf '
// ex {
// var x *Node
// x.Left -> x.GetLeft()
// }
// '
//
// Code addresses
//
// Most commands take “code addresses” as arguments.
// Each code address identifies some code in a program.
// For illustration, consider this program, prog.go:
//
// package p
//
// import (
// "fmt"
// "io"
// )
//
// const (
// C = iota
// D
// )
//
// const E = 2.718281828
//
// func F(w io.Writer) {
// who := "world"
// msg := fmt.Sprintf("hello, %v", who)
// fmt.Fprintf(w, "%s\n", msg)
// }
//
// type T struct { Field int }
//
// func (t T) M() string {
// return fmt.Sprint(t)
// }
//
// func (*T) P() {}
//
// type TAlias = T
//
// var V struct {
// Value int
// thing T
// }
//
// var VT T
//
// The simplest code address is the name of a top-level declaration.
// In this program, those addresses are C, D, F, T, V, and VT.
//
// Adding .Name to an address selects a name within the earlier address,
// whether that's a function variable (F.who, F.msg),
// a struct field (T.Field), a method (T.M, T.P),
// or a variable's field (V.Value, V.thing, V.thing.Field, VT.Field).
//
// Another kind of code address is a Go source file, identified by
// a name ending in “.go”, as in “file.go”. If the file name contains
// a slash, as in “../dir/file.go”, the address identifies a file in
// the package in “../dir”.
//
// Another kind of code address is a Go package, identified by a path
// containing a slash but not ending in “.go”, as in “../dir” or
// “example.com/pkg”.
//
// A final kind of code address is a textual range in a function body
// or source file, identified by the syntax Ident:Range, where Ident
// identifies a file, function, or method and Range identifies a
// section of text within. The Range syntax is as used in the
// Acme and Sam text editors. The most common forms are the line range
// “N,M”, the byte range “#N,M”, and the regular expression range
// “/re1/,/re2/”. For example:
//
// prog.go:9 # "world" line
// prog.go:9,10 # "world" and fmt.Sprintf lines
// prog.go:/msg/-0,/fmt/+0 # "world" and fmt.Sprintf lines
// F:/msg/-0,/fmt/+0 # (same)
// prog.go:/fmt.*/ # the fmt.Sprintf call in F
// F:/fmt.Sprint.*/ # (same)
// T.M:/fmt.*/ # the fmt.Sprint call in T.M
//
// See http://9p.io/sys/doc/sam/sam.html Table II for details on the syntax.
//
// The add command
//
// The add command adds text to the source code. It takes as an argument the
// address after which the text should be added, followed by the text itself.
//
// add address text...
//
// The address may be a declaration, text range, file, or package.
// In all cases, the text is added immediately after the addressed location:
// after the declaration, after the text range, at the end of the file,
// or at the end of the first file in the package (considering the file names
// in lexical order).
//
// Examples:
//
// add T:$ \
// NewField int `tag`
//
// add x.go func F() {}
//
// The cp command
//
// The cp command is like mv (see below) but doesn't delete the source
// and doesn't update any references. (UNIMPLEMENTED)
//
// The ex command
//
// The ex command applies rewrites based on example snippets.
//
// ex { [imports] [declarations] old->new... }
//
// The arguments to ex are interpreted as Go code consisting of a
// sequence of imports and then a list of special “old -> new” rules.
// Each rule specifies that where ex finds a pattern matching old,
// it should replace the code with new. For example, to replace all
// log.Error calls with log.Panic:
//
// ex { import "log"; log.Error -> log.Panic }
//
// Declarations introduce typed pattern variables that can be used
// in rules. For example, to simplify certain needlessly complex
// uses of fmt.Sprintf:
//
// ex {
// import "fmt";
// import "strconv";
// var s string;
// fmt.Sprintf("%s", s) -> s;
// fmt.Sprintf("%v", s) -> s;
// fmt.Sprintf("%q", s) -> strconv.Quote(s)
// }
//
// The inline command
//
// The inline command inlines uses of declared constants, functions, and types.
//
// inline [-rm] decl...
//
// Each use of the named declarations is replaced by the declaration's definition.
// If the -rm flag is given, inline removes the declarations as well.
//
// Examples:
//
// inline E
//
// inline -rm TAlias
//
// Given the declarations in the “Code addresses” section above, the first command
// replaces all uses of E with 2.718281828. The second replaces all uses of
// TAlias with T and then removes TAlias.
//
// UNIMPLEMENTED: Inlining of functions.
//
// The key command
//
// The key command converts all struct literals for a list of types to keyed literals.
//
// key address...
//
// Each address must identify a struct type. All literals of those struct types are
// updated to use the keyed form.
//
// Example:
//
// key Point
//
// The mv command
//
// The mv command moves and renames code.
//
// mv [-f] old... new
//
// When mv moves or renames old code, it also updates any references
// to use the new names or locations for the code.
// This includes updating other packages in the current module.
//
// In general, mv aims to act appropriately for any sensible
// combination of old and new address form.
// The rest of this section enumerates the specific cases that
// mv handles.
//
// item → renamed item
//
// Any named item can be renamed by specifying a destination
// that is the same code address with the final element changed.
// For example:
//
// mv E Euler # constant
// mv F Func # function
// mv F.w F.writer # argument name
// mv F.who F.greetee # local variable name
// mv T MyType # type
// mv T.M T.Method # method
// mv T.M.t T.M.rcvr # receiver name
// mv Point.x Point.X # struct field
// mv V Var # var
// mv V.Value V.IntValue # var struct field
//
// In this form, the destination address must repeat the dot-separated elements
// leading up to the new name, changing only the final element.
// The repetition here distinguishes this form from other forms.
//
// var → var field
//
// A top-level variable can be moved to a new or existing field in a
// global variable of struct type. For example:
//
// mv VT V.VT
//
// method → func
//
// A method can be moved to a top-level function, removing the association with the receiver type.
// The receiver remains the first argument of the new function. For example:
//
// mv T.Method TFunction
//
// func → method
//
// A function can be moved to a method on the type of its first argument,
// assuming that type is defined in the same package where the function appears.
// For example:
//
// mv TFunction T.Method
//
// UNIMPLEMENTED.
//
// code text → new function
//
// A text range can be moved to a new function, leaving behind an appropriate
// call to that function. For example:
//
// mv F:/msg/,$ Greet
//
// code text → new method
//
// A text range can be moved to a new method, leaving behind an approriate
// call to that method. For example: TODO.
//
// UNIMPLEMENTED.
//
// declaration → file
//
// If the source is a top-level declaration (const, func, method, type, var)
// and the destination is a file, mv moves that declaration, along with
// any comments immediately preceding it, to the end of the
// destination file. For example:
//
// mv Template NewTemplate Template.Method thing.go
//
// Naming a single item in a declaration block is taken to indicate
// wanting to move all items in the block. In the example from the
// “Code addresses” section, “mv C x.go” moves D as well.
//
// Any time a destination file must be created, mv initializes it
// with the header comments (those above the package declaration
// and any package doc) from the file the source code is being
// moved from. This heuristic is meant to copy header text like copyright notices.
//
// The file may be in a different package. As usual, mv updates references
// to the moved declaration to refer to its new location, inserting imports
// as needed. If the result is an import cycle, mv reports the cycle
// rather than attempt some kind of automatic (and likely wrong) fix.
//
// declaration → package
//
// If the source is a top-level declaration and the destination is a package,
// mv moves the declaration to the a file in the destination package with
// the same name as the one holding the source item.
//
// mv F ../otherpkg # if F is in f.go, same as mv F ../otherpkg/f.go
//
// If the destination package does not exist, it will be created.
//
// file → file
//
// If the source and destination are both files, mv moves all code from
// the source file to the end of the destination file. For example:
//
// mv x.go y.go
// mv x.go ../otherpkg/y.go
//
// file → package
//
// If the source is a file and the destination is a package, mv moves all code
// from the source file to a file in the destination with the same base name.
// For example:
//
// mv x.go ../otherpkg # same as mv x.go ../otherpkg/x.go
//
// package → file
//
// If the source is a package and the destination is a file, mv moves all code
// from the source package to the named file.
// For example:
//
// mv ../otherpkg x.go
//
// UNIMPLEMENTED.
//
// package → package
//
// If the source is a package and the destination is a file, mv moves all code
// from the source package to the destination package.
// from the source package to the named file.
// For example:
//
// mv ../otherpkg x.go
//
// UNIMPLEMENTED.
//
// many → file, many → package
//
// If the destination is a file or package, multiple sources can be listed.
// The mv command moves each source item in turn to the destination.
//
// The rm command
//
// The rm command removes code.
//
// rm old...
//
// Rm deletes the old code. All address forms are valid.
// When deleting a declaration, rm also deletes line comments
// immediately preceding it, up to a blank line.
//
// UNIMPLEMENTED: removal of struct fields, interface methods, text ranges.
//
// Bugs Bugs Bugs
//
// Rf is very very rough. Everything is subject to change, and it may break your programs.
//
package main