Skip to content

Commit

Permalink
address PR comments made by @joeced
Browse files Browse the repository at this point in the history
  • Loading branch information
apozharski committed Sep 5, 2024
1 parent 3e4f778 commit 2a40cd1
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 57 deletions.
90 changes: 55 additions & 35 deletions sphinxcontrib/mat_tree_sitter_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,41 @@
from tree_sitter import Language, Parser
import re

# rpath = "../../../syscop/software/nosnoc/+nosnoc/Options.m"
rpath = "/home/anton/tools/matlabdomain/tests/test_data/ClassWithTrailingCommentAfterBases.m"
# rpath = "/home/anton/tools/matlabdomain/tests/test_data/f_with_dummy_argument.m"
# Attribute default dictionary used to give default values for e.g. `Abstract` or `Static` when used without
# a right hand side i.e. `classdef (Abstract)` vs `classdef (Abstract=true)`
# From:
# - http://www.mathworks.com/help/matlab/matlab_oop/class-attributes.html
# - https://mathworks.com/help/matlab/matlab_oop/property-attributes.html
# - https://mathworks.com/help/matlab/matlab_prog/define-property-attributes-1.htm
# - https://mathworks.com/help/matlab/matlab_oop/method-attributes.html
# - https://mathworks.com/help/matlab/ref/matlab.unittest.testcase-class.html
MATLAB_ATTRIBUTE_DEFAULTS = {
"AbortSet": True,
"Abstract": True,
"ClassSetupParameter": True,
"Constant": True,
"ConstructOnLoad": True,
"Dependent": True,
"DiscreteState": True,
"GetObservable": True,
"HandleCompatible": True,
"Hidden": True,
"MethodSetupParameter": True,
"NonCopyable": True,
"Nontunable": True,
"PartialMatchPriority": True,
"Sealed": True,
"SetObservable": True,
"Static": True,
"Test": None,
"TestClassSetup": None,
"TestClassTeardown": None,
"TestMethodSetup": None,
"TestMethodTeardown": None,
"TestParameter": None,
"Transient": True,
}


tree_sitter_ver = tuple([int(sec) for sec in version("tree_sitter").split(".")])
if tree_sitter_ver[1] == 21:
Expand Down Expand Up @@ -499,12 +531,21 @@ def _parse_attributes(self, attrs_nodes):
name = attr_match.get("name").text.decode(
self.encoding, errors="backslashreplace"
)

value_node = attr_match.get("value")
attrs[name] = (
value_node.text.decode(self.encoding, errors="backslashreplace")
if value_node is not None
else None
)
rhs_node = attr_match.get("rhs")
if rhs_node is not None:
if rhs_node.type == "cell":
attrs[name] = [
vn.text.decode(self.encoding, errors="backslashreplace")
for vn in value_node
]
else:
attrs[name] = value_node[0].text.decode(
self.encoding, errors="backslashreplace"
)
else:
attrs[name] = MATLAB_ATTRIBUTE_DEFAULTS.get(name)
return attrs


Expand Down Expand Up @@ -537,13 +578,11 @@ def __init__(self, root_node, encoding):
if supers_nodes is not None:
for super_node in supers_nodes:
_, super_match = q_supers.matches(super_node)[0]
super_cls = tuple(
[
sec.text.decode(self.encoding, errors="backslashreplace")
for sec in super_match.get("secs")
]
)
self.supers.append(super_cls)
super_cls = [
sec.text.decode(self.encoding, errors="backslashreplace")
for sec in super_match.get("secs")
]
self.supers.append(".".join(super_cls))

# get docstring and check that it consecutive
docstring_node = class_match.get("docstring")
Expand Down Expand Up @@ -916,25 +955,6 @@ def _parse_attributes(self, attrs_nodes):
self.encoding, errors="backslashreplace"
)
else:
attrs[name] = None
attrs[name] = MATLAB_ATTRIBUTE_DEFAULTS.get(name)

return attrs


if __name__ == "__main__":
tree_sitter_ver = tuple([int(sec) for sec in version("tree_sitter").split(".")])
if tree_sitter_ver[1] == 21:
parser = Parser()
parser.set_language(ML_LANG)
else:
parser = Parser(ML_LANG)

with open(rpath, "rb") as f:
data = f.read()

tree = parser.parse(data)
class_parser = MatClassParser(tree.root_node, "utf-8")
# fun_parser = MatFunctionParser(tree.root_node)
import pdb

pdb.set_trace()
4 changes: 1 addition & 3 deletions sphinxcontrib/mat_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -842,9 +842,7 @@ def __doc__(self):

@property
def __bases__(self):
bases_ = dict.fromkeys(
[".".join(base) for base in self.bases]
) # make copy of bases
bases_ = dict.fromkeys([base for base in self.bases]) # make copy of bases
class_entity_table = {}
for name, entity in entities_table.items():
if isinstance(entity, MatClass) or "@" in name:
Expand Down
12 changes: 6 additions & 6 deletions tests/test_matlabify.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def test_classes(mod):
assert isinstance(cls, doc.MatClass)
assert cls.getter("__name__") == "ClassInheritHandle"
assert cls.getter("__module__") == "test_data"
assert cls.bases == [("handle",), ("my", "super", "Class")]
assert cls.bases == ["handle", "my.super.Class"]
assert cls.attrs == {}
assert cls.properties == {
"x": {
Expand All @@ -161,8 +161,8 @@ def test_abstract_class(mod):
assert abc.getter("__module__") == "test_data"
assert "ClassInheritHandle" in abc.getter("__bases__")
assert "ClassExample" in abc.getter("__bases__")
assert abc.bases == [("ClassInheritHandle",), ("ClassExample",)]
assert abc.attrs == {"Abstract": None, "Sealed": None}
assert abc.bases == ["ClassInheritHandle", "ClassExample"]
assert abc.attrs == {"Abstract": True, "Sealed": True}
assert abc.properties == {
"y": {
"default": None,
Expand All @@ -175,7 +175,7 @@ def test_abstract_class(mod):
"version": {
"default": "'0.1.1-beta'",
"docstring": "version",
"attrs": {"Constant": None},
"attrs": {"Constant": True},
"size": None,
"type": None,
"validators": None,
Expand All @@ -197,7 +197,7 @@ def test_abstract_class(mod):
assert isinstance(abc_version, doc.MatProperty)
assert abc_version.default == "'0.1.1-beta'"
assert abc_version.docstring == "version"
assert abc_version.attrs == {"Constant": None}
assert abc_version.attrs == {"Constant": True}


def test_class_method(mod):
Expand Down Expand Up @@ -230,7 +230,7 @@ def test_submodule_class(mod):
assert isinstance(cls, doc.MatClass)
assert cls.docstring == "Test of MATLAB unittest method attributes"
assert cls.attrs == {}
assert cls.bases == [("matlab", "unittest", "TestCase")]
assert cls.bases == ["matlab.unittest.TestCase"]
assert "compareFirstThreeElementsToExpected" in cls.methods
assert cls.module == "test_data.submodule"
assert cls.properties == {}
Expand Down
26 changes: 13 additions & 13 deletions tests/test_parse_mfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,8 +366,8 @@ def test_ClassWithMethodAttributes():
assert obj.methods["testProtected"].attrs == {"Access": "protected"}
assert obj.methods["testPrivate1"].attrs == {"Access": "private"}
assert obj.methods["testPrivate2"].attrs == {"Access": "'private'"}
assert obj.methods["testHidden"].attrs == {"Hidden": None}
assert obj.methods["testStatic"].attrs == {"Static": None}
assert obj.methods["testHidden"].attrs == {"Hidden": True}
assert obj.methods["testStatic"].attrs == {"Static": True}
assert obj.methods["testFriend1"].attrs == {"Access": "?OtherClass"}
assert obj.methods["testFriend2"].attrs == {
"Access": ["?OtherClass", "?pack.OtherClass2"]
Expand Down Expand Up @@ -397,13 +397,13 @@ def test_ClassWithPropertyAttributes():
"GetAccess": "private",
"SetAccess": "private",
}
assert obj.properties["TEST_CONSTANT"]["attrs"] == {"Constant": None}
assert obj.properties["TEST_CONSTANT"]["attrs"] == {"Constant": True}
assert obj.properties["TEST_CONSTANT_PROTECTED"]["attrs"] == {
"Access": "protected",
"Constant": None,
"Constant": True,
}
assert obj.properties["testDependent"]["attrs"] == {"Dependent": None}
assert obj.properties["testHidden"]["attrs"] == {"Hidden": None}
assert obj.properties["testDependent"]["attrs"] == {"Dependent": True}
assert obj.properties["testHidden"]["attrs"] == {"Hidden": True}


def test_ClassWithoutIndent():
Expand Down Expand Up @@ -564,7 +564,7 @@ def test_ClassWithAttributes():
obj = mat_types.MatObject.parse_mfile(mfile, "ClassWithAttributes", "test_data")
assert isinstance(obj, mat_types.MatClass)
assert obj.name == "ClassWithAttributes"
assert obj.attrs == {"Sealed": None}
assert obj.attrs == {"Sealed": True}


# Fails when running with other test files. Warnings are already logged.
Expand Down Expand Up @@ -696,7 +696,7 @@ def test_ClassWithMethodsWithSpaces():
assert (
obj.docstring == "Class with methods that have space after the function name."
)
assert obj.methods["static_method"].attrs == {"Static": None}
assert obj.methods["static_method"].attrs == {"Static": True}


def test_ClassContainingParfor():
Expand Down Expand Up @@ -779,7 +779,7 @@ def test_ClassWithTrailingCommentAfterBases():
mfile, "ClassWithTrailingCommentAfterBases", "test_data"
)
assert obj.name == "ClassWithTrailingCommentAfterBases"
assert obj.bases == [("handle",), ("my", "super", "Class")]
assert obj.bases == ["handle", "my.super.Class"]
assert (
obj.docstring
== "test class methods\n\n:param a: the input to :class:`ClassWithTrailingCommentAfterBases`"
Expand All @@ -801,7 +801,7 @@ def test_ClassWithEllipsisProperties():
mfile, "ClassWithEllipsisProperties", "test_data"
)
assert obj.name == "ClassWithEllipsisProperties"
assert obj.bases == [("handle",)]
assert obj.bases == ["handle"]
assert obj.docstring == "stuff"
assert len(obj.methods) == 0

Expand Down Expand Up @@ -846,7 +846,7 @@ def test_ClassWithTrailingSemicolons():
obj.docstring
== "Smoothing like it is performed withing Cxx >v7.0 (until v8.2 at least).\nUses constant 228p_12k frequency vector:"
)
assert obj.bases == [("hgsetget",)]
assert obj.bases == ["hgsetget"]
assert list(obj.methods.keys()) == [
"ClassWithTrailingSemicolons",
"CxxSmoothing",
Expand Down Expand Up @@ -896,7 +896,7 @@ def test_ClassWithNamedAsArguments():
mfile = os.path.join(TESTDATA_ROOT, "arguments.m")
obj = mat_types.MatObject.parse_mfile(mfile, "arguments", "test_data")
assert obj.name == "arguments"
assert obj.bases == [("handle",), ("matlab", "mixin", "Copyable")]
assert obj.bases == ["handle", "matlab.mixin.Copyable"]
assert "value" in obj.properties
meth = obj.methods["arguments"]
assert meth.docstring == "Constructor for arguments"
Expand All @@ -919,7 +919,7 @@ def test_ClassWithTests():
mfile = os.path.join(TESTDATA_ROOT, "ClassWithTests.m")
obj = mat_types.MatObject.parse_mfile(mfile, "ClassWithTests", "test_data")
assert obj.name == "ClassWithTests"
assert obj.bases == [("matlab", "unittest", "TestCase")]
assert obj.bases == ["matlab.unittest.TestCase"]
assert "testRunning" in obj.methods
testRunning = obj.methods["testRunning"]
assert testRunning.attrs["TestTags"] == ["'Unit'"]
Expand Down

0 comments on commit 2a40cd1

Please sign in to comment.