From 180183789c5eec579b41f0584c85c07578798706 Mon Sep 17 00:00:00 2001 From: Joel Day Date: Sat, 14 Jan 2023 13:03:50 -0800 Subject: [PATCH 1/5] fix: Prerelease versioning scheme produced invalid semvers. --- build.cake | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/build.cake b/build.cake index 494aaf1a..288aca4c 100644 --- a/build.cake +++ b/build.cake @@ -96,8 +96,14 @@ Task("get-version") .Does(() => { if (isPrerelease) { - // Set version to a YYYY.MMDD.HHMM formatted string. - version = DateTime.UtcNow.ToString("yyyy.MMdd.HHmm"); + // Generate a correctly sortable and valid semver based on the current date and time. + var now = DateTime.UtcNow; + var secondOfDay = (((now.Hour * 60) + now.Minute) * 60) + now.Second; + + // Adding 200 due to the previous incorrect versioning scheme that, while invalid, may still be sorted by + // something (VS marketplace, maybe? Don't really feel like finding out.) + version = $"{now.Year}.{now.DayOfYear + 200}.{secondOfDay}"; + return; } From 1d64045dd22b41df94f9dec6fd5a7282cfd0550f Mon Sep 17 00:00:00 2001 From: Joel Day Date: Sat, 14 Jan 2023 15:00:36 -0800 Subject: [PATCH 2/5] chore: Replace decoration-ioc with inversify (actually maintained and not broken) docs: Add notes about updated debugger, Address Library requirements. --- src/papyrus-lang-vscode/package-lock.json | 22 +++---- src/papyrus-lang-vscode/package.json | 2 +- .../resources/welcome/index.md | 49 +++++++++++----- .../src/CreationKitInfoProvider.ts | 9 +-- .../src/ExtensionConfigProvider.ts | 5 +- .../src/PapyrusExtension.ts | 58 +++++++++---------- src/papyrus-lang-vscode/src/common/Ioc.ts | 8 --- .../src/common/PathResolver.ts | 10 ++-- .../src/common/vscode/IocDecorators.ts | 4 +- .../src/common/vscode/commands/CommandBase.ts | 4 +- .../vscode/commands/EditorCommandBase.ts | 4 +- .../view/ActiveDocTreeDataProviderBase.ts | 2 + .../vscode/view/TreeDataProviderBase.ts | 2 + .../debugger/DebugSupportInstallService.ts | 11 ++-- .../PapyrusDebugAdapterDescriptorFactory.ts | 12 ++-- .../PapyrusDebugConfigurationProvider.ts | 2 + .../features/AssemblyTextContentProvider.ts | 4 +- .../features/LanguageServiceStatusItems.ts | 11 ++-- .../src/features/PyroTaskProvider.ts | 5 +- .../features/ScriptStatusCodeLensProvider.ts | 4 +- .../src/features/WelcomeHandler.ts | 1 - .../commands/AttachDebuggerCommand.ts | 2 + .../src/features/commands/GameCommandBase.ts | 4 +- .../commands/GenerateProjectCommand.ts | 7 ++- .../commands/InstallDebugSupportCommand.ts | 4 +- .../commands/SearchCreationKitWikiCommand.ts | 4 +- .../features/commands/ShowWelcomeCommand.ts | 4 +- .../features/commands/ViewAssemblyCommand.ts | 2 + .../projects/ProjectsTreeDataProvider.ts | 6 +- .../src/server/LanguageClientHost.ts | 3 +- .../src/server/LanguageClientManager.ts | 11 ++-- 31 files changed, 163 insertions(+), 113 deletions(-) delete mode 100644 src/papyrus-lang-vscode/src/common/Ioc.ts diff --git a/src/papyrus-lang-vscode/package-lock.json b/src/papyrus-lang-vscode/package-lock.json index 50567eee..f98bf9e0 100644 --- a/src/papyrus-lang-vscode/package-lock.json +++ b/src/papyrus-lang-vscode/package-lock.json @@ -10,13 +10,13 @@ "dependencies": { "@semantic-release/exec": "^6.0.3", "@types/semantic-release": "^17.2.4", - "decoration-ioc": "^2.1.0", "deepmerge": "^4.2.2", "fast-deep-equal": "^3.1.3", "ini": "^3.0.1", "inversify": "^6.0.1", "md5-file": "^5.0.0", "ps-list": "^6.3.0", + "reflect-metadata": "^0.1.13", "rxjs": "^6.6.7", "vscode-debugprotocol": "^1.37.0", "vscode-languageclient": "^5.2.1", @@ -1899,11 +1899,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/decoration-ioc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/decoration-ioc/-/decoration-ioc-2.1.0.tgz", - "integrity": "sha512-JpUmeLp6kEc635+vQjfNM+aPiRMUwyfBeWn3cA+Toi99oZzjmdw30lSgo2UBl0S/Ej1eKatOkv10isKuJ1hdKg==" - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -6864,6 +6859,11 @@ "esprima": "~4.0.0" } }, + "node_modules/reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "node_modules/registry-auth-token": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", @@ -9885,11 +9885,6 @@ "mimic-response": "^3.1.0" } }, - "decoration-ioc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/decoration-ioc/-/decoration-ioc-2.1.0.tgz", - "integrity": "sha512-JpUmeLp6kEc635+vQjfNM+aPiRMUwyfBeWn3cA+Toi99oZzjmdw30lSgo2UBl0S/Ej1eKatOkv10isKuJ1hdKg==" - }, "deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -13369,6 +13364,11 @@ "esprima": "~4.0.0" } }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, "registry-auth-token": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.2.tgz", diff --git a/src/papyrus-lang-vscode/package.json b/src/papyrus-lang-vscode/package.json index 8f642cde..559d3c96 100644 --- a/src/papyrus-lang-vscode/package.json +++ b/src/papyrus-lang-vscode/package.json @@ -515,7 +515,7 @@ "dependencies": { "@semantic-release/exec": "^6.0.3", "@types/semantic-release": "^17.2.4", - "decoration-ioc": "^2.1.0", + "reflect-metadata": "^0.1.13", "deepmerge": "^4.2.2", "fast-deep-equal": "^3.1.3", "ini": "^3.0.1", diff --git a/src/papyrus-lang-vscode/resources/welcome/index.md b/src/papyrus-lang-vscode/resources/welcome/index.md index be16b6f6..cc1dc5fd 100644 --- a/src/papyrus-lang-vscode/resources/welcome/index.md +++ b/src/papyrus-lang-vscode/resources/welcome/index.md @@ -1,12 +1,32 @@ +# New in Papyrus for VSCode! + +## Debugger + +- You can now debug scripts in Skyrim AE, thanks to the hard work of nikitalita! This also includes improvements under the hood that will enable us to add more features in the future and ensure compatibility with future releases of Skyrim and Fallout 4. + +### It is now necessary to install the Address Library mods for debugging to work! + +- Skyrim: https://www.nexusmods.com/skyrimspecialedition/mods/32444 +- Fallout 4: https://www.nexusmods.com/fallout4/mods/46068 + +Future versions of the extension will assist in locating and installing these mods as a part of the debugger setup process. + +## Pyro + +- Starting in v3, Pyro has been updated and will continue to be going forward, so there's no need to copy new versions of Pyro into the extension. In the future, Pyro will be automatically updated independent of new releases of the extension. + +--- + # Getting Started With Papyrus for VSCode **Welcome to the Papyrus language support VSCode extension!** This document is here to help you get up and running as quickly as possible. Once you no longer need it, just close the tab. You can open it again from the Papyrus project explorer menu if needed. ## Requirements + If you have ever modded a game that uses Papyrus before then you likely already meet these requirements. 1. Have a supported [game installed](https://github.com/joelday/papyrus-lang/wiki/Game#installation) such as Skyrim or Fallout 4. -2. Have the [Creation Kit installed](https://github.com/joelday/papyrus-lang/wiki/Creation-Kit#installation) and included [base scripts](https://github.com/joelday/papyrus-lang/wiki/Glossary#base-script) extracted. The *Creation Kit* requires a supported game to be installed. +2. Have the [Creation Kit installed](https://github.com/joelday/papyrus-lang/wiki/Creation-Kit#installation) and included [base scripts](https://github.com/joelday/papyrus-lang/wiki/Glossary#base-script) extracted. The _Creation Kit_ requires a supported game to be installed. 3. **Optionally** have [xSE](https://github.com/joelday/papyrus-lang/wiki/Glossary#script-extender-xse-skse-f4se) installed for [Debugging](https://github.com/joelday/papyrus-lang/wiki/Debugging) support. ## Configuration @@ -18,9 +38,10 @@ First you want to check your configuration settings. You can access the configur Click on the gear and select **Configure Extension Settings**. The main things you need to do are: + 1. Enable any games you want to use the extension with and disable any games that you don't want to develop for. 2. Make sure the paths to the game install directories are correct. The game will try to find these using the Windows Registry, but it's better to explicitly define them here. -3. If you are using *Mod Organizer 2* then you might want to set your **Mod Directory Path** for any games you plan to use. More information about using Mod Organizer 2 with the Papyrus extension [can be found here on the wiki](https://github.com/joelday/papyrus-lang/wiki/Using-Mod-Organizer-2). +3. If you are using _Mod Organizer 2_ then you might want to set your **Mod Directory Path** for any games you plan to use. More information about using Mod Organizer 2 with the Papyrus extension [can be found here on the wiki](https://github.com/joelday/papyrus-lang/wiki/Using-Mod-Organizer-2). So now your configuration is done and you're ready to generate some project files! @@ -44,7 +65,7 @@ To build using the `.ppj` file, select **Terminal->Run Task...** and you should ## Debugging -The debugger needs to install an *xSE Extension* (script extender extension) in order to work, but this is done for you the first time you try to launch the debugger. If you want this extension installed in your Mod Organizer 2 mod directory as a mod where it can be enabled and disabled easily, make sure to set the path for the MO2 "mods" folder in the extension configuration for each game you want to use. +The debugger needs to install an _xSE Extension_ (script extender extension) in order to work, but this is done for you the first time you try to launch the debugger. If you want this extension installed in your Mod Organizer 2 mod directory as a mod where it can be enabled and disabled easily, make sure to set the path for the MO2 "mods" folder in the extension configuration for each game you want to use. ![Debugging](debugging.jpg) @@ -53,20 +74,22 @@ To launch the debugger, click the icon that looks like a bug with an X in it in Now all you need to do is launch the game and start up the debugger again. Breakpoints are supported as is inspection of variables. ## Features -At this point all features are supported for all games *except* debugging is not supported for Skyrim LE. -| Feature | Skyrim LE | Skyrim SE | Fallout 4 | -| ------------------------------------------ | --------- | --------- | --------- | -| [Language Definition](https://github.com/joelday/papyrus-lang/wiki/Language-Definition) | Yes | Yes | Yes | -| [Static Analysis](https://github.com/joelday/papyrus-lang/wiki/Static-Analysis) | Yes | Yes | Yes | -| [IntelliSense](https://github.com/joelday/papyrus-lang/wiki/IntelliSense) | Yes | Yes | Yes | -| [Refactoring](https://github.com/joelday/papyrus-lang/wiki/Refactoring) | Yes | Yes | Yes | -| [Compilation](https://github.com/joelday/papyrus-lang/wiki/Compilation) | Yes | Yes | Yes | -| [Debugging](https://github.com/joelday/papyrus-lang/wiki/Debugging) | No | Yes | Yes | +At this point all features are supported for all games _except_ debugging is not supported for Skyrim LE. + +| Feature | Skyrim LE | Skyrim SE | Fallout 4 | +| --------------------------------------------------------------------------------------- | --------- | --------- | --------- | +| [Language Definition](https://github.com/joelday/papyrus-lang/wiki/Language-Definition) | Yes | Yes | Yes | +| [Static Analysis](https://github.com/joelday/papyrus-lang/wiki/Static-Analysis) | Yes | Yes | Yes | +| [IntelliSense](https://github.com/joelday/papyrus-lang/wiki/IntelliSense) | Yes | Yes | Yes | +| [Refactoring](https://github.com/joelday/papyrus-lang/wiki/Refactoring) | Yes | Yes | Yes | +| [Compilation](https://github.com/joelday/papyrus-lang/wiki/Compilation) | Yes | Yes | Yes | +| [Debugging](https://github.com/joelday/papyrus-lang/wiki/Debugging) | No | Yes | Yes | ## Further Resources + First, [see the wiki](https://github.com/joelday/papyrus-lang/wiki) for more documentation. Also, consider joining the [Papyrus Language Tools Discord Server](https://discord.gg/upNN3TJ) to let us know what you think or ask questions. -Happy modding! \ No newline at end of file +Happy modding! diff --git a/src/papyrus-lang-vscode/src/CreationKitInfoProvider.ts b/src/papyrus-lang-vscode/src/CreationKitInfoProvider.ts index d849dee4..4b506409 100644 --- a/src/papyrus-lang-vscode/src/CreationKitInfoProvider.ts +++ b/src/papyrus-lang-vscode/src/CreationKitInfoProvider.ts @@ -1,4 +1,4 @@ -import { createDecorator } from 'decoration-ioc'; +import { interfaces, inject, injectable } from 'inversify'; import { PapyrusGame, getGames } from './PapyrusGame'; import { IExtensionConfigProvider } from './ExtensionConfigProvider'; import { Observable, combineLatest } from 'rxjs'; @@ -68,12 +68,13 @@ export interface ICreationKitInfoProvider { readonly infos: ReadonlyMap>; } +@injectable() export class CreationKitInfoProvider { private readonly _infos: Map>; constructor( - @IExtensionConfigProvider infoProvider: IExtensionConfigProvider, - @IPathResolver pathResolver: IPathResolver + @inject(IExtensionConfigProvider) infoProvider: IExtensionConfigProvider, + @inject(IPathResolver) pathResolver: IPathResolver ) { const createInfoObservable = (game: PapyrusGame) => { const gameConfig = infoProvider.config.pipe(map((config) => config[game])); @@ -170,4 +171,4 @@ export class CreationKitInfoProvider { } } -export const ICreationKitInfoProvider = createDecorator('creationKitInfoProvider'); +export const ICreationKitInfoProvider: interfaces.ServiceIdentifier = Symbol('creationKitInfoProvider'); diff --git a/src/papyrus-lang-vscode/src/ExtensionConfigProvider.ts b/src/papyrus-lang-vscode/src/ExtensionConfigProvider.ts index 37503493..7519bb70 100644 --- a/src/papyrus-lang-vscode/src/ExtensionConfigProvider.ts +++ b/src/papyrus-lang-vscode/src/ExtensionConfigProvider.ts @@ -1,4 +1,4 @@ -import { createDecorator } from 'decoration-ioc'; +import { injectable, interfaces } from 'inversify'; import { workspace, Disposable } from 'vscode'; import { eventToValueObservable } from './common/vscode/reactive/Events'; import { Observable } from 'rxjs'; @@ -25,6 +25,7 @@ function getPapyrusConfig() { return workspace.getConfiguration().get('papyrus'); } +@injectable() export class ExtensionConfigProvider implements IExtensionConfigProvider { private readonly _config = eventToValueObservable( workspace.onDidChangeConfiguration, @@ -39,4 +40,4 @@ export class ExtensionConfigProvider implements IExtensionConfigProvider { dispose() { } } -export const IExtensionConfigProvider = createDecorator('extensionConfigProvider'); +export const IExtensionConfigProvider: interfaces.ServiceIdentifier = Symbol('extensionConfigProvider'); diff --git a/src/papyrus-lang-vscode/src/PapyrusExtension.ts b/src/papyrus-lang-vscode/src/PapyrusExtension.ts index 63058303..531faa92 100644 --- a/src/papyrus-lang-vscode/src/PapyrusExtension.ts +++ b/src/papyrus-lang-vscode/src/PapyrusExtension.ts @@ -1,5 +1,6 @@ +import "reflect-metadata"; + import { Disposable, extensions, ExtensionContext } from 'vscode'; -import { ServiceCollection, IInstantiationService, InstantiationService, Descriptor } from 'decoration-ioc'; import { extensionQualifiedId, GlobalState } from './common/constants'; import { IExtensionContext } from './common/vscode/IocDecorators'; import { IExtensionConfigProvider, ExtensionConfigProvider } from './ExtensionConfigProvider'; @@ -7,7 +8,6 @@ import { IPathResolver, PathResolver } from './common/PathResolver'; import { LanguageClientManager, ILanguageClientManager } from './server/LanguageClientManager'; import { LanguageServiceStatusItems } from './features/LanguageServiceStatusItems'; import { LanguageConfigurations } from './features/LanguageConfigurations'; -import { getInstance } from './common/Ioc'; import { PyroTaskProvider } from './features/PyroTaskProvider'; import { ICreationKitInfoProvider, CreationKitInfoProvider } from './CreationKitInfoProvider'; import { ScriptStatusCodeLensProvider } from './features/ScriptStatusCodeLensProvider'; @@ -25,10 +25,10 @@ import { ViewAssemblyCommand } from './features/commands/ViewAssemblyCommand'; import { GenerateProjectCommand } from './features/commands/GenerateProjectCommand'; import { showWelcome } from './features/WelcomeHandler'; import { ShowWelcomeCommand } from './features/commands/ShowWelcomeCommand'; +import { Container } from 'inversify'; class PapyrusExtension implements Disposable { - private readonly _serviceCollection: ServiceCollection; - private readonly _instantiationService: IInstantiationService; + private readonly _serviceContainer: Container; private readonly _configProvider: IExtensionConfigProvider; private readonly _clientManager: ILanguageClientManager; private readonly _statusItems: LanguageServiceStatusItems; @@ -57,45 +57,43 @@ class PapyrusExtension implements Disposable { this._languageConfigurations = new LanguageConfigurations(); - this._serviceCollection = new ServiceCollection( - [IExtensionContext, context], - [IExtensionConfigProvider, new Descriptor(ExtensionConfigProvider)], - [IPathResolver, new Descriptor(PathResolver)], - [ICreationKitInfoProvider, new Descriptor(CreationKitInfoProvider)], - [ILanguageClientManager, new Descriptor(LanguageClientManager)], - [IDebugSupportInstallService, new Descriptor(DebugSupportInstallService)], + this._serviceContainer = new Container( + { + defaultScope: 'Singleton', + } ); - this._instantiationService = new InstantiationService(this._serviceCollection); - - this._configProvider = getInstance(this._serviceCollection, IExtensionConfigProvider); - this._clientManager = getInstance(this._serviceCollection, ILanguageClientManager); - this._statusItems = this._instantiationService.createInstance(LanguageServiceStatusItems); + this._serviceContainer.bind(IExtensionContext).toConstantValue(context); + this._serviceContainer.bind(IExtensionConfigProvider).to(ExtensionConfigProvider); + this._serviceContainer.bind(IPathResolver).to(PathResolver); + this._serviceContainer.bind(ICreationKitInfoProvider).to(CreationKitInfoProvider); + this._serviceContainer.bind(ILanguageClientManager).to(LanguageClientManager); + this._serviceContainer.bind(IDebugSupportInstallService).to(DebugSupportInstallService); - this._pyroProvider = this._instantiationService.createInstance(PyroTaskProvider); + this._configProvider = this._serviceContainer.get(IExtensionConfigProvider); + this._clientManager = this._serviceContainer.get(ILanguageClientManager); - this._scriptStatusCodeLensProvider = this._instantiationService.createInstance(ScriptStatusCodeLensProvider); - this._searchWikiCommand = this._instantiationService.createInstance(SearchCreationKitWikiCommand); - - this._debugConfigurationProvider = this._instantiationService.createInstance(PapyrusDebugConfigurationProvider); - this._debugAdapterDescriptorFactory = this._instantiationService.createInstance( - PapyrusDebugAdapterDescriptorFactory - ); + this._statusItems = this._serviceContainer.resolve(LanguageServiceStatusItems); + this._pyroProvider = this._serviceContainer.resolve(PyroTaskProvider); + this._scriptStatusCodeLensProvider = this._serviceContainer.resolve(ScriptStatusCodeLensProvider); + this._searchWikiCommand = this._serviceContainer.resolve(SearchCreationKitWikiCommand); + this._debugConfigurationProvider = this._serviceContainer.resolve(PapyrusDebugConfigurationProvider); + this._debugAdapterDescriptorFactory = this._serviceContainer.resolve(PapyrusDebugAdapterDescriptorFactory); + this._installDebugSupportCommand = this._serviceContainer.resolve(InstallDebugSupportCommand); - this._installDebugSupportCommand = this._instantiationService.createInstance(InstallDebugSupportCommand); this._debugAdapterTrackerFactory = new PapyrusDebugAdapterTrackerFactory(); this._attachCommand = new AttachDebuggerCommand(); - this._projectsTreeDataProvider = this._instantiationService.createInstance(ProjectsTreeDataProvider); + this._projectsTreeDataProvider = this._serviceContainer.resolve(ProjectsTreeDataProvider); this._projectsView = new ProjectsView(this._projectsTreeDataProvider); - this._assemblyTextContentProvider = this._instantiationService.createInstance(AssemblyTextContentProvider); - this._viewAssemblyCommand = this._instantiationService.createInstance(ViewAssemblyCommand); + this._assemblyTextContentProvider = this._serviceContainer.resolve(AssemblyTextContentProvider); + this._viewAssemblyCommand = this._serviceContainer.resolve(ViewAssemblyCommand); - this._generateProjectCommand = this._instantiationService.createInstance(GenerateProjectCommand); + this._generateProjectCommand = this._serviceContainer.resolve(GenerateProjectCommand); - this._showWelcomeCommand = this._instantiationService.createInstance(ShowWelcomeCommand); + this._showWelcomeCommand = this._serviceContainer.resolve(ShowWelcomeCommand); // Show the getting started document if there's no previous version (new install) // At some point we might want a "what's new" so I included both version numbers. diff --git a/src/papyrus-lang-vscode/src/common/Ioc.ts b/src/papyrus-lang-vscode/src/common/Ioc.ts deleted file mode 100644 index 5859a257..00000000 --- a/src/papyrus-lang-vscode/src/common/Ioc.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ServiceCollection } from 'decoration-ioc'; -import { ServiceIdentifier, IInstantiationService } from 'decoration-ioc/lib/instantiation'; - -export function getInstance(serviceCollection: ServiceCollection, serviceIdentifier: ServiceIdentifier) { - return (serviceCollection.get(IInstantiationService) as IInstantiationService).invokeFunction((accessor) => - accessor.get(serviceIdentifier) - ); -} diff --git a/src/papyrus-lang-vscode/src/common/PathResolver.ts b/src/papyrus-lang-vscode/src/common/PathResolver.ts index 009def94..355f33fd 100644 --- a/src/papyrus-lang-vscode/src/common/PathResolver.ts +++ b/src/papyrus-lang-vscode/src/common/PathResolver.ts @@ -1,7 +1,7 @@ import * as fs from 'fs'; import * as path from 'path'; -import { createDecorator } from 'decoration-ioc'; +import { inject, injectable, interfaces } from 'inversify'; import { take } from 'rxjs/operators'; import winreg from 'winreg'; import { promisify } from 'util'; @@ -31,14 +31,14 @@ export interface IPathResolver { getDebugPluginInstallPath(game: PapyrusGame, legacy?: boolean): Promise; } - +@injectable() export class PathResolver implements IPathResolver { private readonly _configProvider: IExtensionConfigProvider; private readonly _context: ExtensionContext; constructor( - @IExtensionConfigProvider configProvider: IExtensionConfigProvider, - @IExtensionContext context: ExtensionContext + @inject(IExtensionConfigProvider) configProvider: IExtensionConfigProvider, + @inject(IExtensionContext) context: ExtensionContext ) { this._configProvider = configProvider; this._context = context; @@ -141,7 +141,7 @@ export class PathResolver implements IPathResolver { dispose() { } } -export const IPathResolver = createDecorator('pathResolver'); +export const IPathResolver: interfaces.ServiceIdentifier = Symbol('pathResolver'); /************************************************************************* */ diff --git a/src/papyrus-lang-vscode/src/common/vscode/IocDecorators.ts b/src/papyrus-lang-vscode/src/common/vscode/IocDecorators.ts index 55e7cfb6..26f3e29c 100644 --- a/src/papyrus-lang-vscode/src/common/vscode/IocDecorators.ts +++ b/src/papyrus-lang-vscode/src/common/vscode/IocDecorators.ts @@ -1,4 +1,4 @@ -import { createDecorator } from 'decoration-ioc'; +import { interfaces } from 'inversify'; import { ExtensionContext } from 'vscode'; -export const IExtensionContext = createDecorator('extensionContext'); +export const IExtensionContext: interfaces.ServiceIdentifier = Symbol('extensionContext'); diff --git a/src/papyrus-lang-vscode/src/common/vscode/commands/CommandBase.ts b/src/papyrus-lang-vscode/src/common/vscode/commands/CommandBase.ts index 7d0dcc89..6f1957dd 100644 --- a/src/papyrus-lang-vscode/src/common/vscode/commands/CommandBase.ts +++ b/src/papyrus-lang-vscode/src/common/vscode/commands/CommandBase.ts @@ -1,10 +1,12 @@ +import { injectable, unmanaged } from 'inversify'; import { commands, Disposable } from 'vscode'; +@injectable() export abstract class CommandBase implements Disposable { private readonly _name: string; private readonly _registration: Disposable; - constructor(name: string) { + constructor(@unmanaged() name: string) { this._name = name; this._registration = commands.registerCommand(this._name, (...args) => { return this.onExecute(...((args || []) as TArgs)); diff --git a/src/papyrus-lang-vscode/src/common/vscode/commands/EditorCommandBase.ts b/src/papyrus-lang-vscode/src/common/vscode/commands/EditorCommandBase.ts index 54daaca1..2057075b 100644 --- a/src/papyrus-lang-vscode/src/common/vscode/commands/EditorCommandBase.ts +++ b/src/papyrus-lang-vscode/src/common/vscode/commands/EditorCommandBase.ts @@ -1,10 +1,12 @@ +import { injectable, unmanaged } from 'inversify'; import { Disposable, commands, TextEditor, TextEditorEdit } from 'vscode'; +@injectable() export abstract class EditorCommandBase implements Disposable { private readonly _name: string; private readonly _registration: Disposable; - constructor(name: string) { + constructor(@unmanaged() name: string) { this._name = name; this._registration = commands.registerTextEditorCommand(this._name, (editor, edit, ...args) => { return this.onExecute(editor, edit, ...((args || []) as TArgs)); diff --git a/src/papyrus-lang-vscode/src/common/vscode/view/ActiveDocTreeDataProviderBase.ts b/src/papyrus-lang-vscode/src/common/vscode/view/ActiveDocTreeDataProviderBase.ts index ead89e92..3632cbff 100644 --- a/src/papyrus-lang-vscode/src/common/vscode/view/ActiveDocTreeDataProviderBase.ts +++ b/src/papyrus-lang-vscode/src/common/vscode/view/ActiveDocTreeDataProviderBase.ts @@ -1,7 +1,9 @@ +import { injectable } from 'inversify'; import * as vs from 'vscode'; import { TreeDataProviderBase } from './TreeDataProviderBase'; +@injectable() export abstract class ActiveDocTreeDataProviderBase extends TreeDataProviderBase { constructor() { super(); diff --git a/src/papyrus-lang-vscode/src/common/vscode/view/TreeDataProviderBase.ts b/src/papyrus-lang-vscode/src/common/vscode/view/TreeDataProviderBase.ts index b3946732..621386f1 100644 --- a/src/papyrus-lang-vscode/src/common/vscode/view/TreeDataProviderBase.ts +++ b/src/papyrus-lang-vscode/src/common/vscode/view/TreeDataProviderBase.ts @@ -1,7 +1,9 @@ +import { injectable } from 'inversify'; import * as vs from 'vscode'; import { TreeDataNode } from './TreeDataNode'; +@injectable() export abstract class TreeDataProviderBase implements vs.TreeDataProvider, vs.Disposable { diff --git a/src/papyrus-lang-vscode/src/debugger/DebugSupportInstallService.ts b/src/papyrus-lang-vscode/src/debugger/DebugSupportInstallService.ts index 07d4a904..46110208 100644 --- a/src/papyrus-lang-vscode/src/debugger/DebugSupportInstallService.ts +++ b/src/papyrus-lang-vscode/src/debugger/DebugSupportInstallService.ts @@ -1,4 +1,4 @@ -import { createDecorator } from 'decoration-ioc'; +import { inject, injectable, interfaces } from 'inversify'; import { IExtensionConfigProvider } from '../ExtensionConfigProvider'; import { CancellationToken, CancellationTokenSource } from 'vscode'; import { take } from 'rxjs/operators'; @@ -32,15 +32,16 @@ export interface IDebugSupportInstallService { installPlugin(game: PapyrusGame, cancellationToken?: CancellationToken): Promise; } +@injectable() export class DebugSupportInstallService implements IDebugSupportInstallService { private readonly _configProvider: IExtensionConfigProvider; private readonly _languageClientManager: ILanguageClientManager; private readonly _pathResolver: IPathResolver; constructor( - @ILanguageClientManager languageClientManager: ILanguageClientManager, - @IExtensionConfigProvider configProvider: IExtensionConfigProvider, - @IPathResolver pathResolver: IPathResolver + @inject(ILanguageClientManager) languageClientManager: ILanguageClientManager, + @inject(IExtensionConfigProvider) configProvider: IExtensionConfigProvider, + @inject(IPathResolver) pathResolver: IPathResolver ) { this._languageClientManager = languageClientManager; this._configProvider = configProvider; @@ -114,4 +115,4 @@ export class DebugSupportInstallService implements IDebugSupportInstallService { } } -export const IDebugSupportInstallService = createDecorator('debugSupportInstallService'); +export const IDebugSupportInstallService: interfaces.ServiceIdentifier = Symbol('debugSupportInstallService'); diff --git a/src/papyrus-lang-vscode/src/debugger/PapyrusDebugAdapterDescriptorFactory.ts b/src/papyrus-lang-vscode/src/debugger/PapyrusDebugAdapterDescriptorFactory.ts index 4ad2c570..007cb939 100644 --- a/src/papyrus-lang-vscode/src/debugger/PapyrusDebugAdapterDescriptorFactory.ts +++ b/src/papyrus-lang-vscode/src/debugger/PapyrusDebugAdapterDescriptorFactory.ts @@ -25,6 +25,7 @@ import { IPathResolver } from '../common/PathResolver'; import { IDebugSupportInstallService, DebugSupportInstallState } from './DebugSupportInstallService'; import { ILanguageClientManager } from '../server/LanguageClientManager'; import { showGameDisabledMessage, showGameMissingMessage } from '../features/commands/InstallDebugSupportCommand'; +import { inject, injectable } from 'inversify'; const noopExecutable = new DebugAdapterExecutable('node', ['-e', '""']); @@ -42,6 +43,7 @@ function getDefaultPortForGame(game: PapyrusGame) { return game === PapyrusGame.fallout4 ? 2077 : 43201; } +@injectable() export class PapyrusDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory { private readonly _languageClientManager: ILanguageClientManager; private readonly _creationKitInfoProvider: ICreationKitInfoProvider; @@ -51,11 +53,11 @@ export class PapyrusDebugAdapterDescriptorFactory implements DebugAdapterDescrip private readonly _registration: Disposable; constructor( - @ILanguageClientManager languageClientManager: ILanguageClientManager, - @ICreationKitInfoProvider creationKitInfoProvider: ICreationKitInfoProvider, - @IExtensionConfigProvider configProvider: IExtensionConfigProvider, - @IPathResolver pathResolver: IPathResolver, - @IDebugSupportInstallService debugSupportInstaller: IDebugSupportInstallService + @inject(ILanguageClientManager) languageClientManager: ILanguageClientManager, + @inject(ICreationKitInfoProvider) creationKitInfoProvider: ICreationKitInfoProvider, + @inject(IExtensionConfigProvider) configProvider: IExtensionConfigProvider, + @inject(IPathResolver) pathResolver: IPathResolver, + @inject(IDebugSupportInstallService) debugSupportInstaller: IDebugSupportInstallService ) { this._languageClientManager = languageClientManager; this._creationKitInfoProvider = creationKitInfoProvider; diff --git a/src/papyrus-lang-vscode/src/debugger/PapyrusDebugConfigurationProvider.ts b/src/papyrus-lang-vscode/src/debugger/PapyrusDebugConfigurationProvider.ts index e950b41c..41841d6b 100644 --- a/src/papyrus-lang-vscode/src/debugger/PapyrusDebugConfigurationProvider.ts +++ b/src/papyrus-lang-vscode/src/debugger/PapyrusDebugConfigurationProvider.ts @@ -1,3 +1,4 @@ +import { injectable } from 'inversify'; import { DebugConfigurationProvider, CancellationToken, WorkspaceFolder, debug, Disposable } from 'vscode'; import { PapyrusGame } from '../PapyrusGame'; import { IPapyrusDebugConfiguration } from './PapyrusDebugSession'; @@ -9,6 +10,7 @@ import { IPapyrusDebugConfiguration } from './PapyrusDebugSession'; // TODO: Resolve project from whichever that includes the active editor file. // TODO: Provide configurations based on .ppj files in current directory. +@injectable() export class PapyrusDebugConfigurationProvider implements DebugConfigurationProvider, Disposable { private readonly _registration: Disposable; diff --git a/src/papyrus-lang-vscode/src/features/AssemblyTextContentProvider.ts b/src/papyrus-lang-vscode/src/features/AssemblyTextContentProvider.ts index 3e746b76..1f55496f 100644 --- a/src/papyrus-lang-vscode/src/features/AssemblyTextContentProvider.ts +++ b/src/papyrus-lang-vscode/src/features/AssemblyTextContentProvider.ts @@ -1,11 +1,13 @@ +import { inject, injectable } from 'inversify'; import { TextDocumentContentProvider, Uri, CancellationToken, Disposable, workspace, window } from 'vscode'; import { ILanguageClientManager } from '../server/LanguageClientManager'; +@injectable() export class AssemblyTextContentProvider implements TextDocumentContentProvider { private readonly _languageClientManager: ILanguageClientManager; private readonly _registration: Disposable; - constructor(@ILanguageClientManager languageClientManager: ILanguageClientManager) { + constructor(@inject(ILanguageClientManager) languageClientManager: ILanguageClientManager) { this._languageClientManager = languageClientManager; this._registration = workspace.registerTextDocumentContentProvider('papyrus-assembly', this); diff --git a/src/papyrus-lang-vscode/src/features/LanguageServiceStatusItems.ts b/src/papyrus-lang-vscode/src/features/LanguageServiceStatusItems.ts index b950194c..6f84c889 100644 --- a/src/papyrus-lang-vscode/src/features/LanguageServiceStatusItems.ts +++ b/src/papyrus-lang-vscode/src/features/LanguageServiceStatusItems.ts @@ -8,6 +8,7 @@ import { eventToValueObservable } from '../common/vscode/reactive/Events'; import { asyncDisposable } from '../common/Reactive'; import { ShowOutputChannelCommand } from './commands/ShowOutputChannelCommand'; import { LocateOrDisableGameCommand } from './commands/LocateOrDisableGameCommand'; +import { inject, injectable } from 'inversify'; class StatusBarItemController implements Disposable { private readonly _statusBarItem: StatusBarItem; @@ -85,10 +86,9 @@ class StatusBarItemController implements Disposable { this._statusBarItem.tooltip = `${fullName} language service starting...`; break; case ClientHostStatus.running: - this._statusBarItem.text = `${displayName} ${ - activeDocumentScriptInfo && activeDocumentScriptInfo.identifiers.length > 0 - ? '$(verified)' - : '$(check)' + this._statusBarItem.text = `${displayName} ${activeDocumentScriptInfo && activeDocumentScriptInfo.identifiers.length > 0 + ? '$(verified)' + : '$(check)' }`; this._statusBarItem.tooltip = `${fullName} language service running.`; break; @@ -120,11 +120,12 @@ class StatusBarItemController implements Disposable { } } +@injectable() export class LanguageServiceStatusItems implements Disposable { private readonly _languageClientManager: ILanguageClientManager; private readonly _statusItems: Map; - constructor(@ILanguageClientManager languageClientManager: ILanguageClientManager) { + constructor(@inject(ILanguageClientManager) languageClientManager: ILanguageClientManager) { this._languageClientManager = languageClientManager; this._statusItems = new Map([ diff --git a/src/papyrus-lang-vscode/src/features/PyroTaskProvider.ts b/src/papyrus-lang-vscode/src/features/PyroTaskProvider.ts index 0a8843de..78a6d193 100644 --- a/src/papyrus-lang-vscode/src/features/PyroTaskProvider.ts +++ b/src/papyrus-lang-vscode/src/features/PyroTaskProvider.ts @@ -7,8 +7,9 @@ import { CancellationToken, Disposable } from 'vscode-jsonrpc'; import { IPyroTaskDefinition, TaskOf, PyroGameToPapyrusGame } from './PyroTaskDefinition'; import { PapyrusGame, getWorkspaceGameFromProjects, getWorkspaceGame } from '../PapyrusGame'; import { IPathResolver, PathResolver, pathToOsPath } from '../common/PathResolver'; +import { inject, injectable } from 'inversify'; - +@injectable() export class PyroTaskProvider implements TaskProvider, Disposable { private readonly _taskProviderHandle: Disposable; private readonly _pathResolver: IPathResolver; @@ -19,7 +20,7 @@ export class PyroTaskProvider implements TaskProvider, Disposable { private _workspaceGame: PapyrusGame; constructor( - @IPathResolver pathResolver: PathResolver + @inject(IPathResolver) pathResolver: PathResolver ) { this._pathResolver = pathResolver; diff --git a/src/papyrus-lang-vscode/src/features/ScriptStatusCodeLensProvider.ts b/src/papyrus-lang-vscode/src/features/ScriptStatusCodeLensProvider.ts index c574b5ca..d7165c3d 100644 --- a/src/papyrus-lang-vscode/src/features/ScriptStatusCodeLensProvider.ts +++ b/src/papyrus-lang-vscode/src/features/ScriptStatusCodeLensProvider.ts @@ -15,18 +15,20 @@ import { } from 'vscode'; import { mergeMap, distinctUntilChanged } from 'rxjs/operators'; import { Unsubscribable } from 'rxjs'; +import { inject, injectable } from 'inversify'; function createZeroLens() { return new CodeLens(new Range(new Position(0, 0), new Position(0, 0))); } +@injectable() export class ScriptStatusCodeLensProvider implements CodeLensProvider, Disposable { private readonly _languageClientManager: ILanguageClientManager; private readonly _codeLensProviderHandle: Disposable; private readonly _onDidChangeCodeLenses: EventEmitter; private readonly _languageServerSubscriptions: Unsubscribable[]; - constructor(@ILanguageClientManager languageClientManager: ILanguageClientManager) { + constructor(@inject(ILanguageClientManager) languageClientManager: ILanguageClientManager) { this._languageClientManager = languageClientManager; // Any server status changes need to trigger the code lenses to refresh. diff --git a/src/papyrus-lang-vscode/src/features/WelcomeHandler.ts b/src/papyrus-lang-vscode/src/features/WelcomeHandler.ts index b387d3fd..adc974d5 100644 --- a/src/papyrus-lang-vscode/src/features/WelcomeHandler.ts +++ b/src/papyrus-lang-vscode/src/features/WelcomeHandler.ts @@ -1,6 +1,5 @@ import { commands } from "vscode"; - export async function showWelcome(papyrusVersion: string, previousVersion: string): Promise { if (previousVersion === undefined) { console.log("No previous version found. This is a first time install. Showing welcome message."); diff --git a/src/papyrus-lang-vscode/src/features/commands/AttachDebuggerCommand.ts b/src/papyrus-lang-vscode/src/features/commands/AttachDebuggerCommand.ts index 44b33a78..d7d342f7 100644 --- a/src/papyrus-lang-vscode/src/features/commands/AttachDebuggerCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/AttachDebuggerCommand.ts @@ -1,8 +1,10 @@ +import { injectable } from 'inversify'; import { debug } from 'vscode'; import { IPapyrusDebugConfiguration } from '../../debugger/PapyrusDebugSession'; import { PapyrusGame, getShortDisplayNameForGame } from '../../PapyrusGame'; import { GameCommandBase } from './GameCommandBase'; +@injectable() export class AttachDebuggerCommand extends GameCommandBase { constructor() { super('attachDebugger', [PapyrusGame.fallout4, PapyrusGame.skyrimSpecialEdition]); diff --git a/src/papyrus-lang-vscode/src/features/commands/GameCommandBase.ts b/src/papyrus-lang-vscode/src/features/commands/GameCommandBase.ts index 04d9f089..d6d55984 100644 --- a/src/papyrus-lang-vscode/src/features/commands/GameCommandBase.ts +++ b/src/papyrus-lang-vscode/src/features/commands/GameCommandBase.ts @@ -1,11 +1,13 @@ +import { injectable, unmanaged } from 'inversify'; import { commands, Disposable } from 'vscode'; import { PapyrusGame, getGames } from '../../PapyrusGame'; +@injectable() export abstract class GameCommandBase implements Disposable { private readonly _name: string; private readonly _registrations: Disposable[]; - constructor(name: string, supportedGames: PapyrusGame[] = getGames()) { + constructor(@unmanaged() name: string, @unmanaged() supportedGames: PapyrusGame[] = getGames()) { this._name = name; this._registrations = supportedGames.map((game) => diff --git a/src/papyrus-lang-vscode/src/features/commands/GenerateProjectCommand.ts b/src/papyrus-lang-vscode/src/features/commands/GenerateProjectCommand.ts index d6708266..95c1e469 100644 --- a/src/papyrus-lang-vscode/src/features/commands/GenerateProjectCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/GenerateProjectCommand.ts @@ -9,20 +9,21 @@ import { copyAndFillTemplate, mkDirByPathSync } from '../../Utilities'; import * as path from 'path'; import * as fs from 'fs'; import { promisify } from 'util'; +import { inject, injectable } from 'inversify'; const exists = promisify(fs.exists); const mkdir = promisify(fs.mkdir); const copyFile = promisify(fs.copyFile); //const removeFile = promisify(fs.unlink); - +@injectable() export class GenerateProjectCommand extends GameCommandBase<[string]> { private readonly _context: ExtensionContext; private readonly _pathResolver: IPathResolver; constructor( - @IExtensionContext context: ExtensionContext, - @IPathResolver pathResolver: IPathResolver, + @inject(IExtensionContext) context: ExtensionContext, + @inject(IPathResolver) pathResolver: IPathResolver, ) { super("generateProject"); // pass additional args for execute() and onExecute() here this._context = context; diff --git a/src/papyrus-lang-vscode/src/features/commands/InstallDebugSupportCommand.ts b/src/papyrus-lang-vscode/src/features/commands/InstallDebugSupportCommand.ts index fc2240ff..dac3f057 100644 --- a/src/papyrus-lang-vscode/src/features/commands/InstallDebugSupportCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/InstallDebugSupportCommand.ts @@ -3,6 +3,7 @@ import { window, ProgressLocation } from 'vscode'; import { PapyrusGame, getDisplayNameForGame } from '../../PapyrusGame'; import { GameCommandBase } from './GameCommandBase'; import { getGameIsRunning, waitWhile } from '../../Utilities'; +import { inject, injectable } from 'inversify'; export function showGameDisabledMessage(game: PapyrusGame) { window.showErrorMessage( @@ -18,10 +19,11 @@ export function showGameMissingMessage(game: PapyrusGame) { ); } +@injectable() export class InstallDebugSupportCommand extends GameCommandBase { private readonly _installer: IDebugSupportInstallService; - constructor(@IDebugSupportInstallService installer: IDebugSupportInstallService) { + constructor(@inject(IDebugSupportInstallService) installer: IDebugSupportInstallService) { super('installDebuggerSupport', [PapyrusGame.fallout4, PapyrusGame.skyrimSpecialEdition]); this._installer = installer; diff --git a/src/papyrus-lang-vscode/src/features/commands/SearchCreationKitWikiCommand.ts b/src/papyrus-lang-vscode/src/features/commands/SearchCreationKitWikiCommand.ts index 7b509949..50a3fb87 100644 --- a/src/papyrus-lang-vscode/src/features/commands/SearchCreationKitWikiCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/SearchCreationKitWikiCommand.ts @@ -2,11 +2,13 @@ import { EditorCommandBase } from '../../common/vscode/commands/EditorCommandBas import { TextEditor, env, Uri, window } from 'vscode'; import { ILanguageClientManager } from '../../server/LanguageClientManager'; import { PapyrusGame } from '../../PapyrusGame'; +import { inject, injectable } from 'inversify'; +@injectable() export class SearchCreationKitWikiCommand extends EditorCommandBase { private readonly _languageClientManager: ILanguageClientManager; - constructor(@ILanguageClientManager languageClientManager: ILanguageClientManager) { + constructor(@inject(ILanguageClientManager) languageClientManager: ILanguageClientManager) { super('papyrus.searchCreationKitWiki'); this._languageClientManager = languageClientManager; diff --git a/src/papyrus-lang-vscode/src/features/commands/ShowWelcomeCommand.ts b/src/papyrus-lang-vscode/src/features/commands/ShowWelcomeCommand.ts index 099200d8..4cee3758 100644 --- a/src/papyrus-lang-vscode/src/features/commands/ShowWelcomeCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/ShowWelcomeCommand.ts @@ -1,11 +1,13 @@ import { Uri, commands } from 'vscode'; import { CommandBase } from '../../common/vscode/commands/CommandBase'; import { IPathResolver } from '../../common/PathResolver'; +import { inject, injectable } from 'inversify'; +@injectable() export class ShowWelcomeCommand extends CommandBase<[Uri]> { private readonly _pathResolver: IPathResolver; constructor( - @IPathResolver pathResolver: IPathResolver + @inject(IPathResolver) pathResolver: IPathResolver ) { super('papyrus.showWelcome'); this._pathResolver = pathResolver; diff --git a/src/papyrus-lang-vscode/src/features/commands/ViewAssemblyCommand.ts b/src/papyrus-lang-vscode/src/features/commands/ViewAssemblyCommand.ts index 99d439c4..03a66816 100644 --- a/src/papyrus-lang-vscode/src/features/commands/ViewAssemblyCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/ViewAssemblyCommand.ts @@ -1,6 +1,8 @@ +import { injectable } from 'inversify'; import { Uri, commands, window } from 'vscode'; import { CommandBase } from '../../common/vscode/commands/CommandBase'; +@injectable() export class ViewAssemblyCommand extends CommandBase<[Uri]> { constructor() { super('papyrus.viewAssembly'); diff --git a/src/papyrus-lang-vscode/src/features/projects/ProjectsTreeDataProvider.ts b/src/papyrus-lang-vscode/src/features/projects/ProjectsTreeDataProvider.ts index b127db3a..baa40261 100644 --- a/src/papyrus-lang-vscode/src/features/projects/ProjectsTreeDataProvider.ts +++ b/src/papyrus-lang-vscode/src/features/projects/ProjectsTreeDataProvider.ts @@ -13,6 +13,7 @@ import { import { PapyrusGame, getShortDisplayNameForGame } from '../../PapyrusGame'; import { flatten } from '../../Utilities'; import { IExtensionContext } from '../../common/vscode/IocDecorators'; +import { inject, injectable } from 'inversify'; export class GameTreeDataNode implements TreeDataNode { private readonly _context: ExtensionContext; @@ -170,6 +171,7 @@ export class ProjectScriptTreeDataNode implements TreeDataNode { } } +@injectable() export class ProjectsTreeDataProvider extends TreeDataProviderBase { private readonly _languageClientManager: ILanguageClientManager; private readonly _context: ExtensionContext; @@ -177,8 +179,8 @@ export class ProjectsTreeDataProvider extends TreeDataProviderBase { private readonly _projectInfosObservables: [PapyrusGame, Observable][]; constructor( - @ILanguageClientManager languageClientManager: ILanguageClientManager, - @IExtensionContext context: ExtensionContext + @inject(ILanguageClientManager) languageClientManager: ILanguageClientManager, + @inject(IExtensionContext) context: ExtensionContext ) { super(); diff --git a/src/papyrus-lang-vscode/src/server/LanguageClientHost.ts b/src/papyrus-lang-vscode/src/server/LanguageClientHost.ts index b368144e..49cbedbc 100644 --- a/src/papyrus-lang-vscode/src/server/LanguageClientHost.ts +++ b/src/papyrus-lang-vscode/src/server/LanguageClientHost.ts @@ -9,6 +9,7 @@ import { DocumentScriptInfo } from './messages/DocumentScriptInfo'; import { shareReplay, take, map, switchMap } from 'rxjs/operators'; import { getDefaultFlagsFileNameForGame, IPathResolver } from '../common/PathResolver'; import { ProjectInfos } from './messages/ProjectInfos'; +import { inject } from 'inversify'; export enum ClientHostStatus { none, @@ -54,7 +55,7 @@ export class LanguageClientHost implements ILanguageClientHost, Disposable { game: PapyrusGame, config: IGameConfig, creationKitInfo: ICreationKitInfo, - @IPathResolver pathResolver: IPathResolver + @inject(IPathResolver) pathResolver: IPathResolver ) { this._game = game; this._config = config; diff --git a/src/papyrus-lang-vscode/src/server/LanguageClientManager.ts b/src/papyrus-lang-vscode/src/server/LanguageClientManager.ts index ee1fc2b3..08f5845e 100644 --- a/src/papyrus-lang-vscode/src/server/LanguageClientManager.ts +++ b/src/papyrus-lang-vscode/src/server/LanguageClientManager.ts @@ -1,4 +1,4 @@ -import { createDecorator } from 'decoration-ioc'; +import { inject, injectable, interfaces } from 'inversify'; import { ILanguageClient } from './LanguageClient'; import { PapyrusGame, getGames } from '../PapyrusGame'; import { Observable, Subscription, combineLatest } from 'rxjs'; @@ -18,15 +18,16 @@ export interface ILanguageClientManager extends Disposable { getLanguageClient(game: PapyrusGame): Promise; } +@injectable() export class LanguageClientManager implements Disposable, ILanguageClientManager { private readonly _clients: ReadonlyMap>; private readonly _clientSubscriptions: Subscription[]; constructor( - @IExtensionConfigProvider configProvider: IExtensionConfigProvider, - @ICreationKitInfoProvider infoProvider: ICreationKitInfoProvider, - @IPathResolver pathResolver: IPathResolver + @inject(IExtensionConfigProvider) configProvider: IExtensionConfigProvider, + @inject(ICreationKitInfoProvider) infoProvider: ICreationKitInfoProvider, + @inject(IPathResolver) pathResolver: IPathResolver ) { const createClientObservable = (game: PapyrusGame) => { return combineLatest( @@ -106,4 +107,4 @@ export class LanguageClientManager implements Disposable, ILanguageClientManager } } -export const ILanguageClientManager = createDecorator('languageClientManager'); +export const ILanguageClientManager: interfaces.ServiceIdentifier = Symbol('languageClientManager'); From 40c647c478b9e767b1ea6ee67ba2e4ba432d1b4f Mon Sep 17 00:00:00 2001 From: Joel Day Date: Sun, 15 Jan 2023 16:05:23 -0800 Subject: [PATCH 3/5] chore: enable strict mode in tsconfig.json and fix resulting compile-time null/undefined and typing errors. chore: Improvements to eventToValueObservable handling and typing of undefined. chore: Removing ancient legacy debug plugin upgrade check. fix: Ensure that language service status items are updated properly. feat: Updated welcome message with debugger upgrade info. fix: Various potential extension errors/crashes in rare circumstances. (Empty config values, etc.) feat: Update display name for Skyrim to include AE. --- build.cake | 4 - src/papyrus-lang-vscode/package-lock.json | 223 +++++++----------- src/papyrus-lang-vscode/package.json | 28 ++- .../resources/sse/launch.json | 4 +- .../resources/welcome/index.md | 16 +- .../src/CreationKitInfoProvider.ts | 12 +- .../src/ExtensionConfigProvider.ts | 3 +- .../src/PapyrusExtension.ts | 2 - src/papyrus-lang-vscode/src/PapyrusGame.ts | 31 ++- src/papyrus-lang-vscode/src/Utilities.ts | 50 ++-- .../src/common/PathResolver.ts | 47 ++-- .../src/common/Reactive.ts | 8 +- .../src/common/vscode/reactive/Events.ts | 35 ++- .../vscode/view/TreeDataProviderBase.ts | 2 +- .../debugger/DebugSupportInstallService.ts | 18 +- .../PapyrusDebugAdapterDescriptorFactory.ts | 16 +- .../features/AssemblyTextContentProvider.ts | 2 +- .../features/LanguageServiceStatusItems.ts | 44 ++-- .../src/features/PyroTaskProvider.ts | 39 ++- .../features/ScriptStatusCodeLensProvider.ts | 4 +- .../src/features/WelcomeHandler.ts | 16 +- .../commands/GenerateProjectCommand.ts | 8 +- .../commands/LocateOrDisableGameCommand.ts | 2 +- .../commands/SearchCreationKitWikiCommand.ts | 4 +- .../commands/ShowOutputChannelCommand.ts | 6 +- .../projects/ProjectsTreeDataProvider.ts | 2 +- .../src/server/LanguageClient.ts | 22 +- .../src/server/LanguageClientHost.ts | 45 ++-- .../src/server/LanguageClientManager.ts | 10 +- src/papyrus-lang-vscode/tsconfig.json | 1 + 30 files changed, 379 insertions(+), 325 deletions(-) diff --git a/build.cake b/build.cake index 288aca4c..c459b99f 100644 --- a/build.cake +++ b/build.cake @@ -337,10 +337,6 @@ Task("update-bin") .IsDependentOn("copy-debug-plugin"); Task("build-extension") - .IsDependentOn("npm-clean") - .IsDependentOn("npm-copy-bin") - .IsDependentOn("npm-copy-debug-bin") - .IsDependentOn("copy-debug-plugin") .IsDependentOn("npm-build"); Task("build-test") diff --git a/src/papyrus-lang-vscode/package-lock.json b/src/papyrus-lang-vscode/package-lock.json index f98bf9e0..d0119b6c 100644 --- a/src/papyrus-lang-vscode/package-lock.json +++ b/src/papyrus-lang-vscode/package-lock.json @@ -18,6 +18,7 @@ "ps-list": "^6.3.0", "reflect-metadata": "^0.1.13", "rxjs": "^6.6.7", + "semver": "^7.3.8", "vscode-debugprotocol": "^1.37.0", "vscode-languageclient": "^5.2.1", "winreg": "^1.2.4", @@ -29,6 +30,7 @@ "@types/ini": "^1.3.31", "@types/mocha": "^10.0.1", "@types/node": "^18.11.18", + "@types/semver": "^7.3.13", "@types/vscode": "^1.74.0", "@types/winreg": "^1.2.31", "@vscode/test-electron": "2.2.0", @@ -577,20 +579,6 @@ "node": ">=12" } }, - "node_modules/@semantic-release/npm/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/@semantic-release/release-notes-generator": { "version": "10.0.3", "resolved": "https://registry.npmjs.org/@semantic-release/release-notes-generator/-/release-notes-generator-10.0.3.tgz", @@ -724,6 +712,12 @@ "@types/node": "*" } }, + "node_modules/@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "node_modules/@types/vscode": { "version": "1.74.0", "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.74.0.tgz", @@ -796,6 +790,15 @@ "node": ">= 6" } }, + "node_modules/@vscode/vsce/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/@webassemblyjs/ast": { "version": "1.11.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", @@ -2450,21 +2453,6 @@ "node": ">=8" } }, - "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/fork-ts-checker-webpack-plugin/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -3736,22 +3724,6 @@ "node": ">=10" } }, - "node_modules/node-abi/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "optional": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/node-abort-controller": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", @@ -3812,20 +3784,6 @@ "node": ">=10" } }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -6397,6 +6355,15 @@ "semver": "^5.1.0" } }, + "node_modules/parse-semver/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, "node_modules/parse5": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.1.2.tgz", @@ -6793,6 +6760,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/read-pkg/node_modules/type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", @@ -7066,7 +7041,7 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/semantic-release/node_modules/semver": { + "node_modules/semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", @@ -7080,14 +7055,6 @@ "node": ">=10" } }, - "node_modules/semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "bin": { - "semver": "bin/semver" - } - }, "node_modules/semver-diff": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", @@ -7772,21 +7739,6 @@ "node": ">=8" } }, - "node_modules/ts-loader/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "dependencies": { - "lru-cache": "^6.0.0" - }, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/ts-loader/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -8077,6 +8029,14 @@ "vscode": "^1.30" } }, + "node_modules/vscode-languageclient/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/vscode-languageserver-protocol": { "version": "3.14.1", "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.14.1.tgz", @@ -8840,14 +8800,6 @@ "jsonfile": "^6.0.1", "universalify": "^2.0.0" } - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "requires": { - "lru-cache": "^6.0.0" - } } } }, @@ -8975,6 +8927,12 @@ "@types/node": "*" } }, + "@types/semver": { + "version": "7.3.13", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.3.13.tgz", + "integrity": "sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==", + "dev": true + }, "@types/vscode": { "version": "1.74.0", "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.74.0.tgz", @@ -9032,6 +8990,12 @@ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", "dev": true + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true } } }, @@ -10284,15 +10248,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -11223,18 +11178,6 @@ "optional": true, "requires": { "semver": "^7.3.5" - }, - "dependencies": { - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "optional": true, - "requires": { - "lru-cache": "^6.0.0" - } - } } }, "node-abort-controller": { @@ -11281,16 +11224,6 @@ "is-core-module": "^2.5.0", "semver": "^7.3.4", "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "requires": { - "lru-cache": "^6.0.0" - } - } } }, "normalize-path": { @@ -13018,6 +12951,14 @@ "dev": true, "requires": { "semver": "^5.1.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } } }, "parse5": { @@ -13269,6 +13210,11 @@ "lines-and-columns": "^1.1.6" } }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, "type-fest": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", @@ -13503,21 +13449,16 @@ "requires": { "escape-string-regexp": "^1.0.5" } - }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "requires": { - "lru-cache": "^6.0.0" - } } } }, "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "requires": { + "lru-cache": "^6.0.0" + } }, "semver-diff": { "version": "3.1.1", @@ -14017,15 +13958,6 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, - "semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", - "dev": true, - "requires": { - "lru-cache": "^6.0.0" - } - }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -14235,6 +14167,13 @@ "requires": { "semver": "^5.5.0", "vscode-languageserver-protocol": "3.14.1" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } } }, "vscode-languageserver-protocol": { diff --git a/src/papyrus-lang-vscode/package.json b/src/papyrus-lang-vscode/package.json index 559d3c96..40d8b7ba 100644 --- a/src/papyrus-lang-vscode/package.json +++ b/src/papyrus-lang-vscode/package.json @@ -90,7 +90,7 @@ } }, { - "label": "Papyrus: Skyrim Special Edition", + "label": "Papyrus: Skyrim Special Edition/Anniversary Edition", "body": { "name": "Skyrim", "type": "papyrus", @@ -99,9 +99,9 @@ } }, { - "label": "Papyrus: Skyrim Special Edition (with .ppj)", + "label": "Papyrus: Skyrim Special Editio/Anniversary Editionn (with .ppj)", "body": { - "name": "Skyrim Special Edition Project", + "name": "Skyrim Special Edition/Anniversary Edition Project", "type": "papyrus", "request": "attach", "game": "skyrimSpecialEdition", @@ -240,7 +240,7 @@ "papyrus.skyrim.enabled": { "default": true, "type": "boolean", - "description": "Enable support for Skyrim LE (\"Oldrim\"). This is not for Skyrim Special Edition!" + "description": "Enable support for Skyrim LE (\"Oldrim\"). This is not for Skyrim Special Edition/Anniversary Edition!" }, "papyrus.skyrim.creationKitIniFiles": { "default": [ @@ -260,7 +260,7 @@ "papyrus.skyrimSpecialEdition.enabled": { "default": true, "type": "boolean", - "markdownDescription": "Enable support for **Skyrim Special Edition**. Use the [Generate Project Files](command:papyrus.skyrimSpecialEdition.generateProject) command to set up the language server and builds." + "markdownDescription": "Enable support for **Skyrim Special Edition/Anniversary Edition**. Use the [Generate Project Files](command:papyrus.skyrimSpecialEdition.generateProject) command to set up the language server and builds." }, "papyrus.skyrimSpecialEdition.creationKitIniFiles": { "default": [ @@ -271,22 +271,22 @@ "items": { "type": "string" }, - "description": "INI Files for the Skyrim Special Edition version of the Creation Kit." + "description": "INI Files for the Skyrim Special Edition/Anniversary Edition version of the Creation Kit." }, "papyrus.skyrimSpecialEdition.installPath": { "default": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Skyrim Special Edition\\", "type": "string", - "description": "Pathname of the directory where Skyrim Special Edition is installed." + "description": "Pathname of the directory where Skyrim Special Edition/Anniversary Edition is installed." }, "papyrus.skyrimSpecialEdition.ignoreDebuggerVersion": { "default": false, "type": "boolean", - "description": "Allow using old version of the debugger script extender plugin with Skyrim Special Edition." + "description": "Allow using old version of the debugger script extender plugin with Skyrim Special Edition/Anniversary Edition." }, "papyrus.skyrimSpecialEdition.modDirectoryPath": { "default": "", "type": "string", - "description": "If you want to use a mod manager to manage the debugger plugin as a mod, set this to the path of the directory where installed mods for Skyrim SE are kept. Otherwise it will be installed in the game directory." + "description": "If you want to use a mod manager to manage the debugger plugin as a mod, set this to the path of the directory where installed mods for Skyrim SE/AE are kept. Otherwise it will be installed in the game directory." } }, "title": "Papyrus", @@ -369,12 +369,12 @@ { "category": "Papyrus", "command": "papyrus.skyrimSpecialEdition.installDebuggerSupport", - "title": "Install Papyrus debugging support for Skyrim Special Edition" + "title": "Install Papyrus debugging support for Skyrim Special Edition/Anniversary Edition" }, { "category": "Debug", "command": "papyrus.skyrimSpecialEdition.attachDebugger", - "title": "Attach to Skyrim Special Edition" + "title": "Attach to Skyrim Special Edition/Anniversary Edition" }, { "category": "Papyrus", @@ -384,7 +384,7 @@ { "category": "Papyrus", "command": "papyrus.skyrimSpecialEdition.generateProject", - "title": "Generate Skyrim Special Edition Project Files" + "title": "Generate Skyrim Special Edition/Anniversary Edition Project Files" }, { "category": "Papyrus", @@ -515,14 +515,15 @@ "dependencies": { "@semantic-release/exec": "^6.0.3", "@types/semantic-release": "^17.2.4", - "reflect-metadata": "^0.1.13", "deepmerge": "^4.2.2", "fast-deep-equal": "^3.1.3", "ini": "^3.0.1", "inversify": "^6.0.1", "md5-file": "^5.0.0", "ps-list": "^6.3.0", + "reflect-metadata": "^0.1.13", "rxjs": "^6.6.7", + "semver": "^7.3.8", "vscode-debugprotocol": "^1.37.0", "vscode-languageclient": "^5.2.1", "winreg": "^1.2.4", @@ -535,6 +536,7 @@ "@types/ini": "^1.3.31", "@types/mocha": "^10.0.1", "@types/node": "^18.11.18", + "@types/semver": "^7.3.13", "@types/vscode": "^1.74.0", "@types/winreg": "^1.2.31", "@vscode/test-electron": "2.2.0", diff --git a/src/papyrus-lang-vscode/resources/sse/launch.json b/src/papyrus-lang-vscode/resources/sse/launch.json index 0c72597f..5da1320a 100644 --- a/src/papyrus-lang-vscode/resources/sse/launch.json +++ b/src/papyrus-lang-vscode/resources/sse/launch.json @@ -3,10 +3,10 @@ "version": "0.2.0", "configurations": [ { - "name": "Skyrim SE", + "name": "Skyrim SE/AE", "type": "papyrus", "request": "attach", "game": "skyrimSpecialEdition" } ] -} \ No newline at end of file +} diff --git a/src/papyrus-lang-vscode/resources/welcome/index.md b/src/papyrus-lang-vscode/resources/welcome/index.md index cc1dc5fd..0c7fd6df 100644 --- a/src/papyrus-lang-vscode/resources/welcome/index.md +++ b/src/papyrus-lang-vscode/resources/welcome/index.md @@ -77,14 +77,14 @@ Now all you need to do is launch the game and start up the debugger again. Break At this point all features are supported for all games _except_ debugging is not supported for Skyrim LE. -| Feature | Skyrim LE | Skyrim SE | Fallout 4 | -| --------------------------------------------------------------------------------------- | --------- | --------- | --------- | -| [Language Definition](https://github.com/joelday/papyrus-lang/wiki/Language-Definition) | Yes | Yes | Yes | -| [Static Analysis](https://github.com/joelday/papyrus-lang/wiki/Static-Analysis) | Yes | Yes | Yes | -| [IntelliSense](https://github.com/joelday/papyrus-lang/wiki/IntelliSense) | Yes | Yes | Yes | -| [Refactoring](https://github.com/joelday/papyrus-lang/wiki/Refactoring) | Yes | Yes | Yes | -| [Compilation](https://github.com/joelday/papyrus-lang/wiki/Compilation) | Yes | Yes | Yes | -| [Debugging](https://github.com/joelday/papyrus-lang/wiki/Debugging) | No | Yes | Yes | +| Feature | Skyrim LE | Skyrim SE/AE | Fallout 4 | +| --------------------------------------------------------------------------------------- | --------- | ------------ | --------- | +| [Language Definition](https://github.com/joelday/papyrus-lang/wiki/Language-Definition) | Yes | Yes | Yes | +| [Static Analysis](https://github.com/joelday/papyrus-lang/wiki/Static-Analysis) | Yes | Yes | Yes | +| [IntelliSense](https://github.com/joelday/papyrus-lang/wiki/IntelliSense) | Yes | Yes | Yes | +| [Refactoring](https://github.com/joelday/papyrus-lang/wiki/Refactoring) | Yes | Yes | Yes | +| [Compilation](https://github.com/joelday/papyrus-lang/wiki/Compilation) | Yes | Yes | Yes | +| [Debugging](https://github.com/joelday/papyrus-lang/wiki/Debugging) | No | Yes | Yes | ## Further Resources diff --git a/src/papyrus-lang-vscode/src/CreationKitInfoProvider.ts b/src/papyrus-lang-vscode/src/CreationKitInfoProvider.ts index 4b506409..0ad692b3 100644 --- a/src/papyrus-lang-vscode/src/CreationKitInfoProvider.ts +++ b/src/papyrus-lang-vscode/src/CreationKitInfoProvider.ts @@ -15,8 +15,8 @@ const readFile = promisify(fs.readFile); const exists = promisify(fs.exists); export interface ICreationKitInfo { - resolvedInstallPath: string; - resolvedCompilerPath: string; + resolvedInstallPath: string | null; + resolvedCompilerPath: string | null; config: ICreationKitConfig; } @@ -111,7 +111,7 @@ export class CreationKitInfoProvider { ); const parsedInis = iniTexts.pipe( - map((iniTexts) => iniTexts.filter((iniText) => iniText !== null).map((iniText) => ini.parse(iniText))) + map((iniTexts) => iniTexts.filter((iniText) => iniText !== null).map((iniText) => ini.parse(iniText!))) ); const mergedIni = parsedInis.pipe( @@ -133,7 +133,7 @@ export class CreationKitInfoProvider { return combineLatest(resolvedInstallPath, mergedIni).pipe( mergeMap(async ([resolvedInstallPath, mergedIni]) => { - const compilerPath = resolvedInstallPath + const compilerPath = resolvedInstallPath && mergedIni.Papyrus?.sCompilerFolder ? path.resolve(resolvedInstallPath, mergedIni.Papyrus.sCompilerFolder) : null; @@ -141,7 +141,7 @@ export class CreationKitInfoProvider { compilerPath && (await exists(compilerPath)) ? compilerPath : inDevelopmentEnvironment() && game !== PapyrusGame.skyrim - ? path.resolve(resolvedInstallPath, getDevelopmentCompilerFolderForGame(game)) + ? path.resolve(resolvedInstallPath!, getDevelopmentCompilerFolderForGame(game)) : null; return { @@ -149,7 +149,7 @@ export class CreationKitInfoProvider { resolvedCompilerPath: inDevelopmentEnvironment() && game !== PapyrusGame.skyrim && - !(await exists(resolvedCompilerPath)) + (!resolvedCompilerPath || !(await exists(resolvedCompilerPath))) ? null : resolvedCompilerPath, config: mergedIni, diff --git a/src/papyrus-lang-vscode/src/ExtensionConfigProvider.ts b/src/papyrus-lang-vscode/src/ExtensionConfigProvider.ts index 7519bb70..217f8578 100644 --- a/src/papyrus-lang-vscode/src/ExtensionConfigProvider.ts +++ b/src/papyrus-lang-vscode/src/ExtensionConfigProvider.ts @@ -2,6 +2,7 @@ import { injectable, interfaces } from 'inversify'; import { workspace, Disposable } from 'vscode'; import { eventToValueObservable } from './common/vscode/reactive/Events'; import { Observable } from 'rxjs'; +import { filter } from 'rxjs/operators'; export interface IGameConfig { readonly enabled: boolean; @@ -30,7 +31,7 @@ export class ExtensionConfigProvider implements IExtensionConfigProvider { private readonly _config = eventToValueObservable( workspace.onDidChangeConfiguration, () => getPapyrusConfig(), - (e) => (e.affectsConfiguration('papyrus') ? getPapyrusConfig() : undefined) + (e) => (e.affectsConfiguration('papyrus') ? getPapyrusConfig() : undefined), ); get config() { diff --git a/src/papyrus-lang-vscode/src/PapyrusExtension.ts b/src/papyrus-lang-vscode/src/PapyrusExtension.ts index 531faa92..f15bd67b 100644 --- a/src/papyrus-lang-vscode/src/PapyrusExtension.ts +++ b/src/papyrus-lang-vscode/src/PapyrusExtension.ts @@ -95,8 +95,6 @@ class PapyrusExtension implements Disposable { this._showWelcomeCommand = this._serviceContainer.resolve(ShowWelcomeCommand); - // Show the getting started document if there's no previous version (new install) - // At some point we might want a "what's new" so I included both version numbers. void showWelcome(papyrusVersion, previousVersion); context.globalState.update(GlobalState.PapyrusVersion, papyrusVersion); } diff --git a/src/papyrus-lang-vscode/src/PapyrusGame.ts b/src/papyrus-lang-vscode/src/PapyrusGame.ts index cf671063..33703b90 100644 --- a/src/papyrus-lang-vscode/src/PapyrusGame.ts +++ b/src/papyrus-lang-vscode/src/PapyrusGame.ts @@ -18,7 +18,7 @@ export enum PapyrusGame { const displayNames = new Map([ [PapyrusGame.fallout4, 'Fallout 4'], [PapyrusGame.skyrim, 'Skyrim'], - [PapyrusGame.skyrimSpecialEdition, 'Skyrim Special Edition'], + [PapyrusGame.skyrimSpecialEdition, 'Skyrim Special Edition/Anniversary Edition'], ]); export function getDisplayNameForGame(game: PapyrusGame) { @@ -28,7 +28,7 @@ export function getDisplayNameForGame(game: PapyrusGame) { const shortDisplayNames = new Map([ [PapyrusGame.fallout4, 'Fallout 4'], [PapyrusGame.skyrim, 'Skyrim'], - [PapyrusGame.skyrimSpecialEdition, 'Skyrim SE'], + [PapyrusGame.skyrimSpecialEdition, 'Skyrim SE/AE'], ]); const scriptExtenderNames = new Map([[PapyrusGame.fallout4, 'F4SE'], [PapyrusGame.skyrimSpecialEdition, 'SKSE']]); @@ -43,41 +43,50 @@ const scriptExtenderUrls = new Map([ ]); export function getScriptExtenderUrl(game: PapyrusGame) { - return scriptExtenderUrls.get(game); + return scriptExtenderUrls.get(game)!; } -export function getShortDisplayNameForGame(game: PapyrusGame) { - return shortDisplayNames.get(game); +export function getShortDisplayNameForGame(game: PapyrusGame): string { + return shortDisplayNames.get(game)!; } export function getGames(): PapyrusGame[] { - return Object.keys(PapyrusGame).map((k) => PapyrusGame[k]); + return (Object.keys(PapyrusGame) as (keyof typeof PapyrusGame)[]).map((k) => PapyrusGame[k]); } export async function getWorkspaceGameFromProjects(ppjFiles: Uri[]): Promise { - let game: string = undefined; + let game: string | undefined = undefined; if (!ppjFiles) { return undefined; } + for (let ppjFile of ppjFiles) { game = await getWorkspaceGameFromProjectFile(ppjFile.fsPath); if (game) { break; } } - if (!game) { + + if (!game || !PyroGameToPapyrusGame[game as keyof typeof PyroGameToPapyrusGame]) { return undefined; } - return PyroGameToPapyrusGame[game]; + + return PyroGameToPapyrusGame[game as keyof typeof PyroGameToPapyrusGame] as unknown as PapyrusGame; } export async function getWorkspaceGameFromProjectFile(projectFile: string): Promise { - let xml = await readFile(projectFile, { encoding: 'utf-8' }); - let results = xml2js(xml, { compact: true, trim: true }); + const xml = await readFile(projectFile, { encoding: 'utf-8' }); + // TODO: Annoying type cast here: + const results = xml2js(xml, { compact: true, trim: true }) as Record; + return results['PapyrusProject']['_attributes']['Game']; } export async function getWorkspaceGame(): Promise { + if (!workspace.workspaceFolders) { + return undefined; + } + const ppjFiles: Uri[] = await workspace.findFiles(new RelativePattern(workspace.workspaceFolders[0], "**/*.ppj")); return getWorkspaceGameFromProjects(ppjFiles); } \ No newline at end of file diff --git a/src/papyrus-lang-vscode/src/Utilities.ts b/src/papyrus-lang-vscode/src/Utilities.ts index 0d2bdad8..32b689d5 100644 --- a/src/papyrus-lang-vscode/src/Utilities.ts +++ b/src/papyrus-lang-vscode/src/Utilities.ts @@ -8,12 +8,18 @@ import { CancellationTokenSource } from 'vscode'; import { PapyrusGame } from './PapyrusGame'; import { getExecutableNameForGame } from './common/PathResolver'; +import { + isNativeError, +} from "util/types"; + +import { + getSystemErrorMap +} from "util"; const readFile = promisify(fs.readFile); const writeFile = promisify(fs.writeFile); const exists = promisify(fs.exists); - export function* flatten(arrs: T[][]): IterableIterator { for (const arr of arrs) { for (const el of arr) { @@ -45,13 +51,13 @@ export function inDevelopmentEnvironment() { return process.execArgv.some((arg) => arg.startsWith('--inspect-brk')); } -export function toCommandLineArgs(obj: Object): string[] { - return [].concat( +export function toCommandLineArgs(obj: any): string[] { + return ([] as string[]).concat( ...Object.keys(obj).map((key) => { const value = obj[key]; if (typeof value === 'undefined' || value === null) { - return []; + return [] as string[]; } return [ @@ -69,6 +75,16 @@ export async function mkdirIfNeeded(pathname: string) { mkDirByPathSync(pathname); } +export function isNodeError(obj: unknown): obj is NodeJS.ErrnoException { + if (isNativeError(obj)) { + if ((obj as NodeJS.ErrnoException).errno !== undefined && getSystemErrorMap().has((obj as NodeJS.ErrnoException)!.errno!)) { + return true; + } + } + + return false; +} + // Apparently recursive mkdir doesn't want to work on windows. // Copied this from https://stackoverflow.com/questions/31645738/how-to-create-full-path-with-nodes-fs-mkdirsync export function mkDirByPathSync(targetDir: string, { isRelativeToScript = false } = {}) { @@ -81,18 +97,20 @@ export function mkDirByPathSync(targetDir: string, { isRelativeToScript = false try { fs.mkdirSync(curDir); } catch (err) { - if (err.code === 'EEXIST') { // curDir already exists! - return curDir; - } - - // To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows. - if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure. - throw new Error(`EACCES: permission denied, mkdir '${parentDir}'`); - } - - const caughtErr = ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1; - if (!caughtErr || caughtErr && curDir === path.resolve(targetDir)) { - throw err; // Throw if it's just the last created dir. + if (isNodeError(err)) { + if (err.code === 'EEXIST') { // curDir already exists! + return curDir; + } + + // To avoid `EISDIR` error on Mac and `EACCES`-->`ENOENT` and `EPERM` on Windows. + if (err.code === 'ENOENT') { // Throw the original parentDir error on curDir `ENOENT` failure. + throw new Error(`EACCES: permission denied, mkdir '${parentDir}'`); + } + + const caughtErr = !err.code || ['EACCES', 'EPERM', 'EISDIR'].indexOf(err.code) > -1; + if (!caughtErr || caughtErr && curDir === path.resolve(targetDir)) { + throw err; // Throw if it's just the last created dir. + } } } diff --git a/src/papyrus-lang-vscode/src/common/PathResolver.ts b/src/papyrus-lang-vscode/src/common/PathResolver.ts index 355f33fd..e855e8e8 100644 --- a/src/papyrus-lang-vscode/src/common/PathResolver.ts +++ b/src/papyrus-lang-vscode/src/common/PathResolver.ts @@ -26,9 +26,9 @@ export interface IPathResolver { getResourceDir(): Promise; getWelcomeFile(): Promise; // External paths - getInstallPath(game: PapyrusGame): Promise; - getModDirectoryPath(game: PapyrusGame): Promise; - getDebugPluginInstallPath(game: PapyrusGame, legacy?: boolean): Promise; + getInstallPath(game: PapyrusGame): Promise; + getModDirectoryPath(game: PapyrusGame): Promise; + getDebugPluginInstallPath(game: PapyrusGame, legacy?: boolean): Promise; } @injectable() @@ -44,10 +44,6 @@ export class PathResolver implements IPathResolver { this._context = context; } - private async _getExtensionConfig(): Promise { - return this._configProvider.config.pipe(take(1)).toPromise(); - } - private async _getGameConfig(game: PapyrusGame): Promise { return (await this._configProvider.config.pipe(take(1)).toPromise())[game]; } @@ -113,21 +109,29 @@ export class PathResolver implements IPathResolver { /*** External paths (ones that are not "ours") */ /************************************************************************* */ - public async getInstallPath(game: PapyrusGame): Promise { - return resolveInstallPath(game, (await this._getGameConfig(game)).installPath, this._context); + public async getInstallPath(game: PapyrusGame): Promise { + const config = await this._getGameConfig(game); + + return resolveInstallPath(game, config.installPath, this._context); } - public async getDebugPluginInstallPath(game: PapyrusGame, legacy?: boolean): Promise { - const config = await this._getGameConfig(game); - if (config.modDirectoryPath) { + public async getDebugPluginInstallPath(game: PapyrusGame, legacy?: boolean): Promise { + const modDirectoryPath = await this.getModDirectoryPath(game); + + if (modDirectoryPath) { return path.join( - await this.getModDirectoryPath(game), "Papyrus Debug Extension", + modDirectoryPath, "Papyrus Debug Extension", await this._getModMgrExtenderPluginPath(game), getPluginDllName(game, legacy) ); } else { + const installPath = await this.getInstallPath(game); + if (!installPath) { + return null; + } + return path.join( - await this.getInstallPath(game), + installPath, await this._getExtenderPluginPath(game), getPluginDllName(game, legacy) ); @@ -135,7 +139,12 @@ export class PathResolver implements IPathResolver { } public async getModDirectoryPath(game: PapyrusGame) { - return (await this._getGameConfig(game)).modDirectoryPath; + const config = await this._getGameConfig(game); + if (!config) { + return null; + } + + return config.modDirectoryPath; } dispose() { } @@ -202,7 +211,7 @@ export async function resolveInstallPath( game: PapyrusGame, installPath: string, context: ExtensionContext -): Promise { +): Promise { if (await exists(installPath)) { return installPath; } @@ -239,9 +248,9 @@ const executableNames = new Map([ ]); export function getExecutableNameForGame(game: PapyrusGame) { - return executableNames.get(game); + return executableNames.get(game)!; } -export function pathToOsPath(pathname) { - return path.format(path.parse(pathname)); +export function pathToOsPath(pathName: string) { + return path.format(path.parse(pathName)); } \ No newline at end of file diff --git a/src/papyrus-lang-vscode/src/common/Reactive.ts b/src/papyrus-lang-vscode/src/common/Reactive.ts index 86533990..07088730 100644 --- a/src/papyrus-lang-vscode/src/common/Reactive.ts +++ b/src/papyrus-lang-vscode/src/common/Reactive.ts @@ -3,13 +3,13 @@ import { Disposable } from 'vscode'; import { switchMap, distinctUntilChanged, shareReplay } from 'rxjs/operators'; export class UnsubscribableDisposableProxy { - private _disposable: T; + private _disposable: T | undefined; get disposable() { return this._disposable; } - set disposable(disposable: T) { + set disposable(disposable: T | undefined) { this._disposable = disposable; } @@ -29,9 +29,9 @@ export function asyncDisposable( switchMap((value: T) => using( () => new UnsubscribableDisposableProxy(), - (proxy: UnsubscribableDisposableProxy) => { + (proxy) => { const instance = factory(value); - proxy.disposable = instance; + (proxy as UnsubscribableDisposableProxy).disposable = instance; return concat( from([instance]), diff --git a/src/papyrus-lang-vscode/src/common/vscode/reactive/Events.ts b/src/papyrus-lang-vscode/src/common/vscode/reactive/Events.ts index d2fdb9f8..d54d0871 100644 --- a/src/papyrus-lang-vscode/src/common/vscode/reactive/Events.ts +++ b/src/papyrus-lang-vscode/src/common/vscode/reactive/Events.ts @@ -2,20 +2,47 @@ import { Event } from 'vscode'; import { Observable } from 'rxjs'; import { shareReplay } from 'rxjs/operators'; +export function eventToValueObservable( + event: Event, + getCurrent: () => TValue, + map: ((event: TEvent) => TValue | undefined) | undefined, + emitUndefined: true, +): Observable; + +export function eventToValueObservable( + event: Event, + getCurrent: () => TValue, + map: ((event: TEvent) => TValue) | undefined, + emitUndefined: false, +): Observable>; + +export function eventToValueObservable( + event: Event, + getCurrent: () => TValue, + map?: (event: TEvent) => TValue | undefined, + emitUndefined?: boolean, +): Observable>; + export function eventToValueObservable( event: Event, getCurrent: () => TValue, - map: (event: TEvent) => TValue = (e) => (e as any) as TValue + map: (event: TEvent) => TValue = (e) => (e as any) as TValue, + emitUndefined: boolean = false, ) { return new Observable((s) => { - s.next(getCurrent()); + const initialValue = getCurrent(); + if (!(typeof initialValue === 'undefined' && !emitUndefined)) { + s.next(initialValue); + } const disposable = event((value) => { const newValue = map(value); - if (typeof newValue !== 'undefined') { - s.next(newValue); + if (typeof newValue === 'undefined' && !emitUndefined) { + return; } + + s.next(newValue); }); return { diff --git a/src/papyrus-lang-vscode/src/common/vscode/view/TreeDataProviderBase.ts b/src/papyrus-lang-vscode/src/common/vscode/view/TreeDataProviderBase.ts index 621386f1..4a20c9ff 100644 --- a/src/papyrus-lang-vscode/src/common/vscode/view/TreeDataProviderBase.ts +++ b/src/papyrus-lang-vscode/src/common/vscode/view/TreeDataProviderBase.ts @@ -8,7 +8,7 @@ export abstract class TreeDataProviderBase implements vs.TreeDataProvider, vs.Disposable { private readonly _disposables: vs.Disposable[] = []; - private readonly _onDidChangeTreeDataEventEmitter = new vs.EventEmitter(); + private readonly _onDidChangeTreeDataEventEmitter = new vs.EventEmitter(); get onDidChangeTreeData() { return this._onDidChangeTreeDataEventEmitter.event; diff --git a/src/papyrus-lang-vscode/src/debugger/DebugSupportInstallService.ts b/src/papyrus-lang-vscode/src/debugger/DebugSupportInstallService.ts index 46110208..625a3f76 100644 --- a/src/papyrus-lang-vscode/src/debugger/DebugSupportInstallService.ts +++ b/src/papyrus-lang-vscode/src/debugger/DebugSupportInstallService.ts @@ -69,15 +69,8 @@ export class DebugSupportInstallService implements IDebugSupportInstallService { return DebugSupportInstallState.installed; } - // For clarity and consistency, the plugin is being renamed to end with Fallout4.dll - // This handles the case where the old version is installed. - const legacyInstalledPluginPath = await this._pathResolver.getDebugPluginInstallPath(game, true); - if (game === PapyrusGame.fallout4 && (await exists(legacyInstalledPluginPath))) { - return DebugSupportInstallState.incorrectVersion; - } - const installedPluginPath = await this._pathResolver.getDebugPluginInstallPath(game, false); - if (!(await exists(installedPluginPath))) { + if (!installedPluginPath || !(await exists(installedPluginPath))) { return DebugSupportInstallState.notInstalled; } @@ -96,13 +89,11 @@ export class DebugSupportInstallService implements IDebugSupportInstallService { } async installPlugin(game: PapyrusGame, cancellationToken = new CancellationTokenSource().token): Promise { - // Remove the legacy dll if it exists. - const legacyInstalledPluginPath = await this._pathResolver.getDebugPluginInstallPath(game, true); - if (game === PapyrusGame.fallout4 && (await exists(legacyInstalledPluginPath))) { - await removeFile(legacyInstalledPluginPath); + const pluginInstallPath = await this._pathResolver.getDebugPluginInstallPath(game, false); + if (!pluginInstallPath) { + return false; } - const pluginInstallPath = await this._pathResolver.getDebugPluginInstallPath(game, false); const bundledPluginPath = await this._pathResolver.getDebugPluginBundledPath(game); if (cancellationToken.isCancellationRequested) { @@ -111,6 +102,7 @@ export class DebugSupportInstallService implements IDebugSupportInstallService { await mkdirIfNeeded(path.dirname(pluginInstallPath)); await copyFile(bundledPluginPath, pluginInstallPath); + return true; } } diff --git a/src/papyrus-lang-vscode/src/debugger/PapyrusDebugAdapterDescriptorFactory.ts b/src/papyrus-lang-vscode/src/debugger/PapyrusDebugAdapterDescriptorFactory.ts index 007cb939..736a2fc2 100644 --- a/src/papyrus-lang-vscode/src/debugger/PapyrusDebugAdapterDescriptorFactory.ts +++ b/src/papyrus-lang-vscode/src/debugger/PapyrusDebugAdapterDescriptorFactory.ts @@ -165,18 +165,24 @@ export class PapyrusDebugAdapterDescriptorFactory implements DebugAdapterDescrip const config = (await this._configProvider.config.pipe(take(1)).toPromise())[game]; const creationKitInfo = await this._creationKitInfoProvider.infos - .get(game) + .get(game)! .pipe(take(1)) .toPromise(); + if (!creationKitInfo.resolvedInstallPath) { + throw new Error( + `Creation Kit install path for ${getDisplayNameForGame(game)} is not configured.` + ); + } + const toolArguments: IDebugToolArguments = { port: session.configuration.port || getDefaultPortForGame(game), projectPath: session.configuration.projectPath, creationKitInstallPath: creationKitInfo.resolvedInstallPath, relativeIniPaths: config.creationKitIniFiles, - defaultScriptSourceFolder: creationKitInfo.config.Papyrus.sScriptSourceFolder, - defaultAdditionalImports: creationKitInfo.config.Papyrus.sAdditionalImports, - clientProcessId: Number.parseInt(process.env.VSCODE_PID), + defaultScriptSourceFolder: creationKitInfo.config.Papyrus?.sScriptSourceFolder, + defaultAdditionalImports: creationKitInfo.config.Papyrus?.sAdditionalImports, + clientProcessId: Number.parseInt(process.env.VSCODE_PID!), }; const toolPath = await this._pathResolver.getDebugToolPath(game); @@ -184,7 +190,7 @@ export class PapyrusDebugAdapterDescriptorFactory implements DebugAdapterDescrip const outputChannel = (await this._languageClientManager.getLanguageClientHost(session.configuration.game)) .outputChannel; - outputChannel.appendLine( + outputChannel?.appendLine( `Debug session: Launching debug adapter client: ${toolPath} ${commandLineArgs.join(' ')}` ); diff --git a/src/papyrus-lang-vscode/src/features/AssemblyTextContentProvider.ts b/src/papyrus-lang-vscode/src/features/AssemblyTextContentProvider.ts index 1f55496f..879cfb4c 100644 --- a/src/papyrus-lang-vscode/src/features/AssemblyTextContentProvider.ts +++ b/src/papyrus-lang-vscode/src/features/AssemblyTextContentProvider.ts @@ -18,7 +18,7 @@ export class AssemblyTextContentProvider implements TextDocumentContentProvider const activeClients = await this._languageClientManager.getActiveLanguageClients(cancellationToken); const assemblyResults = await Promise.all( - activeClients.map((c) => c.client.requestAssembly(scriptUri.toString())) + activeClients.map((c) => c.client?.requestAssembly(scriptUri.toString())) ); const firstValidResult = assemblyResults.find((a) => !!a && !!a.assembly); diff --git a/src/papyrus-lang-vscode/src/features/LanguageServiceStatusItems.ts b/src/papyrus-lang-vscode/src/features/LanguageServiceStatusItems.ts index 6f84c889..4a83cd2d 100644 --- a/src/papyrus-lang-vscode/src/features/LanguageServiceStatusItems.ts +++ b/src/papyrus-lang-vscode/src/features/LanguageServiceStatusItems.ts @@ -1,7 +1,7 @@ import { ILanguageClientManager } from '../server/LanguageClientManager'; -import { StatusBarItem, Disposable, window, StatusBarAlignment } from 'vscode'; +import { StatusBarItem, Disposable, window, StatusBarAlignment, TextEditor } from 'vscode'; import { PapyrusGame, getGames, getShortDisplayNameForGame, getDisplayNameForGame } from '../PapyrusGame'; -import { Observable, Unsubscribable, combineLatest } from 'rxjs'; +import { Observable, Unsubscribable, combineLatest as combineLatest, ObservableInput, ObservedValueOf } from 'rxjs'; import { ILanguageClientHost, ClientHostStatus } from '../server/LanguageClientHost'; import { mergeMap, shareReplay } from 'rxjs/operators'; import { eventToValueObservable } from '../common/vscode/reactive/Events'; @@ -9,6 +9,10 @@ import { asyncDisposable } from '../common/Reactive'; import { ShowOutputChannelCommand } from './commands/ShowOutputChannelCommand'; import { LocateOrDisableGameCommand } from './commands/LocateOrDisableGameCommand'; import { inject, injectable } from 'inversify'; +import { DocumentScriptInfo } from '../server/messages/DocumentScriptInfo'; + +declare function combineLatest_, O2 extends ObservableInput, O3 extends ObservableInput, O4 extends ObservableInput, O5 extends ObservableInput, O6 extends ObservableInput, O7 extends ObservableInput>(...sources: [O1, O2, O3, O4, O5, O6, O7]): Observable<[ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf, ObservedValueOf]>; +declare type ExtendedCombineLatestSignature = typeof combineLatest_; class StatusBarItemController implements Disposable { private readonly _statusBarItem: StatusBarItem; @@ -20,7 +24,7 @@ class StatusBarItemController implements Disposable { this._locateOrDisableCommand = new LocateOrDisableGameCommand(game); - const activeEditor = eventToValueObservable(window.onDidChangeActiveTextEditor, () => window.activeTextEditor); + const activeEditor = eventToValueObservable(window.onDidChangeActiveTextEditor, () => window.activeTextEditor, undefined, true); const visibleEditors = eventToValueObservable(window.onDidChangeVisibleTextEditors, () => window.visibleTextEditors); @@ -41,7 +45,7 @@ class StatusBarItemController implements Disposable { activeEditor && activeEditor.document.languageId === 'papyrus' ) { - return await host.client.requestScriptInfo(activeEditor.document.uri.toString()); + return await host.client?.requestScriptInfo(activeEditor.document.uri.toString()) || null; } return null; @@ -53,7 +57,16 @@ class StatusBarItemController implements Disposable { asyncDisposable((host) => new ShowOutputChannelCommand(game, () => host.outputChannel)) ); - this._hostSubscription = combineLatest( + // TODO: Need to update RxJS, combineLatest here doesn't have enough overloads to support the typings here. + this._hostSubscription = (combineLatest as ExtendedCombineLatestSignature)< + Observable, + Observable, + Observable, + Observable, + Observable, + Observable, + Observable + >( languageClientHost, hostStatus, hostError, @@ -72,7 +85,7 @@ class StatusBarItemController implements Disposable { return; } - const displayName = getShortDisplayNameForGame(host.game); + const shortName = getShortDisplayNameForGame(host.game); const fullName = getDisplayNameForGame(host.game); this._statusBarItem.command = showOutputChannelCommand.name; @@ -82,28 +95,27 @@ class StatusBarItemController implements Disposable { this._statusBarItem.hide(); return; case ClientHostStatus.starting: - this._statusBarItem.text = `${displayName} $(sync)`; + this._statusBarItem.text = `${shortName} $(sync)`; this._statusBarItem.tooltip = `${fullName} language service starting...`; break; case ClientHostStatus.running: - this._statusBarItem.text = `${displayName} ${activeDocumentScriptInfo && activeDocumentScriptInfo.identifiers.length > 0 - ? '$(verified)' - : '$(check)' - }`; - this._statusBarItem.tooltip = `${fullName} language service running.`; + const hasActiveDocument = activeDocumentScriptInfo && activeDocumentScriptInfo.identifiers.length > 0; + + this._statusBarItem.text = `${shortName} $(check)` + (hasActiveDocument ? ` $(file-code)` : ``); + this._statusBarItem.tooltip = `${fullName} language service is running${hasActiveDocument ? ` and has active scripts.` : `.`}`; break; case ClientHostStatus.missing: - this._statusBarItem.text = `${displayName} $(alert)`; + this._statusBarItem.text = `${shortName} $(alert)`; this._statusBarItem.tooltip = `Unable to locate ${fullName}. Click for more options...`; this._statusBarItem.command = this._locateOrDisableCommand.name; break; case ClientHostStatus.compilerMissing: - this._statusBarItem.text = `${displayName} $(alert)`; + this._statusBarItem.text = `${shortName} $(alert)`; this._statusBarItem.tooltip = `Unable to locate the Papyrus compiler. Make sure that the game install path is correct, Creation Kit has been installed and that, if specified in an ini file, sCompilerFolder is also correct.`; this._statusBarItem.command = this._locateOrDisableCommand.name; break; case ClientHostStatus.error: - this._statusBarItem.text = `${displayName} $(stop)`; + this._statusBarItem.text = `${shortName} $(stop)`; this._statusBarItem.tooltip = `Unexpected error while starting ${fullName} language service.`; break; } @@ -135,7 +147,7 @@ export class LanguageServiceStatusItems implements Disposable { (game, index) => [ game, - new StatusBarItemController(game, this._languageClientManager.clients.get(game), index), + new StatusBarItemController(game, this._languageClientManager.clients.get(game)!, index), ] as [PapyrusGame, StatusBarItemController] ), ]); diff --git a/src/papyrus-lang-vscode/src/features/PyroTaskProvider.ts b/src/papyrus-lang-vscode/src/features/PyroTaskProvider.ts index 78a6d193..1321583e 100644 --- a/src/papyrus-lang-vscode/src/features/PyroTaskProvider.ts +++ b/src/papyrus-lang-vscode/src/features/PyroTaskProvider.ts @@ -14,10 +14,10 @@ export class PyroTaskProvider implements TaskProvider, Disposable { private readonly _taskProviderHandle: Disposable; private readonly _pathResolver: IPathResolver; private _taskCachePromise: Promise | undefined = undefined; - private readonly _projPattern: GlobPattern; - private readonly _fileWatcher: FileSystemWatcher; + private readonly _projPattern!: GlobPattern; + private readonly _fileWatcher!: FileSystemWatcher; private readonly _source: string = "pyro"; - private _workspaceGame: PapyrusGame; + private _workspaceGame!: PapyrusGame; constructor( @inject(IPathResolver) pathResolver: PathResolver @@ -26,6 +26,9 @@ export class PyroTaskProvider implements TaskProvider, Disposable { this._taskProviderHandle = tasks.registerTaskProvider('pyro', this); + // BUG: So... since this is instantiated only once and at extension start up time, if you open a Papyrus script + // before opening a workspace, you're fucked until you restart VSCode. + if (!workspace.workspaceFolders) { return; } @@ -39,8 +42,8 @@ export class PyroTaskProvider implements TaskProvider, Disposable { } public provideTasks(token?: CancellationToken): Promise { - if (token.isCancellationRequested) { - return null; + if (token?.isCancellationRequested) { + return Promise.resolve([]); } if (!this._taskCachePromise) { this._taskCachePromise = this.getPyroTasks(token); @@ -49,8 +52,8 @@ export class PyroTaskProvider implements TaskProvider, Disposable { } async getPyroTasks(token?: CancellationToken): Promise { - if (token.isCancellationRequested) { - return null; + if (token?.isCancellationRequested) { + return []; } // search for all .PPJ files in workspace @@ -76,10 +79,15 @@ export class PyroTaskProvider implements TaskProvider, Disposable { // provide a build task for each one found for (let uri of ppjFiles) { + const installPath = await this._pathResolver.getInstallPath(game); + if (!installPath) { + continue; + } + let taskDef: IPyroTaskDefinition = { type: this._source, projectFile: workspace.asRelativePath(uri), - gamePath: await this._pathResolver.getInstallPath(game) + gamePath: installPath }; tasks.push(await this.createTaskForDefinition(taskDef)); } @@ -88,8 +96,8 @@ export class PyroTaskProvider implements TaskProvider, Disposable { } async resolveTask(task: TaskOf, token?: CancellationToken): Promise { - if (token.isCancellationRequested) { - return null; + if (token?.isCancellationRequested) { + return; } let definition = task.definition; if (definition === undefined) { @@ -151,7 +159,9 @@ export class PyroTaskProvider implements TaskProvider, Disposable { if (taskDef.game) { argv.push('--game-type'); argv.push(taskDef.game); - game = PyroGameToPapyrusGame[game]; + + // TODO: Who knows how many bugs this change will fix... + game = PyroGameToPapyrusGame[taskDef.game] as unknown as PapyrusGame; } else { game = this._workspaceGame; } @@ -159,8 +169,13 @@ export class PyroTaskProvider implements TaskProvider, Disposable { argv.push('--game-path'); argv.push(taskDef.gamePath); } else { + const installPath = await this._pathResolver.getInstallPath(game); + if (!installPath) { + throw new Error("Could not find game install path."); + } + argv.push('--game-path'); - argv.push(await this._pathResolver.getInstallPath(game)); + argv.push(installPath); } if (taskDef.registryPath) { argv.push('--registry-path'); diff --git a/src/papyrus-lang-vscode/src/features/ScriptStatusCodeLensProvider.ts b/src/papyrus-lang-vscode/src/features/ScriptStatusCodeLensProvider.ts index d7165c3d..2151d5a0 100644 --- a/src/papyrus-lang-vscode/src/features/ScriptStatusCodeLensProvider.ts +++ b/src/papyrus-lang-vscode/src/features/ScriptStatusCodeLensProvider.ts @@ -1,6 +1,6 @@ import * as path from 'path'; import { ILanguageClientManager } from '../server/LanguageClientManager'; -import { ClientHostStatus } from '../server/LanguageClientHost'; +import { ClientHostStatus, IScriptDocumentStatus } from '../server/LanguageClientHost'; import { CodeLens, Range, @@ -69,7 +69,7 @@ export class ScriptStatusCodeLensProvider implements CodeLensProvider, Disposabl const documentInfos = (await Promise.all( activeClients.map((client) => client.getDocumentScriptStatus(document)) - )).filter((documentInfo) => documentInfo !== null); + )).filter((documentInfo) => documentInfo !== null) as IScriptDocumentStatus[]; if (cancellationToken.isCancellationRequested) { return []; diff --git a/src/papyrus-lang-vscode/src/features/WelcomeHandler.ts b/src/papyrus-lang-vscode/src/features/WelcomeHandler.ts index adc974d5..89a1f5c8 100644 --- a/src/papyrus-lang-vscode/src/features/WelcomeHandler.ts +++ b/src/papyrus-lang-vscode/src/features/WelcomeHandler.ts @@ -1,8 +1,20 @@ +import { SemVer } from "semver"; import { commands } from "vscode"; -export async function showWelcome(papyrusVersion: string, previousVersion: string): Promise { - if (previousVersion === undefined) { +const updateMessageSemver = new SemVer("3.0.1"); + +export async function showWelcome(papyrusVersion: string, previousVersion: string | undefined): Promise { + if (!previousVersion) { console.log("No previous version found. This is a first time install. Showing welcome message."); await commands.executeCommand('papyrus.showWelcome'); + return; + } + + const previous = new SemVer(previousVersion); + const current = new SemVer(papyrusVersion); + + if (previous.compare(updateMessageSemver) <= 0 && current.compare(updateMessageSemver) >= 0) { + console.log("Previous version was less than or equal to 3.0.1. Showing welcome message."); + await commands.executeCommand('papyrus.showWelcome'); } } \ No newline at end of file diff --git a/src/papyrus-lang-vscode/src/features/commands/GenerateProjectCommand.ts b/src/papyrus-lang-vscode/src/features/commands/GenerateProjectCommand.ts index 95c1e469..8d02a392 100644 --- a/src/papyrus-lang-vscode/src/features/commands/GenerateProjectCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/GenerateProjectCommand.ts @@ -30,9 +30,14 @@ export class GenerateProjectCommand extends GameCommandBase<[string]> { this._pathResolver = pathResolver; } - protected async onExecute(game: PapyrusGame, ...args: [string]) { + protected async onExecute(game: PapyrusGame, ...args: [string | undefined]) { const installPath = await this._pathResolver.getInstallPath(game); + if (!installPath) { + window.showErrorMessage("Could not find the game installation path."); + return; + } + const defaultProjectSubdir = { 'fallout4': "Data", 'skyrimSpecialEdition': "Data", @@ -50,6 +55,7 @@ export class GenerateProjectCommand extends GameCommandBase<[string]> { if (game === PapyrusGame.fallout4) { args[0] = undefined; } + let projectFolderUri: Uri = args[0] ? Uri.parse(args[0]) : Uri.file(path.join(installPath, defaultProjectSubdir[game])); console.log("Default projectFolderUri = " + projectFolderUri.fsPath); diff --git a/src/papyrus-lang-vscode/src/features/commands/LocateOrDisableGameCommand.ts b/src/papyrus-lang-vscode/src/features/commands/LocateOrDisableGameCommand.ts index 3d8f9bb2..c7bbc007 100644 --- a/src/papyrus-lang-vscode/src/features/commands/LocateOrDisableGameCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/LocateOrDisableGameCommand.ts @@ -32,7 +32,7 @@ export class LocateOrDisableGameCommand extends CommandBase { canSelectMany: false, }); - if (location.length > 0) { + if (location && location.length > 0) { await workspace .getConfiguration('papyrus') .update(`${this._game}.installPath`, location[0].fsPath, true); diff --git a/src/papyrus-lang-vscode/src/features/commands/SearchCreationKitWikiCommand.ts b/src/papyrus-lang-vscode/src/features/commands/SearchCreationKitWikiCommand.ts index 50a3fb87..66f56adf 100644 --- a/src/papyrus-lang-vscode/src/features/commands/SearchCreationKitWikiCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/SearchCreationKitWikiCommand.ts @@ -22,7 +22,7 @@ export class SearchCreationKitWikiCommand extends EditorCommandBase { } const range = selection.isEmpty ? document.getWordRangeAtPosition(selection.start) : selection; - if (range.isEmpty) { + if (!range || range.isEmpty) { return; } @@ -34,7 +34,7 @@ export class SearchCreationKitWikiCommand extends EditorCommandBase { const activeClients = await this._languageClientManager.getActiveLanguageClients(); const documentInfos = await Promise.all(activeClients.map((c) => c.getDocumentScriptStatus(editor.document))); - const firstActiveDocument = documentInfos.find((docInfo) => !docInfo.documentIsUnresolved); + const firstActiveDocument = documentInfos.find((docInfo) => !docInfo?.documentIsUnresolved); if (!firstActiveDocument) { window.showErrorMessage( 'Failed to open Creation Kit search page because this script is currently unresolved.' diff --git a/src/papyrus-lang-vscode/src/features/commands/ShowOutputChannelCommand.ts b/src/papyrus-lang-vscode/src/features/commands/ShowOutputChannelCommand.ts index 8cc60484..b96a6976 100644 --- a/src/papyrus-lang-vscode/src/features/commands/ShowOutputChannelCommand.ts +++ b/src/papyrus-lang-vscode/src/features/commands/ShowOutputChannelCommand.ts @@ -2,14 +2,14 @@ import { CommandBase } from '../../common/vscode/commands/CommandBase'; import { OutputChannel } from 'vscode'; export class ShowOutputChannelCommand extends CommandBase { - private readonly _outputChannelProvider: () => OutputChannel; + private readonly _outputChannelProvider: () => OutputChannel | null; - constructor(uniqueId: string, outputChannelProvider: () => OutputChannel) { + constructor(uniqueId: string, outputChannelProvider: () => OutputChannel | null) { super(`papyrus.showOutputChannel.${uniqueId}`); this._outputChannelProvider = outputChannelProvider; } onExecute() { - this._outputChannelProvider()!.show(true); + this._outputChannelProvider()?.show(true); } } \ No newline at end of file diff --git a/src/papyrus-lang-vscode/src/features/projects/ProjectsTreeDataProvider.ts b/src/papyrus-lang-vscode/src/features/projects/ProjectsTreeDataProvider.ts index baa40261..04ad63da 100644 --- a/src/papyrus-lang-vscode/src/features/projects/ProjectsTreeDataProvider.ts +++ b/src/papyrus-lang-vscode/src/features/projects/ProjectsTreeDataProvider.ts @@ -26,7 +26,7 @@ export class GameTreeDataNode implements TreeDataNode { this._projects = projects; } - async getParent(): Promise { + async getParent(): Promise { return null; } diff --git a/src/papyrus-lang-vscode/src/server/LanguageClient.ts b/src/papyrus-lang-vscode/src/server/LanguageClient.ts index 25e3bb49..35220b73 100644 --- a/src/papyrus-lang-vscode/src/server/LanguageClient.ts +++ b/src/papyrus-lang-vscode/src/server/LanguageClient.ts @@ -29,10 +29,10 @@ export interface IToolArguments { export interface ILanguageClient { readonly projectsUpdated: Observable; - requestProjectInfos(): Thenable; - requestScriptInfo(uri: string): Thenable; - requestSyntaxTree(uri: string): Thenable; - requestAssembly(uri: string): Thenable; + requestProjectInfos(): Thenable; + requestScriptInfo(uri: string): Thenable; + requestSyntaxTree(uri: string): Thenable; + requestAssembly(uri: string): Thenable; } const projectsUpdatedNotificationType = { @@ -43,9 +43,9 @@ export class LanguageClient implements ILanguageClient { private readonly _client: BaseClient; private readonly _fsWatcher: FileSystemWatcher; private readonly _outputChannel: OutputChannel; - private _isDisposed: boolean; + private _isDisposed: boolean = false; - private readonly _projectsUpdated = new BehaviorSubject(null); + private readonly _projectsUpdated = new BehaviorSubject(undefined); get projectsUpdated(): Observable { return this._projectsUpdated; @@ -83,7 +83,7 @@ export class LanguageClient implements ILanguageClient { await this._client.onReady(); this._client.onNotification(projectsUpdatedNotificationType.type, () => { - this._projectsUpdated.next(null); + this._projectsUpdated.next(undefined); }); this._outputChannel.appendLine('Language service started.'); @@ -104,7 +104,7 @@ export class LanguageClient implements ILanguageClient { } } - requestProjectInfos(): Thenable { + requestProjectInfos(): Thenable { try { return this._client.sendRequest(projectInfosRequestType.type, {}); } catch (_) { @@ -114,19 +114,19 @@ export class LanguageClient implements ILanguageClient { } } - requestAssembly(uri: string): Thenable { + requestAssembly(uri: string): Thenable { return this._client.sendRequest(documentAssemblyRequestType.type, { textDocument: TextDocumentIdentifier.create(uri), }); } - requestScriptInfo(uri: string): Thenable { + requestScriptInfo(uri: string): Thenable { return this._client.sendRequest(documentScriptInfoRequestType.type, { textDocument: TextDocumentIdentifier.create(uri), }); } - requestSyntaxTree(uri: string): Thenable { + requestSyntaxTree(uri: string): Thenable { return this._client.sendRequest(documentSyntaxTreeRequestType.type, { textDocument: TextDocumentIdentifier.create(uri), }); diff --git a/src/papyrus-lang-vscode/src/server/LanguageClientHost.ts b/src/papyrus-lang-vscode/src/server/LanguageClientHost.ts index 49cbedbc..9cdecff0 100644 --- a/src/papyrus-lang-vscode/src/server/LanguageClientHost.ts +++ b/src/papyrus-lang-vscode/src/server/LanguageClientHost.ts @@ -3,7 +3,7 @@ import { Disposable, ExtensionContext, OutputChannel, window, TextDocument } fro import { LanguageClient, ILanguageClient, IToolArguments } from './LanguageClient'; import { PapyrusGame, getShortDisplayNameForGame } from '../PapyrusGame'; import { IGameConfig } from '../ExtensionConfigProvider'; -import { Observable, BehaviorSubject } from 'rxjs'; +import { Observable, BehaviorSubject, observable, of } from 'rxjs'; import { ICreationKitInfo } from '../CreationKitInfoProvider'; import { DocumentScriptInfo } from './messages/DocumentScriptInfo'; import { shareReplay, take, map, switchMap } from 'rxjs/operators'; @@ -24,11 +24,11 @@ export enum ClientHostStatus { export interface ILanguageClientHost { readonly game: PapyrusGame; readonly status: Observable; - readonly client: ILanguageClient; - readonly error: Observable; - readonly outputChannel: OutputChannel; - readonly projectInfos: Observable; - getDocumentScriptStatus(document: TextDocument): Promise; + readonly client: ILanguageClient | null; + readonly error: Observable; + readonly outputChannel: OutputChannel | null; + readonly projectInfos: Observable; + getDocumentScriptStatus(document: TextDocument): Promise; } export interface IScriptDocumentStatus { @@ -43,13 +43,13 @@ export class LanguageClientHost implements ILanguageClientHost, Disposable { private readonly _config: IGameConfig; private readonly _creationKitInfo: ICreationKitInfo; private readonly _pathResolver: IPathResolver; - private _outputChannel: OutputChannel; - private _client: LanguageClient; + private _outputChannel: OutputChannel | null = null; + private _client: LanguageClient | null = null; - private _projectInfos: Observable; + private _projectInfos: Observable; private readonly _status = new BehaviorSubject(ClientHostStatus.none); - private readonly _error = new BehaviorSubject(null); + private readonly _error = new BehaviorSubject(null); constructor( game: PapyrusGame, @@ -65,10 +65,11 @@ export class LanguageClientHost implements ILanguageClientHost, Disposable { this._projectInfos = this._status.pipe( switchMap((status) => { if (status !== ClientHostStatus.running) { - return Promise.resolve(null); + return of(null); } - return this._client.projectsUpdated; + // Since we're in ClientHostStatus.running, then this._client is defined. + return this._client!.projectsUpdated; }), switchMap(() => (this._client ? this._client.requestProjectInfos() : Promise.resolve(null))) ); @@ -129,8 +130,8 @@ export class LanguageClientHost implements ILanguageClientHost, Disposable { relativeIniPaths: this._config.creationKitIniFiles, flagsFileName: getDefaultFlagsFileNameForGame(this._game), ambientProjectName: 'Creation Kit', - defaultScriptSourceFolder: this._creationKitInfo.config.Papyrus.sScriptSourceFolder, - defaultAdditionalImports: this._creationKitInfo.config.Papyrus.sAdditionalImports, + defaultScriptSourceFolder: this._creationKitInfo.config.Papyrus?.sScriptSourceFolder, + defaultAdditionalImports: this._creationKitInfo.config.Papyrus?.sAdditionalImports, }; this._outputChannel.appendLine(`Creating Language Client instance with options:`); @@ -147,9 +148,11 @@ export class LanguageClientHost implements ILanguageClientHost, Disposable { this._status.next(ClientHostStatus.starting); await this._client.start(); this._status.next(ClientHostStatus.running); - } catch (error) { + } catch (err) { + const error = err instanceof Error ? err : new Error((err as any).toString()); + this._outputChannel.appendLine(`Error on language service pre-start: ${error.toString()}`); - if (error instanceof Error) { + if (error.stack) { this._outputChannel.appendLine(error.stack); } @@ -158,13 +161,21 @@ export class LanguageClientHost implements ILanguageClientHost, Disposable { } } - async getDocumentScriptStatus(document: TextDocument): Promise { + async getDocumentScriptStatus(document: TextDocument): Promise { + if (!this._client) { + return null + } + if ((await this._status.pipe(take(1)).toPromise()) !== ClientHostStatus.running) { return null; } const scriptInfo = await this._client.requestScriptInfo(document.uri.toString()); + if (!scriptInfo) { + return null; + } + const documentIsUnresolved = scriptInfo.identifiers.length === 0; const documentIsOverridden = !documentIsUnresolved && diff --git a/src/papyrus-lang-vscode/src/server/LanguageClientManager.ts b/src/papyrus-lang-vscode/src/server/LanguageClientManager.ts index 08f5845e..5982cafc 100644 --- a/src/papyrus-lang-vscode/src/server/LanguageClientManager.ts +++ b/src/papyrus-lang-vscode/src/server/LanguageClientManager.ts @@ -15,7 +15,7 @@ export interface ILanguageClientManager extends Disposable { readonly clients: ReadonlyMap>; getActiveLanguageClients(cancellationToken?: CancellationToken): Promise; getLanguageClientHost(game: PapyrusGame): Promise; - getLanguageClient(game: PapyrusGame): Promise; + getLanguageClient(game: PapyrusGame): Promise; } @injectable() @@ -32,7 +32,7 @@ export class LanguageClientManager implements Disposable, ILanguageClientManager const createClientObservable = (game: PapyrusGame) => { return combineLatest( configProvider.config.pipe(map((config) => config[game])), - infoProvider.infos.get(game) + infoProvider.infos.get(game)! ).pipe( asyncDisposable<[IGameConfig, ICreationKitInfo], LanguageClientHost>( ([gameConfig, creationKitInfo]) => @@ -79,17 +79,17 @@ export class LanguageClientManager implements Disposable, ILanguageClientManager return client; }) - )).filter((client) => client !== null); + )).filter((client) => client !== null) as ILanguageClientHost[]; } async getLanguageClientHost(game: PapyrusGame): Promise { return await this.clients - .get(game) + .get(game)! .pipe(take(1)) .toPromise(); } - async getLanguageClient(game: PapyrusGame): Promise { + async getLanguageClient(game: PapyrusGame): Promise { const clientHost = await this.getLanguageClientHost(game); const status = await clientHost.status.pipe(take(1)).toPromise(); diff --git a/src/papyrus-lang-vscode/tsconfig.json b/src/papyrus-lang-vscode/tsconfig.json index 55329b2b..d21b6d53 100644 --- a/src/papyrus-lang-vscode/tsconfig.json +++ b/src/papyrus-lang-vscode/tsconfig.json @@ -9,6 +9,7 @@ "sourceMap": true, "rootDir": "src", "experimentalDecorators": true, + "strict": true }, "include": ["src/**/*.ts"] } From 3413c2e17c6685500eac9b4be3ef5f2462503b93 Mon Sep 17 00:00:00 2001 From: Joel Day Date: Sun, 15 Jan 2023 18:11:15 -0800 Subject: [PATCH 4/5] chore: Add CI build version to debugger dlls. chore: Use Release build configuration for CI builds. --- build.cake | 21 ++++++++--- ...arkId.Papyrus.DebugServer.Fallout4.vcxproj | 34 ++++++++++++------ .../DarkId.Papyrus.DebugServer.Skyrim.vcxproj | 36 ++++++++++++------- src/DarkId.Papyrus.DebugServer/version.h | 30 ++++++++-------- src/DarkId.Papyrus.DebugServer/version.rc | 6 ++-- 5 files changed, 84 insertions(+), 43 deletions(-) diff --git a/build.cake b/build.cake index c459b99f..b28bda74 100644 --- a/build.cake +++ b/build.cake @@ -208,12 +208,14 @@ Task("copy-debug-plugin") { CreateDirectory("./src/papyrus-lang-vscode/debug-plugin"); + var configuration = isRelease ? "Release" : "Debug"; + CopyFileToDirectory( - "src/DarkId.Papyrus.DebugServer/bin/DarkId.Papyrus.DebugServer.Skyrim/x64/Debug/DarkId.Papyrus.DebugServer.Skyrim.dll", + $"src/DarkId.Papyrus.DebugServer/bin/DarkId.Papyrus.DebugServer.Skyrim/x64/{configuration}/DarkId.Papyrus.DebugServer.Skyrim.dll", "./src/papyrus-lang-vscode/debug-plugin"); CopyFileToDirectory( - "src/DarkId.Papyrus.DebugServer/bin/DarkId.Papyrus.DebugServer.Fallout4/x64/Debug/DarkId.Papyrus.DebugServer.Fallout4.dll", + $"src/DarkId.Papyrus.DebugServer/bin/DarkId.Papyrus.DebugServer.Fallout4/x64/{configuration}/DarkId.Papyrus.DebugServer.Fallout4.dll", "./src/papyrus-lang-vscode/debug-plugin"); } catch (Exception) @@ -239,13 +241,24 @@ Task("restore") Task("build-debugger") .Does(() => { - // TODO: How do we set the version on these? Does AssemblyVersion work? - // TODO: Do release builds when running CI. + var parsedVersion = System.Version.Parse(version); + + var patch = parsedVersion.Build & 0xFFFF0000; + var build = parsedVersion.Build & 0x0000FFFF; MSBuild(debuggerSolution, new MSBuildSettings() { PlatformTarget = PlatformTarget.x64, + Configuration = isRelease ? "Release" : "Debug", + Properties = + { + { "VersionMajor", new List(){ parsedVersion.Major.ToString() } }, + { "VersionMinor", new List(){ parsedVersion.Minor.ToString() } }, + { "VersionPatch", new List(){ patch.ToString() } }, + { "VersionBuild", new List(){ build.ToString() } }, + } }); + }); Task("build") diff --git a/src/DarkId.Papyrus.DebugServer/DarkId.Papyrus.DebugServer.Fallout4.vcxproj b/src/DarkId.Papyrus.DebugServer/DarkId.Papyrus.DebugServer.Fallout4.vcxproj index a805f16d..abb3c638 100644 --- a/src/DarkId.Papyrus.DebugServer/DarkId.Papyrus.DebugServer.Fallout4.vcxproj +++ b/src/DarkId.Papyrus.DebugServer/DarkId.Papyrus.DebugServer.Fallout4.vcxproj @@ -1,5 +1,6 @@  - + Debug @@ -16,6 +17,10 @@ DarkId::Papyrus::DebugServer Win32Proj 10.0 + 0 + 0 + 0 + 0 @@ -33,10 +38,14 @@ - + - + @@ -59,7 +68,8 @@ $(ProjectDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\ - $(registry:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Bethesda Softworks\Fallout4@installed path) + $(registry:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Bethesda + Softworks\Fallout4@installed path) $(FalloutInstallPath)Data\F4SE\Plugins @@ -81,7 +91,8 @@ Disabled - WIN32;FALLOUT;SPDLOG_COMPILED_LIB;SPDLOG_FMT_EXTERNAL;F4SE_SUPPORT_XBYAK;_DEBUG;_WINDOWS;_USRDLL;DARKID_PAPYRUS_DEBUGSERVER_EXPORTS;%(PreprocessorDefinitions) + + WIN32;FALLOUT;SPDLOG_COMPILED_LIB;SPDLOG_FMT_EXTERNAL;F4SE_SUPPORT_XBYAK;_DEBUG;_WINDOWS;_USRDLL;DARKID_PAPYRUS_DEBUGSERVER_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 @@ -104,7 +115,8 @@ Use pdsPCH.h /bigobj %(AdditionalOptions) - $(ProjectDir);$(ProjectDir)..\..\dependencies;$(ProjectDir)..\..\dependencies\MetaStuff\include;$(VcpkgInstalledDir)\$(VcpkgTriplet)\include\Champollion;%(AdditionalIncludeDirectories) + + $(ProjectDir);$(ProjectDir)..\..\dependencies;$(ProjectDir)..\..\dependencies\MetaStuff\include;$(VcpkgInstalledDir)\$(VcpkgTriplet)\include\Champollion;%(AdditionalIncludeDirectories) true @@ -129,14 +141,15 @@ - FALLOUT + FALLOUT;DIDPDS_VERSION_MAJOR=$(VersionMajor);DIDPDS_VERSION_MINOR=$(VersionMinor);DIDPDS_VERSION_PATCH=$(VersionPatch);DIDPDS_VERSION_BUILD=$(VersionBuild); MaxSpeed true - WIN32;FALLOUT;SPDLOG_COMPILED_LIB;SPDLOG_FMT_EXTERNAL;F4SE_SUPPORT_XBYAK;NDEBUG;_WINDOWS;_USRDLL;DARKID_PAPYRUS_DEBUGSERVER_EXPORTS;%(PreprocessorDefinitions) + + WIN32;FALLOUT;SPDLOG_COMPILED_LIB;SPDLOG_FMT_EXTERNAL;F4SE_SUPPORT_XBYAK;NDEBUG;_WINDOWS;_USRDLL;DARKID_PAPYRUS_DEBUGSERVER_EXPORTS;%(PreprocessorDefinitions) MultiThreaded true Level3 @@ -157,7 +170,8 @@ Use pdsPCH.h /bigobj %(AdditionalOptions) - $(ProjectDir);$(ProjectDir)..\..\dependencies;$(ProjectDir)..\..\dependencies\MetaStuff\include;$(VcpkgInstalledDir)\$(VcpkgTriplet)\include\Champollion;%(AdditionalIncludeDirectories) + + $(ProjectDir);$(ProjectDir)..\..\dependencies;$(ProjectDir)..\..\dependencies\MetaStuff\include;$(VcpkgInstalledDir)\$(VcpkgTriplet)\include\Champollion;%(AdditionalIncludeDirectories) true @@ -180,7 +194,7 @@ - FALLOUT + FALLOUT;DIDPDS_VERSION_MAJOR=$(VersionMajor);DIDPDS_VERSION_MINOR=$(VersionMinor);DIDPDS_VERSION_PATCH=$(VersionPatch);DIDPDS_VERSION_BUILD=$(VersionBuild); diff --git a/src/DarkId.Papyrus.DebugServer/DarkId.Papyrus.DebugServer.Skyrim.vcxproj b/src/DarkId.Papyrus.DebugServer/DarkId.Papyrus.DebugServer.Skyrim.vcxproj index 3b4dc054..3f9cd0c0 100644 --- a/src/DarkId.Papyrus.DebugServer/DarkId.Papyrus.DebugServer.Skyrim.vcxproj +++ b/src/DarkId.Papyrus.DebugServer/DarkId.Papyrus.DebugServer.Skyrim.vcxproj @@ -1,5 +1,6 @@ - + Debug @@ -16,8 +17,10 @@ DarkId::Papyrus::DebugServer Win32Proj 10.0 - $(APPVEYOR_BUILD_NUMBER) - 0 + 0 + 0 + 0 + 0 @@ -35,10 +38,14 @@ - + - + @@ -61,7 +68,8 @@ $(ProjectDir)obj\$(ProjectName)\$(Platform)\$(Configuration)\ - $(registry:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Bethesda Softworks\Skyrim Special Edition@installed path) + $(registry:HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Bethesda Softworks\Skyrim + Special Edition@installed path) $(SkyrimInstallPath)Data\SKSE\Plugins @@ -83,8 +91,10 @@ Disabled - $(ProjectDir);$(ProjectDir)..\..\dependencies;$(ProjectDir)..\..\dependencies\MetaStuff\include;$(VcpkgInstalledDir)\$(VcpkgTriplet)\include\Champollion;%(AdditionalIncludeDirectories) - WIN32;SKYRIM;ENABLE_SKYRIM_VR;ENABLE_SKYRIM_AE;ENABLE_SKYRIM_SE;SKSE_SUPPORT_XBYAK;_DEBUG;_WINDOWS;_USRDLL;DARKID_PAPYRUS_DEBUGSERVER_EXPORTS;%(PreprocessorDefinitions) + + $(ProjectDir);$(ProjectDir)..\..\dependencies;$(ProjectDir)..\..\dependencies\MetaStuff\include;$(VcpkgInstalledDir)\$(VcpkgTriplet)\include\Champollion;%(AdditionalIncludeDirectories) + + WIN32;SKYRIM;ENABLE_SKYRIM_VR;ENABLE_SKYRIM_AE;ENABLE_SKYRIM_SE;SKSE_SUPPORT_XBYAK;_DEBUG;_WINDOWS;_USRDLL;DARKID_PAPYRUS_DEBUGSERVER_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 @@ -131,15 +141,17 @@ - SKYRIM + SKYRIM;DIDPDS_VERSION_MAJOR=$(VersionMajor);DIDPDS_VERSION_MINOR=$(VersionMinor);DIDPDS_VERSION_PATCH=$(VersionPatch);DIDPDS_VERSION_BUILD=$(VersionBuild); MaxSpeed true - $(ProjectDir);$(ProjectDir)..\..\dependencies;$(ProjectDir)..\..\dependencies\MetaStuff\include;$(VcpkgInstalledDir)\$(VcpkgTriplet)\include\Champollion;%(AdditionalIncludeDirectories) - WIN32;SKYRIM;ENABLE_SKYRIM_VR;ENABLE_SKYRIM_AE;ENABLE_SKYRIM_SE;SKSE_SUPPORT_XBYAK;NDEBUG;_WINDOWS;_USRDLL;DARKID_PAPYRUS_DEBUGSERVER_EXPORTS;%(PreprocessorDefinitions) + + $(ProjectDir);$(ProjectDir)..\..\dependencies;$(ProjectDir)..\..\dependencies\MetaStuff\include;$(VcpkgInstalledDir)\$(VcpkgTriplet)\include\Champollion;%(AdditionalIncludeDirectories) + + WIN32;SKYRIM;ENABLE_SKYRIM_VR;ENABLE_SKYRIM_AE;ENABLE_SKYRIM_SE;SKSE_SUPPORT_XBYAK;NDEBUG;_WINDOWS;_USRDLL;DARKID_PAPYRUS_DEBUGSERVER_EXPORTS;%(PreprocessorDefinitions) MultiThreaded true Level3 @@ -182,7 +194,7 @@ - SKYRIM + SKYRIM;DIDPDS_VERSION_MAJOR=$(VersionMajor);DIDPDS_VERSION_MINOR=$(VersionMinor);DIDPDS_VERSION_PATCH=$(VersionPatch);DIDPDS_VERSION_BUILD=$(VersionBuild); diff --git a/src/DarkId.Papyrus.DebugServer/version.h b/src/DarkId.Papyrus.DebugServer/version.h index 392dc7e2..8afa2574 100644 --- a/src/DarkId.Papyrus.DebugServer/version.h +++ b/src/DarkId.Papyrus.DebugServer/version.h @@ -1,4 +1,4 @@ -#ifndef DIDPDS_VERSION_INCLUDED +#ifndef DIDPDS_VERSION_INCLUDED #define DIDPDS_VERSION_INCLUDED #define MAKE_STR_HELPER(a_str) #a_str @@ -10,21 +10,23 @@ #define DIDPDS_DLL_NAME "DarkId.Papyrus.DebugServer.Fallout4.dll" #endif -// Manual update for now -#define DIDPDS_VERSION_MAJOR 1 - -#define DIDPDS_VERSION_MINOR 57 +#ifndef DIDPDS_VERSION_MAJOR +#define DIDPDS_VERSION_MAJOR 0 +#endif -#define DIDPDS_VERSION_PATCH 0 +#ifndef DIDPDS_VERSION_MINOR +#define DIDPDS_VERSION_MINOR 0 +#endif -// Just manually update DIDPDS_VERSION_BETA for now -#define DIDPDS_VERSION_BETA 1 +#ifndef DIDPDS_VERSION_PATCH +#define DIDPDS_VERSION_PATCH 0 +#endif -#define DIDPDS_VERSION_WIN_VERSTRING MAKE_STR(DIDPDS_VERSION_MAJOR) "." MAKE_STR(DIDPDS_VERSION_MINOR) "." MAKE_STR(DIDPDS_VERSION_PATCH) "." MAKE_STR(DIDPDS_VERSION_BETA) -#if DIDPDS_VERSION_BETA == 0 -#define DIDPDS_VERSION_SEMVER MAKE_STR(DIDPDS_VERSION_MAJOR) "." MAKE_STR(DIDPDS_VERSION_MINOR) "." MAKE_STR(DIDPDS_VERSION_PATCH) -#else -#define DIDPDS_VERSION_SEMVER MAKE_STR(DIDPDS_VERSION_MAJOR) "." MAKE_STR(DIDPDS_VERSION_MINOR) "." MAKE_STR(DIDPDS_VERSION_PATCH) "-beta" MAKE_STR(DIDPDS_VERSION_BETA) +#ifndef DIDPDS_VERSION_BUILD +#define DIDPDS_VERSION_BUILD 0 #endif -#endif //DIDPDS_VERSION_INCLUDED +#define DIDPDS_VERSION_WIN_VERSTRING MAKE_STR(DIDPDS_VERSION_MAJOR) "." MAKE_STR(DIDPDS_VERSION_MINOR) "." MAKE_STR(DIDPDS_VERSION_PATCH) "." MAKE_STR(DIDPDS_VERSION_BUILD) +#define DIDPDS_VERSION_SEMVER MAKE_STR(DIDPDS_VERSION_MAJOR) "." MAKE_STR(DIDPDS_VERSION_MINOR) "." MAKE_STR(DIDPDS_VERSION_PATCH) + +#endif // DIDPDS_VERSION_INCLUDED diff --git a/src/DarkId.Papyrus.DebugServer/version.rc b/src/DarkId.Papyrus.DebugServer/version.rc index 1830159c..87c58f1e 100644 --- a/src/DarkId.Papyrus.DebugServer/version.rc +++ b/src/DarkId.Papyrus.DebugServer/version.rc @@ -2,8 +2,8 @@ #include 1 VERSIONINFO - FILEVERSION DIDPDS_VERSION_MAJOR, DIDPDS_VERSION_MINOR, DIDPDS_VERSION_PATCH, DIDPDS_VERSION_BETA - PRODUCTVERSION DIDPDS_VERSION_MAJOR, DIDPDS_VERSION_MINOR, DIDPDS_VERSION_PATCH, DIDPDS_VERSION_BETA + FILEVERSION DIDPDS_VERSION_MAJOR, DIDPDS_VERSION_MINOR, DIDPDS_VERSION_PATCH, DIDPDS_VERSION_BUILD + PRODUCTVERSION DIDPDS_VERSION_MAJOR, DIDPDS_VERSION_MINOR, DIDPDS_VERSION_PATCH, DIDPDS_VERSION_BUILD FILEFLAGSMASK 0x17L #ifndef DIDPDS_DLL_NAME @@ -31,7 +31,7 @@ BEGIN VALUE "FileDescription", "Papyrus Debug Server" VALUE "FileVersion", DIDPDS_VERSION_WIN_VERSTRING VALUE "InternalName", DIDPDS_DLL_NAME - VALUE "LegalCopyright", "Copyright (c) 2019 Joel Day" + VALUE "LegalCopyright", "Copyright (c) 2023 Joel Day" VALUE "ProductName", DIDPDS_DLL_NAME VALUE "ProductVersion", DIDPDS_VERSION_WIN_VERSTRING END From f0b005211bba2ad862ccf2a5bcb2d884c9bbb3be Mon Sep 17 00:00:00 2001 From: nikitalita <69168929+nikitalita@users.noreply.github.com> Date: Sun, 15 Jan 2023 18:59:21 -0800 Subject: [PATCH 5/5] Fix typo --- src/papyrus-lang-vscode/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/papyrus-lang-vscode/package.json b/src/papyrus-lang-vscode/package.json index 40d8b7ba..3e0b250e 100644 --- a/src/papyrus-lang-vscode/package.json +++ b/src/papyrus-lang-vscode/package.json @@ -99,7 +99,7 @@ } }, { - "label": "Papyrus: Skyrim Special Editio/Anniversary Editionn (with .ppj)", + "label": "Papyrus: Skyrim Special Edition/Anniversary Edition (with .ppj)", "body": { "name": "Skyrim Special Edition/Anniversary Edition Project", "type": "papyrus",