Skip to content

Commit

Permalink
automatic correction suggestion for dependencies syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
HJfod committed Jan 18, 2025
1 parent 04a6f16 commit 1dc89d6
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 15 deletions.
11 changes: 8 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,12 @@
"languages": [
{
"id": "bro",
"aliases": ["Broma"],
"extensions": [".bro"],
"aliases": [
"Broma"
],
"extensions": [
".bro"
],
"configuration": "./src/broma/language-configuration.json"
}
],
Expand Down Expand Up @@ -327,9 +331,10 @@
"@vscode/webview-ui-toolkit": "^1.1.0",
"camelcase": "^7.0.0",
"fuse.js": "^6.6.2",
"jsonc-parser": "^3.3.1",
"object-hash": "^3.0.0",
"plist": "^3.0.6",
"semver": "^7.5.4",
"sharp": "^0.33.4"
}
}
}
25 changes: 15 additions & 10 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { CCColor3bProvider, CCColor4bProvider } from "./project/color";
import { SpriteHoverPreview } from "./project/hover";
import { registerLinters } from "./project/lint";
import { ModifyClassMethodCompletion } from "./project/suggest";
import { ModJsonSuggestionsProvider } from "./project/mod";

export async function activate(context: ExtensionContext) {
const channel = window.createOutputChannel("Geode");
Expand Down Expand Up @@ -90,6 +91,12 @@ export async function activate(context: ExtensionContext) {
new ModifyClassMethodCompletion(),
),
);
context.subscriptions.push(
languages.registerCodeActionsProvider(
{ pattern: "**/mod.json" },
new ModJsonSuggestionsProvider(),
)
);

registerLinters(context);

Expand Down
79 changes: 77 additions & 2 deletions src/project/mod.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
/* eslint-disable @typescript-eslint/naming-convention */

import { CancellationToken, CodeAction, CodeActionContext, CodeActionKind, CodeActionProvider, Command, commands, languages, Position, ProviderResult, Range, Selection, TextDocument, WorkspaceEdit } from "vscode";
import { createScanner, getNodeValue, parseTree } from "jsonc-parser";
import { getOutputChannel } from "../config";

export interface Font {
/**
* Path to the font's TTF / OTF file (relative to mod root folder)
Expand Down Expand Up @@ -413,12 +417,31 @@ export interface Dependency {
*/
settings?: any,
}
export interface LegacyDependency extends Dependency {
export type Dependencies = { [id: string]: Version | Dependency };

export interface LegacyDependency {
/**
* ID of the dependency
* @pattern [a-z0-9\-_]+\.[a-z0-9\-_]+
*/
id: string,
/**
* Version of the dependency. Geode assumes the mod follows [semver](https://semver.org);
* this means that versions "1.5.3" and "1.4.0" will be considered valid
* for dependency version "1.4.5" but "2.1.0" would not be valid
*/
version: Version,
/**
* Whether this dependency is required for the mod to work, or only
* recommended for users
*/
importance: "required" | "recommended" | "suggested",
/**
* If this dependency should only be on certain platforms, specify this
* property; by default, Geode assumes dependencies are used on all
* platforms
*/
platforms?: ShortPlatformIDOrGeneric[],
}
/**
* @deprecated
Expand Down Expand Up @@ -568,7 +591,7 @@ interface ModJsonBase {
* List of mods this mod depends on. See [the docs](https://docs.geode-sdk.org/mods/dependencies)
* for more information
*/
dependencies?: { [id: string]: Version | Dependency } | LegacyDependencies,
dependencies?: Dependencies | LegacyDependencies,
/**
* List of mods this mod is incompatible with
*/
Expand Down Expand Up @@ -659,3 +682,55 @@ export interface RTModJson extends ModJsonBase {
binary: string;
runtime: ModRunTimeInfo;
}

export class ModJsonSuggestionsProvider implements CodeActionProvider {
provideCodeActions(
document: TextDocument,
range: Range | Selection,
context: CodeActionContext,
token: CancellationToken
): ProviderResult<(CodeAction | Command)[]> {
const modJson = parseTree(document.getText());
const dependencies = modJson?.children?.find(c => c.children?.at(0)?.value === "dependencies");
if (!dependencies) {
return undefined;
}
const dependenciesValue = dependencies.children?.at(1);
const indentation = document.positionAt(dependencies.offset).character;
if (
dependenciesValue && dependenciesValue.type === "array" &&
new Range(
document.positionAt(dependencies.offset),
document.positionAt(dependencies.offset + dependencies.length)
).intersection(range) !== undefined
) {
const action = new CodeAction("Convert to new `dependencies` syntax", CodeActionKind.QuickFix);
action.isPreferred = true;
action.edit = new WorkspaceEdit();
action.edit.replace(
document.uri,
new Range(
document.positionAt(dependenciesValue.offset),
document.positionAt(dependenciesValue.offset + dependenciesValue.length)
),
JSON.stringify((getNodeValue(dependenciesValue) as LegacyDependencies).reduce((result, dep) => {
// Shorthand
if (dep.importance === "required" && dep.platforms === undefined) {
result[dep.id] = dep.version;
}
// Longhand
else {
result[dep.id] = {
importance: dep.importance,
version: dep.version,
platforms: dep.platforms,
};
}
return result;
}, {} as Dependencies), undefined, indentation).replace(/\n/g, `\n${" ".repeat(indentation)}`)
);
return [action];
}
return undefined;
}
}

0 comments on commit 1dc89d6

Please sign in to comment.