|
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