Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | 4x 4x 1x 3x 3x 3x 4x 4x 1x 2x 1x 1x 6x 6x 6x 1x 5x 5x 5x 6x 6x 6x 6x 6x 1x 1x 2x 2x 2x 4x 2x 2x 2x 2x 2x 3x 3x 3x 3x 2x 2x 5x 5x 5x 1x 4x 4x 4x 5x 7x | import * as vscode from 'vscode';
/**
* Provides renaming for Datalog symbols including: Relations (predicates), Variables (uppercase identifiers) and Prefixed names (e.g., rdf:type)
*/
export class DatalogRenameProvider implements vscode.RenameProvider {
/**
* Prepares the rename operation by determining the range of the symbol to rename.
*/
public async prepareRename(document: vscode.TextDocument, position: vscode.Position): Promise<vscode.Range | { range: vscode.Range; placeholder: string } | null> {
const wordRange = document.getWordRangeAtPosition(position, /[a-zA-Z_][a-zA-Z0-9_]*/);
if (!wordRange) {
throw new Error('Cannot rename this element.');
}
const word = document.getText(wordRange);
// Check if this is part of a prefixed name (e.g., rdf:type)
const text = document.lineAt(position.line).text;
const charBefore = wordRange.start.character > 0 ? text[wordRange.start.character - 1] : '';
const charAfter = wordRange.end.character < text.length ? text[wordRange.end.character] : '';
// If character after is ':', this is a prefix (e.g., "rdf" in "rdf:type")
if (charAfter === ':') {
return {
range: wordRange,
placeholder: word
};
}
// If character before is ':', this is a local name (e.g., "type" in "rdf:type")
if (charBefore === ':') {
return {
range: wordRange,
placeholder: word
};
}
// Regular identifier (relation or variable)
return {
range: wordRange,
placeholder: word
};
}
/**
* Provides the rename edits for the symbol.
*/
public provideRenameEdits(document: vscode.TextDocument, position: vscode.Position, newName: string): vscode.ProviderResult<vscode.WorkspaceEdit> {
const edits = new vscode.WorkspaceEdit();
const wordRange = document.getWordRangeAtPosition(position, /[a-zA-Z_][a-zA-Z0-9_]*/);
if (!wordRange) {
return edits;
}
const word = document.getText(wordRange);
const lineText = document.lineAt(position.line).text;
const charBefore = wordRange.start.character > 0 ? lineText[wordRange.start.character - 1] : '';
const charAfter = wordRange.end.character < lineText.length ? lineText[wordRange.end.character] : '';
// Determine the type of symbol we're renaming
const isPrefix = charAfter === ':';
const isLocalName = charBefore === ':';
const text = document.getText();
if (isPrefix) {
// Renaming a prefix (e.g., "rdf" in "rdf:type")
// Find all occurrences of "prefix:" pattern
const prefixPattern = new RegExp(`\\b${this.escapeRegEx(word)}:`, 'g');
let match;
while ((match = prefixPattern.exec(text)) !== null) {
const startPos = document.positionAt(match.index);
const endPos = document.positionAt(match.index + word.length);
edits.replace(document.uri, new vscode.Range(startPos, endPos), newName);
}
} else if (isLocalName) {
// Renaming a local name (e.g., "type" in "rdf:type")
// Find the prefix before the colon
const prefixMatch = lineText.substring(0, wordRange.start.character - 1).match(/([a-zA-Z_][a-zA-Z0-9_]*)$/);
const prefix = prefixMatch ? prefixMatch[1] : '';
Eif (prefix) {
// Find all occurrences of "prefix:localname" pattern
const localNamePattern = new RegExp(`\\b${this.escapeRegEx(prefix)}:${this.escapeRegEx(word)}\\b`, 'g');
let match;
while ((match = localNamePattern.exec(text)) !== null) {
const localNameStart = match.index + prefix.length + 1; // +1 for the colon
const startPos = document.positionAt(localNameStart);
const endPos = document.positionAt(localNameStart + word.length);
edits.replace(document.uri, new vscode.Range(startPos, endPos), newName);
}
}
} else {
// Renaming a regular identifier (relation or variable)
// Use word boundary to match whole words only
const identifierPattern = new RegExp(`\\b${this.escapeRegEx(word)}\\b`, 'g');
let match;
while ((match = identifierPattern.exec(text)) !== null) {
// Skip if this is part of a prefixed name
const charBeforeMatch = match.index > 0 ? text[match.index - 1] : '';
const charAfterMatch = match.index + word.length < text.length ? text[match.index + word.length] : '';
if (charBeforeMatch === ':' || charAfterMatch === ':') {
continue;
}
const startPos = document.positionAt(match.index);
const endPos = document.positionAt(match.index + word.length);
edits.replace(document.uri, new vscode.Range(startPos, endPos), newName);
}
}
return edits;
}
/**
* Escapes special regex characters in a string.
*/
private escapeRegEx(string: string): string {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
}
|