Skip to content

Commit b80a396

Browse files
authored
Merge pull request #58 from gnikit/feature/refactor
Feature/refactor
2 parents 4e0bb5d + 6a4fb9f commit b80a396

29 files changed

+2557
-1552
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# CHANGELONG
22

3+
## 2.2.9
4+
5+
### Changed
6+
7+
- Changed how renaming of implicitly named type-bound procedures and their
8+
implementations is handled. Unittest was added.
9+
- Rewrote the Fortran parser to be clearer and more modular
10+
311
## 2.2.8
412

513
### Changed

docs/fortls.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ fortls.constants module
1212
:undoc-members:
1313
:show-inheritance:
1414

15+
fortls.ftypes module
16+
--------------------
17+
18+
.. automodule:: fortls.ftypes
19+
:members:
20+
:undoc-members:
21+
:show-inheritance:
22+
1523
fortls.helper\_functions module
1624
-------------------------------
1725

@@ -36,6 +44,14 @@ fortls.intrinsics module
3644
:undoc-members:
3745
:show-inheritance:
3846

47+
fortls.json\_templates module
48+
-----------------------------
49+
50+
.. automodule:: fortls.json_templates
51+
:members:
52+
:undoc-members:
53+
:show-inheritance:
54+
3955
fortls.jsonrpc module
4056
---------------------
4157

fortls/__init__.py

Lines changed: 3 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from .interface import commandline_args
1111
from .jsonrpc import JSONRPC2Connection, ReadWriter, path_from_uri
1212
from .langserver import LangServer
13-
from .parse_fortran import fortran_file, process_file
13+
from .parse_fortran import fortran_file
1414
from .version import __version__
1515

1616
__all__ = ["__version__"]
@@ -52,7 +52,7 @@ def main():
5252
debug_server_general(args, vars(args))
5353

5454
else:
55-
stdin, stdout = _binary_stdio()
55+
stdin, stdout = sys.stdin.buffer, sys.stdout.buffer
5656
LangServer(
5757
conn=JSONRPC2Connection(ReadWriter(stdin, stdout)),
5858
settings=vars(args),
@@ -492,18 +492,7 @@ def debug_server_parser(args):
492492
error_exit(f"Reading file failed: {err_str}")
493493
print(f" Detected format: {'fixed' if file_obj.fixed else 'free'}")
494494
print("\n=========\nParser Output\n=========\n")
495-
_, file_ext = os.path.splitext(os.path.basename(args.debug_filepath))
496-
preproc_file = False
497-
if pp_suffixes is not None:
498-
preproc_file = file_ext in pp_suffixes
499-
else:
500-
preproc_file = file_ext == file_ext.upper()
501-
if preproc_file:
502-
file_ast = process_file(
503-
file_obj, debug=True, pp_defs=pp_defs, include_dirs=include_dirs
504-
)
505-
else:
506-
file_ast = process_file(file_obj, debug=True)
495+
file_ast = file_obj.parse(debug=True, pp_defs=pp_defs, include_dirs=include_dirs)
507496
print("\n=========\nObject Tree\n=========\n")
508497
for obj in file_ast.get_scopes():
509498
print("{0}: {1}".format(obj.get_type(), obj.FQSN))
@@ -533,26 +522,3 @@ def print_children(obj, indent=""):
533522
for child in obj.get_children():
534523
print(" {0}{1}: {2}".format(indent, child.get_type(), child.FQSN))
535524
print_children(child, indent + " ")
536-
537-
538-
def _binary_stdio():
539-
"""Construct binary stdio streams (not text mode).
540-
This seems to be different for Window/Unix Python2/3, so going by:
541-
https://stackoverflow.com/questions/2850893/reading-binary-data-from-stdin
542-
"""
543-
PY3K = sys.version_info >= (3, 0)
544-
545-
if PY3K:
546-
stdin, stdout = sys.stdin.buffer, sys.stdout.buffer
547-
else:
548-
# Python 2 on Windows opens sys.stdin in text mode, and
549-
# binary data that read from it becomes corrupted on \r\n
550-
if sys.platform == "win32":
551-
# set sys.stdin to binary mode
552-
import msvcrt
553-
554-
msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
555-
msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
556-
stdin, stdout = sys.stdin, sys.stdout
557-
558-
return stdin, stdout

fortls/constants.py

Lines changed: 11 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
from __future__ import annotations
22

33
import logging
4-
import sys
5-
from dataclasses import dataclass, field
64

75
from fortls.regex_patterns import FortranRegularExpressions
86

9-
PY3K = sys.version_info >= (3, 0)
10-
117
log = logging.getLogger(__name__)
128

139
# Global variables
@@ -56,103 +52,20 @@
5652
ASSOC_TYPE_ID = 14
5753
ENUM_TYPE_ID = 15
5854

59-
# A string used to mark literals e.g. 10, 3.14, "words", etc.
60-
# The description name chosen is non-ambiguous and cannot naturally
61-
# occur in Fortran (with/out C preproc) code
62-
# It is invalid syntax to define a type starting with numerics
63-
# it cannot also be a comment that requires !, c, d
64-
# and ^= (xor_eq) operator is invalid in Fortran C++ preproc
65-
FORTRAN_LITERAL = "0^=__LITERAL_INTERNAL_DUMMY_VAR_"
66-
67-
68-
@dataclass
69-
class VAR_info:
70-
type_word: str
71-
keywords: list[str]
72-
var_names: list[str]
73-
74-
75-
@dataclass
76-
class SUB_info:
77-
name: str
78-
args: str
79-
mod_flag: bool
80-
keywords: list[str]
81-
82-
83-
@dataclass
84-
class SELECT_info:
85-
type: int
86-
binding: str
87-
desc: str
88-
89-
90-
@dataclass
91-
class CLASS_info:
92-
name: str
93-
parent: str
94-
keywords: str
95-
96-
97-
@dataclass
98-
class USE_info:
99-
mod_name: str
100-
only_list: set[str]
101-
rename_map: dict[str, str]
102-
10355

104-
@dataclass
105-
class GEN_info:
106-
bound_name: str
107-
pro_links: list[str]
108-
vis_flag: int
56+
class Severity:
57+
error = 1
58+
warn = 2
59+
info = 3
10960

11061

111-
@dataclass
112-
class SMOD_info:
113-
name: str
114-
parent: str
115-
116-
117-
@dataclass
118-
class INT_info:
119-
name: str
120-
abstract: bool
121-
122-
123-
@dataclass
124-
class VIS_info:
125-
type: int
126-
obj_names: list[str]
127-
128-
129-
@dataclass
130-
class INCLUDE_info:
131-
line_number: int
132-
path: str
133-
file: None # fortran_file
134-
scope_objs: list[str]
135-
136-
137-
@dataclass
138-
class RESULT_sig:
139-
name: str = field(default=None)
140-
type: str = field(default=None)
141-
keywords: list[str] = field(default_factory=list)
142-
143-
144-
@dataclass
145-
class FUN_sig:
146-
name: str
147-
args: str
148-
keywords: list[str] = field(default_factory=list)
149-
mod_flag: bool = field(default=False)
150-
result: RESULT_sig = field(default_factory=RESULT_sig)
151-
152-
def __post_init__(self):
153-
if not self.result.name:
154-
self.result.name = self.name
155-
62+
#: A string used to mark literals e.g. 10, 3.14, "words", etc.
63+
#: The description name chosen is non-ambiguous and cannot naturally
64+
#: occur in Fortran (with/out C preproc) code
65+
#: It is invalid syntax to define a type starting with numerics
66+
#: it cannot also be a comment that requires !, c, d
67+
#: and ^= (xor_eq) operator is invalid in Fortran C++ preproc
68+
FORTRAN_LITERAL = "0^=__LITERAL_INTERNAL_DUMMY_VAR_"
15669

15770
# Fortran Regular Expressions dataclass variable, immutable
15871
FRegex = FortranRegularExpressions()

fortls/ftypes.py

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
from __future__ import annotations
2+
3+
from dataclasses import dataclass, field
4+
from typing import NamedTuple
5+
6+
#: A single line range tuple
7+
Range = NamedTuple("Range", [("start", int), ("end", int)])
8+
9+
10+
@dataclass
11+
class VAR_info:
12+
"""Holds information about a Fortran VARIABLE"""
13+
14+
var_type: str #: Type of variable e.g. ``INTEGER``, ``REAL``, etc.
15+
#: keywords associated with this variable e.g. SAVE, DIMENSION, etc.
16+
keywords: list[str] #: Keywords associated with variable
17+
var_names: list[str] #: Variable names
18+
19+
20+
@dataclass
21+
class SELECT_info:
22+
"""Holds information about a SELECT construct"""
23+
24+
type: int #: Type of SELECT e.g. normal, select type, select kind, select rank
25+
binding: str #: Variable/Object being selected upon
26+
desc: str #: Description of select e.g. "TYPE", "CLASS", None
27+
28+
29+
@dataclass
30+
class CLASS_info:
31+
"""Holds information about a Fortran CLASS"""
32+
33+
name: str #: Class name
34+
parent: str #: Parent object of class e.g. ``TYPE, EXTENDS(scaled_vector) :: a``
35+
keywords: str #: Keywords associated with the class
36+
37+
38+
@dataclass
39+
class USE_info:
40+
"""Holds information about a Fortran USE statement"""
41+
42+
mod_name: str #: Module name
43+
#: List of procedures, variables, interfaces, etc. imported via only
44+
only_list: set[str]
45+
#: A dictionary holding the new names after a rename operation
46+
rename_map: dict[str, str]
47+
48+
49+
@dataclass
50+
class GEN_info:
51+
"""Holds information about a GENERIC PROCEDURE DEFINITION"""
52+
53+
bound_name: str #: Procedure name
54+
pro_links: list[str] #: Procedure links
55+
vis_flag: int #: Visibility flag, public or private
56+
57+
58+
@dataclass
59+
class SMOD_info:
60+
"""Holds information about Fortran SUBMODULES"""
61+
62+
name: str #: Submodule name
63+
parent: str #: Submodule i.e. module, parent
64+
65+
66+
@dataclass
67+
class INT_info:
68+
"""Holds information about a Fortran INTERFACE"""
69+
70+
name: str #: Interface name
71+
abstract: bool #: Whether or not the interface is abstract
72+
73+
74+
@dataclass
75+
class VIS_info:
76+
"""Holds information about the VISIBILITY of a module's contents"""
77+
78+
type: int #: Visibility type 0: PUBLIC 1: PRIVATE TODO: convert to boolean
79+
obj_names: list[str] #: Module variables, procedures, etc. with that visibility
80+
81+
82+
@dataclass
83+
class INCLUDE_info:
84+
"""Holds information about a Fortran INCLUDE statement"""
85+
86+
line_number: int #: Line number of include
87+
path: str #: File path to include
88+
file: None # fortran_file #: fortran_file object
89+
scope_objs: list[str] #: A list of available scopes
90+
91+
92+
@dataclass
93+
class SUB_info:
94+
"""Holds information about a Fortran SUBROUTINE"""
95+
96+
name: str #: Procedure name
97+
args: str #: Argument list
98+
#: Keywords associated with procedure
99+
keywords: list[str] = field(default_factory=list)
100+
#: Whether or not this is a ``MODULE PROCEDURE``
101+
mod_flag: bool = field(default=False)
102+
103+
104+
@dataclass
105+
class RESULT_sig:
106+
"""Holds information about the RESULT section of a Fortran FUNCTION"""
107+
108+
name: str = field(default=None) #: Variable name of result
109+
type: str = field(default=None) #: Variable type of result
110+
#: Keywords associated with the result variable, can append without init
111+
keywords: list[str] = field(default_factory=list)
112+
113+
114+
@dataclass
115+
class FUN_sig(SUB_info):
116+
"""Holds information about a Fortran FUNCTION"""
117+
118+
#: Function's result with default ``result.name = name``
119+
result: RESULT_sig = field(default_factory=RESULT_sig)
120+
121+
def __post_init__(self):
122+
if not self.result.name:
123+
self.result.name = self.name

0 commit comments

Comments
 (0)