Closed Ganimed closed 6 years ago
Just a few comments. In https://se.mathworks.com/help/matlab/matlab_oop/defining-properties.html and https://se.mathworks.com/help/matlab/matlab_oop/validate-property-values.html the notation for types on properties is a bit different than what you showed, but the end result is the same error.
classdef PropertiesWithType
% PROPERTIESWITHTYPE is a data type (class) for specific links.
%
% Args:
% link_name (string): Name of the reference link.
% pos (double, vector): Cartesian position of the link.
% rotm (double, matrix): (3 x 3) rotation matrix.
% idx (uint8, scalar): Index of the reference link.
properties
link_name string = 'none';
pos(3, 1) double = zeros(3,1);
rotm(3,3) double = eye(3,3);
idx uint8 = 0;
end
end
Regarding the comment header, just keep a empty line between the docstring and the header like
function a = rot(b)
% Some docstring
%* Copyright header
% ...
%*
Thank's for the fast response. I have checked your links above. Your example is a newer variant of setting types for properties. I have found out, that the undocumented syntax that I use, is an older and stricter variant of the newer version which was officially introduced in Matlab R2016a. So the newer variant is quite young. I guess, there are still some variants under development.
Thank's for the information about the comment header. Now I know how to do it. But there is no possibility to put it outside of a class or single function, i.e. when the class/function is very small and the comment header is quite large?
By the way, this link is also quite interesting: https://undocumentedmatlab.com/blog/setting-class-property-types-2
Thanks for the link.
You are right about the new syntax being introduced in Matlab 2016a, and as far I can tell the size restrictions are first documented in Matlab 2017a (https://se.mathworks.com/help/releases/R2017a/matlab/matlab_oop/validate-property-values.html).
I'm mostly for only supporting the official syntax, but the first task is to figure out how to support property types. I'm still not sure what will be best. I could start out with not throwing an error :)
I fully agree with you, but I have read in setting-class-property-types-2, that the older syntax is backward compatible until R2010a and quite a lot of professional Matlab-programmer using it, whereas the newer (official) syntax is only supported from R2016a/R2017a and newer. Furthermore nobody knows how long the older syntax will be supported by Matlab or if it will be officially introduced later. I have also the feeling, that in the next releases (≥ R2018a) new changes will be come out stepwisely.
I would suggest, if somebody is using the old syntax beginning with the "@" symbol after the variable name, that the parser is cutting out this section of the line and sticking the rest ("=" symbol with default value or a comment/docstring) together. I.e. the parser will ignore this part.
For the newer syntax, an own sub-function for parsing should be helpful. Maybe with the help of regular expression you can parse the round brackets "( )" for the dimensions and the corresponding type. The function-part with the curly brackets "{ }", I would cut it out (there are too many special function names to be cared) or, add it to the comment line as it is.
For example the following code line,
Label(1,:) char {mustBeMember(Label,{'High','Medium','Low'})} = 'Low'; % This is a special label.
,
will be converted to "Label (char, vector) - This is a special label. Restricted to: mustBeMember(Label,{'High', 'Medium', 'Low'})".
Moreover, the dimensions of the properties could be interpreted by the parser as,
At the moment I can make only some suggestions, I have not the time to help in coding (maybe later).
In accordance to the comment header, I have to set the header on the top of the file. Maybe I will add this part by myself to the parser (when I have time). But this is not urgent now.
Thanks for the suggestions.
I cannot recommend comment header in the top of the file, sphinxcontrib-matlabdomain will ignore the file.
Sorry, I should have chimed in here. The ethic of the MATLAB domain is to use the Pygments MATLAB lexer to parse the code. Therefore, if there is an issue with interpretation of the MATLAB code, then this should be pushed up to Pygments, not posted here. Of course the MATLAB lexicon is changing every year. It should not be Sphinx's job to keep up with a languages lexicon, other than to know how to format it for publishing the API. Does that help clarify anything? If not, of course, you can ignore me.
Do you know what tokens Pygments is returning for these new properties blocks?
Using this class as input
classdef PropTypeOld
properties
link_name@char = 'none';
pos@double vector = zeros(3,1);
rotm@double matrix = zeros(3,3);
idx@uint8 scalar = 0;
end
end
Produces this list of tokens from Pygments
[(Token.Keyword, 'classdef'),
(Token.Text, ' '),
(Token.Name, 'PropTypeOld'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Keyword, 'properties'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'link_name'),
(Token.Punctuation, '@'),
(Token.Name, 'char'),
(Token.Text, ' '),
(Token.Punctuation, '='),
(Token.Text, ' '),
(Token.Literal.String, "'"),
(Token.Literal.String, "none'"),
(Token.Punctuation, ';'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'pos'),
(Token.Punctuation, '@'),
(Token.Name, 'double'),
(Token.Text, ' '),
(Token.Name, 'vector'),
(Token.Text, ' '),
(Token.Punctuation, '='),
(Token.Text, ' '),
(Token.Name.Builtin, 'zeros'),
(Token.Punctuation, '('),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ','),
(Token.Literal.Number.Integer, '1'),
(Token.Punctuation, ')'),
(Token.Punctuation, ';'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'rotm'),
(Token.Punctuation, '@'),
(Token.Name, 'double'),
(Token.Text, ' '),
(Token.Name, 'matrix'),
(Token.Text, ' '),
(Token.Punctuation, '='),
(Token.Text, ' '),
(Token.Name.Builtin, 'zeros'),
(Token.Punctuation, '('),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ','),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ')'),
(Token.Punctuation, ';'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'idx'),
(Token.Punctuation, '@'),
(Token.Name, 'uint8'),
(Token.Text, ' '),
(Token.Name, 'scalar'),
(Token.Text, ' '),
(Token.Punctuation, '='),
(Token.Text, ' '),
(Token.Literal.Number.Integer, '0'),
(Token.Punctuation, ';'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Keyword, 'end'),
(Token.Text, '\n'),
(Token.Keyword, 'end'),
(Token.Text, '\n')]
Given a new style class
classdef PropTypeNew
properties
link_name string = 'none';
pos(3,1) double = zeros(3,1);
rotm(3,3) double = eye(3,3);
idx uint8 = 0;
end
end
Produces this list of tokens
[(Token.Keyword, 'classdef'),
(Token.Text, ' '),
(Token.Name, 'PropTypeNew'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Keyword, 'properties'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'link_name'),
(Token.Text, ' '),
(Token.Name, 'string'),
(Token.Text, ' '),
(Token.Punctuation, '='),
(Token.Text, ' '),
(Token.Literal.String, "'"),
(Token.Literal.String, "none'"),
(Token.Punctuation, ';'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'pos'),
(Token.Punctuation, '('),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ','),
(Token.Literal.Number.Integer, '1'),
(Token.Punctuation, ')'),
(Token.Text, ' '),
(Token.Name, 'double'),
(Token.Text, ' '),
(Token.Punctuation, '='),
(Token.Text, ' '),
(Token.Name.Builtin, 'zeros'),
(Token.Punctuation, '('),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ','),
(Token.Literal.Number.Integer, '1'),
(Token.Punctuation, ')'),
(Token.Punctuation, ';'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'rotm'),
(Token.Punctuation, '('),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ','),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ')'),
(Token.Text, ' '),
(Token.Name, 'double'),
(Token.Text, ' '),
(Token.Punctuation, '='),
(Token.Text, ' '),
(Token.Name.Builtin, 'eye'),
(Token.Punctuation, '('),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ','),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ')'),
(Token.Punctuation, ';'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'idx'),
(Token.Text, ' '),
(Token.Name, 'uint8'),
(Token.Text, ' '),
(Token.Punctuation, '='),
(Token.Text, ' '),
(Token.Literal.Number.Integer, '0'),
(Token.Punctuation, ';'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Keyword, 'end'),
(Token.Text, '\n'),
(Token.Keyword, 'end'),
(Token.Text, '\n')]
So it look OK to me. A property with type, can be a series of ((Token.Name, '...'),[Token.Text or Token.Punctuation],[(Token.Name, '...')).
So the Matlab-Lexer from Pygments is parsing both variants, the old and the new syntax, correctly (or it seems to be). But then is the question what is causing the exception?
@joeced: I have tried out (just for fun) if the sphinxcontrib-matlabdomain will really ignore a file, if inside is a comment header or any comment at first. And I must say it does not, the parser will crash for functions and classes (scripts are not tested yet):
Exception occurred:
File "/usr/local/lib/python2.7/dist-packages/sphinxcontrib/mat_types.py", line 1104, in for_module
obj = cls.for_folder(mod.path, modname)
AttributeError: 'module' object has no attribute 'path'
In this case I would open a second issue. Furthermore I have made already a solution for it. Sorry that I'm producing some work.
Just for reference i tried an example from https://se.mathworks.com/help/matlab/matlab_oop/validate-property-values.html
classdef ValidateProps
properties
Location(1,3) double {mustBeReal, mustBeFinite}
Label(1,:) char {mustBeMember(Label,{'High','Medium','Low'})} = 'Low'
State(1,1) matlab.lang.OnOffSwitchState
end
end
Which produces this list of tokens
[(Token.Keyword, 'classdef'),
(Token.Text, ' '),
(Token.Name, 'ValidateProps'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Keyword, 'properties'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'Location'),
(Token.Punctuation, '('),
(Token.Literal.Number.Integer, '1'),
(Token.Punctuation, ','),
(Token.Literal.Number.Integer, '3'),
(Token.Punctuation, ')'),
(Token.Text, ' '),
(Token.Name, 'double'),
(Token.Text, ' '),
(Token.Punctuation, '{'),
(Token.Name, 'mustBeReal'),
(Token.Punctuation, ','),
(Token.Text, ' '),
(Token.Name, 'mustBeFinite'),
(Token.Punctuation, '}'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'Label'),
(Token.Punctuation, '('),
(Token.Literal.Number.Integer, '1'),
(Token.Punctuation, ','),
(Token.Punctuation, ':'),
(Token.Punctuation, ')'),
(Token.Text, ' '),
(Token.Name, 'char'),
(Token.Text, ' '),
(Token.Punctuation, '{'),
(Token.Name, 'mustBeMember'),
(Token.Punctuation, '('),
(Token.Name, 'Label'),
(Token.Punctuation, ','),
(Token.Punctuation, '{'),
(Token.Literal.String, "'"),
(Token.Literal.String, "High'"),
(Token.Punctuation, ','),
(Token.Literal.String, "'"),
(Token.Literal.String, "Medium'"),
(Token.Punctuation, ','),
(Token.Literal.String, "'"),
(Token.Literal.String, "Low'"),
(Token.Punctuation, '}'),
(Token.Punctuation, ')'),
(Token.Punctuation, '}'),
(Token.Text, ' '),
(Token.Punctuation, '='),
(Token.Text, ' '),
(Token.Literal.String, "'"),
(Token.Literal.String, "Low'"),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Name, 'State'),
(Token.Punctuation, '('),
(Token.Literal.Number.Integer, '1'),
(Token.Punctuation, ','),
(Token.Literal.Number.Integer, '1'),
(Token.Punctuation, ')'),
(Token.Text, ' '),
(Token.Name, 'matlab'),
(Token.Punctuation, '.'),
(Token.Name, 'lang'),
(Token.Punctuation, '.'),
(Token.Name, 'OnOffSwitchState'),
(Token.Text, '\n'),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Text, ' '),
(Token.Keyword, 'end'),
(Token.Text, '\n'),
(Token.Keyword, 'end'),
(Token.Text, '\n')]
Firstly, I'll work on sphinxcontrib-matlabdomain, not crashing while parsing property types/classes. The key thing that separates the properties are (Token.Text, '\n')
. I'm doing this in the property_types branch.
That's a good idea for the begin. In the next days I will check your property_types
branch. Maybe I can help.
Dear all,
In the last 3 Years Mathworks made a lot of changes and extensions for the Matlab-language, i.e. in OO-programming.
Currently I'm documenting my Matlab-Library for my thesis. In this library I needed to use very often the new (undocumented) syntax extensions to enforce the property types for the class property names. These new extensions are very helpful and makes the verification very easy if a property has the correct type. See following discussions below:
In general, the new syntax for the class properties is defined as follows:
For the
dimensionType
there are three possible options, matrix, vector or scalar.I have made a very simple test class which has only properties. For example this simple class works in Sphinx with your latest matlabdomain very well:
But when I replace the above properties with
Then I will get following error from your parser:
Here is the full log:
Sphinx is with its plugins one of the best documentation tools, but unfortunately all current parser for documenting code in Matlab doesn't support this new syntax.
Is it possible to extend the parser with this new syntax s.t. Sphinx can interpret the new property syntax like below (in Google style with Napoleon)?
Or optional, which should be easier, is it possible that the new syntax right beside the property name will be ignored by the parser?
By the way, I have to set also a comment header into each file (copyright, license, etc.), like in C/C++:
% This is an Comment Header % Copyright (C) 2018, by John Doe. % % some descriptions ... % % lisence (GPL, BSD, etc.) %%
How is it possible, or how can I force, that the parser of the matlabdomain will ignore this comment header without raising any errors?
Thank you very much in advance!
With best regards, Ganimed.