@imc-trading/svlangserver
Version:
A language server for systemverilog
272 lines (271 loc) • 8.63 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.tmpFileManager = exports.ChildProcManager = exports.DelayedCaller = exports.childProcessStderrRedir = exports.childProcessStdoutRedir = exports.ConnectionLogger = exports.isStringListEqual = exports.getTmpDirSync = exports.resolvedPath = exports.pathToUri = exports.uriToPath = exports.fsUnlinkSync = exports.fsWriteFileSync = exports.fsWriteFile = exports.fsExists = exports.fsReadFileSync = exports.fsReadFile = void 0;
const node_1 = require("vscode-languageserver/node");
const vscode_uri_1 = require("vscode-uri");
const child = require("child_process");
const fs = require('fs');
const path = require('path');
const util = require('util');
const tmp = require('tmp');
const fsMkDir = util.promisify(fs.mkdir);
const _fsWriteFile = util.promisify(fs.writeFile);
exports.fsReadFile = util.promisify(fs.readFile);
exports.fsReadFileSync = fs.readFileSync;
exports.fsExists = util.promisify(fs.exists);
async function fsWriteFile(file, content) {
try {
return fsMkDir(path.dirname(file), { recursive: true })
.then(() => { return _fsWriteFile(file, content); })
.catch(error => { ConnectionLogger.error(error); });
}
catch (error) {
ConnectionLogger.error(error);
}
}
exports.fsWriteFile = fsWriteFile;
function fsWriteFileSync(file, content) {
try {
fs.mkdirSync(path.dirname(file), { recursive: true });
fs.writeFileSync(file, content);
return true;
}
catch (error) {
ConnectionLogger.error(error);
return false;
}
}
exports.fsWriteFileSync = fsWriteFileSync;
function fsUnlinkSync(file) {
try {
fs.unlinkSync(file);
return true;
}
catch (error) {
ConnectionLogger.error(error);
return false;
}
}
exports.fsUnlinkSync = fsUnlinkSync;
function uriToPath(uri) {
try {
let fsPath = vscode_uri_1.URI.parse(uri).fsPath;
try {
return fs.realpathSync(fsPath);
}
catch (error) {
ConnectionLogger.error(error);
return fsPath;
}
}
catch (error) {
ConnectionLogger.error(error);
return undefined;
}
}
exports.uriToPath = uriToPath;
;
function pathToUri(path) {
try {
return (vscode_uri_1.URI.file(path).toString());
}
catch (error) {
ConnectionLogger.error(error);
return undefined;
}
}
exports.pathToUri = pathToUri;
function resolvedPath(file) {
try {
return path.resolve(__dirname, file);
}
catch (error) {
ConnectionLogger.error(error);
return undefined;
}
}
exports.resolvedPath = resolvedPath;
function getTmpDirSync() {
try {
return tmp.dirSync({ unsafeCleanup: true });
}
catch (error) {
ConnectionLogger.error(error);
return undefined;
}
}
exports.getTmpDirSync = getTmpDirSync;
function isStringListEqual(stringList1, stringList2) {
try {
if ((stringList1 == undefined) && (stringList2 == undefined)) {
return true;
}
else if (stringList1 == undefined) {
return false;
}
else if (stringList2 == undefined) {
return false;
}
else if (stringList1.length != stringList2.length) {
return false;
}
let sortedStringList1 = stringList1.sort((one, two) => (one > two ? -1 : 1));
let sortedStringList2 = stringList1.sort((one, two) => (one > two ? -1 : 1));
for (let i = 0; i < stringList1.length; i++) {
if (sortedStringList1[i] != sortedStringList2[i]) {
return false;
}
}
return true;
}
catch (error) {
ConnectionLogger.error(error);
return false;
}
}
exports.isStringListEqual = isStringListEqual;
class ConnectionLogger {
static sendNotification(type, message) {
if (!ConnectionLogger._connection) {
switch (type) {
case node_1.MessageType.Error: {
console.error(message);
break;
}
default: {
console.log(message);
break;
}
}
}
else {
try {
ConnectionLogger._connection.sendNotification(node_1.LogMessageNotification.type, { type: type, message: message });
}
catch (error) {
console.error(error);
}
}
}
static setConnection(connection) {
ConnectionLogger._connection = connection;
}
static log(message, prefix = true) {
ConnectionLogger.sendNotification(node_1.MessageType.Log, `${prefix ? "INFO: " : ""}${message}`);
}
static warn(message, prefix = true) {
ConnectionLogger.sendNotification(node_1.MessageType.Warning, `${prefix ? "WARNING: " : ""}${message}`);
}
static error(message, prefix = true) {
ConnectionLogger.sendNotification(node_1.MessageType.Error, `${prefix ? "ERROR: " : ""}${message}`);
}
}
exports.ConnectionLogger = ConnectionLogger;
ConnectionLogger._connection = null;
function childProcessStdoutRedir(data) {
try {
let message = data.toString();
if (message.startsWith("WARNING: ")) {
ConnectionLogger.warn(message, false);
}
else {
ConnectionLogger.log(message, false);
}
}
catch (error) {
ConnectionLogger.error(error, false);
return;
}
}
exports.childProcessStdoutRedir = childProcessStdoutRedir;
function childProcessStderrRedir(data) {
try {
let message = data.toString();
ConnectionLogger.error(message, false);
}
catch (error) {
ConnectionLogger.error(error, false);
return;
}
}
exports.childProcessStderrRedir = childProcessStderrRedir;
class DelayedCaller {
constructor(timeOut = 1000) {
this._callWaiting = new Map();
this._timeOut = timeOut;
}
run(callName, successCallback, errorCallback) {
if (this._callWaiting.has(callName)) {
let [waitTimer, resolver] = this._callWaiting.get(callName);
clearTimeout(waitTimer);
resolver(false);
}
return new Promise(resolve => {
this._callWaiting.set(callName, [setTimeout(resolve, this._timeOut, true), resolve]);
}).then((success) => {
if (!!success) {
this._callWaiting.delete(callName);
}
return successCallback(!!success);
}).catch(error => {
return errorCallback(error);
});
}
}
exports.DelayedCaller = DelayedCaller;
class ChildProcManager {
constructor() {
this._alreadyRunning = new Map();
}
kill(key) {
if (this._alreadyRunning.has(key)) {
//ConnectionLogger.log(`DEBUG: Killing already running command to start a new one`);
let [proc, statusRef] = this._alreadyRunning.get(key);
statusRef[0] = false;
proc.kill();
}
}
run(key, command, callBack) {
let statusRef = [true];
this._alreadyRunning.set(key, [
child.exec(command, (error, stdout, stderr) => {
if (statusRef[0]) {
this._alreadyRunning.delete(key);
}
callBack(statusRef[0], error, stdout, stderr);
}),
statusRef
]);
}
}
exports.ChildProcManager = ChildProcManager;
class TmpFileManager {
constructor() {
this._freeTmpFileNums = new Map();
this._tmpDir = getTmpDirSync();
}
getTmpFilePath(...elems) {
return path.join(this._tmpDir.name, ...elems);
}
cleanupTmpFiles() {
this._tmpDir.removeCallback();
}
getFreeTmpFileNum(key) {
if (!this._freeTmpFileNums.has(key)) {
this._freeTmpFileNums.set(key, { total: 0, nums: [] });
}
if (this._freeTmpFileNums.get(key).nums.length <= 0) {
this._freeTmpFileNums.get(key).nums.push(this._freeTmpFileNums.get(key).total++);
}
return this._freeTmpFileNums.get(key).nums.shift();
}
returnFreeTmpFileNum(key, tmpFileNum) {
if (this._freeTmpFileNums.has(key)) {
this._freeTmpFileNums.get(key).nums.push(tmpFileNum);
}
else {
ConnectionLogger.error(`FreeTmpFileNums doesn't have the key ${key}`);
}
}
}
exports.tmpFileManager = new TmpFileManager();