Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions strictdoc/backend/sdoc/error_handling.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@
SDocNodeField,
)
from strictdoc.backend.sdoc.models.reference import Reference
from strictdoc.backend.sdoc_source_code.models.function_range_marker import (
ForwardFunctionRangeMarker,
FunctionRangeMarker,
from strictdoc.backend.sdoc_source_code.models.language_item_marker import (
ForwardLanguageItemMarker,
LanguageItemMarker,
)
from strictdoc.backend.sdoc_source_code.models.line_marker import LineMarker
from strictdoc.backend.sdoc_source_code.models.range_marker import (
Expand Down Expand Up @@ -323,8 +323,8 @@ def invalid_reference_type_item(
def invalid_marker_role(
node: SDocNode,
marker: Union[
ForwardFunctionRangeMarker,
FunctionRangeMarker,
ForwardLanguageItemMarker,
LanguageItemMarker,
LineMarker,
RangeMarker,
ForwardRangeMarker,
Expand Down
4 changes: 2 additions & 2 deletions strictdoc/backend/sdoc_source_code/grammar.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// The EmptyLine is needed in addition to the SingleLineString because
// otherwise textX's get_location() ignores the whitespaces.
// TODO: Maybe there is a trick to disable that and only use SingleLineString.
EmptyLine | RangeMarker | LineMarker | FunctionRangeMarker | SingleLineString
EmptyLine | RangeMarker | LineMarker | LanguageItemMarker | SingleLineString
;

EmptyLine[noskipws]:
Expand All @@ -25,7 +25,7 @@
(reqs_objs += Req[', ']) ', scope=' scope=/(range_start|range_end)/ (", role=" role=/{REGEX_ROLE}/)? ')' '\n'?
;

FunctionRangeMarker[noskipws]:
LanguageItemMarker[noskipws]:
/^.*?@relation/
"(" (reqs_objs += Req[', ']) ', scope=' scope="file" (", role=" role=/{REGEX_ROLE}/)? ')' '\n'?
;
Expand Down
28 changes: 15 additions & 13 deletions strictdoc/backend/sdoc_source_code/marker_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
from strictdoc.backend.sdoc_source_code.helpers.comment_preprocessor import (
preprocess_source_code_comment,
)
from strictdoc.backend.sdoc_source_code.models.function_range_marker import (
FunctionRangeMarker,
from strictdoc.backend.sdoc_source_code.models.language_item_marker import (
LanguageItemMarker,
)
from strictdoc.backend.sdoc_source_code.models.line_marker import LineMarker
from strictdoc.backend.sdoc_source_code.models.range_marker import (
Expand Down Expand Up @@ -104,8 +104,8 @@ def _parse_relation_marker(
comment_line_start: int,
entity_name: Optional[str] = None,
col_offset: int = 0,
) -> List[Union[FunctionRangeMarker, RangeMarker, LineMarker]]:
markers: List[Union[FunctionRangeMarker, RangeMarker, LineMarker]] = []
) -> List[Union[LanguageItemMarker, RangeMarker, LineMarker]]:
markers: List[Union[LanguageItemMarker, RangeMarker, LineMarker]] = []

relation_uid_elements = []
relation_scope_element: Optional[Tree[Token]] = None
Expand Down Expand Up @@ -155,24 +155,26 @@ def _parse_relation_marker(
requirements.append(requirement)

if relation_scope in ("file", "class", "function"):
function_marker = FunctionRangeMarker(
language_item_marker = LanguageItemMarker(
None, requirements, scope=relation_scope, role=relation_role
)
function_marker.ng_source_line_begin = (
language_item_marker.ng_source_line_begin = (
comment_line_start + element_.meta.line - 1
)
function_marker.ng_source_column_begin = (
language_item_marker.ng_source_column_begin = (
element_.meta.column + col_offset
)
function_marker.ng_range_line_begin = line_start
function_marker.ng_range_line_end = line_end
language_item_marker.ng_range_line_begin = line_start
language_item_marker.ng_range_line_end = line_end
if relation_scope == "file":
function_marker.set_description("entire file")
language_item_marker.set_description("entire file")
elif relation_scope == "function":
function_marker.set_description(f"function {entity_name}()")
language_item_marker.set_description(
f"function {entity_name}()"
)
elif relation_scope == "class":
function_marker.set_description(f"class {entity_name}")
markers.append(function_marker)
language_item_marker.set_description(f"class {entity_name}")
markers.append(language_item_marker)
elif relation_scope in ("range_start", "range_end"):
range_marker = RangeMarker(
None,
Expand Down
55 changes: 0 additions & 55 deletions strictdoc/backend/sdoc_source_code/models/function.py

This file was deleted.

111 changes: 111 additions & 0 deletions strictdoc/backend/sdoc_source_code/models/language.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""
@relation(SDOC-SRS-142, scope=file)
"""

from typing import Any, List, Optional, Set

from strictdoc.backend.sdoc_source_code.constants import FunctionAttribute
from strictdoc.backend.sdoc_source_code.models.language_item_marker import (
LanguageItemMarker,
)
from strictdoc.backend.sdoc_source_code.models.source_location import ByteRange
from strictdoc.helpers.auto_described import auto_described


@auto_described
class LanguageItem:
def __init__(
self,
*,
parent: Any,
name: str,
display_name: str,
line_begin: int,
line_end: int,
code_byte_range: Optional[ByteRange],
child_functions: List[Any],
markers: List[LanguageItemMarker],
attributes: Set[FunctionAttribute],
):
"""
Create a LanguageItem object.

A LanguageItem records essential data like name and location of
programming language items from language-aware parsing. It's up to a
StrictDoc language parser what items they want to support.

For languages that scatter parts of a function over different places
(e.g. declaration and definition in C), the caller is responsible to
create a separate LanguageItem object for each part, where the parts
match on name. Since it's more common to stick documentation to the
declaration part, StrictDoc will automatically find and link
corresponding definition parts. Not vice versa: If definition parts are
documented, only the definition will be linked.

parent should be set to the SourceFileTraceabilityInfo that corresponds
to the file where the function is defined. Purpose is to provide meta
information like file name and path while the FileTraceabilityIndex is
not yet fully resolved.

name is an identifier that should be globally unique for a set of
declarations/definitions. Its purpose is to tie declarations and
definitions. It's up to StrictDoc language parsers to define a naming
convention for their language. The convention should follow language
specific notation for qualified names. E.g. in C++, a member bar in
class Foo will be named "Foo:bar(const CanFrame &frame)". It may be
hard to reimplement the full module and naming system of each language,
so naming is best-effort.

display_name is an identifier used to resolve forward relations from
users to function objects created by language parsers. The display_name
must thus be predictable for users and as unique as possible. It's up
to StrictDoc language parsers to define a naming convention for their
language. The convention should follow language specific notation for
qualified identifiers. E.g. in C++, a member bar in class Foo will be
named "Foo:bar".

line start/end (1-based) mark first and last line of the definition
block, *without* leading comment lines, if any. Used to jump to and
highlight the function in source file view in case of forward
relations.

child_functions could store LanguageItem objects that represent nested
functions. It's currently unused and may be removed.

markers are only needed if the LanguageItem is a declaration function
(C, C++) that shall be automatically linked to the corresponding
definition function, or if it is a test framework function that shall
be automatically linked with requirements and test results. Otherwise,
it can be empty.

attributes: For example static, declaration, definition. Enables some
special handling, e.g. automatic linking of definitions if the
LanguageItem is a declaration.
"""

assert parent is not None
self.parent = parent
self.name = name
self.display_name = display_name

# Child functions are supported in programming languages that can nest
# functions, for example, Python.
self.child_functions: List[LanguageItem] = child_functions
self.markers: List[LanguageItemMarker] = markers
self.line_begin = line_begin
self.line_end = line_end

# Not all source code functions have ranges.
# Example: Robot framework files.
self.code_byte_range: Optional[ByteRange] = code_byte_range

self.attributes: Set[FunctionAttribute] = attributes

def is_declaration(self) -> bool:
return FunctionAttribute.DECLARATION in self.attributes

def is_definition(self) -> bool:
return FunctionAttribute.DEFINITION in self.attributes

def is_public(self) -> bool:
return FunctionAttribute.STATIC not in self.attributes
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class RangeMarkerType(Enum):


@auto_described
class FunctionRangeMarker:
class LanguageItemMarker:
def __init__(
self, parent: Any, reqs_objs: List[Req], scope: str, role: Optional[str]
):
Expand Down Expand Up @@ -78,7 +78,7 @@ def set_description(self, description: str) -> None:
assert isinstance(description, str)
self._description = description

def create_end_marker(self) -> "FunctionRangeMarker":
def create_end_marker(self) -> "LanguageItemMarker":
marker_copy = copy(self)
marker_copy.begin_or_end = False
marker_copy.ng_range_line_begin = self.ng_range_line_begin
Expand All @@ -87,7 +87,7 @@ def create_end_marker(self) -> "FunctionRangeMarker":


@auto_described
class ForwardFunctionRangeMarker(FunctionRangeMarker):
class ForwardLanguageItemMarker(LanguageItemMarker):
def __init__(
self,
parent: Any,
Expand Down
12 changes: 6 additions & 6 deletions strictdoc/backend/sdoc_source_code/models/source_file_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

from typing_extensions import TypeAlias

from strictdoc.backend.sdoc_source_code.models.function import Function
from strictdoc.backend.sdoc_source_code.models.function_range_marker import (
FunctionRangeMarker,
from strictdoc.backend.sdoc_source_code.models.language import LanguageItem
from strictdoc.backend.sdoc_source_code.models.language_item_marker import (
LanguageItemMarker,
)
from strictdoc.backend.sdoc_source_code.models.line_marker import LineMarker
from strictdoc.backend.sdoc_source_code.models.range_marker import (
Expand All @@ -17,7 +17,7 @@
from strictdoc.helpers.file_stats import SourceFileStats

RelationMarkerType: TypeAlias = Union[
FunctionRangeMarker, LineMarker, RangeMarker, ForwardRangeMarker
LanguageItemMarker, LineMarker, RangeMarker, ForwardRangeMarker
]


Expand All @@ -41,7 +41,7 @@ class SourceFileTraceabilityInfo:
def __init__(self, g_parts: List[Any]): # noqa: ARG002
self.source_file: Optional[SourceFile] = None
self.source_nodes: List[SourceNode] = []
self.functions: List[Function] = []
self.functions: List[LanguageItem] = []

#
# { # noqa: ERA001
Expand All @@ -51,7 +51,7 @@ def __init__(self, g_parts: List[Any]): # noqa: ARG002
self.ng_map_reqs_to_markers: Dict[str, List[RelationMarkerType]] = {}

self.ng_map_names_to_markers: Dict[str, List[RelationMarkerType]] = {}
self.ng_map_names_to_definition_functions: Dict[str, Function] = {}
self.ng_map_names_to_definition_functions: Dict[str, LanguageItem] = {}

#
# Merged ranges contain ranges that are fully covered by one or more
Expand Down
10 changes: 5 additions & 5 deletions strictdoc/backend/sdoc_source_code/models/source_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from dataclasses import dataclass, field
from typing import Any, List, Optional, Union

from strictdoc.backend.sdoc_source_code.models.function import Function
from strictdoc.backend.sdoc_source_code.models.function_range_marker import (
FunctionRangeMarker,
from strictdoc.backend.sdoc_source_code.models.language import LanguageItem
from strictdoc.backend.sdoc_source_code.models.language_item_marker import (
LanguageItemMarker,
)
from strictdoc.backend.sdoc_source_code.models.line_marker import LineMarker
from strictdoc.backend.sdoc_source_code.models.range_marker import (
Expand All @@ -29,12 +29,12 @@ class SourceNode:

entity_name: Optional[str]
comment_byte_range: Optional[ByteRange]
markers: List[Union[FunctionRangeMarker, RangeMarker, LineMarker]] = field(
markers: List[Union[LanguageItemMarker, RangeMarker, LineMarker]] = field(
default_factory=list
)
fields: dict[str, str] = field(default_factory=dict)
fields_locations: dict[str, tuple[int, int]] = field(default_factory=dict)
function: Optional[Function] = None
function: Optional[LanguageItem] = None
# FIXME: Adding SDocNode here causes circular import problem.
sdoc_node: Optional[Any] = None

Expand Down
6 changes: 3 additions & 3 deletions strictdoc/backend/sdoc_source_code/parse_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

from typing import Any, Dict, List, Optional, Union

from strictdoc.backend.sdoc_source_code.models.function_range_marker import (
FunctionRangeMarker,
from strictdoc.backend.sdoc_source_code.models.language_item_marker import (
LanguageItemMarker,
)
from strictdoc.backend.sdoc_source_code.models.line_marker import LineMarker
from strictdoc.backend.sdoc_source_code.models.range_marker import RangeMarker
Expand All @@ -20,6 +20,6 @@ def __init__(
self.file_stats: SourceFileStats = file_stats
self.markers: List[Any] = []
self.marker_stack: List[
Union[RangeMarker, FunctionRangeMarker, LineMarker]
Union[RangeMarker, LanguageItemMarker, LineMarker]
] = []
self.map_reqs_to_markers: Dict[str, Any] = {}
Loading