greybel-languageserver-core
Version:
Core functionality of language server for GreyScript
226 lines • 8.68 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.LookupHelper = void 0;
const miniscript_core_1 = require("miniscript-core");
const ASTScraper = __importStar(require("./ast-scraper"));
const ast_utils_1 = require("./ast-utils");
const is_valid_identifier_literal_1 = require("./is-valid-identifier-literal");
class LookupHelper {
constructor(document, context) {
this.document = document;
this.context = context;
this.mergedTypeMap = null;
}
async getTypeMap() {
if (this.mergedTypeMap == null) {
this.mergedTypeMap = await this.context.documentMerger.build(this.document, this.context);
}
return this.mergedTypeMap;
}
async findAllAssignmentsOfIdentifier(identifier, root) {
const typeDoc = await this.getTypeMap();
if (typeDoc == null) {
return [];
}
const context = typeDoc.scopeRefMapping.get(root);
if (context == null) {
return [];
}
return context.scope.resolveAllAvailableWithQuery(identifier);
}
async findAllAssignmentsOfItem(item) {
const typeDoc = await this.getTypeMap();
if (typeDoc == null) {
return null;
}
const result = typeDoc.resolveNamespace(item, false);
if (result == null) {
return null;
}
return result.item;
}
async findAllAvailableIdentifierInRoot() {
const typeDoc = await this.getTypeMap();
if (typeDoc == null) {
return new Map();
}
return typeDoc.globals.getAllProperties().reduce((result, it) => {
const sources = it.type.getSource();
result.set(it.name, {
kind: it.kind,
line: sources && sources.length > 0 ? sources[0].start.line - 1 : -1
});
return result;
}, new Map());
}
async findAllAvailableIdentifier(root) {
const typeDoc = await this.getTypeMap();
if (typeDoc == null) {
return new Map();
}
const context = typeDoc.scopeRefMapping.get(root);
if (context == null) {
return new Map();
}
return context.scope.getAllProperties().reduce((result, it) => {
const sources = it.type.getSource();
result.set(it.name, {
kind: it.kind,
line: sources && sources.length > 0 ? sources[0].start.line - 1 : -1
});
return result;
}, new Map());
}
async findAllAvailableIdentifierRelatedToPosition(item) {
const typeDoc = await this.getTypeMap();
const result = new Map();
if (typeDoc == null) {
return result;
}
const scopeContext = typeDoc.scopeRefMapping.get(item.scope);
const properties = scopeContext.scope.getAllProperties();
const alwaysVisibleProperties = [];
const locationDependendProperties = [];
for (let index = 0; index < properties.length; index++) {
const property = properties[index];
const sources = property.type.getSource();
if (property.type.document != null &&
property.type.document.name === typeDoc.name &&
sources != null &&
sources.length > 0) {
locationDependendProperties.push(property);
}
else {
alwaysVisibleProperties.push(property);
}
}
for (let index = 0; index < alwaysVisibleProperties.length; index++) {
const property = alwaysVisibleProperties[index];
result.set(property.name, {
kind: property.kind,
line: -1
});
}
locationDependendProperties.sort((a, b) => a.type.getSource()[0].start.line - b.type.getSource()[0].start.line);
for (let index = 0; index < locationDependendProperties.length; index++) {
const property = locationDependendProperties[index];
const source = property.type.getSource()[0];
if (source.start.line >= item.end.line)
break;
result.set(property.name, {
kind: property.kind,
line: source.start.line - 1
});
}
return result;
}
async lookupAST(position) {
const me = this;
const chunk = me.document.parsedPayload;
const lineItems = chunk.lines[position.line + 1];
if (!lineItems) {
return null;
}
for (let index = 0; index < lineItems.length; index++) {
const lineItem = lineItems[index];
const outer = ASTScraper.findEx((item, _level) => {
const startLine = item.start.line - 1;
const startCharacter = item.start.character - 1;
const endLine = item.end.line - 1;
const endCharacter = item.end.character - 1;
if (startLine > position.line) {
return {
exit: true
};
}
if (startLine < endLine) {
return {
valid: (position.line > startLine && position.line < endLine) ||
(position.line === startLine &&
startCharacter <= position.character) ||
(position.line === endLine && endCharacter >= position.character)
};
}
return {
valid: startLine <= position.line &&
startCharacter <= position.character &&
endLine >= position.line &&
endCharacter >= position.character
};
}, lineItem);
// get closest AST
const closest = outer.pop();
// nothing to get info for
if (!closest) {
continue;
}
return {
closest,
outer
};
}
return null;
}
async lookupBasePath(item) {
const typeDoc = await this.getTypeMap();
if (typeDoc === null) {
return null;
}
const base = (0, ast_utils_1.lookupBase)(item);
if (base) {
return typeDoc.resolveNamespace(base, true);
}
return null;
}
async lookupTypeInfo({ closest, outer }) {
const typeDoc = await this.getTypeMap();
if (typeDoc === null) {
return null;
}
const previous = outer.length > 0 ? outer[outer.length - 1] : undefined;
if (previous?.type === miniscript_core_1.ASTType.MemberExpression &&
closest === previous.identifier) {
return typeDoc.resolveNamespace(previous, false);
}
else if (previous?.type === miniscript_core_1.ASTType.IndexExpression &&
closest === previous.index &&
(0, is_valid_identifier_literal_1.isValidIdentifierLiteral)(closest)) {
return typeDoc.resolveNamespace(previous, false);
}
return typeDoc.resolveNamespace(closest, false);
}
async lookupType(position) {
const me = this;
const astResult = await me.lookupAST(position);
// nothing to get info for
if (!astResult) {
return null;
}
return me.lookupTypeInfo(astResult);
}
}
exports.LookupHelper = LookupHelper;
//# sourceMappingURL=lookup-type.js.map