astro-ghostcms/.pnpm-store/v3/files/d1/68cf2bff797824069eae892ddfc...

274 lines
14 KiB
Plaintext

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.register = void 0;
const language_core_1 = require("@volar/language-core");
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument");
const documents_1 = require("../documents");
const cancellation_1 = require("../utils/cancellation");
const common_1 = require("../utils/common");
const featureWorkers_1 = require("../utils/featureWorkers");
function register(context) {
let fakeVersion = 0;
return async (uri, options, range, onTypeParams, token = cancellation_1.NoneCancellationToken) => {
const sourceFile = context.language.files.get(uri);
if (!sourceFile) {
return;
}
let document = context.documents.get(uri, sourceFile.languageId, sourceFile.snapshot);
range ??= {
start: document.positionAt(0),
end: document.positionAt(document.getText().length),
};
if (!sourceFile.generated) {
return onTypeParams
? (await tryFormat(document, onTypeParams.position, onTypeParams.ch))?.edits
: (await tryFormat(document, range, undefined))?.edits;
}
const initialIndentLanguageId = await context.env.getConfiguration?.('volar.format.initialIndent') ?? { html: true };
let tempSourceSnapshot = sourceFile.snapshot;
let tempVirtualFile = sourceFile.generated.languagePlugin.createVirtualCode(uri, sourceFile.languageId, sourceFile.snapshot, context.language.files);
const originalDocument = document;
let level = 0;
while (true) {
const embeddedCodes = (0, featureWorkers_1.getEmbeddedFilesByLevel)(context, sourceFile.id, tempVirtualFile, level++);
if (embeddedCodes.length === 0) {
break;
}
let edits = [];
const toPatchIndent = [];
for (const code of embeddedCodes) {
if (!code.mappings.some(mapping => (0, language_core_1.isFormattingEnabled)(mapping.data))) {
continue;
}
const isCodeBlock = code.mappings.length === 1
&& code.mappings[0].sourceOffsets.length === 1
&& code.mappings[0].generatedOffsets[0] === 0
&& code.mappings[0].lengths[0] === code.snapshot.getLength();
if (onTypeParams && !isCodeBlock) {
continue;
}
const docMap = createDocMap(code, uri, sourceFile.languageId, tempSourceSnapshot);
if (!docMap) {
continue;
}
let embeddedCodeResult;
if (onTypeParams) {
const embeddedPosition = docMap.getGeneratedPosition(onTypeParams.position);
if (embeddedPosition) {
embeddedCodeResult = await tryFormat(docMap.virtualFileDocument, embeddedPosition, onTypeParams.ch);
}
}
else {
embeddedCodeResult = await tryFormat(docMap.virtualFileDocument, {
start: docMap.virtualFileDocument.positionAt(0),
end: docMap.virtualFileDocument.positionAt(docMap.virtualFileDocument.getText().length),
});
}
if (!embeddedCodeResult) {
continue;
}
toPatchIndent.push({
virtualCodeId: code.id,
isCodeBlock,
service: embeddedCodeResult.service[1],
});
for (const textEdit of embeddedCodeResult.edits) {
const range = docMap.getSourceRange(textEdit.range);
if (range) {
edits.push({
newText: textEdit.newText,
range,
});
}
}
}
edits = edits.filter(edit => (0, common_1.isInsideRange)(range, edit.range));
if (edits.length > 0) {
const newText = vscode_languageserver_textdocument_1.TextDocument.applyEdits(document, edits);
document = vscode_languageserver_textdocument_1.TextDocument.create(document.uri, document.languageId, document.version + 1, newText);
tempSourceSnapshot = (0, common_1.stringToSnapshot)(newText);
tempVirtualFile = sourceFile.generated.languagePlugin.updateVirtualCode(uri, tempVirtualFile, tempSourceSnapshot, context.language.files);
}
if (level > 1) {
const baseIndent = options.insertSpaces ? ' '.repeat(options.tabSize) : '\t';
const editLines = new Set();
if (onTypeParams) {
for (const edit of edits) {
for (let line = edit.range.start.line; line <= edit.range.end.line; line++) {
editLines.add(line);
}
}
}
for (const item of toPatchIndent) {
let virtualCode;
for (const file of (0, language_core_1.forEachEmbeddedCode)(tempVirtualFile)) {
if (file.id === item.virtualCodeId) {
virtualCode = file;
break;
}
}
const docMap = createDocMap(virtualCode, uri, sourceFile.languageId, tempSourceSnapshot);
if (!docMap) {
continue;
}
const indentSensitiveLines = new Set();
for (const service of item.service.provideFormattingIndentSensitiveLines ? [item.service] : context.services.map(service => service[1])) {
if (token.isCancellationRequested) {
break;
}
if (service.provideFormattingIndentSensitiveLines) {
const lines = await service.provideFormattingIndentSensitiveLines(docMap.virtualFileDocument, token);
if (lines) {
for (const line of lines) {
const sourceLine = docMap.getSourcePosition({ line: line, character: 0 })?.line;
if (sourceLine !== undefined) {
indentSensitiveLines.add(sourceLine);
}
}
}
}
}
let indentEdits = patchIndents(document, item.isCodeBlock, docMap.map, initialIndentLanguageId[docMap.virtualFileDocument.languageId] ? baseIndent : '');
indentEdits = indentEdits.filter(edit => {
for (let line = edit.range.start.line; line <= edit.range.end.line; line++) {
if (indentSensitiveLines.has(line) && !edit.newText.includes('\n')) {
return false;
}
if (onTypeParams && !editLines.has(line)) {
return false;
}
if (!(0, common_1.isInsideRange)(range, edit.range)) {
return false;
}
}
return true;
});
if (indentEdits.length > 0) {
const newText = vscode_languageserver_textdocument_1.TextDocument.applyEdits(document, indentEdits);
document = vscode_languageserver_textdocument_1.TextDocument.create(document.uri, document.languageId, document.version + 1, newText);
tempSourceSnapshot = (0, common_1.stringToSnapshot)(newText);
tempVirtualFile = sourceFile.generated.languagePlugin.updateVirtualCode(uri, tempVirtualFile, tempSourceSnapshot, context.language.files);
}
}
}
}
if (document.getText() === originalDocument.getText()) {
return;
}
const editRange = {
start: originalDocument.positionAt(0),
end: originalDocument.positionAt(originalDocument.getText().length),
};
const textEdit = {
range: editRange,
newText: document.getText(),
};
return [textEdit];
async function tryFormat(document, range, ch) {
let formatRange = range;
for (const service of context.services) {
if (context.disabledServicePlugins.has(service[1])) {
continue;
}
if (token.isCancellationRequested) {
break;
}
let edits;
try {
if (ch !== undefined && 'line' in formatRange && 'character' in formatRange) {
if (service[0].autoFormatTriggerCharacters?.includes(ch)) {
edits = await service[1].provideOnTypeFormattingEdits?.(document, formatRange, ch, options, token);
}
}
else if (ch === undefined && 'start' in formatRange && 'end' in formatRange) {
edits = await service[1].provideDocumentFormattingEdits?.(document, formatRange, options, token);
}
}
catch (err) {
console.warn(err);
}
if (!edits) {
continue;
}
return {
service,
edits,
};
}
}
};
function createDocMap(file, sourceFileUri, sourceLanguageId, _sourceSnapshot) {
const maps = (0, language_core_1.updateVirtualCodeMaps)(file, sourceFileUri2 => {
if (!sourceFileUri2) {
return [sourceFileUri, _sourceSnapshot];
}
});
if (maps.has(sourceFileUri) && maps.get(sourceFileUri)[0] === _sourceSnapshot) {
const map = maps.get(sourceFileUri);
const version = fakeVersion++;
return new documents_1.SourceMapWithDocuments(vscode_languageserver_textdocument_1.TextDocument.create(sourceFileUri, sourceLanguageId ?? (0, language_core_1.resolveCommonLanguageId)(sourceFileUri), version, _sourceSnapshot.getText(0, _sourceSnapshot.getLength())), vscode_languageserver_textdocument_1.TextDocument.create(context.documents.getVirtualCodeUri(sourceFileUri, file.id), file.languageId, version, file.snapshot.getText(0, file.snapshot.getLength())), map[1]);
}
}
}
exports.register = register;
function patchIndents(document, isCodeBlock, map, initialIndent) {
const indentTextEdits = [];
if (!isCodeBlock) {
initialIndent = '';
}
for (let i = 0; i < map.mappings.length; i++) {
const mapping = map.mappings[i];
for (let j = 0; j < mapping.sourceOffsets.length; j++) {
const firstLineIndent = getBaseIndent(mapping.sourceOffsets[j]);
const text = document.getText().substring(mapping.sourceOffsets[j], mapping.sourceOffsets[j] + mapping.lengths[j]);
const lines = text.split('\n');
const baseIndent = firstLineIndent + initialIndent;
let lineOffset = lines[0].length + 1;
let insertedFinalNewLine = false;
if (!text.trim()) {
continue;
}
if (isCodeBlock && text.trimStart().length === text.length) {
indentTextEdits.push({
newText: '\n' + baseIndent,
range: {
start: document.positionAt(mapping.sourceOffsets[j]),
end: document.positionAt(mapping.sourceOffsets[j]),
},
});
}
if (isCodeBlock && text.trimEnd().length === text.length) {
indentTextEdits.push({
newText: '\n',
range: {
start: document.positionAt(mapping.sourceOffsets[j] + mapping.lengths[j]),
end: document.positionAt(mapping.sourceOffsets[j] + mapping.lengths[j]),
},
});
insertedFinalNewLine = true;
}
if (baseIndent && lines.length > 1) {
for (let i = 1; i < lines.length; i++) {
if (lines[i].trim() || i === lines.length - 1) {
const isLastLine = i === lines.length - 1 && !insertedFinalNewLine;
indentTextEdits.push({
newText: isLastLine ? firstLineIndent : baseIndent,
range: {
start: document.positionAt(mapping.sourceOffsets[j] + lineOffset),
end: document.positionAt(mapping.sourceOffsets[j] + lineOffset),
},
});
}
lineOffset += lines[i].length + 1;
}
}
}
}
return indentTextEdits;
function getBaseIndent(pos) {
const startPos = document.positionAt(pos);
const startLineText = document.getText({ start: { line: startPos.line, character: 0 }, end: startPos });
return startLineText.substring(0, startLineText.length - startLineText.trimStart().length);
}
}
//# sourceMappingURL=provideDocumentFormattingEdits.js.map