Skip to content

Commit 10818d2

Browse files
author
Deep Furiya
committed
rev-2 made Indentation a property of Document
1 parent 0895918 commit 10818d2

File tree

3 files changed

+105
-116
lines changed

3 files changed

+105
-116
lines changed

src/document/Document.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
import { TextDocument, Position, Range, DocumentUri } from 'vscode-languageserver-textdocument';
2+
import { EditorSettings } from '../settings/Settings';
23
import { LoggerFactory } from '../telemetry/LoggerFactory';
34
import { extractErrorMessage } from '../utils/Errors';
45
import { detectCfnFileType } from './CloudFormationDetection';
56
import { DocumentMetadata } from './DocumentProtocol';
67
import { detectDocumentType, uriToPath } from './DocumentUtils';
78

9+
export type Indentation = {
10+
tabSize: number;
11+
detectedFromContent: boolean;
12+
};
13+
814
export class Document {
915
private readonly log = LoggerFactory.getLogger(Document);
1016
public readonly extension: Extension;
1117
public readonly documentType: DocumentType;
1218
public readonly cfnFileType: CloudFormationFileType;
1319
public readonly fileName: string;
20+
private indentation?: Indentation;
1421

1522
constructor(
1623
private readonly textDocument: TextDocument,
@@ -78,6 +85,69 @@ export class Document {
7885
lineCount: this.lineCount,
7986
};
8087
}
88+
89+
public getEditorSettings(baseSettings: EditorSettings): EditorSettings {
90+
if (!baseSettings.detectIndentation) {
91+
return baseSettings;
92+
}
93+
94+
const detectedIndentation = this.getIndentation(baseSettings);
95+
96+
return {
97+
...baseSettings,
98+
tabSize: detectedIndentation.tabSize,
99+
};
100+
}
101+
102+
private getIndentation(editorSettings: EditorSettings): Indentation {
103+
if (!editorSettings.detectIndentation) {
104+
return {
105+
tabSize: editorSettings.tabSize,
106+
detectedFromContent: false,
107+
};
108+
}
109+
110+
if (this.indentation) {
111+
return this.indentation;
112+
}
113+
114+
this.indentation = this.detectIndentationFromContent(editorSettings);
115+
return this.indentation;
116+
}
117+
118+
public clearIndentation(): void {
119+
this.indentation = undefined;
120+
}
121+
122+
private detectIndentationFromContent(fallbackSettings: EditorSettings): Indentation {
123+
const content = this.contents();
124+
const lines = content.split('\n');
125+
126+
const maxLinesToAnalyze = Math.min(lines.length, 30);
127+
128+
for (let i = 0; i < maxLinesToAnalyze; i++) {
129+
const line = lines[i];
130+
131+
if (line.trim().length === 0) {
132+
continue;
133+
}
134+
135+
const leadingSpaces = line.match(/^( *)/)?.[1]?.length ?? 0;
136+
137+
if (leadingSpaces > 0) {
138+
return {
139+
tabSize: leadingSpaces,
140+
detectedFromContent: true,
141+
};
142+
}
143+
}
144+
145+
// If no indented lines found, use fallback settings
146+
return {
147+
tabSize: fallbackSettings.tabSize,
148+
detectedFromContent: false,
149+
};
150+
}
81151
}
82152

83153
export enum DocumentType {

src/document/DocumentManager.ts

Lines changed: 35 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -8,17 +8,12 @@ import { Delayer } from '../utils/Delayer';
88
import { Document } from './Document';
99
import { DocumentMetadata } from './DocumentProtocol';
1010

11-
export type DetectedIndentation = {
12-
tabSize: number;
13-
detectedFromContent: boolean;
14-
};
15-
1611
export class DocumentManager implements Configurable {
1712
private readonly log = LoggerFactory.getLogger(DocumentManager);
1813
private readonly delayer = new Delayer(5 * 1000);
1914
private editorSettings: EditorSettings = DefaultSettings.editor;
2015
private settingsSubscription?: SettingsSubscription;
21-
private readonly documentIndentation = new Map<string, DetectedIndentation>();
16+
private readonly documentMap = new Map<string, Document>();
2217

2318
constructor(
2419
private readonly documents: TextDocuments<TextDocument>,
@@ -39,11 +34,19 @@ export class DocumentManager implements Configurable {
3934
}
4035

4136
get(uri: string) {
37+
let document = this.documentMap.get(uri);
38+
if (document) {
39+
return document;
40+
}
41+
4242
const textDocument = this.documents.get(uri);
4343
if (!textDocument) {
4444
return;
4545
}
46-
return new Document(textDocument);
46+
47+
document = new Document(textDocument);
48+
this.documentMap.set(uri, document);
49+
return document;
4750
}
4851

4952
getByName(name: string) {
@@ -53,9 +56,18 @@ export class DocumentManager implements Configurable {
5356
}
5457

5558
allDocuments() {
56-
return this.documents.all().map((doc) => {
57-
return new Document(doc);
58-
});
59+
const allDocs: Document[] = [];
60+
61+
for (const textDoc of this.documents.all()) {
62+
let document = this.documentMap.get(textDoc.uri);
63+
if (!document) {
64+
document = new Document(textDoc);
65+
this.documentMap.set(textDoc.uri, document);
66+
}
67+
allDocs.push(document);
68+
}
69+
70+
return allDocs;
5971
}
6072

6173
isTemplate(uri: string) {
@@ -83,40 +95,28 @@ export class DocumentManager implements Configurable {
8395
});
8496
}
8597

86-
/**
87-
* Get document-specific editor settings with indentation detection
88-
* @param uri Document URI
89-
* @returns Editor settings with detected indentation if enabled
90-
*/
9198
getEditorSettingsForDocument(uri: string): EditorSettings {
92-
const baseSettings = this.editorSettings;
93-
94-
if (!baseSettings.detectIndentation) {
95-
return baseSettings;
96-
}
97-
9899
const document = this.get(uri);
99-
const detectedIndentation = this.getIndentationForDocument(uri, document?.contents() ?? '', baseSettings);
100+
if (!document) {
101+
return this.editorSettings;
102+
}
100103

101-
return {
102-
...baseSettings,
103-
tabSize: detectedIndentation.tabSize,
104-
};
104+
return document.getEditorSettings(this.editorSettings);
105105
}
106106

107-
/**
108-
* Clear stored indentation for a document (called when document is closed)
109-
* @param uri Document URI
110-
*/
111107
clearIndentationForDocument(uri: string): void {
112-
this.documentIndentation.delete(uri);
108+
const document = this.documentMap.get(uri);
109+
if (document) {
110+
document.clearIndentation();
111+
this.documentMap.delete(uri);
112+
}
113113
}
114114

115-
/**
116-
* Clear all stored indentation data
117-
*/
118115
clearAllStoredIndentation(): void {
119-
this.documentIndentation.clear();
116+
for (const document of this.documentMap.values()) {
117+
document.clearIndentation();
118+
}
119+
this.documentMap.clear();
120120
}
121121

122122
private onEditorSettingsChanged(newEditorSettings: EditorSettings): void {
@@ -128,84 +128,7 @@ export class DocumentManager implements Configurable {
128128

129129
if (detectIndentationChanged) {
130130
this.clearAllStoredIndentation();
131-
132-
if (newEditorSettings.detectIndentation) {
133-
const openDocuments = this.allDocuments();
134-
135-
for (const document of openDocuments) {
136-
this.getIndentationForDocument(document.uri, document.contents(), newEditorSettings);
137-
}
138-
}
139-
}
140-
}
141-
142-
/**
143-
* Get effective indentation for a document
144-
* @param uri Document URI
145-
* @param content Document content
146-
* @param editorSettings Current editor settings
147-
* @returns Effective indentation settings for the document
148-
*/
149-
private getIndentationForDocument(
150-
uri: string,
151-
content: string,
152-
editorSettings: EditorSettings,
153-
): DetectedIndentation {
154-
// If detectIndentation is false, use configured settings
155-
if (!editorSettings.detectIndentation) {
156-
return {
157-
tabSize: editorSettings.tabSize,
158-
detectedFromContent: false,
159-
};
160131
}
161-
162-
const stored = this.documentIndentation.get(uri);
163-
if (stored) {
164-
return stored;
165-
}
166-
167-
const detected = this.detectIndentationFromContent(content, editorSettings);
168-
169-
this.documentIndentation.set(uri, detected);
170-
171-
return detected;
172-
}
173-
174-
/**
175-
* Detect indentation from document content by finding the first indented line
176-
* @param content Document content to analyze
177-
* @param fallbackSettings Fallback settings to use if detection fails
178-
* @returns Detected indentation settings
179-
*/
180-
private detectIndentationFromContent(content: string, fallbackSettings: EditorSettings): DetectedIndentation {
181-
const lines = content.split('\n');
182-
183-
const maxLinesToAnalyze = Math.min(lines.length, 30);
184-
185-
for (let i = 0; i < maxLinesToAnalyze; i++) {
186-
const line = lines[i];
187-
188-
if (line.trim().length === 0) {
189-
continue;
190-
}
191-
192-
const leadingSpaces = line.match(/^( *)/)?.[1]?.length ?? 0;
193-
194-
if (leadingSpaces > 0) {
195-
const result: DetectedIndentation = {
196-
tabSize: leadingSpaces,
197-
detectedFromContent: true,
198-
};
199-
200-
return result;
201-
}
202-
}
203-
204-
// If no indented lines found, use fallback settings
205-
return {
206-
tabSize: fallbackSettings.tabSize,
207-
detectedFromContent: false,
208-
};
209132
}
210133

211134
static create(components: ServerComponents) {

src/handlers/DocumentHandler.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ export function didOpenHandler(components: ServerComponents): (event: TextDocume
2525

2626
const content = document.contents();
2727

28-
if (components.settingsManager.getCurrentSettings().editor.detectIndentation) {
29-
components.documentManager.getEditorSettingsForDocument(uri);
30-
}
31-
3228
if (document.isTemplate()) {
3329
try {
3430
components.syntaxTreeManager.addWithTypes(uri, content, document.documentType, document.cfnFileType);

0 commit comments

Comments
 (0)