|
6 | 6 | * @description Using each VS Code command from only one location makes |
7 | 7 | * our telemtry more useful because we can differentiate more user |
8 | 8 | * interactions and know which features of the UI users are using. |
| 9 | + * To fix this alert, new commands will need to be made so that each one |
| 10 | + * is only used from one location. The commands should share the same |
| 11 | + * implementation so we do not introduce duplicate code. |
| 12 | + * When fixing this alert, search the codebase for all other references |
| 13 | + * to the commnad name. The location of the alert is an arbitrarily |
| 14 | + * chosen usage of the command, and may not necessarily be the location |
| 15 | + * that should be changed to fix the alert. |
9 | 16 | */ |
10 | 17 |
|
11 | 18 | import javascript |
12 | 19 |
|
| 20 | + /** |
| 21 | + * The name of a VS Code command. |
| 22 | + */ |
13 | 23 | class CommandName extends string { |
14 | 24 | CommandName() { exists(CommandUsage e | e.getCommandName() = this) } |
15 | 25 |
|
| 26 | + /** |
| 27 | + * In how many ways is this command used. Will always be at least 1. |
| 28 | + */ |
16 | 29 | int getNumberOfUsages() { result = count(CommandUsage e | e.getCommandName() = this | e) } |
17 | 30 |
|
| 31 | + /** |
| 32 | + * Get the canonical first usage of this command, to use for the location |
| 33 | + * of the alert. The implementation of this ordering of usages is arbitrary |
| 34 | + * and the usage given may not be the one that should be changed when fixing |
| 35 | + * the alert. |
| 36 | + */ |
18 | 37 | CommandUsage getFirstUsage() { |
19 | 38 | result.getCommandName() = this and |
20 | 39 | forall(CommandUsage e | e.getCommandName() = this | |
|
23 | 42 | } |
24 | 43 | } |
25 | 44 |
|
| 45 | + /** |
| 46 | + * Represents a single usage of a command, either from within code or |
| 47 | + * from the command's definition in package.json |
| 48 | + */ |
26 | 49 | abstract class CommandUsage extends Locatable { |
27 | 50 | abstract string getCommandName(); |
28 | 51 |
|
| 52 | + /** |
| 53 | + * Used as a way of ordering locations. The implementation is basically |
| 54 | + * arbitrary, so long as the ordering is consistent across analyses. |
| 55 | + */ |
29 | 56 | string getLocationOrdinal() { |
30 | 57 | result = |
31 | 58 | this.getFile().getRelativePath() + ":" + this.getLocation().getStartLine() + ":" + |
32 | 59 | this.getLocation().getStartColumn() |
33 | 60 | } |
34 | 61 | } |
35 | 62 |
|
| 63 | + /** |
| 64 | + * A usage of a command from the typescript code, by calling `executeCommand`. |
| 65 | + */ |
36 | 66 | class CommandUsageCallExpr extends CommandUsage, CallExpr { |
37 | 67 | CommandUsageCallExpr() { |
38 | 68 | this.getCalleeName() = "executeCommand" and |
|
43 | 73 | override string getCommandName() { result = this.getArgument(0).(StringLiteral).getValue() } |
44 | 74 | } |
45 | 75 |
|
| 76 | + /** |
| 77 | + * A usage of a command from any menu that isn't the command palette. |
| 78 | + * This means a user could invoke the command by clicking on a button in a |
| 79 | + * something like a menu or a dropdown. |
| 80 | + */ |
46 | 81 | class CommandUsagePackageJsonMenuItem extends CommandUsage, JsonObject { |
47 | 82 | CommandUsagePackageJsonMenuItem() { |
48 | 83 | exists(this.getPropValue("command")) and |
|
59 | 94 | override string getCommandName() { result = this.getPropValue("command").getStringValue() } |
60 | 95 | } |
61 | 96 |
|
| 97 | + /** |
| 98 | + * Is the given command disabled for use in the command palette by |
| 99 | + * a block with a `"when": "false"` field. |
| 100 | + */ |
62 | 101 | predicate isDisabledInCommandPalette(string commandName) { |
63 | 102 | exists(PackageJson packageJson, JsonObject commandPaletteObject | |
64 | 103 | packageJson |
|
71 | 110 | ) |
72 | 111 | } |
73 | 112 |
|
| 113 | + /** |
| 114 | + * Represents a command being usable from the command palette. |
| 115 | + * This means that a user could choose to manually invoke the command. |
| 116 | + */ |
74 | 117 | class CommandUsagePackageJsonCommandPalette extends CommandUsage, JsonObject { |
75 | 118 | CommandUsagePackageJsonCommandPalette() { |
76 | 119 | this.getFile().getBaseName() = "package.json" and |
|
0 commit comments