This repository has been archived by the owner on Jul 10, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
server.ts
executable file
·141 lines (125 loc) · 5.47 KB
/
server.ts
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
133
134
135
136
137
138
139
140
141
'use strict';
import {
createConnection, TextDocuments, ProposedFeatures, TextDocumentSyncKind,
Diagnostic, DiagnosticSeverity, TextDocument
} from 'vscode-languageserver';
import { glob } from 'glob';
import * as fs from 'fs';
import * as path from 'path';
import fileUriToPath from './fileUriToPath';
import { TemplateLogic } from '@accordproject/ergo-compiler';
import { ModelFile } from 'composer-concerto';
// Creates the LSP connection
let connection = createConnection(ProposedFeatures.all);
// Create a manager for open text documents
let documents = new TextDocuments();
// Cache the modelManager instances for each document
let templateLogics = {};
// The workspace folder this server is operating on
let workspaceFolder: string;
documents.onDidOpen((event) => {
connection.console.log(`[Server(${process.pid}) ${workspaceFolder}] Document opened: ${event.document.uri}`);
})
documents.listen(connection);
connection.onInitialize((params) => {
workspaceFolder = params.rootUri;
connection.console.log(`[Server(${process.pid}) ${workspaceFolder}] Started and initialize received`);
return {
capabilities: {
textDocumentSync: {
openClose: true,
change: TextDocumentSyncKind.Full
}
}
}
});
// The content of a text document has changed. This event is emitted
// when the text document is first opened or when its content has changed.
documents.onDidChangeContent(async (change) => {
// Revalidate any open text documents
documents.all().forEach(validateTextDocument);
});
// This function is not currently triggered by changes to model files, only ergo files
async function validateTextDocument(textDocument: TextDocument): Promise<void> {
const pathStr = path.resolve(fileUriToPath(textDocument.uri));
const folder = pathStr.substring(0,pathStr.lastIndexOf("/")+1);
const parentDir = path.resolve(`${folder}../`);
let thisTemplateLogic = templateLogics[parentDir];
if(!thisTemplateLogic){
thisTemplateLogic = new TemplateLogic('cicero');
templateLogics[parentDir] = thisTemplateLogic;
}
const thisModelManager = thisTemplateLogic.getModelManager();
let diagnostics: Diagnostic[] = [];
try {
// Find all cto files in ./ relative to this file or in the parent director
// if this is a Cicero template.
let newModels = false;
const modelFiles = glob.sync(`{${folder},${parentDir}/models/}**/*.cto`);
for (const file of modelFiles) {
connection.console.log(file);
const contents = fs.readFileSync(file, 'utf8');
const modelFile: any = new ModelFile(thisModelManager, contents, file);
if (!thisModelManager.getModelFile(modelFile.getNamespace())) {
// only add if not existing
thisModelManager.addModelFile(contents, file, true);
newModels = true;
}
}
// Only pull external models if a new file was added to the model manager
if(newModels){
await thisModelManager.updateExternalModels();
}
try {
// Find all ergo files in ./ relative to this file
const ergoFiles = glob.sync(`{${folder},${parentDir}/lib/}**/*.ergo`);
for (const file of ergoFiles) {
if (file === pathStr) {
// Update the current file being edited
thisTemplateLogic.updateLogic(textDocument.getText(), pathStr);
} else {
connection.console.log(file);
const contents = fs.readFileSync(file, 'utf8');
thisTemplateLogic.updateLogic(contents, file);
}
}
const compiled = await thisTemplateLogic.compileLogic(true);
} catch (error) {
const descriptor = error.descriptor;
if(descriptor.kind === 'CompilationError' || descriptor.kind === 'TypeError' ){
const range = {
start: { line: 0, character: 0 },
end: { line: 0, character: 0 },
};
if(descriptor.locstart.line > 0) {
range.start = { line: descriptor.locstart.line-1, character: descriptor.locstart.character };
range.end = range.start;
}
if(descriptor.locend.line > 0) {
range.end = { line: descriptor.locend.line-1, character: descriptor.locend.character };
}
diagnostics.push({
severity: DiagnosticSeverity.Error,
range,
message: descriptor.message,
source: 'ergo'
});
} else {
diagnostics.push({
severity: DiagnosticSeverity.Error,
range: {
start: { line: descriptor.locstart.line-1, character: descriptor.locstart.character },
end: { line: descriptor.locend.line-1, character: descriptor.locend.character },
},
message: descriptor.message,
source: 'ergo'
});
}
}
} catch (error) {
connection.console.error(error.message);
connection.console.error(error.stack);
}
connection.sendDiagnostics({ uri: textDocument.uri, diagnostics });
}
connection.listen();