-
Notifications
You must be signed in to change notification settings - Fork 668
/
Filer.java
426 lines (419 loc) · 22.3 KB
/
Filer.java
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
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
/*
* Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.annotation.processing;
import java.io.IOException;
import javax.lang.model.element.Element;
import javax.lang.model.util.Elements;
import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.StandardLocation;
/**
* This interface supports the creation of new files by an annotation
* processor. Files created in this way will be known to the
* annotation processing tool implementing this interface, better
* enabling the tool to manage them. Source and class files so
* created will be {@linkplain RoundEnvironment#getRootElements
* considered for processing} by the tool in a subsequent {@linkplain
* RoundEnvironment round of processing} after the {@code close}
* method has been called on the {@code Writer} or {@code
* OutputStream} used to write the contents of the file.
*
* Three kinds of files are distinguished: source files, class files,
* and auxiliary resource files.
*
* <p> There are two distinguished supported locations (subtrees
* within the logical file system) where newly created files are
* placed: one for {@linkplain
* javax.tools.StandardLocation#SOURCE_OUTPUT new source files}, and
* one for {@linkplain javax.tools.StandardLocation#CLASS_OUTPUT new
* class files}. (These might be specified on a tool's command line,
* for example, using flags such as {@code -s} and {@code -d}.) The
* actual locations for new source files and new class files may or
* may not be distinct on a particular run of the tool. Resource
* files may be created in either location. The methods for reading
* and writing resources take a relative name argument. A relative
* name is a non-null, non-empty sequence of path segments separated
* by {@code '/'}; {@code '.'} and {@code '..'} are invalid path
* segments. A valid relative name must match the
* "path-rootless" rule of <a
* href="http://www.ietf.org/rfc/rfc3986.txt">RFC 3986</a>, section
* 3.3.
*
* <p>The file creation methods take a variable number of arguments to
* allow the <em>originating elements</em> to be provided as hints to
* the tool infrastructure to better manage dependencies. The
* originating elements are the types or packages (representing {@code
* package-info} files) or modules (representing {@code
* module-info} files) which caused an annotation processor to
* attempt to create a new file. For example, if an annotation
* processor tries to create a source file, {@code
* GeneratedFromUserSource}, in response to processing
*
* <blockquote><pre>
* @Generate
* public class UserSource {}
* </pre></blockquote>
*
* the type element for {@code UserSource} should be passed as part of
* the creation method call as in:
*
* <blockquote><pre>
* filer.createSourceFile("GeneratedFromUserSource",
* eltUtils.getTypeElement("UserSource"));
* </pre></blockquote>
*
* If there are no originating elements, none need to be passed. This
* information may be used in an incremental environment to determine
* the need to rerun processors or remove generated files.
* Non-incremental environments may ignore the originating element
* information.
*
* <p> During each run of an annotation processing tool, a file with a
* given pathname may be created only once. If that file already
* exists before the first attempt to create it, the old contents will
* be deleted. Any subsequent attempt to create the same file during
* a run will throw a {@link FilerException}, as will attempting to
* create both a class file and source file for the same type name or
* same package name. The {@linkplain Processor initial inputs} to
* the tool are considered to be created by the zeroth round;
* therefore, attempting to create a source or class file
* corresponding to one of those inputs will result in a {@link
* FilerException}.
*
* <p> In general, processors must not knowingly attempt to overwrite
* existing files that were not generated by some processor. A {@code
* Filer} may reject attempts to open a file corresponding to an
* existing type, like {@code java.lang.Object}. Likewise, the
* invoker of the annotation processing tool must not knowingly
* configure the tool such that the discovered processors will attempt
* to overwrite existing files that were not generated.
*
* <p> Processors can indicate a source or class file is generated by
* including a {@code javax.annotation.Generated} annotation if the
* environment is configured so that that type is accessible.
*
* @author Joseph D. Darcy
* @author Scott Seligman
* @author Peter von der Ahé
* @apiNote Some of the effect of overwriting a file can be
* achieved by using a <i>decorator</i>-style pattern. Instead of
* modifying a class directly, the class is designed so that either
* its superclass is generated by annotation processing or subclasses
* of the class are generated by annotation processing. If the
* subclasses are generated, the parent class may be designed to use
* factories instead of public constructors so that only subclass
* instances would be presented to clients of the parent class.
* @since 1.6
*/
// 用于在注解处理器工作期间创建/读取文件
public interface Filer {
/**
* Creates a new source file and returns an object to allow
* writing to it. A source file for a type, or a package can
* be created.
*
* The file's name and path (relative to the {@linkplain
* StandardLocation#SOURCE_OUTPUT root output location for source
* files}) are based on the name of the item to be declared in
* that file as well as the specified module for the item (if
* any).
*
* If more than one type is being declared in a single file (that
* is, a single compilation unit), the name of the file should
* correspond to the name of the principal top-level type (the
* public one, for example).
*
* <p>A source file can also be created to hold information about
* a package, including package annotations. To create a source
* file for a named package, have the {@code name} argument be the
* package's name followed by {@code ".package-info"}; to create a
* source file for an unnamed package, use {@code "package-info"}.
*
* <p>The optional module name is prefixed to the type name or
* package name and separated using a "{@code /}" character. For
* example, to create a source file for type {@code a.B} in module
* {@code foo}, use a {@code name} argument of {@code "foo/a.B"}.
*
* <p>If no explicit module prefix is given and modules are supported
* in the environment, a suitable module is inferred. If a suitable
* module cannot be inferred {@link FilerException} is thrown.
* An implementation may use information about the configuration of
* the annotation processing tool as part of the inference.
*
* <p>Creating a source file in or for an unnamed package in a named
* module is <em>not</em> supported.
*
* @param name canonical (fully qualified) name of the principal type
* being declared in this file or a package name followed by
* {@code ".package-info"} for a package information file
* @param originatingElements type or package or module elements causally
* associated with the creation of this file, may be elided or
* {@code null}
*
* @return a {@code JavaFileObject} to write the new source file
*
* @throws FilerException if the same pathname has already been
* created, the same type has already been created, the name is
* otherwise not valid for the entity requested to being created,
* if the target module cannot be determined, if the target
* module is not writable, or a module is specified when the environment
* doesn't support modules.
* @throws IOException if the file cannot be created
* @apiNote To use a particular {@linkplain
* java.nio.charset.Charset charset} to encode the contents of the
* file, an {@code OutputStreamWriter} with the chosen charset can
* be created from the {@code OutputStream} from the returned
* object. If the {@code Writer} from the returned object is
* directly used for writing, its charset is determined by the
* implementation. An annotation processing tool may have an
* {@code -encoding} flag or analogous option for specifying this;
* otherwise, it will typically be the platform's default
* encoding.
*
* <p>To avoid subsequent errors, the contents of the source file
* should be compatible with the {@linkplain
* ProcessingEnvironment#getSourceVersion source version} being used
* for this run.
* @implNote In the reference implementation, if the annotation
* processing tool is processing a single module <i>M</i>,
* then <i>M</i> is used as the module for files created without
* an explicit module prefix. If the tool is processing multiple
* modules, and {@link
* Elements#getPackageElement(java.lang.CharSequence)
* Elements.getPackageElement(package-of(name))}
* returns a package, the module that owns the returned package is used
* as the target module. A separate option may be used to provide the target
* module if it cannot be determined using the above rules.
* @jls 7.3 Compilation Units
*/
/*
* 用来创建一个.java文件,name是全限定名,最后一个参数目前没用
* 文件存放路径是相对StandardLocation#SOURCE_OUTPUT而言的
*/
JavaFileObject createSourceFile(CharSequence name, Element... originatingElements)
throws IOException;
/**
* Creates a new class file, and returns an object to allow
* writing to it. A class file for a type, or a package can
* be created.
*
* The file's name and path (relative to the {@linkplain
* StandardLocation#CLASS_OUTPUT root output location for class
* files}) are based on the name of the item to be declared as
* well as the specified module for the item (if any).
*
* <p>A class file can also be created to hold information about a
* package, including package annotations. To create a class file
* for a named package, have the {@code name} argument be the
* package's name followed by {@code ".package-info"}; creating a
* class file for an unnamed package is not supported.
*
* <p>The optional module name is prefixed to the type name or
* package name and separated using a "{@code /}" character. For
* example, to create a class file for type {@code a.B} in module
* {@code foo}, use a {@code name} argument of {@code "foo/a.B"}.
*
* <p>If no explicit module prefix is given and modules are supported
* in the environment, a suitable module is inferred. If a suitable
* module cannot be inferred {@link FilerException} is thrown.
* An implementation may use information about the configuration of
* the annotation processing tool as part of the inference.
*
* <p>Creating a class file in or for an unnamed package in a named
* module is <em>not</em> supported.
*
* @param name binary name of the type being written or a package name followed by
* {@code ".package-info"} for a package information file
* @param originatingElements type or package or module elements causally
* associated with the creation of this file, may be elided or
* {@code null}
*
* @return a {@code JavaFileObject} to write the new class file
*
* @throws FilerException if the same pathname has already been
* created, the same type has already been created, the name is
* not valid for a type, if the target module cannot be determined,
* if the target module is not writable, or a module is specified when
* the environment doesn't support modules.
* @throws IOException if the file cannot be created
* @apiNote To avoid subsequent errors, the contents of the class
* file should be compatible with the {@linkplain
* ProcessingEnvironment#getSourceVersion source version} being
* used for this run.
* @implNote In the reference implementation, if the annotation
* processing tool is processing a single module <i>M</i>,
* then <i>M</i> is used as the module for files created without
* an explicit module prefix. If the tool is processing multiple
* modules, and {@link
* Elements#getPackageElement(java.lang.CharSequence)
* Elements.getPackageElement(package-of(name))}
* returns a package, the module that owns the returned package is used
* as the target module. A separate option may be used to provide the target
* module if it cannot be determined using the above rules.
*/
/*
* 用来创建一个.class文件,name是全限定名,最后一个参数目前没用
* 文件存放路径是相对StandardLocation#CLASS_OUTPUT而言的
*/
JavaFileObject createClassFile(CharSequence name, Element... originatingElements)
throws IOException;
/**
* Creates a new auxiliary resource file for writing and returns a
* file object for it. The file may be located along with the
* newly created source files, newly created binary files, or
* other supported location. The locations {@link
* StandardLocation#CLASS_OUTPUT CLASS_OUTPUT} and {@link
* StandardLocation#SOURCE_OUTPUT SOURCE_OUTPUT} must be
* supported. The resource may be named relative to some module
* and/or package (as are source and class files), and from there
* by a relative pathname. In a loose sense, the full pathname of
* the new file will be the concatenation of {@code location},
* {@code moduleAndPkg}, and {@code relativeName}.
*
* If {@code moduleAndPkg} contains a "{@code /}" character, the
* prefix before the "{@code /}" character is the module name and
* the suffix after the "{@code /}" character is the package
* name. The package suffix may be empty. If {@code moduleAndPkg}
* does not contain a "{@code /}" character, the entire argument
* is interpreted as a package name.
*
* <p>If the given location is neither a {@linkplain
* JavaFileManager.Location#isModuleOrientedLocation()
* module oriented location}, nor an {@linkplain
* JavaFileManager.Location#isOutputLocation()
* output location containing multiple modules}, and the explicit
* module prefix is given, {@link FilerException} is thrown.
*
* <p>If the given location is either a module oriented location,
* or an output location containing multiple modules, and no explicit
* modules prefix is given, a suitable module is
* inferred. If a suitable module cannot be inferred {@link
* FilerException} is thrown. An implementation may use information
* about the configuration of the annotation processing tool
* as part of the inference.
*
* <p>Files created via this method are <em>not</em> registered for
* annotation processing, even if the full pathname of the file
* would correspond to the full pathname of a new source file
* or new class file.
*
* @param location location of the new file
* @param moduleAndPkg module and/or package relative to which the file
* should be named, or the empty string if none
* @param relativeName final pathname components of the file
* @param originatingElements type or package or module elements causally
* associated with the creation of this file, may be elided or
* {@code null}
*
* @return a {@code FileObject} to write the new resource
*
* @throws IOException if the file cannot be created
* @throws FilerException if the same pathname has already been
* created, if the target module cannot be determined,
* or if the target module is not writable, or if an explicit
* target module is specified and the location does not support it.
* @throws IllegalArgumentException for an unsupported location
* @throws IllegalArgumentException if {@code moduleAndPkg} is ill-formed
* @throws IllegalArgumentException if {@code relativeName} is not relative
* @implNote In the reference implementation, if the annotation
* processing tool is processing a single module <i>M</i>,
* then <i>M</i> is used as the module for files created without
* an explicit module prefix. If the tool is processing multiple
* modules, and {@link
* Elements#getPackageElement(java.lang.CharSequence)
* Elements.getPackageElement(package-of(name))}
* returns a package, the module that owns the returned package is used
* as the target module. A separate option may be used to provide the target
* module if it cannot be determined using the above rules.
*/
/*
* 用来创建一个资源文件,可以是任意类型。moduleAndPkg是包名,relativeName是资源名称(带后缀),最后一个参数目前没用
* 文件存放路径由location指定
*/
FileObject createResource(JavaFileManager.Location location, CharSequence moduleAndPkg, CharSequence relativeName, Element... originatingElements)
throws IOException;
/**
* Returns an object for reading an existing resource. The
* locations {@link StandardLocation#CLASS_OUTPUT CLASS_OUTPUT}
* and {@link StandardLocation#SOURCE_OUTPUT SOURCE_OUTPUT} must
* be supported.
*
* <p>If {@code moduleAndPkg} contains a "{@code /}" character, the
* prefix before the "{@code /}" character is the module name and
* the suffix after the "{@code /}" character is the package
* name. The package suffix may be empty; however, if a module
* name is present, it must be nonempty. If {@code moduleAndPkg}
* does not contain a "{@code /}" character, the entire argument
* is interpreted as a package name.
*
* <p>If the given location is neither a {@linkplain
* JavaFileManager.Location#isModuleOrientedLocation()
* module oriented location}, nor an {@linkplain
* JavaFileManager.Location#isOutputLocation()
* output location containing multiple modules}, and the explicit
* module prefix is given, {@link FilerException} is thrown.
*
* <p>If the given location is either a module oriented location,
* or an output location containing multiple modules, and no explicit
* modules prefix is given, a suitable module is
* inferred. If a suitable module cannot be inferred {@link
* FilerException} is thrown. An implementation may use information
* about the configuration of the annotation processing tool
* as part of the inference.
*
* @param location location of the file
* @param moduleAndPkg module and/or package relative to which the file
* should be searched for, or the empty string if none
* @param relativeName final pathname components of the file
*
* @return an object to read the file
*
* @throws FilerException if the same pathname has already been
* opened for writing, if the source module cannot be determined,
* or if the target module is not writable, or if an explicit target
* module is specified and the location does not support it.
* @throws IOException if the file cannot be opened
* @throws IllegalArgumentException for an unsupported location
* @throws IllegalArgumentException if {@code moduleAndPkg} is ill-formed
* @throws IllegalArgumentException if {@code relativeName} is not relative
* @implNote In the reference implementation, if the annotation
* processing tool is processing a single module <i>M</i>,
* then <i>M</i> is used as the module for files read without
* an explicit module prefix. If the tool is processing multiple
* modules, and {@link
* Elements#getPackageElement(java.lang.CharSequence)
* Elements.getPackageElement(package-of(name))}
* returns a package, the module that owns the returned package is used
* as the source module. A separate option may be used to provide the target
* module if it cannot be determined using the above rules.
*/
/*
* 用来读取一个资源文件,可以是任意类型。moduleAndPkg是包名,relativeName是资源名称(带后缀)
* 文件读取路径由location指定
*/
FileObject getResource(JavaFileManager.Location location, CharSequence moduleAndPkg, CharSequence relativeName)
throws IOException;
}