Skip to content

Commit

Permalink
Check structure health befor range-format
Browse files Browse the repository at this point in the history
  • Loading branch information
PEZ committed Nov 21, 2021
1 parent de643b4 commit 6e756d7
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 21 deletions.
6 changes: 0 additions & 6 deletions src/calva-fmt/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,5 @@ function _updateConfig(): FormatConfig {
export function onConfigurationChanged(e: vscode.ConfigurationChangeEvent) {
if (e.affectsConfiguration("calva.fmt")) {
updateConfig();
if (e.affectsConfiguration("calva.fmt.experimental.inferParensAsYouType")) {
const parinferOn = getConfig()['infer-parens-as-you-type'];
docMirror.getDocuments().forEach((doc: docMirror.MirroredDocument, _key: any) => {
doc.model.performInferParens = parinferOn;
});
}
}
}
46 changes: 45 additions & 1 deletion src/cursor-doc/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,6 @@ export interface EditableModel {
*/
edit: (edits: ModelEdit[], options: ModelEditOptions) => Thenable<boolean>;
parinferReadiness: parinfer.ParinferReadiness,
performInferParens: boolean;
isWritable: boolean;
getText: (start: number, end: number, mustBeWithin?: boolean) => string;
getLineText: (line: number) => string;
Expand Down Expand Up @@ -487,3 +486,48 @@ export class LineInputModel implements EditableModel {
}


export class StringDocument implements EditableDocument {
constructor(contents: string) {
this.insertString(contents);
}

selectionLeft: number;
selectionRight: number;

get selection() {
return new ModelEditSelection(this.selectionLeft, this.selectionRight);
}

set selection(sel: ModelEditSelection) {
this.selectionLeft = sel.anchor;
this.selectionRight = sel.active;
}

model: LineInputModel = new LineInputModel(1, this);

selectionStack: ModelEditSelection[] = [];

getTokenCursor(offset?: number, previous?: boolean): LispTokenCursor {
return this.model.getTokenCursor(offset);
};

insertString(text: string) {
this.model.insertString(0, text);
};

getSelectionText: () => string;

delete() {
const p = this.selectionLeft;
return this.model.edit([
new ModelEdit('deleteRange', [p, 1])
], { selection: new ModelEditSelection(p) });
};

backspace() {
const p = this.selectionLeft;
return this.model.edit([
new ModelEdit('deleteRange', [p - 1, 1])
], { selection: new ModelEditSelection(p - 1) });
};
}
28 changes: 16 additions & 12 deletions src/doc-mirror/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as vscode from "vscode"
import * as utilities from '../utilities';
import * as formatter from '../calva-fmt/src/format';
import { LispTokenCursor } from "../cursor-doc/token-cursor";
import { ModelEdit, EditableDocument, EditableModel, ModelEditOptions, LineInputModel, ModelEditSelection } from "../cursor-doc/model";
import { ModelEdit, EditableDocument, EditableModel, ModelEditOptions, LineInputModel, ModelEditSelection, StringDocument } from "../cursor-doc/model";
import * as parinfer from "../calva-fmt/src/infer";
import * as formatConfig from '../calva-fmt/src/config';
import statusbar from '../statusbar';
Expand All @@ -29,8 +29,6 @@ export class DocumentModel implements EditableModel {
this._parinferReadiness = readiness;
}

performInferParens = formatConfig.getConfig()["infer-parens-as-you-type"];

isWritable = false;

constructor(private document: MirroredDocument) {
Expand All @@ -43,9 +41,6 @@ export class DocumentModel implements EditableModel {
const undoStopBefore = !!options.undoStopBefore;
return editor.edit(builder => {
for (const modelEdit of modelEdits) {
if (!options.performInferParens) {
this.document.model.performInferParens = false;
}
switch (modelEdit.editFn) {
case 'insertString':
this.insertEdit.apply(this, [builder, ...modelEdit.args]);
Expand Down Expand Up @@ -116,6 +111,9 @@ export class DocumentModel implements EditableModel {
export class MirroredDocument implements EditableDocument {
constructor(public document: vscode.TextDocument) { }

parensInferred = false;
rangeFormatted = false;

get selectionLeft(): number {
return this.document.offsetAt(vscode.window.activeTextEditor.selection.anchor);
}
Expand Down Expand Up @@ -180,7 +178,7 @@ function processChanges(event: vscode.TextDocumentChangeEvent) {
const parinferOn = formatConfig.getConfig()["infer-parens-as-you-type"];
const formatAsYouTypeOn = formatConfig.getConfig()["format-as-you-type"];
const performFormatAsYouType = formatAsYouTypeOn && event.reason != vscode.TextDocumentChangeReason.Undo;
const performInferParens = parinferOn && event.reason != vscode.TextDocumentChangeReason.Undo && model.performInferParens;
const performInferParens = parinferOn && event.reason != vscode.TextDocumentChangeReason.Undo && !mirroredDoc.parensInferred;
let performHealthCheck = !performFormatAsYouType;
const edits: ModelEdit[] = event.contentChanges.map(change => {
// vscode may have a \r\n marker, so it's line offsets are all wrong.
Expand All @@ -192,20 +190,27 @@ function processChanges(event: vscode.TextDocumentChangeEvent) {
performInferParens: !vscode.TextDocumentChangeReason.Undo
}).then(async _v => {
if (event.document === vscode.window.activeTextEditor?.document) {
if (performFormatAsYouType) {
if (performFormatAsYouType && !mirroredDoc.rangeFormatted) {
if (event.contentChanges.length === 1 && event.contentChanges[0].text.match(/[\[\](){}]/)) {
const change = event.contentChanges[0];
const start = event.document.offsetAt(change.range.start);
const formatForwardIndex = formatter.indexForFormatForward(mirroredDoc);
const end = formatForwardIndex !== mirroredDoc.selection.active ? formatForwardIndex + 1 : mirroredDoc.selection.active;
await formatter.formatRangeEditableDoc(mirroredDoc, [start, end], true);
const checkDoc = new StringDocument(mirroredDoc.model.getText(start, end));
if (parinfer.getParinferReadiness(checkDoc).isStructureHealthy) {
await formatter.formatRangeEditableDoc(mirroredDoc, [start, end], true);
} else {
await formatter.formatForward(mirroredDoc);
}
mirroredDoc.rangeFormatted = true;
} else {
await formatter.formatForward(mirroredDoc);
}
performHealthCheck = true;
}
if ((mirroredDoc.model.parinferReadiness.isIndentationHealthy || performHealthCheck) && performInferParens) {
await parinfer.inferParens(mirroredDoc);
mirroredDoc.parensInferred = true;
}
if (!performFormatAsYouType) {
performHealthCheck = true;
Expand All @@ -216,9 +221,8 @@ function processChanges(event: vscode.TextDocumentChangeEvent) {
statusBar.update(vscode.window.activeTextEditor?.document);
}
});
if (event.contentChanges.length > 0) {
model.performInferParens = formatConfig.getConfig()["infer-parens-as-you-type"];
}
mirroredDoc.parensInferred = false;
mirroredDoc.rangeFormatted = false;
model.lineInputModel.flushChanges()

// we must clear out the repaint cache data, since we don't use it.
Expand Down
2 changes: 0 additions & 2 deletions src/extension-test/unit/common/mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import { LispTokenCursor } from '../../../cursor-doc/token-cursor'
model.initScanner(20000);

export class MockDocument implements model.EditableDocument {
isIndentationHealthy = true;
isStructureHealthy = true;
selectionLeft: number;
selectionRight: number;

Expand Down

0 comments on commit 6e756d7

Please sign in to comment.