def build_from_string(self, source, from_file=False): """Index from given string instead of using saved file (for real time completion).""" if not self.external: if from_file: logging.info(f"building module {self.name} from file.") else: logging.info(f"building module {self.name} from buffer.") try: module_ast = ast.parse(source, self.name) # We erase everything ONLY if the file is valid! self.scope = [] # That means we have to rebind import... self.imports = [] self.imports_from = [] self.visit_date = datetime.datetime.now() module_scope = Scope(indent_level=0, indent_level_id=0, name=self.name, lineno=0) self.scope.append(module_scope) indent_table = {0: 0} self.build_helper(module_scope, module_ast, indent_table) except SyntaxError: logging.warn(f"Couldn't parse {self.name} (Invalid Syntax)") except Exception as error: logging.error(str(error))
def bf_initialize(self, params: InitializeParams): """Called when the Language Server starts. Start Reference Server for given projects.""" if not params.rootPath and not params.rootUri: logging.error( "Language Client might have a problem! rootPath or rootUri is required." ) exit(1) rootPath = str(params.rootUri) if not rootPath: rootPath = str(params.rootPath) rootPath = urlparse(rootPath).path logging.info(f"Workspace path is {rootPath}") projectManager = ProjectManager() self.project = projectManager.lsp_add_workspace(rootPath) if not self.project: logging.error("Couldn't load workspace.") exit(1) logging.info("Ponthon Language Server initialized.") return super().bf_initialize(params)
def module(self): if self._module: return self._module module = self.server_context.project.get_module( self.get_document_path()) if not module: logging.error( f"Module at {self.get_document_path()} is not registered!") self._module = module return self._module
def get_scope_from_lineno(self, lineno): """Return Scope from this Module matching given line number.""" try: good_scope = self.scope[0] except IndexError: if len(self.scope) == 0: logging.error("Scope can't be empty! What the f**k?!") return Scope() for scope in self.scope: if scope.lineno > good_scope.lineno and scope.lineno <= lineno: good_scope = scope return good_scope
def get_context(self): """Return context for given symbol in given context. Context can be a Type or a Module.""" symbol_chain = self.split_completion_object(self.get_word_before()) current_rs_object = self.module for symbol in symbol_chain: try: current_rs_object = current_rs_object.get_object(symbol) logging.info(f"New context found: {current_rs_object.name}") except: logging.error( f"{type(current_rs_object)} has no method get_object yet.") return current_rs_object return current_rs_object
def build(self): """Index all scopes and imports within module.""" module_path = Path(self.path) module_name = self.name if module_path.is_dir(): module_path = module_path.joinpath("__init__.py") try: with open(str(module_path), "r") as file: module_text = file.read() self.build_from_string(module_text, True) except: logging.error( f"Couldn't read file {module_name} (codec error), skipping.") self.build_from_string("", True)
def complete_dot(self): """Check type of word before (Object or Module ?) and give completions accordingly.""" symbol_chain = self.split_completion_object(self.get_word_before()) if len(symbol_chain) > 2: logging.error("Can't complete complex chain object yet!") return [] else: new_context = self.get_context(self.module, symbol_chain[0]) if not new_context: logging.error( f"Can't complete without valid context. {symbol_chain[0]} doesn't point to a valid object in {self.module.name} context." ) return [] new_context.complete logging.info("Context found!")