🚧 First kind of working version for tagRenderingImplementationProvider
This commit is contained in:
parent
b7ebfee84d
commit
4d1ea863df
3 changed files with 165 additions and 3 deletions
|
@ -6,6 +6,7 @@ import {
|
|||
filterDefinitionProvider,
|
||||
tagRenderingCompletionProvider,
|
||||
tagRenderingDefinitionProvider,
|
||||
tagRenderingImplementationProvider,
|
||||
} from "./layers";
|
||||
import { pathDefinitionProvider } from "./license_info";
|
||||
import { CacheWorker } from "./utils/cache";
|
||||
|
@ -19,7 +20,8 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||
tagRenderingCompletionProvider,
|
||||
tagRenderingDefinitionProvider,
|
||||
filterCompletionProvider,
|
||||
filterDefinitionProvider
|
||||
filterDefinitionProvider,
|
||||
tagRenderingImplementationProvider
|
||||
);
|
||||
|
||||
// Activate all license info related features
|
||||
|
|
146
src/layers.ts
146
src/layers.ts
|
@ -13,6 +13,7 @@ import { getCursorPath, getRawCursorPath, getStartEnd } from "./utils/cursor";
|
|||
import { getFilters, getTagRenderings } from "./utils/mapcomplete";
|
||||
import { getValueFromPath } from "./utils/json";
|
||||
import { JSONPath } from "jsonc-parser";
|
||||
import { Cache } from "./utils/cache";
|
||||
|
||||
/**
|
||||
* Tag rendering completion provider
|
||||
|
@ -172,6 +173,151 @@ export const tagRenderingDefinitionProvider =
|
|||
}
|
||||
);
|
||||
|
||||
export const tagRenderingImplementationProvider =
|
||||
vscode.languages.registerImplementationProvider(
|
||||
{
|
||||
language: "json",
|
||||
scheme: "file",
|
||||
pattern: "**/assets/*/*/*.json",
|
||||
},
|
||||
{
|
||||
async provideImplementation(
|
||||
document: vscode.TextDocument,
|
||||
position: vscode.Position,
|
||||
_token: vscode.CancellationToken
|
||||
) {
|
||||
console.log("tagRenderingImplementationProvider");
|
||||
const text = document.getText();
|
||||
const jsonPath = getCursorPath(text, position);
|
||||
const rawJsonPath = getRawCursorPath(text, position);
|
||||
|
||||
const regex = /^tagRenderings(\+)?\.\d+\.id$/;
|
||||
|
||||
if (regex.exec(jsonPath)) {
|
||||
const tagRenderingId = getValueFromPath(text, rawJsonPath);
|
||||
const layerName = document.fileName.split("/").pop()?.split(".")[0];
|
||||
const to = `layers.${layerName}.tagRenderings.${tagRenderingId}`;
|
||||
|
||||
try {
|
||||
const cache = await Cache.create();
|
||||
const references = cache.getReferences(to);
|
||||
|
||||
if (references.length === 0) {
|
||||
return null;
|
||||
} else {
|
||||
// TODO: This is way too much to be executing at this time, most of this should be cached
|
||||
// TODO: Also, this seems to fail for the first time, but work for every subsequent time
|
||||
console.log(`Found ${references.length} references to ${to}`);
|
||||
|
||||
const links: vscode.DefinitionLink[] = [];
|
||||
for (const reference of references) {
|
||||
const originType = reference.reference?.from.split(".")[0];
|
||||
const originName = reference.reference?.from.split(".")[1];
|
||||
|
||||
// We need to open the file where the reference is located
|
||||
const originFile = await vscode.workspace.findFiles(
|
||||
`assets/${originType}/${originName}/${originName}.json`
|
||||
);
|
||||
if (originFile.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const originText = await vscode.workspace.fs.readFile(
|
||||
originFile[0]
|
||||
);
|
||||
const originTextString = new TextDecoder().decode(originText);
|
||||
const origin = JSON.parse(originTextString);
|
||||
|
||||
let tagRenderings: unknown[] = [];
|
||||
let tagRenderingsPath: JSONPath = [];
|
||||
|
||||
// Now we'll need to find the tagRenderings object, and its path
|
||||
if (originType === "themes") {
|
||||
const parts = reference.reference?.from.split(".");
|
||||
if (!parts) {
|
||||
continue;
|
||||
} else {
|
||||
console.log("Parts", parts);
|
||||
// Now we need to find the correct inline layer
|
||||
const layerIndex = origin.layers.findIndex(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(layer: any) => layer.id === parts[3]
|
||||
);
|
||||
|
||||
const path: JSONPath = [
|
||||
parts[2],
|
||||
layerIndex,
|
||||
...reference.jsonPath,
|
||||
];
|
||||
|
||||
console.log("Trying to get tagRenderings from theme", path);
|
||||
|
||||
const tagRenderingsFromOrigin = getValueFromPath(
|
||||
originTextString,
|
||||
path
|
||||
);
|
||||
if (!tagRenderingsFromOrigin) {
|
||||
console.error(
|
||||
"Could not find tagRenderings in theme",
|
||||
originName
|
||||
);
|
||||
continue;
|
||||
} else {
|
||||
// Yaay, we found the tagRenderings
|
||||
console.log("Found tagRenderings in theme", originName);
|
||||
tagRenderings = tagRenderingsFromOrigin as unknown[];
|
||||
tagRenderingsPath = path;
|
||||
}
|
||||
}
|
||||
} else if (originType === "layers") {
|
||||
tagRenderings = origin.tagRenderings;
|
||||
tagRenderingsPath = ["tagRenderings"];
|
||||
}
|
||||
|
||||
// The index is actually a really complicated, because a reference could be a string or an object with a builtin property, which can be a string or a list of strings
|
||||
// Also if the reference is from an inline layer
|
||||
const tagRenderingIndex = tagRenderings.findIndex(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(tr: any) => {
|
||||
if (typeof tr === "string") {
|
||||
return tr === reference.id;
|
||||
} else if (typeof tr.builtin === "string") {
|
||||
return tr.builtin === reference.id;
|
||||
}
|
||||
// } else if (tr.builtin) {
|
||||
// return tr.builtin.includes(reference.id);
|
||||
// }
|
||||
}
|
||||
);
|
||||
const path: JSONPath = [
|
||||
...tagRenderingsPath,
|
||||
tagRenderingIndex,
|
||||
];
|
||||
const startEnd = getStartEnd(originTextString, path);
|
||||
|
||||
console.log(
|
||||
`Pushing link from ${document.fileName} to ${originFile[0].path} at ${startEnd.start.line}.${startEnd.start.character} to ${startEnd.end.line}.${startEnd.end.character}`
|
||||
);
|
||||
|
||||
links.push({
|
||||
originSelectionRange: getStartEnd(text, rawJsonPath),
|
||||
targetRange: startEnd,
|
||||
targetUri: originFile[0],
|
||||
});
|
||||
}
|
||||
console.log(`Found ${links.length} implementations`);
|
||||
return links;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error get implementation", error);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter completion provider
|
||||
*
|
||||
|
|
|
@ -280,7 +280,7 @@ export class CacheWorker {
|
|||
const json = JSON.parse(text);
|
||||
|
||||
// Check if this layer doesn't have a special source, or uses a geoJson source
|
||||
if (json.source === "special" || json.source.geoJson) {
|
||||
if (json.source === "special" || json.source?.geoJson) {
|
||||
console.log("Layer has a special source, only saving references");
|
||||
referencesOnly = true;
|
||||
}
|
||||
|
@ -453,7 +453,6 @@ export class Cache {
|
|||
const cache = await vscode.workspace.fs.readFile(cacheUri);
|
||||
const cacheString = new TextDecoder().decode(cache);
|
||||
this.cache = JSON.parse(cacheString);
|
||||
console.log(`Cache loaded, ${this.cache.length} items`);
|
||||
} else {
|
||||
console.error("No workspace folder found");
|
||||
throw new Error("No workspace folder found");
|
||||
|
@ -513,6 +512,21 @@ export class Cache {
|
|||
}
|
||||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all references to a specific item
|
||||
*
|
||||
* @param to Item to get references for (e.g. layers.bicycle_rental)
|
||||
* @returns List of references
|
||||
*/
|
||||
public getReferences(to: string): CacheItem[] {
|
||||
return this.cache.filter((item) => {
|
||||
if (item.type === "reference") {
|
||||
return item.reference?.to === to;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue