Skip to content

Commit

Permalink
⚡ Add tree-sitter-query
Browse files Browse the repository at this point in the history
  • Loading branch information
Freed-Wu committed Oct 30, 2023
1 parent 1d21783 commit 2bc1942
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 36 deletions.
27 changes: 27 additions & 0 deletions src/autotools_language_server/assets/queries/define.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
(define_directive
name: (word) @function.def
) @function

(variable_assignment
name: (word) @variable.def
) @variable

(rule
(targets
(word) @rule.def
)
normal: (prerequisites
(word) @rule.call
)
) @rule

(function_call
(arguments
argument: (text) @function.arg
)
)

(variable_reference
(word) @variable.call
)
; ex: filetype=query
7 changes: 7 additions & 0 deletions src/autotools_language_server/assets/queries/include.scm
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
(
(include_directive
filenames: (list (word) @path)
) @include
(#match? @include "^include")
)
; ex: filetype=query
96 changes: 60 additions & 36 deletions src/autotools_language_server/finders.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,74 @@
from lsprotocol.types import DiagnosticSeverity
from tree_sitter import Node, Tree
from tree_sitter_languages import get_parser
from tree_sitter_lsp import UNI, Finder
from tree_sitter_lsp.finders import ErrorFinder, MissingFinder, RepeatedFinder
from tree_sitter_lsp import UNI
from tree_sitter_lsp.finders import (
ErrorQueryFinder,
QueryFinder,
RepeatedFinder,
)

from .utils import get_query

@dataclass
class InvalidPathFinder(Finder):
r"""Invalidpathfinder."""

message: str = "{{uni.get_text()}}: no such file"
severity: DiagnosticSeverity = DiagnosticSeverity.Error
@dataclass(init=False)
class ErrorMakeFinder(ErrorQueryFinder):
r"""Errormakefinder."""

def __init__(
self,
message: str = "{{uni.get_text()}}: error",
severity: DiagnosticSeverity = DiagnosticSeverity.Error,
) -> None:
r"""Init.
@staticmethod
def get_option(uni: UNI) -> str:
r"""Get option.
:param filetype:
:type filetype: str
:param message:
:type message: str
:param severity:
:type severity: DiagnosticSeverity
:rtype: None
"""
super().__init__("make", message, severity)

:param uni:
:type uni: UNI
:rtype: str

@dataclass(init=False)
class InvalidPathFinder(QueryFinder):
r"""Invalidpathfinder."""

def __init__(
self,
message: str = "{{uni.get_text()}}: no such file",
severity: DiagnosticSeverity = DiagnosticSeverity.Error,
) -> None:
r"""Init.
:param message:
:type message: str
:param severity:
:type severity: DiagnosticSeverity
:rtype: None
"""
option = ""
if parent := uni.node.parent:
if children := getattr(parent.parent, "children", None):
if parent.parent == "include_directive" and len(children) > 0:
option = children[0].type
return option
query = get_query("include")
super().__init__(query, message, severity)

def __call__(self, uni: UNI) -> bool:
r"""Call.
def capture2uni(self, capture: tuple[Node, str], uri: str) -> UNI | None:
r"""Capture2uni.
:param uni:
:type uni: UNI
:rtype: bool
:param capture:
:type capture: tuple[Node, str]
:param uri:
:type uri: str
:rtype: UNI | None
"""
path = self.uni2path(uni)
option = self.get_option(uni)
if parent := uni.node.parent:
return (
uni.node.type == "word"
and parent.type == "list"
and option == "include"
and not os.path.isfile(path)
)
return False
node, label = capture
uni = UNI(uri, node)
return (
uni
if label == "path" and not os.path.isfile(self.uni2path(uni))
else None
)


@dataclass
Expand Down Expand Up @@ -302,8 +327,7 @@ def __call__(self, uni: UNI) -> bool:


DIAGNOSTICS_FINDER_CLASSES = [
ErrorFinder,
MissingFinder,
ErrorMakeFinder,
InvalidPathFinder,
RepeatedTargetFinder,
]
29 changes: 29 additions & 0 deletions src/autotools_language_server/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,38 @@
import os
from typing import Any, Literal

from tree_sitter.binding import Query
from tree_sitter_languages import get_language

from . import FILETYPE

SCHEMAS = {}
QUERIES = {}


def get_query(name: str, filetype: FILETYPE = "make") -> Query:
r"""Get query.
:param name:
:type name: str
:param filetype:
:type filetype: FILETYPE
:rtype: Query
"""
if name not in QUERIES:
with open(
os.path.join(
os.path.join(
os.path.join(os.path.dirname(__file__), "assets"),
"queries",
),
f"{name}{os.path.extsep}scm",
)
) as f:
text = f.read()
language = get_language(filetype)
QUERIES[name] = language.query(text)
return QUERIES[name]


def get_schema(filetype: FILETYPE) -> dict[str, Any]:
Expand Down

0 comments on commit 2bc1942

Please sign in to comment.