-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #15 from CESNET/cabal_improve
SPHINX VHDL version 0.2.0
- Loading branch information
Showing
9 changed files
with
115 additions
and
90 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,13 @@ | ||
# Sphinx-vhdl | ||
# SPHINX-VHDL | ||
|
||
[![PyPI](https://img.shields.io/pypi/v/sphinx-vhdl)](https://pypi.org/project/sphinx-vhdl/) | ||
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/CESNET/sphinx-vhdl/documentation?label=documentation)](https://cesnet.github.io/sphinx-vhdl/) | ||
[![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/CESNET/sphinx-vhdl/.github/workflows/doc.yml)](https://cesnet.github.io/sphinx-vhdl/) | ||
|
||
> A [sphinx](https://www.sphinx-doc.org/) domain for semi-automatically documenting VHDL | ||
This extension for Sphinx allows you to keep your documentation in code and automatically draw it out into your main documentation using just few simple directives. | ||
|
||
You can see the detailed documentation at https://cesnet.github.io/sphinx-vhdl/, or build it yourself (running `make html` while in the `doc` directory and having `sphinx` installed should be sufficient) | ||
You can see the detailed documentation at https://cesnet.github.io/sphinx-vhdl/, or build it yourself (running `make` while in the `doc` directory and having `sphinx` + `sphinx_rtd_theme` installed should be sufficient) | ||
|
||
## Usage | ||
|
||
|
@@ -16,7 +16,9 @@ The python package must be installed with | |
pip3 install sphinx-vhdl | ||
``` | ||
|
||
The usage of this extension requires Python >= 3.6 and Sphinx >= 4.0.0. | ||
This extension requires Python >= 3.8 and Sphinx >= 6.0.0. | ||
|
||
*Note that your documentation may use multiple sphinx extensions or an alternative theme (such as `sphinx_rtd_theme`), which you must also have installed.* | ||
|
||
## Configuration | ||
|
||
|
@@ -27,6 +29,12 @@ extensions = ['sphinxvhdl.vhdl'] | |
vhdl_autodoc_source_path = 'path/to/your/vhdl/sources/root' | ||
``` | ||
|
||
## Where is the SPHINX-VHDL extension used? | ||
|
||
- [Open FPGA Modules (OFM) by CESNET](https://github.com/CESNET/ofm/) | ||
- [NDK Minimal Application by CESNET](https://github.com/CESNET/ndk-app-minimal) | ||
- *Do you use SPHINX-VHDL in your public VHDL repository? Please add a link to this list!* | ||
|
||
## Repository maintainer | ||
|
||
- Jakub Cabal, [email protected] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Minimal makefile for Sphinx documentation | ||
|
||
.PHONY: all clean | ||
|
||
all: | ||
sphinx-build -M html source build -v -E | ||
|
||
clean: | ||
rm -rf ./build |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
[metadata] | ||
name = sphinx-vhdl | ||
version = 0.1.6 | ||
version = 0.2.0 | ||
author = CESNET z.s.p.o. | ||
author_email = [email protected] | ||
description = A Sphinx domain and autodocumenter for VHDL | ||
|
@@ -21,7 +21,9 @@ classifiers = | |
package_dir = | ||
= src | ||
packages = find: | ||
python_requires = >=3.6 | ||
python_requires = >=3.8 | ||
install_requires = | ||
sphinx >= 6.0 | ||
|
||
[options.packages.find] | ||
where = src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
# autodoc.py: A basic VHDL parser and documentation extractor | ||
# Copyright (C) 2021 CESNET z.s.p.o. | ||
# Author(s): Jindrich Dite <[email protected]> | ||
# Jakub Cabal <[email protected]> | ||
# | ||
# SPDX-License-Identifier: BSD-3-Clause | ||
|
||
|
@@ -10,9 +11,8 @@ | |
from typing import Optional, List | ||
from enum import Enum, auto | ||
|
||
import logging | ||
|
||
LOG = logging.getLogger('sphinxvhdl-autodoc') | ||
from sphinx.util import logging | ||
logger = logging.getLogger(__name__) | ||
|
||
entities = {} | ||
portsignals = defaultdict(dict) | ||
|
@@ -28,24 +28,14 @@ | |
functions = {} | ||
|
||
# Function for parsing line comments | ||
def parse_inline_doc_or_raise(line: str, current_doc: List[str]): | ||
def parse_inline_doc_or_print_error(current_doc, filename, line, lineno): | ||
if '-- ' in line: | ||
if len(current_doc) > 0: | ||
raise ValueError( | ||
'Documented entity has both a pre- and inline documentation; only one is allowed. Offending line:\n' + | ||
line) | ||
logger.warning(f"SPHINX-VHDL: Documented entity has both a pre- and inline documentation; only one is allowed!\n Offending line: {line}", location=f"{filename}:{lineno}") | ||
else: | ||
current_doc.append(line.split('-- ', 1)[1]) | ||
|
||
|
||
def parse_inline_doc_or_print_error(current_doc, filename, line, lineno): | ||
try: | ||
parse_inline_doc_or_raise(line, current_doc) | ||
except ValueError as ex: | ||
LOG.warning(f'Error parsing file {filename} at line {lineno}:') | ||
LOG.warning(ex.args) | ||
|
||
|
||
class ParseState(Enum): | ||
ENTITY_DECL = auto() | ||
ARCH_DECL = auto() | ||
|
@@ -79,24 +69,25 @@ def init(path: str) -> None: | |
for line in source_code: | ||
lineno += 1 | ||
line = line.strip() | ||
line_lowercase = line.lower() | ||
# Group parsing logic | ||
if state == ParseState.PORT and group_state == ParseState.GENERIC: | ||
current_group = "" | ||
|
||
# Line comments logic | ||
if line.startswith('-- '): | ||
if line_lowercase.startswith('-- '): | ||
# Logic for sampling names of groups of ports and generics | ||
if (state == ParseState.PORT or state == ParseState.GENERIC) and '====' in line: | ||
if (state == ParseState.PORT or state == ParseState.GENERIC) and '====' in line_lowercase: | ||
group_state = state | ||
state = ParseState.GROUPS | ||
current_group = "" | ||
current_doc = [] | ||
elif state == ParseState.GROUPS and current_group != '' and '====' not in line: | ||
elif state == ParseState.GROUPS and current_group != '' and '====' not in line_lowercase: | ||
current_doc.append(line[3:]) | ||
elif state == ParseState.GROUPS and '====' not in line: | ||
elif state == ParseState.GROUPS and '====' not in line_lowercase: | ||
current_group = current_entity + " " + line[3:].strip() | ||
current_doc = [] | ||
elif state == ParseState.GROUPS and '====' in line: | ||
elif state == ParseState.GROUPS and '====' in line_lowercase: | ||
group_definition = current_doc | ||
groups_desc[current_group] = group_definition | ||
state = group_state | ||
|
@@ -105,12 +96,12 @@ def init(path: str) -> None: | |
current_doc.append(line[3:]) | ||
|
||
# If line start with keyword architecture then save name of architecture | ||
elif line.lower().startswith('architecture'): | ||
elif line_lowercase.startswith('architecture'): | ||
state = ParseState.ARCH_DECL | ||
current_constant = line.split()[3] | ||
|
||
# If line contains keyword constant and state is not generice then start to collecting constants | ||
elif state == ParseState.ARCH_DECL and 'constant' in line: | ||
elif state == ParseState.ARCH_DECL and 'constant' in line_lowercase: | ||
parse_inline_doc_or_print_error(current_doc, filename, line, lineno) | ||
definition = line.split('--')[0].split(';')[0] | ||
if ':=' not in definition: | ||
|
@@ -120,30 +111,30 @@ def init(path: str) -> None: | |
current_doc = [] | ||
|
||
# If there is -- without gap, then ignore | ||
elif line == '--': | ||
elif line_lowercase == '--': | ||
current_doc.append('') | ||
|
||
# If there is word entity then try parse, save entity name and add description of entity to associative array | ||
# ID of ass. array is name of entity. At the end clear current description and change state to entity declaration | ||
elif line.lower().startswith('entity ') and ' is' in line: | ||
elif line_lowercase.startswith('entity ') and ' is' in line_lowercase: | ||
parse_inline_doc_or_print_error(current_doc, filename, line, lineno) | ||
current_entity = line.split()[1] | ||
entities[current_entity.lower()] = current_doc | ||
current_doc = [] | ||
state = ParseState.ENTITY_DECL | ||
|
||
# Check if there is any port declaration | ||
elif state == ParseState.ENTITY_DECL and line.lower().startswith('port'): | ||
elif state == ParseState.ENTITY_DECL and line_lowercase.startswith('port'): | ||
state = ParseState.PORT | ||
current_doc = [] | ||
|
||
# Check if there is any generic declaration | ||
elif state == ParseState.ENTITY_DECL and line.lower().startswith('generic'): | ||
elif state == ParseState.ENTITY_DECL and line_lowercase.startswith('generic'): | ||
state = ParseState.GENERIC | ||
current_doc = [] | ||
|
||
# If there is line which contains ":" then it's one of ports, parse it and save his definition | ||
elif state == ParseState.PORT and ':' in line: | ||
elif state == ParseState.PORT and ':' in line_lowercase: | ||
parse_inline_doc_or_print_error(current_doc, filename, line, lineno) | ||
definition = line.split('--')[0].split(';')[0].split(':=')[0].strip() | ||
if definition.lower().startswith('signal'): | ||
|
@@ -157,7 +148,7 @@ def init(path: str) -> None: | |
current_doc = [] | ||
|
||
# If there is line which contains ":" then it's one of generic, parse it and save his definition | ||
elif state == ParseState.GENERIC and ':' in line: | ||
elif state == ParseState.GENERIC and ':' in line_lowercase: | ||
parse_inline_doc_or_print_error(current_doc, filename, line, lineno) | ||
definition = line.split('--')[0].split(';')[0].strip() | ||
if ':=' not in definition: | ||
|
@@ -173,27 +164,27 @@ def init(path: str) -> None: | |
current_doc = [] | ||
|
||
# End of the entity was found | ||
elif state == ParseState.ENTITY_DECL and line.lower().startswith('end'): | ||
elif state == ParseState.ENTITY_DECL and line_lowercase.startswith('end'): | ||
state = None | ||
group_state = None | ||
current_doc = [] | ||
|
||
# If there is magic word package then parse package and save his definition | ||
elif (state is None or state is ParseState.PACKAGE) and line.lower().startswith('package'): | ||
elif (state is None or state is ParseState.PACKAGE) and line_lowercase.startswith('package'): | ||
parse_inline_doc_or_print_error(current_doc, filename, line, lineno) | ||
state = ParseState.PACKAGE | ||
current_package = ('' if current_package == '' else (current_package + '.')) + line.split()[1] | ||
packages[current_package.lower()] = current_doc | ||
current_doc = [] | ||
|
||
# Signalization of end of the package | ||
elif state is ParseState.PACKAGE and line.lower().startswith('end package'): | ||
elif state is ParseState.PACKAGE and line_lowercase.startswith('end package'): | ||
current_package = '.'.join(current_package.split('.')[:-1]) | ||
state = None if current_package == '' else ParseState.PACKAGE | ||
current_doc = [] | ||
|
||
# Package contains type, parse it | ||
elif (state is None or state is ParseState.PACKAGE) and line.lower().startswith('type'): | ||
elif (state is None or state is ParseState.PACKAGE) and line_lowercase.startswith('type'): | ||
if ' record' in line.split('--')[0].lower().split(maxsplit=2)[-1]: | ||
parse_inline_doc_or_print_error(current_doc, filename, line, lineno) | ||
records[line.split()[1]] = current_doc | ||
|
@@ -212,7 +203,7 @@ def init(path: str) -> None: | |
current_doc = [] | ||
|
||
# Signalization of the end of record | ||
elif state is ParseState.RECORD and line.lower().startswith('end record'): | ||
elif state is ParseState.RECORD and line_lowercase.startswith('end record'): | ||
if current_package != '': | ||
state = ParseState.PACKAGE | ||
else: | ||
|
@@ -228,16 +219,16 @@ def init(path: str) -> None: | |
|
||
# Enumarate parsing | ||
elif state is ParseState.ENUM: | ||
if not line.startswith(')'): | ||
if not line_lowercase.startswith(')'): | ||
parse_inline_doc_or_print_error(current_doc, filename, line, lineno) | ||
enumvals[current_type_name][line.split(',')[0]] = current_doc | ||
current_doc = [] | ||
|
||
# Function parsing | ||
elif line.lower().startswith('function') and line.split('--')[0].strip().endswith(';'): | ||
elif line_lowercase.startswith('function') and line.split('--')[0].strip().endswith(';'): | ||
parse_inline_doc_or_print_error(current_doc, filename, line, lineno) | ||
return_type = '' if 'return' not in line else (line.split('return')[1].strip()[:-1] + '.') | ||
functions[return_type + line.lower().split()[1]] = current_doc | ||
functions[return_type + line_lowercase.split()[1]] = current_doc | ||
current_doc = [] | ||
|
||
# Ignore others | ||
|
Oops, something went wrong.