Skip to content

Commit 2819cd8

Browse files
committed
feat: add configPath setting and remove configFileWatcherBasenames
1 parent d2d8c1e commit 2819cd8

File tree

4 files changed

+102
-46
lines changed

4 files changed

+102
-46
lines changed

.changeset/great-hornets-obey.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"phpstan-vscode": minor
3+
---
4+
5+
Replace the `configFileWatcherBasenames` setting by `configPath`

package.json

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,9 @@
114114
"description": "Enables config file watcher",
115115
"default": true
116116
},
117-
"phpstan.configFileWatcherBasenames": {
118-
"type": "array",
119-
"items": {
120-
"type": "string"
121-
},
122-
"description": "Config file watcher basenames",
123-
"default": [
124-
"phpstan.neon",
125-
"phpstan.neon.dist"
126-
]
117+
"phpstan.configPath": {
118+
"type": "string",
119+
"description": "PHPStan config path"
127120
},
128121
"phpstan.analysedDelay": {
129122
"type": "integer",

src/PHPStan.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ export type ConfigType = {
3030
export class PHPStan {
3131
static settings: {
3232
rootPath: string
33-
basenames: string[]
3433
path: string
3534
}
3635

@@ -49,7 +48,8 @@ export class PHPStan {
4948

5049
static async findConfigPath(): Promise<string | null> {
5150
const dir = PHPStan.settings.rootPath
52-
for (const basename of PHPStan.settings.basenames) {
51+
const baseNames = ["phpstan.neon", "phpstan.neon.dist"]
52+
for (const basename of baseNames) {
5353
const path = join(dir, basename)
5454
if (await checkFile(path)) {
5555
return path

src/extension.ts

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ import { ChildProcessWithoutNullStreams, spawn } from "child_process"
33
import { killProcess, waitForClose } from "./util"
44
import { uncolorize } from "./util/color"
55
import { PHPStan, ConfigType, ResultType } from "./PHPStan"
6+
import { isAbsolute, join } from "path"
67

78
type SettingsType = {
89
enabled: boolean
910
path: string
1011
phpPath: string
12+
configPath: string
1113
fileWatcher: boolean
1214
configFileWatcher: boolean
13-
configFileWatcherBasenames: string[]
1415
analysedDelay: number
1516
memoryLimit: string
1617
}
@@ -33,10 +34,11 @@ const $: {
3334
diagnosticCollection?: vscode.DiagnosticCollection
3435
outputChannel?: vscode.OutputChannel
3536
statusBarItem?: vscode.StatusBarItem
36-
configFileWatcher?: vscode.FileSystemWatcher
37-
fileWatcher?: vscode.FileSystemWatcher
37+
fileWatchers: vscode.FileSystemWatcher[]
3838
listeners?: vscode.Disposable[]
39-
} = {}
39+
} = {
40+
fileWatchers: [],
41+
}
4042

4143
export function activate(context: vscode.ExtensionContext): void {
4244
settings = getSettings()
@@ -45,26 +47,35 @@ export function activate(context: vscode.ExtensionContext): void {
4547
$.listeners = [
4648
vscode.workspace.onDidChangeConfiguration((event) => {
4749
if (event.affectsConfiguration(EXT_NAME)) {
48-
deactivate()
50+
$.outputChannel?.appendLine(`# Reload`)
51+
deactivate({
52+
exclude: ["outputChannel"],
53+
})
4954
activate(context)
5055
}
5156
}),
5257
]
5358

54-
if (!settings.enabled || !$.rootPath) return
59+
if (!settings.enabled || !$.rootPath) {
60+
deactivate({
61+
include: ["outputChannel"],
62+
})
63+
return
64+
}
5565

5666
vscode.commands.executeCommand("setContext", `${EXT_NAME}:enabled`, true)
5767

5868
PHPStan.settings = {
59-
basenames: settings.configFileWatcherBasenames,
6069
path: settings.path,
6170
rootPath: sanitizeFsPath($.rootPath),
6271
}
6372

64-
$.outputChannel = vscode.window.createOutputChannel(EXT_NAME)
65-
$.diagnosticCollection = vscode.languages.createDiagnosticCollection(
66-
EXT_NAME
67-
)
73+
if (!$.outputChannel)
74+
$.outputChannel = vscode.window.createOutputChannel(EXT_NAME)
75+
76+
$.outputChannel?.appendLine(`# Load`)
77+
$.diagnosticCollection =
78+
vscode.languages.createDiagnosticCollection(EXT_NAME)
6879
$.statusBarItem = vscode.window.createStatusBarItem()
6980

7081
const commands: ((...args: unknown[]) => void)[] = [
@@ -83,22 +94,7 @@ export function activate(context: vscode.ExtensionContext): void {
8394
vscode.commands.registerCommand(getCommandName(command), command)
8495
)
8596

86-
if (settings.configFileWatcher) {
87-
$.configFileWatcher = vscode.workspace.createFileSystemWatcher(
88-
new vscode.RelativePattern(
89-
$.rootPath,
90-
`{${settings.configFileWatcherBasenames.join(",")}}`
91-
)
92-
)
93-
onFileWatcherEvent($.configFileWatcher, async (uri, eventName) => {
94-
if (!fileWatcherState) return
95-
const fsPath = sanitizeFsPath(uri.fsPath)
96-
$.outputChannel.appendLine(`# Config file ${eventName}: ${fsPath}`)
97-
clearTimeout(initTimeout)
98-
initTimeout = setTimeout(async () => await init(), 250)
99-
})
100-
init()
101-
}
97+
init()
10298
}
10399

104100
function getSettings(): SettingsType {
@@ -109,25 +105,70 @@ function getSettings(): SettingsType {
109105
enabled: get("enabled"),
110106
path: get("path"),
111107
phpPath: get("phpPath"),
108+
configPath: get("configPath"),
112109
fileWatcher: get("fileWatcher"),
113110
configFileWatcher: get("configFileWatcher"),
114-
configFileWatcherBasenames: get("configFileWatcherBasenames"),
115111
analysedDelay: get("analysedDelay"),
116112
memoryLimit: get("memoryLimit"),
117113
}
118114
}
119115

120116
async function init() {
121-
$.fileWatcher?.dispose()
117+
$.fileWatchers.map((w) => w.dispose())
118+
$.fileWatchers = []
119+
$.outputChannel.appendLine("# Init")
120+
121+
try {
122+
configPath = settings.configPath
123+
? isAbsolute(settings.configPath)
124+
? settings.configPath
125+
: join(PHPStan.settings.rootPath, settings.configPath)
126+
: await PHPStan.findConfigPath()
127+
} catch (error) {
128+
return setStatusBarError(error, "Config path error")
129+
}
130+
131+
if (settings.configFileWatcher) {
132+
const run = async (uri: vscode.Uri, eventName: string) => {
133+
if (!fileWatcherState) return
134+
const fsPath = sanitizeFsPath(uri.fsPath)
135+
$.outputChannel.appendLine(`# Config file ${eventName}: ${fsPath}`)
136+
clearTimeout(initTimeout)
137+
initTimeout = setTimeout(async () => await init(), 250)
138+
}
139+
140+
const configFileWatchers: typeof $.fileWatchers = []
141+
142+
if (settings.configPath) {
143+
configFileWatchers.push(
144+
vscode.workspace.createFileSystemWatcher(configPath)
145+
)
146+
} else {
147+
configFileWatchers.push(
148+
vscode.workspace.createFileSystemWatcher(
149+
new vscode.RelativePattern(
150+
$.rootPath,
151+
`{phpstan.neon,phpstan.neon.dist}`
152+
)
153+
)
154+
)
155+
}
156+
157+
for (const watcher of configFileWatchers) {
158+
onFileWatcherEvent(watcher, run)
159+
}
160+
161+
$.fileWatchers.push(...configFileWatchers)
162+
}
122163
try {
123-
configPath = await PHPStan.findConfigPath()
124164
config = configPath ? await PHPStan.parseConfig(configPath) : null
125165
} catch (error) {
126166
return setStatusBarError(error, "Parse config error")
127167
}
168+
128169
$.outputChannel.appendLine(`# Config:\n${JSON.stringify(config, null, 2)}`)
129170
if (config) {
130-
if (settings.fileWatcher) $.fileWatcher = createFileWatcher()
171+
if (settings.fileWatcher) $.fileWatchers.push(createFileWatcher())
131172
analyseCommand(0)
132173
}
133174
}
@@ -151,9 +192,14 @@ function createFileWatcher() {
151192
return watcher
152193
}
153194

154-
export function deactivate(): void {
195+
export function deactivate(filter: {
196+
include?: (keyof typeof $)[]
197+
exclude?: (keyof typeof $)[]
198+
}): void {
155199
for (const key in $) {
156200
const value = $[key]
201+
if (filter.include && !filter.exclude.includes(key as never)) continue
202+
if (filter.exclude && filter.exclude.includes(key as never)) continue
157203
if (isDisposable(value)) {
158204
value.dispose()
159205
} else if (Array.isArray(value)) {
@@ -269,7 +315,13 @@ async function clearCacheCommand() {
269315
try {
270316
const childProcess = spawn(
271317
settings.phpPath,
272-
["-f", settings.path, "clear-result-cache"],
318+
[
319+
"-f",
320+
settings.path,
321+
"--",
322+
"clear-result-cache",
323+
...(configPath ? ["-c", configPath] : []),
324+
],
273325
{
274326
cwd: PHPStan.settings.rootPath,
275327
}
@@ -295,7 +347,13 @@ async function phpstanAnalyse(args?: string[]) {
295347
setStatusBarProgress()
296348

297349
try {
298-
args = ["-f", settings.path, "analyse"]
350+
args = [
351+
"-f",
352+
settings.path,
353+
"--",
354+
"analyse",
355+
...(configPath ? ["-c", configPath] : []),
356+
]
299357
.concat(
300358
settings.memoryLimit
301359
? ["--memory-limit=" + settings.memoryLimit]

0 commit comments

Comments
 (0)