Skip to content

Commit b823a5a

Browse files
Merge pull request #328 from laravel/storage-feature
Autocompletion, linking, and diagnostics for Storage Disks
2 parents d73d2e9 + 93b535b commit b823a5a

File tree

8 files changed

+143
-4
lines changed

8 files changed

+143
-4
lines changed

generatable.json

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,13 @@
6060
"link",
6161
"completion"
6262
]
63+
},
64+
{
65+
"type": "storage",
66+
"features": [
67+
"link",
68+
"completion",
69+
"diagnostics"
70+
]
6371
}
6472
]

package.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -399,6 +399,24 @@
399399
"generated": true,
400400
"description": "Enable completion for route."
401401
},
402+
"Laravel.storage.link": {
403+
"type": "boolean",
404+
"default": true,
405+
"generated": true,
406+
"description": "Enable linking for storage."
407+
},
408+
"Laravel.storage.completion": {
409+
"type": "boolean",
410+
"default": true,
411+
"generated": true,
412+
"description": "Enable completion for storage."
413+
},
414+
"Laravel.storage.diagnostics": {
415+
"type": "boolean",
416+
"default": true,
417+
"generated": true,
418+
"description": "Enable diagnostics for storage."
419+
},
402420
"Laravel.translation.diagnostics": {
403421
"type": "boolean",
404422
"default": true,

src/completion/CompletionProvider.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,24 @@ import { completionProvider as inertia } from "@src/features/inertia";
1010
import { completionProvider as middleware } from "@src/features/middleware";
1111
import { completionProvider as mix } from "@src/features/mix";
1212
import { completionProvider as route } from "@src/features/route";
13+
import { completionProvider as storage } from "@src/features/storage";
1314
import { completionProvider as translation } from "@src/features/translation";
1415
import { completionProvider as view } from "@src/features/view";
1516
import { GeneratedConfigKey } from "@src/support/generated-config";
1617
import { CompletionProvider } from "..";
1718

1819
const allProviders: Partial<Record<GeneratedConfigKey, CompletionProvider>> = {
1920
"appBinding.completion": appBinding,
21+
"asset.completion": asset,
2022
"auth.completion": auth,
2123
"config.completion": config,
22-
"asset.completion": asset,
24+
"controllerAction.completion": controllerAction,
2325
"env.completion": env,
2426
"inertia.completion": inertia,
2527
"middleware.completion": middleware,
2628
"mix.completion": mix,
2729
"route.completion": route,
28-
"controllerAction.completion": controllerAction,
30+
"storage.completion": storage,
2931
"translation.completion": translation,
3032
"view.completion": view,
3133
};

src/diagnostic/diagnostic.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { diagnosticProvider as inertia } from "@src/features/inertia";
88
import { diagnosticProvider as middleware } from "@src/features/middleware";
99
import { diagnosticProvider as mix } from "@src/features/mix";
1010
import { diagnosticProvider as route } from "@src/features/route";
11+
import { diagnosticProvider as storage } from "@src/features/storage";
1112
import { diagnosticProvider as translation } from "@src/features/translation";
1213
import { diagnosticProvider as view } from "@src/features/view";
1314
import { config as getConfig } from "@src/support/config";
@@ -30,6 +31,7 @@ const providers: {
3031
{ provider: middleware, configKey: "middleware.diagnostics" },
3132
{ provider: mix, configKey: "mix.diagnostics" },
3233
{ provider: route, configKey: "route.diagnostics" },
34+
{ provider: storage, configKey: "storage.diagnostics" },
3335
{ provider: translation, configKey: "translation.diagnostics" },
3436
{ provider: view, configKey: "view.diagnostics" },
3537
];

src/diagnostic/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ export type DiagnosticCode =
2525
| "mix"
2626
| "route"
2727
| "translation"
28-
| "view";
28+
| "view"
29+
| "storage_disk";

src/features/storage.ts

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { notFound } from "@src/diagnostic";
2+
import AutocompleteResult from "@src/parser/AutocompleteResult";
3+
import { getConfigs } from "@src/repositories/configs";
4+
import { getPaths } from "@src/repositories/paths";
5+
import { config } from "@src/support/config";
6+
import { detectedRange, detectInDoc } from "@src/support/parser";
7+
import { wordMatchRegex } from "@src/support/patterns";
8+
import { projectPath } from "@src/support/project";
9+
import { facade } from "@src/support/util";
10+
import * as vscode from "vscode";
11+
import { CompletionProvider, FeatureTag, LinkProvider } from "..";
12+
13+
const toFind: FeatureTag = {
14+
class: facade("Storage"),
15+
method: ["disk"],
16+
argumentIndex: 0,
17+
};
18+
19+
export const linkProvider: LinkProvider = (doc: vscode.TextDocument) => {
20+
return detectInDoc<vscode.DocumentLink, "string">(
21+
doc,
22+
toFind,
23+
getPaths,
24+
({ param, item }) => {
25+
const configItem = getConfigs().items.find(
26+
(c) => c.name === `filesystems.disks.${param.value}`,
27+
);
28+
29+
if (!configItem || !configItem.file) {
30+
return null;
31+
}
32+
33+
return new vscode.DocumentLink(
34+
detectedRange(param),
35+
vscode.Uri.file(projectPath(configItem.file)).with({
36+
fragment: `L${configItem.line}`,
37+
}),
38+
);
39+
},
40+
);
41+
};
42+
43+
export const diagnosticProvider = (
44+
doc: vscode.TextDocument,
45+
): Promise<vscode.Diagnostic[]> => {
46+
return detectInDoc<vscode.Diagnostic, "string">(
47+
doc,
48+
toFind,
49+
getConfigs,
50+
({ param, item, index }) => {
51+
const config = getConfigs().items.find(
52+
(c) => c.name === `filesystems.disks.${param.value}`,
53+
);
54+
55+
if (config) {
56+
return null;
57+
}
58+
59+
return notFound(
60+
"Storage Disk",
61+
param.value,
62+
detectedRange(param),
63+
"storage_disk",
64+
);
65+
},
66+
);
67+
};
68+
69+
export const completionProvider: CompletionProvider = {
70+
tags() {
71+
return toFind;
72+
},
73+
74+
provideCompletionItems(
75+
result: AutocompleteResult,
76+
document: vscode.TextDocument,
77+
position: vscode.Position,
78+
token: vscode.CancellationToken,
79+
context: vscode.CompletionContext,
80+
): vscode.CompletionItem[] {
81+
if (!config("storage.completion", true)) {
82+
return [];
83+
}
84+
85+
return getConfigs()
86+
.items.filter((config) => {
87+
return (
88+
config.name.startsWith("filesystems.disks.") &&
89+
config.name.split(".").length === 3
90+
);
91+
})
92+
.map((config) => {
93+
const completeItem = new vscode.CompletionItem(
94+
config.name.replace("filesystems.disks.", ""),
95+
vscode.CompletionItemKind.Value,
96+
);
97+
98+
completeItem.range = document.getWordRangeAtPosition(
99+
position,
100+
wordMatchRegex,
101+
);
102+
103+
return completeItem;
104+
});
105+
},
106+
};

src/link/LinkProvider.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { linkProvider as middleware } from "@src/features/middleware";
1313
import { linkProvider as mix } from "@src/features/mix";
1414
import { linkProvider as paths } from "@src/features/paths";
1515
import { linkProvider as route } from "@src/features/route";
16+
import { linkProvider as storage } from "@src/features/storage";
1617
import { linkProvider as translation } from "@src/features/translation";
1718
import { linkProvider as view } from "@src/features/view";
1819
import { LinkProvider as LinkProviderType } from "@src/index";
@@ -39,6 +40,7 @@ const allProviders: Partial<Record<GeneratedConfigKey, LinkProviderType>> = {
3940
"mix.link": mix,
4041
"paths.link": paths,
4142
"route.link": route,
43+
"storage.link": storage,
4244
"translation.link": translation,
4345
"view.link": view,
4446
};

src/support/generated-config.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
export type GeneratedConfigKey = 'appBinding.diagnostics' | 'appBinding.hover' | 'appBinding.link' | 'appBinding.completion' | 'asset.diagnostics' | 'asset.hover' | 'asset.link' | 'asset.completion' | 'auth.diagnostics' | 'auth.hover' | 'auth.link' | 'auth.completion' | 'bladeComponent.link' | 'bladeComponent.completion' | 'bladeComponent.hover' | 'config.diagnostics' | 'config.hover' | 'config.link' | 'config.completion' | 'controllerAction.diagnostics' | 'controllerAction.hover' | 'controllerAction.link' | 'controllerAction.completion' | 'env.diagnostics' | 'env.hover' | 'env.link' | 'env.completion' | 'inertia.diagnostics' | 'inertia.hover' | 'inertia.link' | 'inertia.completion' | 'livewireComponent.link' | 'livewireComponent.completion' | 'middleware.diagnostics' | 'middleware.hover' | 'middleware.link' | 'middleware.completion' | 'mix.diagnostics' | 'mix.hover' | 'mix.link' | 'mix.completion' | 'paths.link' | 'route.diagnostics' | 'route.hover' | 'route.link' | 'route.completion' | 'translation.diagnostics' | 'translation.hover' | 'translation.link' | 'translation.completion' | 'view.diagnostics' | 'view.hover' | 'view.link' | 'view.completion';
1+
export type GeneratedConfigKey = 'appBinding.diagnostics' | 'appBinding.hover' | 'appBinding.link' | 'appBinding.completion' | 'asset.diagnostics' | 'asset.hover' | 'asset.link' | 'asset.completion' | 'auth.diagnostics' | 'auth.hover' | 'auth.link' | 'auth.completion' | 'bladeComponent.link' | 'bladeComponent.completion' | 'bladeComponent.hover' | 'config.diagnostics' | 'config.hover' | 'config.link' | 'config.completion' | 'controllerAction.diagnostics' | 'controllerAction.hover' | 'controllerAction.link' | 'controllerAction.completion' | 'env.diagnostics' | 'env.hover' | 'env.link' | 'env.completion' | 'inertia.diagnostics' | 'inertia.hover' | 'inertia.link' | 'inertia.completion' | 'livewireComponent.link' | 'livewireComponent.completion' | 'middleware.diagnostics' | 'middleware.hover' | 'middleware.link' | 'middleware.completion' | 'mix.diagnostics' | 'mix.hover' | 'mix.link' | 'mix.completion' | 'paths.link' | 'route.diagnostics' | 'route.hover' | 'route.link' | 'route.completion' | 'storage.link' | 'storage.completion' | 'storage.diagnostics' | 'translation.diagnostics' | 'translation.hover' | 'translation.link' | 'translation.completion' | 'view.diagnostics' | 'view.hover' | 'view.link' | 'view.completion';

0 commit comments

Comments
 (0)