|
169 | 169 |
|
170 | 170 | Many detector methods will pass in a `Context`, or a more specific
|
171 | 171 | subclass of `Context` such as `JavaContext` or `XmlContext`. This
|
172 |
| -allows lint to provide access to the detectors information they may |
173 |
| -need, without passing in a lot of parameters (and allowing lint to add |
174 |
| -additional data over time without breaking signatures). |
| 172 | +allows lint to give the detectors information they may need, without |
| 173 | +passing in a lot of parameters. It also allows lint to add additional data |
| 174 | +over time without breaking signatures. |
175 | 175 |
|
176 | 176 | The `Context` classes also provide many convenience APIs. For example,
|
177 | 177 | for `XmlContext` there are methods for creating locations for XML tags,
|
178 |
| -XML attributes, just the name part of an XML attribute and just the |
| 178 | +XML attributes, just the name part of an XML attribute, and just the |
179 | 179 | value part of an XML attribute. For a `JavaContext` there are also
|
180 | 180 | methods for creating locations, such as for a method call, including
|
181 | 181 | whether to include the receiver and/or the argument list.
|
|
204 | 204 | Lint's API has two halves:
|
205 | 205 |
|
206 | 206 | - The **Client API**: “Integrate (and run) lint from within a tool”.
|
207 |
| - For example, both the IDE and the build system uses this API to embed |
| 207 | + For example, both the IDE and the build system use this API to embed |
208 | 208 | and invoke lint to analyze the code in the project or editor.
|
209 | 209 |
|
210 | 210 | - The **Detector API**: “Implement a new lint check”. This is the API
|
|
213 | 213 | The class in the Client API which represents lint running in a tool is
|
214 | 214 | called `LintClient`. This class is responsible for, among other things:
|
215 | 215 |
|
216 |
| -* Reporting incidents found by detectors. For example, in the IDE, it |
| 216 | +* **Reporting incidents found by detectors**. For example, in the IDE, it |
217 | 217 | will place error markers into the source editor, and in a build
|
218 | 218 | system, it may write warnings to the console or generate a report or
|
219 | 219 | even fail the build.
|
220 | 220 |
|
221 |
| -* Handling I/O. Detectors should never read files from disk directly. |
| 221 | +* **Handling I/O**. Detectors should never read files from disk directly. |
222 | 222 | This allows lint checks to work smoothly in for example the IDE. When
|
223 | 223 | lint runs on the fly, and a lint check asks for the source file
|
224 | 224 | contents (or other supporting files), the `LintClient` in the IDE
|
225 | 225 | will implement the `readFile` method to first look in the open source
|
226 | 226 | editors and if the requested file is being edited, it will return the
|
227 | 227 | current (often unsaved!) contents.
|
228 | 228 |
|
229 |
| -* Handling network traffic. Lint checks should never open |
230 |
| - URLConnections themselves. By going through the lint API to request |
231 |
| - data for a URL, not only can the LintClient for example use any |
232 |
| - configured IDE proxy settings which is done in the IntelliJ |
233 |
| - integration of lint, but even the lint check's own unit tests can |
234 |
| - easily be tested because the special unit test implementation of a |
235 |
| - `LintClient` provides a simple way to provide exact responses for |
236 |
| - specific URLs: |
| 229 | +* **Handling network traffic**. Lint checks should never open |
| 230 | + URLConnections themselves. Instead, they should go through the lint API |
| 231 | + to request data for URLs. Among other things, this allows the |
| 232 | + `LintClient` to use configured IDE proxy settings (as is done in the |
| 233 | + IntelliJ integration of lint). This is also good for testing, because |
| 234 | + the special unit test implementation of a `LintClient` has a simple way |
| 235 | + to provide exact responses for specific URLs: |
237 | 236 |
|
238 | 237 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
239 | 238 | lint()
|
|
256 | 255 |
|
257 | 256 | And much, much, more. **However, most of the implementation of
|
258 | 257 | `LintClient` is intended for integration of lint itself, and as a check
|
259 |
| -author you don't need to worry about it.** It's the detector API that |
260 |
| -matters, and is also less likely to change than the client API. |
| 258 | +author you don't need to worry about it.** The detector API will matter |
| 259 | +more, and it's also less likely to change than the client API. |
261 | 260 |
|
262 | 261 | !!! Tip
|
263 | 262 | The division between the two halves is not perfect; some classes
|
|
273 | 272 | for internal lint usage have been made `public` such that lint's
|
274 | 273 | code in one package can access it from the other. There's normally a
|
275 | 274 | comment explaining that this is for internal use only, but be aware
|
276 |
| - that just because something is `public` or not `final` it's a good |
277 |
| - idea to call or override it. |
| 275 | + that even when something is `public` or not `final`, it might not be a |
| 276 | + good idea to call or override it. |
278 | 277 |
|
279 | 278 | ## Creating an Issue
|
280 | 279 |
|
|
283 | 282 | [publishing](publishing.md.html) chapters.
|
284 | 283 |
|
285 | 284 | `Issue` is a final class, so unlike `Detector`, you don't subclass
|
286 |
| -it, you instantiate it via `Issue.create`. |
| 285 | +it; you instantiate it via `Issue.create`. |
287 | 286 |
|
288 | 287 | By convention, issues are registered inside the companion object of the
|
289 | 288 | corresponding detector, but that is not required.
|
|
631 | 630 |
|
632 | 631 | * When implementing **`SourceCodeScanner`**, in Kotlin and Java files
|
633 | 632 | you can be called back
|
634 |
| - - When a method of a given name is invoked (`getApplicableMethodNames` |
| 633 | + - when a method of a given name is invoked (`getApplicableMethodNames` |
635 | 634 | and `visitMethodCall`)
|
636 |
| - - When a class of the given type is instantiated |
| 635 | + - when a class of the given type is instantiated |
637 | 636 | (`getApplicableConstructorTypes` and `visitConstructor`)
|
638 |
| - - When a new class is declared which extends (possibly indirectly) |
| 637 | + - when a new class is declared which extends (possibly indirectly) |
639 | 638 | a given class or interface (`applicableSuperClasses` and
|
640 | 639 | `visitClass`)
|
641 |
| - - When annotated elements are referenced or combined |
| 640 | + - when annotated elements are referenced or combined |
642 | 641 | (`applicableAnnotations` and `visitAnnotationUsage`)
|
643 |
| - - When any AST nodes of given types appear (`getApplicableUastTypes` |
| 642 | + - when any AST nodes of given types appear (`getApplicableUastTypes` |
644 | 643 | and `createUastHandler`)
|
645 | 644 |
|
646 | 645 | * When implementing a **`ClassScanner`**, in `.class` and `.jar` files
|
|
650 | 649 | - when a given bytecode instruction occurs
|
651 | 650 | (`getApplicableAsmNodeTypes` and `checkInstruction`)
|
652 | 651 | - like with XmlScanner's `visitDocument`, you can perform your own
|
653 |
| - ASM bytecode iteration via `checkClass`. |
| 652 | + ASM bytecode iteration via `checkClass` |
654 | 653 |
|
655 | 654 | * There are various other scanners too, for example `GradleScanner`
|
656 | 655 | which lets you visit `build.gradle` and `build.gradle.kts` DSL
|
|
677 | 676 | the detector in fields and accumulate information for analysis at the
|
678 | 677 | end.
|
679 | 678 |
|
680 |
| -There are some callbacks both before each individual file is analyzed |
681 |
| -(`beforeCheckFile` and `afterCheckFile`), as well as before and after |
682 |
| -analysis of all the modules (`beforeCheckRootProject` and |
| 679 | +There are some callbacks both before and after each individual file is |
| 680 | +analyzed (`beforeCheckFile` and `afterCheckFile`), as well as before and |
| 681 | +after analysis of all the modules (`beforeCheckRootProject` and |
683 | 682 | `afterCheckRootProject`).
|
684 | 683 |
|
685 | 684 | This is for example how the ”unused resources“ check works: we store
|
|
764 | 763 | like the `ResourceRepository` and the `ResourceEvaluator`.
|
765 | 764 |
|
766 | 765 | * Finally, there are a number of utility methods; for example there is
|
767 |
| - an `editDistance` method used to find likely typos used by a number |
768 |
| - of checks. |
| 766 | + an `editDistance` method used to find likely typos. |
769 | 767 |
|
770 | 768 | ## Scanner Example
|
771 | 769 |
|
|
807 | 805 | }
|
808 | 806 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
809 | 807 |
|
810 |
| -The second, older form, may seem simpler, but the new API allows a lot |
| 808 | +The second (older) form may seem simpler, but the new API allows a lot |
811 | 809 | more metadata to be attached to the report, such as an override
|
812 | 810 | severity. You don't have to convert to the builder syntax to do this;
|
813 | 811 | you could also have written the second form as
|
|
1003 | 1001 |
|
1004 | 1002 | !!! Warning
|
1005 | 1003 | Resolving only works if lint has a correct classpath such that the
|
1006 |
| - referenced method, field or class are actually present. If it is |
| 1004 | + referenced method, field, or class is actually present. If it is |
1007 | 1005 | not, resolve will return null, and various lint callbacks will not
|
1008 | 1006 | be invoked. This is a common source of questions for lint checks
|
1009 | 1007 | ”not working“; it frequently comes up in lint unit tests where a
|
|
0 commit comments