Path:
strictdoc/core/file_system/source_tree.py
Lines:
142
Non-empty lines:
116
Non-empty lines covered with requirements:
116 / 116 (100.0%)
Functions:
17
Functions covered by requirements:
17 / 17 (100.0%)
1
"""2
@relation(SDOC-SRS-33, scope=file)3
"""4
5
import os
6
from enum import Enum
7
from typing import Dict, List, Sequence
8
9
from strictdoc.core.file_system.file_tree import File, FileTree
10
from strictdoc.helpers.auto_described import auto_described
11
12
13
class SourceFileType(Enum):
14
PYTHON = [".py"]
15
C = [".h", ".c"]
16
CPP = [".cpp", ".cc"]
17
TEX = [".tex"]
18
# Is there an idiomatic file extension for Jinja templates?19
# https://stackoverflow.com/questions/29590931/is-there-an-idiomatic-file-extension-for-jinja-templates20
TOML = [".toml"]
21
JINJA = [".jinja", ".jinja2", ".j2", ".html.jinja"]
22
JAVASCRIPT = [".js"]
23
YAML = [".yaml", ".yml"]
24
RST = [".rst"]
25
SDOC = [".sdoc"]
26
27
# Structured Text (PLC)28
STRUCTURED_TEXT = [".st"]
29
30
UNKNOWN: List[str] = [] # type: ignore[misc]
31
32
@classmethod33
def create_from_path(cls, path_to_file: str) -> "SourceFileType":
34
if path_to_file.endswith(".py"):
35
return cls.PYTHON
36
if path_to_file.endswith(".h") or path_to_file.endswith(".c"):
37
return cls.C
38
for enum_value in SourceFileType.CPP.value:
39
if path_to_file.endswith(enum_value):
40
return cls.CPP
41
if path_to_file.endswith(".tex"):
42
return cls.TEX
43
if path_to_file.endswith(".toml"):
44
return cls.TOML
45
for enum_value in SourceFileType.JINJA.value:
46
if path_to_file.endswith(enum_value):
47
return cls.JINJA
48
if path_to_file.endswith(".js"):
49
return cls.JAVASCRIPT
50
for enum_value in SourceFileType.YAML.value:
51
if path_to_file.endswith(enum_value):
52
return cls.YAML
53
for enum_value in SourceFileType.RST.value:
54
if path_to_file.endswith(enum_value):
55
return cls.RST
56
if path_to_file.endswith(".sdoc"):
57
return cls.SDOC
58
# FIXME: .st file could conflict between Structured Text (PLC) and Smalltalk.59
# No Smalltalk has been requested by users until now but we may60
# want to set up a general disambiguation procedure for cases like this.61
# https://github.com/strictdoc-project/strictdoc/issues/256962
if path_to_file.endswith(".st"):
63
return cls.STRUCTURED_TEXT
64
65
return cls.UNKNOWN
66
67
68
@auto_described69
class SourceFile:
70
def __init__(
71
self,
72
level: int,
73
full_path: str,
74
in_doctree_source_file_rel_path: str,
75
output_dir_full_path: str,
76
output_file_full_path: str,
77
) -> None:
78
assert isinstance(level, int)
79
assert os.path.exists(full_path)
80
81
self.level = level
82
self.full_path = full_path
83
self.file_name = os.path.basename(full_path)
84
self.in_doctree_source_file_rel_path = in_doctree_source_file_rel_path
85
self.in_doctree_source_file_rel_path_posix: str = (
86
in_doctree_source_file_rel_path.replace("\\", "/")
87
)88
self.output_dir_full_path = output_dir_full_path
89
self.output_file_full_path = output_file_full_path
90
self.path_depth_prefix = ("../" * (level + 1))[:-1]
91
92
self.file_type: SourceFileType = SourceFileType.create_from_path(
93
in_doctree_source_file_rel_path94
)95
96
self.is_referenced = False
97
98
def is_python_file(self) -> bool:
99
return self.file_type == SourceFileType.PYTHON
100
101
def is_c_file(self) -> bool:
102
return self.file_type == SourceFileType.C
103
104
def is_cpp_file(self) -> bool:
105
return self.file_type == SourceFileType.CPP
106
107
def is_tex_file(self) -> bool:
108
return self.file_type == SourceFileType.TEX
109
110
def is_toml_file(self) -> bool:
111
return self.file_type == SourceFileType.TOML
112
113
def is_jinja_file(self) -> bool:
114
return self.file_type == SourceFileType.JINJA
115
116
def is_javascript_file(self) -> bool:
117
return self.file_type == SourceFileType.JAVASCRIPT
118
119
def is_yaml_file(self) -> bool:
120
return self.file_type == SourceFileType.YAML
121
122
def is_rst_file(self) -> bool:
123
return self.file_type == SourceFileType.RST
124
125
def is_st_file(self) -> bool:
126
return self.file_type == SourceFileType.STRUCTURED_TEXT
127
128
129
class SourceTree:
130
def __init__(
131
self,
132
file_tree: FileTree,
133
source_files: Sequence[SourceFile],
134
map_file_to_source: Dict[File, SourceFile],
135
):136
self.file_tree: FileTree = file_tree
137
self.source_files: Sequence[SourceFile] = source_files
138
self.map_file_to_source: Dict[File, SourceFile] = map_file_to_source
139
140
def get_source_for_file(self, file: File) -> SourceFile:
141
assert isinstance(file, File)
142
return self.map_file_to_source[file]