Skip to content

Commit 7a85fcf

Browse files
authored
Merge pull request #48 from fourdigits/add-goto-for-libs
Add goto support for tags and filters
2 parents 80ac161 + a451f8c commit 7a85fcf

File tree

3 files changed

+62
-12
lines changed

3 files changed

+62
-12
lines changed

djlsp/index.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ class Template:
1414
class Tag:
1515
name: str = ""
1616
docs: str = ""
17+
source: str = ""
1718
inner_tags: list[str] = ""
1819
closing_tag: str = ""
1920

@@ -22,6 +23,7 @@ class Tag:
2223
class Filter:
2324
name: str = ""
2425
docs: str = ""
26+
source: str = ""
2527

2628

2729
@dataclass
@@ -56,13 +58,15 @@ def update(self, django_data: dict):
5658
name: Filter(
5759
name=name,
5860
docs=filter_options.get("docs", ""),
61+
source=filter_options.get("source", ""),
5962
)
6063
for name, filter_options in lib_data.get("filters", {}).items()
6164
},
6265
tags={
6366
tag: Tag(
6467
name=tag,
6568
docs=tag_options.get("docs"),
69+
source=tag_options.get("source", ""),
6670
inner_tags=tag_options.get("inner_tags", []),
6771
closing_tag=tag_options.get("closing_tag"),
6872
)

djlsp/parser.py

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -360,6 +360,8 @@ def goto_definition(self, line, character):
360360
re.compile(r""".*{% ?(extends|include) ('|")([\w\-\./]*)$"""),
361361
self.get_template_definition,
362362
),
363+
(re.compile(r"^.*{% ?(\w*)$"), self.get_tag_definition),
364+
(re.compile(r"^.*({%|{{).*?\|(\w*)$"), self.get_filter_definition),
363365
(
364366
re.compile(r".*({{|{% \w+ ).*?([\w\d_\.]*)$"),
365367
self.get_context_definition,
@@ -370,24 +372,43 @@ def goto_definition(self, line, character):
370372
return definition(line, character, match)
371373
return None
372374

375+
def create_location(self, location, path, line):
376+
root_path = (
377+
self.workspace_index.src_path
378+
if location == "src"
379+
else self.workspace_index.env_path
380+
)
381+
return Location(
382+
uri=f"file://{root_path}/{path}",
383+
range=Range(
384+
start=Position(line=int(line), character=0),
385+
end=Position(line=int(line), character=0),
386+
),
387+
)
388+
373389
def get_template_definition(self, line, character, match: Match):
374390
if match_after := re.match(r'^(.*)".*', self.document.lines[line][character:]):
375391
template_name = match.group(3) + match_after.group(1)
376392
logger.debug(f"Find template goto definition for: {template_name}")
377393
if template := self.workspace_index.templates.get(template_name):
378394
location, path = template.path.split(":")
379-
root_path = (
380-
self.workspace_index.src_path
381-
if location == "src"
382-
else self.workspace_index.env_path
383-
)
384-
return Location(
385-
uri=f"file://{root_path}/{path}",
386-
range=Range(
387-
start=Position(line=0, character=0),
388-
end=Position(line=0, character=0),
389-
),
390-
)
395+
return self.create_location(location, path, 0)
396+
397+
def get_tag_definition(self, line, character, match: Match):
398+
full_match = self._get_full_definition_name(line, character, match.group(1))
399+
logger.debug(f"Find tag goto definition for: {full_match}")
400+
for lib in self.loaded_libraries:
401+
if tag := self.workspace_index.libraries[lib].tags.get(full_match):
402+
if tag.source:
403+
return self.create_location(*tag.source.split(":"))
404+
405+
def get_filter_definition(self, line, character, match: Match):
406+
full_match = self._get_full_definition_name(line, character, match.group(2))
407+
logger.debug(f"Find filter goto definition for: {full_match}")
408+
for lib in self.loaded_libraries:
409+
if filter_ := self.workspace_index.libraries[lib].filters.get(full_match):
410+
if filter_.source:
411+
return self.create_location(*filter_.source.split(":"))
391412

392413
def get_context_definition(self, line, character, match: Match):
393414
first_match = match.group(2)

djlsp/scripts/django-collector.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,29 @@ def to_json(self):
187187
indent=4,
188188
)
189189

190+
def get_source_from_type(self, type_):
191+
def unwrap(func):
192+
while hasattr(func, "__wrapped__"):
193+
func = func.__wrapped__
194+
return func
195+
196+
type_ = unwrap(type_)
197+
198+
try:
199+
source_file = inspect.getsourcefile(type_)
200+
line = inspect.getsourcelines(type_)[1]
201+
except Exception as e:
202+
logger.error(e)
203+
return ""
204+
205+
if source_file.startswith(self.project_src_path):
206+
path = source_file.removeprefix(self.project_src_path).lstrip("/")
207+
return f"src:{path}:{line}"
208+
elif source_file.startswith(sys.prefix):
209+
path = source_file.removeprefix(sys.prefix).lstrip("/")
210+
return f"env:{path}:{line}"
211+
return ""
212+
190213
# File watcher globs
191214
# ---------------------------------------------------------------------------------
192215
def get_file_watcher_globs(self):
@@ -336,12 +359,14 @@ def _parse_library(self, lib) -> dict:
336359
"tags": {
337360
name: {
338361
"docs": func.__doc__.strip() if func.__doc__ else "",
362+
"source": self.get_source_from_type(func),
339363
}
340364
for name, func in lib.tags.items()
341365
},
342366
"filters": {
343367
name: {
344368
"docs": func.__doc__.strip() if func.__doc__ else "",
369+
"source": self.get_source_from_type(func),
345370
}
346371
for name, func in lib.filters.items()
347372
},

0 commit comments

Comments
 (0)