From 68c9c170e7377f1f05fe00a84baacba3c063e52d Mon Sep 17 00:00:00 2001 From: Florian Schanda Date: Sun, 21 Aug 2022 12:30:15 +0200 Subject: [PATCH] #86 Allow specification of MATLAB/Octave language Previously there was a very rough switch --octave. Now there is a very fine-grained control of the language dialect; but this brings with it some minor backwards incompatibilities. In particular: * the --octave parameter now has a mandatory argument, if you want to get to the old behaviour use --octave=latest * the octave config file entry still works when using "octave: true" (but you get a deprecation warning soon). The entry "octave: false" is now an error This should also enable finally fixing #240. Closes #86 Closes #258 --- CHANGELOG.md | 22 +- docs/configuration.html | 30 +- mh_debug_parser | 10 +- miss_hit/mh_bmc.py | 7 +- miss_hit/mh_copyright.py | 13 +- miss_hit/mh_lint.py | 7 +- miss_hit/mh_trace.py | 7 +- miss_hit_core/cfg_ast.py | 56 +- miss_hit_core/cfg_parser.py | 136 ++-- miss_hit_core/cfg_tree.py | 6 +- miss_hit_core/command_line.py | 50 +- miss_hit_core/config.py | 18 +- miss_hit_core/m_ast.py | 24 +- miss_hit_core/m_language.py | 396 ++++++++-- miss_hit_core/m_lexer.py | 122 ++- miss_hit_core/m_parser.py | 27 +- miss_hit_core/mh_metric.py | 11 +- miss_hit_core/mh_style.py | 15 +- miss_hit_core/s_parser.py | 6 +- tests/config_parser/language/invalid_1.cfg | 11 + .../config_parser/language/invalid_1.cfg.out | 32 + tests/config_parser/language/valid_1.cfg | 27 + tests/config_parser/language/valid_1.cfg.out | 25 + tests/copyright/octave/cmdline | 2 +- .../invalid_05.m.octave.out | 16 + .../argument_validation/test_01.m.octave.out | 7 + .../argument_validation/test_02.m.octave.out | 7 + .../argument_validation/test_03.m.octave.out | 16 + .../argument_validation/test_04.m.octave.out | 13 + .../argument_validation/test_05.m.octave.out | 7 + .../argument_validation/test_07.m.octave.out | 7 + .../argument_validation/test_09.m.octave.out | 7 + .../argument_validation/test_10.m.octave.out | 16 + .../argument_validation/test_12.m.octave.out | 7 + .../argument_validation/test_14.m.octave.out | 13 + .../argument_validation/test_15.m.octave.out | 13 + .../argument_validation/test_17.m.octave.out | 13 + .../argument_validation/test_19.m.octave.out | 7 + .../argument_validation/test_21.m.octave.out | 13 + .../argument_validation/test_22.m.octave.out | 7 + .../argument_validation/test_24.m.octave.out | 7 + .../argument_validation/test_26.m.octave.out | 16 + .../argument_validation/test_28.m.octave.out | 7 + .../argument_validation/test_30.m.octave.out | 13 + .../argument_validation/test_31.m.octave.out | 7 + .../arguments_as_identifier/test.m.octave.out | 10 + .../property_arguments/test_1.m.octave.out | 7 + .../property_arguments/test_3.m.octave.out | 7 + tests/parser/scripts/bar.m.out | 2 +- tests/parser/spmd/test_01.m.octave.out | 7 + .../language/matlab_2017b/cdef_subfun.m | 9 + .../projects/language/matlab_2017b/comments.m | 1 + .../language/matlab_2017b/fun_contract.m | 7 + tests/projects/language/matlab_2017b/hexlit.m | 3 + .../matlab_2017b/ident_with_underscore.m | 3 + .../language/matlab_2017b/miss_hit.cfg | 1 + .../projects/language/matlab_2017b/negation.m | 3 + .../projects/language/matlab_2017b/sa_pair.m | 3 + .../language/matlab_2017b/script_global.m | 9 + .../language/matlab_2017b/shellescape.m | 3 + .../language/matlab_2020b/cdef_subfun.m | 9 + .../projects/language/matlab_2020b/comments.m | 1 + .../language/matlab_2020b/fun_contract.m | 7 + tests/projects/language/matlab_2020b/hexlit.m | 3 + .../matlab_2020b/ident_with_underscore.m | 3 + .../language/matlab_2020b/miss_hit.cfg | 1 + .../projects/language/matlab_2020b/negation.m | 3 + .../projects/language/matlab_2020b/sa_pair.m | 3 + .../language/matlab_2020b/script_global.m | 9 + .../language/matlab_2020b/shellescape.m | 3 + .../language/matlab_2021a/cdef_subfun.m | 9 + .../projects/language/matlab_2021a/comments.m | 1 + .../language/matlab_2021a/fun_contract.m | 7 + tests/projects/language/matlab_2021a/hexlit.m | 3 + .../matlab_2021a/ident_with_underscore.m | 3 + .../language/matlab_2021a/miss_hit.cfg | 1 + .../projects/language/matlab_2021a/negation.m | 3 + .../projects/language/matlab_2021a/sa_pair.m | 3 + .../language/matlab_2021a/script_global.m | 9 + .../language/matlab_2021a/shellescape.m | 3 + tests/projects/language/mh_trace.json | 29 + tests/projects/language/miss_hit.cfg | 4 + .../language/octave_4_2/cdef_subfun.m | 9 + tests/projects/language/octave_4_2/comments.m | 1 + .../language/octave_4_2/fun_contract.m | 7 + tests/projects/language/octave_4_2/hexlit.m | 3 + .../octave_4_2/ident_with_underscore.m | 3 + .../projects/language/octave_4_2/miss_hit.cfg | 1 + tests/projects/language/octave_4_2/negation.m | 3 + tests/projects/language/octave_4_2/sa_pair.m | 3 + .../language/octave_4_2/script_global.m | 9 + .../language/octave_4_2/shellescape.m | 3 + .../language/octave_4_4/cdef_subfun.m | 9 + tests/projects/language/octave_4_4/comments.m | 1 + .../language/octave_4_4/fun_contract.m | 7 + tests/projects/language/octave_4_4/hexlit.m | 3 + .../octave_4_4/ident_with_underscore.m | 3 + .../projects/language/octave_4_4/miss_hit.cfg | 1 + tests/projects/language/octave_4_4/negation.m | 3 + tests/projects/language/octave_4_4/sa_pair.m | 3 + .../language/octave_4_4/script_global.m | 9 + .../language/octave_4_4/shellescape.m | 3 + tests/projects/language/output.txt | 717 ++++++++++++++++++ .../expected_out.html | 2 +- .../expected_out.txt | 2 +- .../style/program_order/octave/Not_Valid_1.m | 4 - .../program_order/octave/Not_Valid_1.m_fixed | 4 - .../style/program_order/octave/Not_Valid_2.m | 4 - .../program_order/octave/Not_Valid_2.m_fixed | 4 - .../style/program_order/octave/Not_Valid_4.m | 4 - .../program_order/octave/Not_Valid_4.m_fixed | 4 - .../style/program_order/octave/Not_Valid_5.m | 4 - .../program_order/octave/Not_Valid_5.m_fixed | 4 - .../style/program_order/octave/Not_Valid_6.m | 4 - .../program_order/octave/Not_Valid_6.m_fixed | 4 - tests/style/program_order/octave/Valid_1.m | 4 - .../program_order/octave/Valid_1.m_fixed | 4 - tests/style/program_order/octave/Valid_2.m | 4 - .../program_order/octave/Valid_2.m_fixed | 4 - tests/style/program_order/octave/Valid_4.m | 4 - .../program_order/octave/Valid_4.m_fixed | 4 - tests/style/program_order/octave/Valid_5.m | 4 - .../program_order/octave/Valid_5.m_fixed | 4 - tests/style/program_order/octave/Valid_6.m | 4 - .../program_order/octave/Valid_6.m_fixed | 4 - 125 files changed, 1975 insertions(+), 381 deletions(-) create mode 100644 tests/config_parser/language/invalid_1.cfg create mode 100644 tests/config_parser/language/invalid_1.cfg.out create mode 100644 tests/config_parser/language/valid_1.cfg create mode 100644 tests/config_parser/language/valid_1.cfg.out create mode 100644 tests/parser/argument_validation/invalid_05.m.octave.out create mode 100644 tests/parser/argument_validation/test_01.m.octave.out create mode 100644 tests/parser/argument_validation/test_02.m.octave.out create mode 100644 tests/parser/argument_validation/test_03.m.octave.out create mode 100644 tests/parser/argument_validation/test_04.m.octave.out create mode 100644 tests/parser/argument_validation/test_05.m.octave.out create mode 100644 tests/parser/argument_validation/test_07.m.octave.out create mode 100644 tests/parser/argument_validation/test_09.m.octave.out create mode 100644 tests/parser/argument_validation/test_10.m.octave.out create mode 100644 tests/parser/argument_validation/test_12.m.octave.out create mode 100644 tests/parser/argument_validation/test_14.m.octave.out create mode 100644 tests/parser/argument_validation/test_15.m.octave.out create mode 100644 tests/parser/argument_validation/test_17.m.octave.out create mode 100644 tests/parser/argument_validation/test_19.m.octave.out create mode 100644 tests/parser/argument_validation/test_21.m.octave.out create mode 100644 tests/parser/argument_validation/test_22.m.octave.out create mode 100644 tests/parser/argument_validation/test_24.m.octave.out create mode 100644 tests/parser/argument_validation/test_26.m.octave.out create mode 100644 tests/parser/argument_validation/test_28.m.octave.out create mode 100644 tests/parser/argument_validation/test_30.m.octave.out create mode 100644 tests/parser/argument_validation/test_31.m.octave.out create mode 100644 tests/parser/arguments_as_identifier/test.m.octave.out create mode 100644 tests/parser/property_arguments/test_1.m.octave.out create mode 100644 tests/parser/property_arguments/test_3.m.octave.out create mode 100644 tests/parser/spmd/test_01.m.octave.out create mode 100644 tests/projects/language/matlab_2017b/cdef_subfun.m create mode 100644 tests/projects/language/matlab_2017b/comments.m create mode 100644 tests/projects/language/matlab_2017b/fun_contract.m create mode 100644 tests/projects/language/matlab_2017b/hexlit.m create mode 100644 tests/projects/language/matlab_2017b/ident_with_underscore.m create mode 100644 tests/projects/language/matlab_2017b/miss_hit.cfg create mode 100644 tests/projects/language/matlab_2017b/negation.m create mode 100644 tests/projects/language/matlab_2017b/sa_pair.m create mode 100644 tests/projects/language/matlab_2017b/script_global.m create mode 100644 tests/projects/language/matlab_2017b/shellescape.m create mode 100644 tests/projects/language/matlab_2020b/cdef_subfun.m create mode 100644 tests/projects/language/matlab_2020b/comments.m create mode 100644 tests/projects/language/matlab_2020b/fun_contract.m create mode 100644 tests/projects/language/matlab_2020b/hexlit.m create mode 100644 tests/projects/language/matlab_2020b/ident_with_underscore.m create mode 100644 tests/projects/language/matlab_2020b/miss_hit.cfg create mode 100644 tests/projects/language/matlab_2020b/negation.m create mode 100644 tests/projects/language/matlab_2020b/sa_pair.m create mode 100644 tests/projects/language/matlab_2020b/script_global.m create mode 100644 tests/projects/language/matlab_2020b/shellescape.m create mode 100644 tests/projects/language/matlab_2021a/cdef_subfun.m create mode 100644 tests/projects/language/matlab_2021a/comments.m create mode 100644 tests/projects/language/matlab_2021a/fun_contract.m create mode 100644 tests/projects/language/matlab_2021a/hexlit.m create mode 100644 tests/projects/language/matlab_2021a/ident_with_underscore.m create mode 100644 tests/projects/language/matlab_2021a/miss_hit.cfg create mode 100644 tests/projects/language/matlab_2021a/negation.m create mode 100644 tests/projects/language/matlab_2021a/sa_pair.m create mode 100644 tests/projects/language/matlab_2021a/script_global.m create mode 100644 tests/projects/language/matlab_2021a/shellescape.m create mode 100644 tests/projects/language/mh_trace.json create mode 100644 tests/projects/language/miss_hit.cfg create mode 100644 tests/projects/language/octave_4_2/cdef_subfun.m create mode 100644 tests/projects/language/octave_4_2/comments.m create mode 100644 tests/projects/language/octave_4_2/fun_contract.m create mode 100644 tests/projects/language/octave_4_2/hexlit.m create mode 100644 tests/projects/language/octave_4_2/ident_with_underscore.m create mode 100644 tests/projects/language/octave_4_2/miss_hit.cfg create mode 100644 tests/projects/language/octave_4_2/negation.m create mode 100644 tests/projects/language/octave_4_2/sa_pair.m create mode 100644 tests/projects/language/octave_4_2/script_global.m create mode 100644 tests/projects/language/octave_4_2/shellescape.m create mode 100644 tests/projects/language/octave_4_4/cdef_subfun.m create mode 100644 tests/projects/language/octave_4_4/comments.m create mode 100644 tests/projects/language/octave_4_4/fun_contract.m create mode 100644 tests/projects/language/octave_4_4/hexlit.m create mode 100644 tests/projects/language/octave_4_4/ident_with_underscore.m create mode 100644 tests/projects/language/octave_4_4/miss_hit.cfg create mode 100644 tests/projects/language/octave_4_4/negation.m create mode 100644 tests/projects/language/octave_4_4/sa_pair.m create mode 100644 tests/projects/language/octave_4_4/script_global.m create mode 100644 tests/projects/language/octave_4_4/shellescape.m create mode 100644 tests/projects/language/output.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index bdd038f1..5b41a093 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,14 +20,32 @@ Not quite compatible with Octave yet. See #43 [octave support](https://github.co ### 0.9.35-dev - +* You can now specify more precise Octave and MATLAB versions. This + change is massive, and likely to have subtle bugs. You can now write + `octave: "4.4"` or `matlab: "2020b"` in your config files; or specify + `--octave=4.4` or `--matlab=2020b` from the command-line. There is + also a special `latest` version for both Octave and MATLAB, which is + an alias for the latest supported version. + + This is also the first change that introduces backwards + incompatibility, specifically: + * The command-line option `--octave` no longer works. You need to + specify `--octave=latest` to get the same behaviour. + * The config setting `octave: true` still works, but is + deprecated. It means the same thing as `octave: "latest"`. + * The config setting `octave: false` doesn't make sense anymore (and + never really did), so it now raises an error. + + As always note that for MATLAB, support should be faily good and + accurate. For Octave many things are missing (such as the `end_X` + set of keywords). I do plan to improve the situation, but please + create tickets for things you need sooner. ### 0.9.34 * Relaxed docstring recognition: now you can have blank lines (without the comment indicator) in your docstring. - ### 0.9.33 * Add a new configuration option "indent_function_file_body" for MH diff --git a/docs/configuration.html b/docs/configuration.html index 6d175d86..def6e0b2 100644 --- a/docs/configuration.html +++ b/docs/configuration.html @@ -474,7 +474,7 @@

STRING

INTEGER

- Grammar:
STRING ::= <non-negative-integer>
+ Grammar:
INTEGER ::= <non-negative-integer>
@@ -578,16 +578,32 @@

Metric configuration

Language dialect

- Grammar:
DIALECT ::= octave ':' BOOLEAN
+ Grammar: +
+DIALECT ::= octave ':' STRING
+          | matlab ':' STRING
+
This directive controls which language is processed by - MISS_HIT. By default we process MATLAB, but if this is set to - true we instead process Octave. + MISS_HIT. By default we process MATLAB (latest). Note that + specifying the dialect option more than once just means the + most recent one takes effect, which is the same for any other + option. +
+
+ The MATLAB version string can be "latest" or a YEAR[ab] + string, such as "2017b". The earliest MATLAB supported is + 2017b. The latest MATLAB supported is 2022a.
- Please note that Octave support is limited right now, but I - consider it a medium/long term priority. + The OCTAVE version string can be "latest" or a MAJOR.MINOR + string, such as "4.4". The earliest Octave supported is + 4.2. The latest Octave supported is 7.2. Please note that + Octave support is extremely limited right now, but I consider + it a medium/long term priority. Many features are missing, + such as the specific end keywords, the treatment of strings, + default arguments, increments, unwind protect, etc.

Directory exclusion

@@ -691,7 +707,7 @@

Future plans

diff --git a/mh_debug_parser b/mh_debug_parser index b7c0df7f..a05e81eb 100755 --- a/mh_debug_parser +++ b/mh_debug_parser @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2020, Florian Schanda ## +## Copyright (C) 2020-2022, Florian Schanda ## ## ## ## This file is part of MISS_HIT. ## ## ## @@ -29,6 +29,8 @@ import os import traceback +from miss_hit_core.m_language import (MATLAB_Latest_Language, + Octave_Latest_Language) from miss_hit_core.errors import Message_Handler, Error, ICE from miss_hit_core.m_lexer import MATLAB_Lexer, Token_Buffer from miss_hit_core.m_parser import MATLAB_Parser @@ -54,9 +56,11 @@ def sanity_test(mh, filename, show_bt, with open(filename, "r") as fd: content = fd.read() try: - lexer = MATLAB_Lexer(mh, content, filename) if octave_mode: - lexer.set_octave_mode() + language = Octave_Latest_Language() + else: + language = MATLAB_Latest_Language() + lexer = MATLAB_Lexer(language, mh, content, filename) tbuf = Token_Buffer(lexer, Config()) parser = MATLAB_Parser(mh, tbuf, diff --git a/miss_hit/mh_bmc.py b/miss_hit/mh_bmc.py index 86963bd7..5e51b586 100644 --- a/miss_hit/mh_bmc.py +++ b/miss_hit/mh_bmc.py @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2020, Florian Schanda ## +## Copyright (C) 2020-2022, Florian Schanda ## ## ## ## This file is part of MISS_HIT. ## ## ## @@ -337,12 +337,11 @@ def __init__(self, _): @classmethod def process_wp(cls, wp): # Create lexer - lexer = MATLAB_Lexer(wp.mh, + lexer = MATLAB_Lexer(wp.cfg.language, + wp.mh, wp.get_content(), wp.filename, wp.blockname) - if wp.cfg.octave: - lexer.set_octave_mode() if not wp.cfg.pragmas: lexer.process_pragmas = False if len(lexer.text.strip()) == 0: diff --git a/miss_hit/mh_copyright.py b/miss_hit/mh_copyright.py index b35e0b82..16d09c24 100644 --- a/miss_hit/mh_copyright.py +++ b/miss_hit/mh_copyright.py @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2021, Florian Schanda ## +## Copyright (C) 2021-2022, Florian Schanda ## ## ## ## This file is part of MISS_HIT. ## ## ## @@ -33,6 +33,7 @@ from miss_hit_core.m_lexer import MATLAB_Lexer, Token_Buffer from miss_hit_core.m_parser import MATLAB_Parser from miss_hit_core.m_parse_utils import parse_docstrings +from miss_hit_core.m_language import Base_Octave_Language def get_primary_entity(options, cfg): @@ -109,9 +110,11 @@ def process_wp(cls, wp): content = wp.get_content() # Create lexer - lexer = MATLAB_Lexer(wp.mh, content, wp.filename, wp.blockname) - if wp.cfg.octave: - lexer.set_octave_mode() + lexer = MATLAB_Lexer(wp.cfg.language, + wp.mh, + content, + wp.filename, + wp.blockname) if not wp.cfg.pragmas: # pragma: no cover lexer.process_pragmas = False @@ -284,7 +287,7 @@ def process_wp(cls, wp): if wp.options.style == "c_first" or \ (wp.options.style == "dynamic" and - not wp.cfg.octave): + not isinstance(wp.cfg.language, Base_Octave_Language)): copy_notice = "(c) Copyright" else: copy_notice = "Copyright (c)" diff --git a/miss_hit/mh_lint.py b/miss_hit/mh_lint.py index d6399f3b..91e4cb26 100644 --- a/miss_hit/mh_lint.py +++ b/miss_hit/mh_lint.py @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2020-2021, Florian Schanda ## +## Copyright (C) 2020-2022, Florian Schanda ## ## ## ## This file is part of MISS_HIT. ## ## ## @@ -166,12 +166,11 @@ def __init__(self, options): @classmethod def process_wp(cls, wp): # Create lexer - lexer = MATLAB_Lexer(wp.mh, + lexer = MATLAB_Lexer(wp.cfg.language, + wp.mh, wp.get_content(), wp.filename, wp.blockname) - if wp.cfg.octave: - lexer.set_octave_mode() if not wp.cfg.pragmas: lexer.process_pragmas = False if len(lexer.text.strip()) == 0: diff --git a/miss_hit/mh_trace.py b/miss_hit/mh_trace.py index e33d379c..19e0ebb2 100644 --- a/miss_hit/mh_trace.py +++ b/miss_hit/mh_trace.py @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2021, Florian Schanda ## +## Copyright (C) 2021-2022, Florian Schanda ## ## ## ## This file is part of MISS_HIT. ## ## ## @@ -156,12 +156,11 @@ def __init__(self, options): @classmethod def process_wp(cls, wp): # Create lexer - lexer = MATLAB_Lexer(wp.mh, + lexer = MATLAB_Lexer(wp.cfg.language, + wp.mh, wp.get_content(), wp.filename, wp.blockname) - if wp.cfg.octave: - lexer.set_octave_mode() if not wp.cfg.pragmas: lexer.process_pragmas = False if len(lexer.text.strip()) == 0: diff --git a/miss_hit_core/cfg_ast.py b/miss_hit_core/cfg_ast.py index 5a85a8f6..6beb0b33 100644 --- a/miss_hit_core/cfg_ast.py +++ b/miss_hit_core/cfg_ast.py @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2020-2021, Florian Schanda ## +## Copyright (C) 2020-2022, Florian Schanda ## ## ## ## This file is part of MISS_HIT. ## ## ## @@ -31,6 +31,7 @@ from abc import ABCMeta, abstractmethod from miss_hit_core import pathutil +from miss_hit_core import m_language from miss_hit_core.m_ast import MATLAB_Token from miss_hit_core.errors import Location, Message_Handler, ICE from miss_hit_core.config import (Config, @@ -251,25 +252,58 @@ def evaluate(self, mh, config): raise ICE("logic error - called evaluate() for project_root") -class Octave_Mode(Config_Item): - # Toggle octave mode. For now this is just on or off, but in the - # future it could be a 'both' mode as well. - def __init__(self, enabled): +class Language_Version(Config_Item): + # Specify a language + def __init__(self, base, major, minor=None): super().__init__() - assert isinstance(enabled, bool) - self.enabled = enabled + assert base in ("matlab", "octave") + self.base = base + + if major == "latest": + assert minor is None + elif base == "matlab": + assert isinstance(major, int) and major >= 2000 + assert minor in ("a", "b") + else: + assert isinstance(major, int) and major >= 0 + assert isinstance(minor, int) and minor >= 0 + + self.major = major + self.minor = minor + self.language = None + + def assign_language(self, mh, error_location): + try: + if self.base == "matlab": + self.language = m_language.Base_MATLAB_Language.get_version( + self.major, + self.minor) + else: + self.language = m_language.Base_Octave_Language.get_version( + self.major, + self.minor) + except ValueError as verr: + mh.error(error_location, verr.args[0]) def dump(self): - if self.enabled: - print(" Dialect: Octave") + if self.base == "matlab": + if self.major == "latest": + print(" Language: MATLAB (%s)" % self.language.name) + else: + print(" Language: MATLAB %u%s (%s)" % + (self.major, self.minor, self.language.name)) else: - print(" Dialect: MATLAB") + if self.major == "latest": + print(" Language: Octave (%s)" % self.language.name) + else: + print(" Language: Octave %u.%u (%s)" % + (self.major, self.minor, self.language.name)) def evaluate(self, mh, config): assert isinstance(mh, Message_Handler) assert isinstance(config, Config) - config.octave = self.enabled + config.language = self.language class Path_List: diff --git a/miss_hit_core/cfg_parser.py b/miss_hit_core/cfg_parser.py index 93fcdc1c..b70e7555 100644 --- a/miss_hit_core/cfg_parser.py +++ b/miss_hit_core/cfg_parser.py @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2020-2021, Florian Schanda ## +## Copyright (C) 2020-2022, Florian Schanda ## ## ## ## This file is part of MISS_HIT. ## ## ## @@ -40,6 +40,9 @@ from miss_hit_core import pathutil from miss_hit_core import m_lexer +from miss_hit_core.m_language import (Config_Language, + Base_MATLAB_Language, + Base_Octave_Language) from miss_hit_core.errors import ICE, Error, Location, Message_Handler from miss_hit_core.config import (STYLE_RULES, STYLE_CONFIGURATION, METRICS, @@ -52,23 +55,13 @@ Set_Style_Configuration) from miss_hit_core.cfg_ast import * -KEYWORDS = ["metric", - "enable", - "enable_rule", - "suppress_rule", - "exclude_dir", - "project_root", - "octave", - "entrypoint", - "library", - "global"] - class Config_Parser: def __init__(self, mh, config_file): assert isinstance(mh, Message_Handler) assert isinstance(config_file, str) + self.language = Config_Language() self.filename = config_file self.dirname = os.path.dirname(pathutil.abspath(config_file)) self.mh = mh @@ -76,8 +69,9 @@ def __init__(self, mh, config_file): self.mh.register_file(self.filename) with open(config_file, "r") as fd: content = fd.read() - self.lexer = m_lexer.MATLAB_Lexer(mh, content, self.filename) - self.lexer.set_config_file_mode() + self.lexer = m_lexer.MATLAB_Lexer(self.language, + mh, content, self.filename) + self.lexer.process_pragmas = False # pylint: disable=invalid-name self.ct = None @@ -163,34 +157,35 @@ def parse_config_file(self): def parse_config_item(self): n_item = None - if self.peek("IDENTIFIER", "metric"): + if self.peek("KEYWORD", "metric"): n_item = self.parse_metric_limit() - elif self.peek("IDENTIFIER", "enable"): + elif self.peek("KEYWORD", "enable"): n_item = self.parse_simple_enable() - elif self.peek("IDENTIFIER", "enable_rule") or \ - self.peek("IDENTIFIER", "suppress_rule"): + elif self.peek("KEYWORD", "enable_rule") or \ + self.peek("KEYWORD", "suppress_rule"): n_item = self.parse_style_application() - elif self.peek("IDENTIFIER", "exclude_dir"): + elif self.peek("KEYWORD", "exclude_dir"): n_item = self.parse_directory_exclusion() - elif self.peek("IDENTIFIER", "project_root"): + elif self.peek("KEYWORD", "project_root"): n_item = self.parse_project_root() - elif self.peek("IDENTIFIER", "octave"): - n_item = self.parse_octave_mode() + elif self.peek("KEYWORD", "octave") or \ + self.peek("KEYWORD", "matlab"): + n_item = self.parse_language_mode() - elif self.peek("IDENTIFIER", "entrypoint"): + elif self.peek("KEYWORD", "entrypoint"): n_item = self.parse_entrypoint() - elif self.peek("IDENTIFIER", "library"): + elif self.peek("KEYWORD", "library"): n_item = self.parse_library() elif self.peek("KEYWORD", "global"): self.match("KEYWORD", "global") - if self.peek("IDENTIFIER", "library"): + if self.peek("KEYWORD", "library"): n_item = self.parse_library() n_item.set_global() else: @@ -277,14 +272,14 @@ def parse_boolean(self): self.mh.error(self.ct.location, "expected true or false") def parse_simple_enable(self): - self.match("IDENTIFIER", "enable") + self.match("KEYWORD", "enable") self.match("COLON") value = self.parse_boolean() return Activation(value) def parse_style_application(self): - self.match("IDENTIFIER") + self.match("KEYWORD") if self.ct.value == "enable_rule": enabled = True elif self.ct.value == "suppress_rule": @@ -315,7 +310,7 @@ def parse_style_configuration(self): msg = "expected valid style configuration name" suggestions = difflib.get_close_matches( config_name, - list(STYLE_CONFIGURATION) + KEYWORDS, + list(STYLE_CONFIGURATION) + list(self.language.keywords), n=1) if suggestions: msg += " (did you mean %s?)" % suggestions[0] @@ -367,7 +362,7 @@ def parse_style_configuration(self): return Style_Configuration(config_name, value) def parse_directory_exclusion(self): - self.match("IDENTIFIER", "exclude_dir") + self.match("KEYWORD", "exclude_dir") self.match("COLON") value = self.parse_string() @@ -387,7 +382,7 @@ def parse_directory_exclusion(self): return rv def parse_metric_limit(self): - self.match("IDENTIFIER", "metric") + self.match("KEYWORD", "metric") if self.peek("OPERATOR", "*"): self.match("OPERATOR", "*") @@ -406,16 +401,16 @@ def parse_metric_limit(self): self.match("COLON") - if self.peek("IDENTIFIER", "disable"): - self.match("IDENTIFIER", "disable") + if self.peek("KEYWORD", "disable"): + self.match("KEYWORD", "disable") return Metric_Limit(metric_name, False) - elif self.peek("IDENTIFIER", "report"): - self.match("IDENTIFIER", "report") + elif self.peek("KEYWORD", "report"): + self.match("KEYWORD", "report") return Metric_Limit(metric_name, True) - elif self.peek("IDENTIFIER", "limit"): - self.match("IDENTIFIER", "limit") + elif self.peek("KEYWORD", "limit"): + self.match("KEYWORD", "limit") if metric_name == "*": self.mh.error(self.ct.location, "cannot apply limit to all metrics") @@ -432,17 +427,52 @@ def parse_metric_limit(self): "expected disable|report|limit") def parse_project_root(self): - self.match("IDENTIFIER", "project_root") + self.match("KEYWORD", "project_root") return Project_Root() - def parse_octave_mode(self): - self.match("IDENTIFIER", "octave") + def parse_language_mode(self): + if self.peek("KEYWORD", "matlab"): + self.match("KEYWORD", "matlab") + base = "matlab" + else: + self.match("KEYWORD", "octave") + base = "octave" + self.match("COLON") - value = self.parse_boolean() - return Octave_Mode(value) + + if self.peek("NUMBER") or \ + self.peek("IDENTIFIER", "false") or \ + self.peek("IDENTIFIER", "true"): + value = self.parse_boolean() + if value: + self.mh.warning(self.ct.location, + "This usage is deprecated." + " Change to \"latest\"") + else: + self.mh.error(self.ct.location, + "A value of 'false' makes no sense here;" + " use \"latest\" or a specific version.") + rv = Language_Version(base, "latest") + + else: + self.match("STRING") + try: + if base == "matlab": + major, minor = Base_MATLAB_Language.parse_version( + self.ct.value) + else: + major, minor = Base_Octave_Language.parse_version( + self.ct.value) + rv = Language_Version(base, major, minor) + except ValueError as verr: + self.mh.error(self.ct.location, + verr.args[0]) + + rv.assign_language(self.mh, self.ct.location) + return rv def parse_entrypoint(self): - self.match("IDENTIFIER", "entrypoint") + self.match("KEYWORD", "entrypoint") self.match("STRING") rv = Entrypoint_Declaration(self.ct.location, self.dirname, @@ -450,15 +480,15 @@ def parse_entrypoint(self): self.match("C_BRA") while not (self.peek("C_KET") or self.peek_eof()): - if self.peek("IDENTIFIER", "libraries"): + if self.peek("KEYWORD", "libraries"): for t_lib in self.parse_lib_dependencies(): rv.add_lib_dependency(self.mh, t_lib) - elif self.peek("IDENTIFIER", "paths"): - self.match("IDENTIFIER", "paths") + elif self.peek("KEYWORD", "paths"): + self.match("KEYWORD", "paths") for t_path in self.parse_lib_paths(): rv.add_source_path(self.mh, t_path) - elif self.peek("IDENTIFIER", "tests"): - self.match("IDENTIFIER", "tests") + elif self.peek("KEYWORD", "tests"): + self.match("KEYWORD", "tests") for t_path in self.parse_lib_paths(): rv.add_test_path(self.mh, t_path) else: @@ -469,7 +499,7 @@ def parse_entrypoint(self): return rv def parse_library(self): - self.match("IDENTIFIER", "library") + self.match("KEYWORD", "library") if self.peek("STRING"): self.match("STRING") name = self.ct.value @@ -482,12 +512,12 @@ def parse_library(self): self.match("C_BRA") while not (self.peek("C_KET") or self.peek_eof()): - if self.peek("IDENTIFIER", "paths"): - self.match("IDENTIFIER", "paths") + if self.peek("KEYWORD", "paths"): + self.match("KEYWORD", "paths") for t_path in self.parse_lib_paths(): rv.add_source_path(self.mh, t_path) - elif self.peek("IDENTIFIER", "tests"): - self.match("IDENTIFIER", "tests") + elif self.peek("KEYWORD", "tests"): + self.match("KEYWORD", "tests") for t_path in self.parse_lib_paths(): rv.add_test_path(self.mh, t_path) else: @@ -499,7 +529,7 @@ def parse_library(self): def parse_lib_dependencies(self): rv = [] - self.match("IDENTIFIER", "libraries") + self.match("KEYWORD", "libraries") self.match("C_BRA") while self.peek("STRING"): self.match("STRING") diff --git a/miss_hit_core/cfg_tree.py b/miss_hit_core/cfg_tree.py index 2447cda6..6a2bc838 100644 --- a/miss_hit_core/cfg_tree.py +++ b/miss_hit_core/cfg_tree.py @@ -205,8 +205,8 @@ def apply_config(mh, options, dirname, exclusions_only=False): # command-line. if not exclusions_only: # Common options (from command_line.py) to all tools first: - if options.octave: - node.config.octave = True + if options.language is not None: + node.config.language = options.language if options.ignore_pragmas: node.config.pragmas = False if options.ignore_justifications_with_tickets: @@ -484,7 +484,7 @@ def sanity_test(): continue print(" Enabled = %s" % cfg.enabled) - print(" Octave = %s" % cfg.octave) + print(" Octave = %s" % cfg.language) print(" Rules = %u" % len(cfg.style_rules)) print(" SConf = %s" % cfg.style_config) print(" Metrics = %u" % len(cfg.enabled_metrics)) diff --git a/miss_hit_core/command_line.py b/miss_hit_core/command_line.py index e6d0a940..27c3e6b3 100644 --- a/miss_hit_core/command_line.py +++ b/miss_hit_core/command_line.py @@ -41,6 +41,8 @@ from miss_hit_core import s_ast from miss_hit_core.version import GITHUB_ISSUES, VERSION, FULL_NAME +from miss_hit_core.m_language import (Base_MATLAB_Language, + Base_Octave_Language) def create_basic_clp(epilog=None): @@ -54,7 +56,26 @@ def create_basic_clp(epilog=None): ap.add_argument("-v", "--version", action="store_true", default=False, - help="Show version and exit") + help="Show MISS_HIT version and exit") + + language_options = ap.add_mutually_exclusive_group() + language_options.add_argument("--octave", + default=None, + metavar="VERSION", + help=("Enable support for the Octave" + " language at a given version," + " e.g. 4.4. If no version is specified" + " then latest supported is used.")) + + language_options.add_argument("--matlab", + default=None, + metavar="VERSION", + help=("Enable support for the MATLAB" + " language at a given version," + " e.g. 2021a. If no version is " + " specified then the latest supported" + " is used.")) + ap.add_argument("--include-version", action="store_true", default=False, @@ -109,17 +130,6 @@ def create_basic_clp(epilog=None): default=False, help="Don't show line-context on messages") - language_options = ap.add_argument_group("language options") - rv["language_options"] = language_options - - language_options.add_argument("--octave", - default=False, - action="store_true", - help=("Enable support for the Octave" - " language. Note: This is highly" - " incomplete right now, only the" - " # comments are supported.")) - debug_options = ap.add_argument_group("debugging options") rv["debug_options"] = debug_options @@ -161,6 +171,22 @@ def parse_args(clp): except LookupError: clp["ap"].error("invalid encoding '%s'" % options.input_encoding) + options.language = None + if options.octave is not None: + try: + major, minor = Base_Octave_Language.parse_version(options.octave) + options.language = Base_Octave_Language.get_version(major, minor) + except ValueError as verr: + clp["ap"].error(verr.args[0]) + del options.octave + if options.matlab is not None: + try: + major, minor = Base_MATLAB_Language.parse_version(options.matlab) + options.language = Base_MATLAB_Language.get_version(major, minor) + except ValueError as verr: + clp["ap"].error(verr.args[0]) + del options.matlab + return options diff --git a/miss_hit_core/config.py b/miss_hit_core/config.py index a061bf71..e1bca2d2 100644 --- a/miss_hit_core/config.py +++ b/miss_hit_core/config.py @@ -24,6 +24,7 @@ ############################################################################## from copy import deepcopy +from miss_hit_core.m_language import MATLAB_Latest_Language ############################################################################## @@ -36,10 +37,11 @@ def __init__(self, other=None): if other is None: # Set up default configuration - self.enabled = True - self.octave = False - self.pragmas = True - # MH is enabled, octave mode is off, and we process pragmas + self.enabled = True + self.language = MATLAB_Latest_Language() + self.pragmas = True + # MH is enabled, language is the latest matlab, and we + # process pragmas self.ignore_pragmas_with_tickets = False # By default, all justifications are processed @@ -63,7 +65,7 @@ def __init__(self, other=None): assert isinstance(other, Config) # Inherit from existing configuration self.enabled = other.enabled - self.octave = other.octave + self.language = other.language self.pragmas = other.pragmas self.ignore_pragmas_with_tickets = \ other.ignore_pragmas_with_tickets @@ -75,9 +77,9 @@ def __init__(self, other=None): def dump(self, indent=0): items = ["MH Configuration object"] - items.append("Enabled = %s" % self.enabled) - items.append("Octave = %s" % self.octave) - items.append("Pragmas = %s" % self.pragmas) + items.append("Enabled = %s" % self.enabled) + items.append("Language = %s" % self.language) + items.append("Pragmas = %s" % self.pragmas) items.append("Style Rules") maxlen = max(len(item) for item in STYLE_RULES) for rule in sorted(STYLE_RULES): diff --git a/miss_hit_core/m_ast.py b/miss_hit_core/m_ast.py index fba89938..0f8ae7ff 100644 --- a/miss_hit_core/m_ast.py +++ b/miss_hit_core/m_ast.py @@ -30,7 +30,7 @@ from copy import copy from miss_hit_core.config import Config -from miss_hit_core.m_language import TOKEN_KINDS +from miss_hit_core.m_language import Language from miss_hit_core.m_language_builtins import HIGH_IMPACT_BUILTIN_FUNCTIONS from miss_hit_core.errors import Message_Handler, ICE, Location @@ -39,22 +39,6 @@ # Lexical tokens ############################################################################## -TOKENS_WITH_IMPLICIT_VALUE = frozenset([ - "COMMA", - "SEMICOLON", - "COLON", - "BRA", "KET", # ( ) - "C_BRA", "C_KET", # { } - "M_BRA", "M_KET", # [ ] for matrices - "A_BRA", "A_KET", # [ ] for assignment targets - "ASSIGNMENT", - "SELECTION", - "AT", - "METACLASS" -]) -assert TOKENS_WITH_IMPLICIT_VALUE <= TOKEN_KINDS - - class Autofix_Instruction: def __init__(self): self.ensure_trim_before = False @@ -114,6 +98,7 @@ def __init__(self): class MATLAB_Token: def __init__(self, + language, kind, raw_text, location, @@ -124,7 +109,8 @@ def __init__(self, contains_quotes = False, block_comment = False, annotation = False): - assert kind in TOKEN_KINDS + assert isinstance(language, Language) + assert kind in language.token_kinds assert isinstance(raw_text, str) assert isinstance(location, Location) assert isinstance(first_in_line, bool) @@ -146,7 +132,7 @@ def __init__(self, self.annotation = annotation if value is None: - if self.kind in TOKENS_WITH_IMPLICIT_VALUE: + if self.kind in language.tokens_with_implicit_value: self.value = None elif self.kind == "CONTINUATION": self.value = self.raw_text[3:].strip() diff --git a/miss_hit_core/m_language.py b/miss_hit_core/m_language.py index e73c1c8b..e4e30274 100644 --- a/miss_hit_core/m_language.py +++ b/miss_hit_core/m_language.py @@ -3,8 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2019-2020, Florian Schanda ## -## Copyright (C) 2019, Zenuity AB ## +## Copyright (C) 2022, Florian Schanda ## ## ## ## This file is part of MISS_HIT. ## ## ## @@ -24,70 +23,329 @@ ## ## ############################################################################## -# Tokens for the MATLAB language -TOKEN_KINDS = frozenset([ - "NEWLINE", - "CONTINUATION", - "COMMENT", - "IDENTIFIER", - "NUMBER", - "CARRAY", # 'foo' character array - "STRING", # "foo" string class literal - "KEYWORD", # see below - "OPERATOR", # see docs/internal/matlab_operators.txt - "COMMA", # , - "SEMICOLON", # ; - "COLON", # : - "BRA", "KET", # ( ) - "C_BRA", "C_KET", # { } - "M_BRA", "M_KET", # [ ] for matrices - "A_BRA", "A_KET", # [ ] for assignment targets - "ASSIGNMENT", # = - "SELECTION", # . - "AT", # @ - "BANG", # ! - "METACLASS", # ? - "NVP_DELEGATE", # .? (name value pair delegation) - "ANNOTATION", # miss_hit annotation -]) - -# As of MATLAB 2019b -# See: https://www.mathworks.com/help/matlab/ref/iskeyword.html -# -# We have taken the liberty to make "import" a keyword, since that -# simplifies parsing quite a bit. This does mean that you can't have -# variables named "import". -# -# There are a few more keywords, but they are not always keywords. The -# lexer also sometimes emits properties, arguments, methods, events, -# and enumeration as keywords, depending on context. -KEYWORDS = frozenset([ - 'break', - 'case', - 'catch', - 'classdef', - 'continue', - 'else', - 'elseif', - 'end', - 'for', - 'function', - 'global', - 'if', - 'otherwise', - 'parfor', - 'persistent', - 'return', - 'spmd', - 'switch', - 'try', - 'while', - - # These really should be keywords but are not - 'import', -]) - -# The annotation language defines more keywords -ANNOTATION_KEYWORDS = KEYWORDS | frozenset([ - 'pragma', -]) +import re + + +class Language: + def __init__(self, name): + assert isinstance(name, str) + self.name = name + + self.token_kinds = set([ + "NEWLINE", + "CONTINUATION", + "COMMENT", + "IDENTIFIER", + "NUMBER", + "CARRAY", # 'foo' character array + "STRING", # "foo" string class literal + "KEYWORD", # see below + "OPERATOR", # see docs/internal/matlab_operators.txt + "COMMA", # , + "SEMICOLON", # ; + "COLON", # : + "BRA", "KET", # ( ) + "C_BRA", "C_KET", # { } + "M_BRA", "M_KET", # [ ] for matrices + "A_BRA", "A_KET", # [ ] for assignment targets + "ASSIGNMENT", # = + "SELECTION", # . + "AT", # @ + "BANG", # ! + "METACLASS", # ? + "ANNOTATION", # miss_hit annotation + ]) + + self.tokens_with_implicit_value = set([ + "COMMA", + "SEMICOLON", + "COLON", + "BRA", "KET", # ( ) + "C_BRA", "C_KET", # { } + "M_BRA", "M_KET", # [ ] for matrices + "A_BRA", "A_KET", # [ ] for assignment targets + "ASSIGNMENT", + "SELECTION", + "AT", + "METACLASS" + ]) + assert self.tokens_with_implicit_value <= self.token_kinds + # Token kinds, and also a subset for the tokens where there is + # no value (e.g. BRA). + + self.keywords = set() + # Base keywords + + self.class_keywords = set() + # Keywords that are keywords inside classdef regions only (a + # particularly frustrating MATLAB misfeature) + + self.function_contract_keywords = set() + # The arguments block that can appear in newer MATLAB versions + + self.annotation_keywords = set([ + "pragma", + ]) + # Keywords for the %| anotation language + + self.comment_chars = set("") + # Characters that start a line comment. + + self.identifiers_starting_with_underscore = False + # Can identifiers start with an underscore? + + self.bang_is_negation = False + # When false, ! is a shell escape. When true, ! is boolean + # negation. + + self.hex_literals = False + # Language supports hex literals, e.g. 0xdeadbeef and 0b10 + + self.allow_classdef_subfunctions = False + # Allows functions trailing a classdef + + self.allow_command_form = True + # Command form is supported + + self.has_nvp_delegate = False + # Allow .? as a token + + self.ws_insignificant = False + # Sometimes whitespace is significant, e.g. inside a + # matrix. In the config file mode it is never. + + ######################## + # Grammar features + + self.string_argument_pairs = False + # Allows writing foo(x=y) instead of foo('x', y) which is a + # another insane idea. + + self.script_global_functions = False + # Functions sprinkled in the middle of a script, instead of at + # the end only. + + +class Config_Language(Language): + def __init__(self): + super().__init__("MISS_HIT Configuration") + + self.keywords = set([ + "disable", + "enable", + "enable_rule", + "entrypoint", + "exclude_dir", + "global", + "libraries", + "library", + "limit", + "matlab", + "metric", + "octave", + "paths", + "project_root", + "report", + "suppress_rule", + "tests", + ]) + + self.comment_chars.add("#") + + self.allow_command_form = False + self.ws_insignificant = True + + +class Base_Language(Language): + # This is the common subset of MATLAB and Octave + + def __init__(self, name): + super().__init__(name) + + # As of MATLAB 2019b + # See: https://www.mathworks.com/help/matlab/ref/iskeyword.html + # + # We have taken the liberty to make "import" a keyword, since + # that simplifies parsing quite a bit. This does mean that you + # can't have variables named "import". + self.keywords = set([ + 'break', + 'case', + 'catch', + 'classdef', + 'continue', + 'else', + 'elseif', + 'end', + 'for', + 'function', + 'global', + 'if', + 'otherwise', + 'parfor', + 'persistent', + 'return', + 'switch', + 'try', + 'while', + + # These really should be keywords but are not + 'import', + ]) + + self.class_keywords.add("properties") + self.class_keywords.add("enumeration") + self.class_keywords.add("events") + self.class_keywords.add("methods") + + self.comment_chars.add("%") + + +class Base_MATLAB_Language(Base_Language): + # This is the common subset for MATLAB. The earliest MATLAB we + # support is 2017b. + + def __init__(self, name): + super().__init__(name) + + self.token_kinds.add("NVP_DELEGATE") + self.tokens_with_implicit_value.add("NVP_DELEGATE") + self.has_nvp_delegate = True + # .? (name value pair delegation) + + self.keywords.add("spmd") + + self.function_contract_keywords.add("arguments") + + self.allow_classdef_subfunctions = True + + @classmethod + def parse_version(cls, version): + if version == "latest": + return "latest", None + else: + match = re.match(r"^(20\d\d)([ab])$", version) + if match is None: + raise ValueError("MATLAB version must be YEAR[ab]," + " e.g. 2017b") + major, minor = match.groups() + return int(major), minor + + @classmethod + def get_version(cls, major, minor): + if major == "latest": + language = MATLAB_Latest_Language() + elif major < 2017 or (major == 2017 and + minor == "a"): + raise ValueError("earliest MATLAB language supported is 2017b") + elif major > 2022 or (major == 2022 and + minor == "b"): + raise ValueError("latest MATLAB language supported is 2022a") + elif major < 2020 or (major == 2020 and + minor == "a"): + language = MATLAB_2017b_Language() + elif major < 2021: + language = MATLAB_2020b_Language() + else: + language = MATLAB_2021a_Language() + return language + + +class Base_Octave_Language(Base_Language): + # This is the common subset for Octave. The earliest octave we + # support is ??? + + def __init__(self, name): + super().__init__(name) + + self.keywords.add("end_try_catch") + self.keywords.add("end_unwind_protect") + self.keywords.add("endclassdef") + self.keywords.add("endenumeration") + self.keywords.add("endevents") + self.keywords.add("endfor") + self.keywords.add("endfunction") + self.keywords.add("endif") + self.keywords.add("endmethods") + self.keywords.add("endparfor") + self.keywords.add("endproperties") + self.keywords.add("endswitch") + self.keywords.add("endwhile") + self.keywords.add("unwind_protect") + self.keywords.add("unwind_protect_cleanup") + + self.comment_chars.add("#") + + self.identifiers_starting_with_underscore = True + self.bang_is_negation = True + + self.hex_literals = True + + self.script_global_functions = True + + @classmethod + def parse_version(cls, version): + if version == "latest": + return "latest", None + else: + match = re.match(r"^(\d+)\.(\d+)$", version) + if match is None: + raise ValueError("Octave version must be MAJOR.MINOR," + " e.g. 4.4") + major, minor = match.groups() + return int(major), int(minor) + + @classmethod + def get_version(cls, major, minor): + if major == "latest": + language = Octave_Latest_Language() + elif major < 4 or (major == 4 and + minor < 2): + raise ValueError("earliest Octave language supported is 4.2") + elif major > 7 or (major == 7 and + minor > 2): + raise ValueError("latest Octave language supported is 7.2") + elif major == 4 and minor < 4: + language = Octave_4_2_Language() + else: + language = Octave_4_4_Language() + return language + + +class MATLAB_2017b_Language(Base_MATLAB_Language): + def __init__(self, name="MATLAB 2017b"): + super().__init__(name) + + +class MATLAB_2020b_Language(MATLAB_2017b_Language): + def __init__(self, name="MATLAB 2020b"): + super().__init__(name) + + self.hex_literals = True + + +class MATLAB_2021a_Language(MATLAB_2020b_Language): + def __init__(self, name="MATLAB 2021a"): + super().__init__(name) + + self.string_argument_pairs = True + + +class MATLAB_Latest_Language(MATLAB_2021a_Language): + pass + + +class Octave_4_2_Language(Base_Octave_Language): + def __init__(self, name = "Octave 4.2"): + super().__init__(name) + + +class Octave_4_4_Language(Octave_4_2_Language): + def __init__(self, name = "Octave 4.4"): + super().__init__(name) + + self.allow_classdef_subfunctions = True + + +class Octave_Latest_Language(Octave_4_4_Language): + pass diff --git a/miss_hit_core/m_lexer.py b/miss_hit_core/m_lexer.py index 39320f07..b61ce991 100644 --- a/miss_hit_core/m_lexer.py +++ b/miss_hit_core/m_lexer.py @@ -33,7 +33,7 @@ from miss_hit_core import m_ast from miss_hit_core.errors import Location, Error, Message_Handler, ICE -from miss_hit_core.m_language import KEYWORDS, ANNOTATION_KEYWORDS +from miss_hit_core.m_language import Language, MATLAB_Latest_Language # The 1999 technical report "The Design and Implementation of a Parser # and Scanner for the MATLAB Language in the MATCH Compiler" is a key @@ -57,9 +57,7 @@ # A further difference between this lexer and the work outlined in the # TR is that we've based this on a newer MATLAB version. For example # issues such as [1.1.1] no longer exist which simplified the design -# somewhat. We've also got a more complete set of features supported -# (i.e. every single MATLAB 2019b+ feature should be working, except -# for the .? construct). +# somewhat. We've also got a more complete set of features supported. # # The whole concept of a separate lexing phase is put to an extreme # test in MATLAB. It would be "easier" if the lexer can parser could @@ -70,10 +68,12 @@ class Token_Generator(metaclass=ABCMeta): - def __init__(self, filename, blockname=None): + def __init__(self, language, filename, blockname=None): + assert isinstance(language, Language) assert isinstance(filename, str) assert blockname is None or isinstance(blockname, str) + self.language = language self.filename = filename self.blockname = blockname @@ -83,12 +83,6 @@ def __init__(self, filename, blockname=None): os.path.dirname(pathutil.abspath(filename))).startswith("@") # Make a note if this file resides inside a @ directory - self.octave_mode = False - # If set to true, also deal with Octave's extensions to - # MATLAB. - # - # Note that this is highly incomplete right now. - @abstractmethod def token(self): pass @@ -105,8 +99,8 @@ def get_file_loc(self, line=None): class MATLAB_Lexer(Token_Generator): - def __init__(self, mh, content, filename, blockname=None): - super().__init__(filename, blockname) + def __init__(self, language, mh, content, filename, blockname=None): + super().__init__(language, filename, blockname) assert isinstance(content, str) self.text = content @@ -164,20 +158,12 @@ def __init__(self, mh, content, filename, blockname=None): # things will be returned as strings, except for line # continuations. Comments and newlines end command form. - self.comment_char = frozenset("%") - # Characters that start a line comment. MATLAB only uses %, - # and Octave uses either. - self.in_special_section = False # Some keywords (properties, attributes, etc.) introduce a # special section, in which the command_mode is never # activated. This section ends with the first 'end' keyword is # encountered. - self.config_file_mode = False - # We abuse this lexer to parse our config files. If this is - # set, we don't do command_mode or pragmas at all. - self.process_pragmas = True # Process miss_hit pragmas. This could create parse errors for # perfectly valid (legacy) code, that accidentally includes @@ -200,15 +186,6 @@ def __init__(self, mh, content, filename, blockname=None): self.last_kind = None self.last_value = None - def set_octave_mode(self): - self.octave_mode = True - self.comment_char = frozenset("%#") - - def set_config_file_mode(self): - self.config_file_mode = True - self.comment_char = frozenset("#") - self.process_pragmas = False - def line_count(self): return len(self.context_line) @@ -268,11 +245,11 @@ def lex_error(self, message=None): def contains_block_open(self, string): return any(c + "{" in string - for c in self.comment_char) + for c in self.language.comment_chars) def contains_block_close(self, string): return any(c + "}" in string - for c in self.comment_char) + for c in self.language.comment_chars) def __token(self): # If we've been instructed to add an anonymous comma, we do @@ -283,6 +260,7 @@ def __token(self): fake_col = self.lexpos - self.col_offset + 1 fake_line = fake_line[:fake_col] + "" + fake_line[fake_col:] token = m_ast.MATLAB_Token( + self.language, "COMMA", ",", Location(filename = self.filename, @@ -336,7 +314,7 @@ def __token(self): elif self.command_mode: # Lexing in command mode - if self.cc in self.comment_char: + if self.cc in self.language.comment_chars: # Comments go until the end of the line kind = "COMMENT" while self.nc not in ("\n", "\0"): @@ -435,7 +413,7 @@ def __token(self): # line continuatins by accident. break - elif self.nc in self.comment_char: + elif self.nc in self.language.comment_chars: # Comments always terminate the string. break @@ -472,7 +450,7 @@ def __token(self): else: # Ordinary lexing - if self.cc in self.comment_char and \ + if self.cc in self.language.comment_chars and \ self.nc == "|" and \ self.first_in_line and \ self.process_pragmas: @@ -481,7 +459,7 @@ def __token(self): kind = "ANNOTATION" self.skip() - elif self.cc in self.comment_char: + elif self.cc in self.language.comment_chars: # Comments go until the end of the line kind = "COMMENT" while self.nc not in ("\n", "\0"): @@ -515,13 +493,17 @@ def __token(self): else: self.lex_error("expected . to complete continuation token") - elif self.cc.isalpha() or (self.octave_mode and self.cc == "_"): + elif self.cc.isalpha() or \ + (self.language.identifiers_starting_with_underscore and + self.cc == "_"): # Could be an identifier or keyword kind = "IDENTIFIER" while self.nc.isalnum() or self.nc == "_": self.skip() - elif self.cc == "0" and self.nc in ("x", "X", "b", "B"): + elif self.cc == "0" and \ + self.nc in ("x", "X", "b", "B") and \ + self.language.hex_literals: # Hex and binary literals are quite a bit different to # normal numbers. If we see the starting 2 characters # we definitely try to lex or error, which seems @@ -620,7 +602,7 @@ def __token(self): self.lex_error() elif self.cc in ("<", ">", "=", "~") or \ - (self.cc == "!" and self.octave_mode): + (self.cc == "!" and self.language.bang_is_negation): # This is either a boolean relation, negation, or the # assignment. In Octave ! and != are also operators. if self.nc == "=": @@ -643,7 +625,9 @@ def __token(self): kind = "OPERATOR" self.skip() - elif self.cc == "." and self.nc == "?": + elif self.cc == "." and \ + self.nc == "?" and \ + self.language.has_nvp_delegate: kind = "NVP_DELEGATE" self.skip() @@ -737,7 +721,7 @@ def __token(self): elif self.cc == "@": kind = "AT" - elif self.cc == "!" and not self.octave_mode: + elif self.cc == "!" and not self.language.bang_is_negation: # Shell escapes go up to the end of the line while self.nc not in ("\n", "\0"): self.skip() @@ -763,9 +747,11 @@ def __token(self): # Classify keywords, except after selections. That way we # permit structure fields with names like "function". if kind == "IDENTIFIER" and self.last_kind != "SELECTION": - if self.in_annotation and raw_text in ANNOTATION_KEYWORDS: + if self.in_annotation and \ + raw_text in self.language.annotation_keywords: kind = "KEYWORD" - elif not self.in_annotation and raw_text in KEYWORDS: + elif not self.in_annotation and \ + raw_text in self.language.keywords: kind = "KEYWORD" # Keep track of blocks, and special sections where @@ -787,30 +773,20 @@ def __token(self): elif self.block_stack[-1] == "classdef": # Directly inside a classdef, we have 4 extra # keywords - extra_kw = {"properties", - "enumeration", - "events", - "methods"} - elif self.block_stack[-1] in ("properties", - "enumeration", - "events"): + extra_kw = self.language.class_keywords + elif self.block_stack[-1] != "methods" and \ + self.block_stack[-1] in self.language.class_keywords: # In three of the four class blocks, these # keywords persist - extra_kw = {"properties", - "enumeration", - "events", - "methods"} + extra_kw = self.language.class_keywords elif self.block_stack[-1] == "function": # Inside functions we add the arguments block as # an extra keyword - extra_kw = {"arguments"} + extra_kw = self.language.function_contract_keywords if raw_text in extra_kw: kind = "KEYWORD" self.block_stack.append(raw_text) - if raw_text in ("properties", "events", - "enumeration", "arguments"): - self.in_special_section = True elif kind == "KEYWORD" and \ raw_text == "end" and \ @@ -821,6 +797,10 @@ def __token(self): # TODO: Silent error if we can't match blocks? Or # complain loudly? + if kind == "KEYWORD" and raw_text in ("properties", "events", + "enumeration", "arguments"): + self.in_special_section = True + if self.line - 1 < len(self.context_line): ctx_line = self.context_line[self.line - 1] else: @@ -830,7 +810,8 @@ def __token(self): ###################################################################### # Create token - token = m_ast.MATLAB_Token(kind, + token = m_ast.MATLAB_Token(self.language, + kind, raw_text, Location(filename = self.filename, blockname = self.blockname, @@ -863,7 +844,7 @@ def __token(self): # Detect if we should enter command form. If the next # character is not a space, it's never a command. - if not self.config_file_mode and \ + if self.language.allow_command_form and \ not self.in_special_section and \ not self.in_annotation and \ token.first_in_statement and \ @@ -978,8 +959,9 @@ def __token(self): "ignored block comment: no text must appear" " after the {", "low") - elif token.raw_text.strip() not in ["%s{" % c - for c in self.comment_char]: + elif token.raw_text.strip() not in \ + ["%s{" % c + for c in self.language.comment_chars]: self.mh.check(token.location, "ignored block comment: no text must appear" " around the block comment marker", @@ -989,7 +971,7 @@ def __token(self): token.block_comment = True elif self.block_comment and token.kind == "COMMENT": - for c in self.comment_char: + for c in self.language.comment_chars: marker = c + "}" if marker in token.raw_text: if token.raw_text.strip() == marker: @@ -1033,7 +1015,7 @@ def __token(self): # Determine if whitespace is currently significant (i.e. we're # in a matrix). - ws_is_significant = (not self.config_file_mode and + ws_is_significant = (not self.language.ws_insignificant and self.bracket_stack and self.bracket_stack[-1].kind in ("M_BRA", "C_BRA") and @@ -1124,7 +1106,7 @@ def __token(self): # NEWLINE # SEMICOLON pass - elif next_non_ws in self.comment_char: + elif next_non_ws in self.language.comment_chars: # COMMENT pass elif next_non_ws.isalnum(): @@ -1218,15 +1200,13 @@ class Token_Buffer(Token_Generator): def __init__(self, lexer, cfg): assert isinstance(lexer, MATLAB_Lexer) assert isinstance(cfg, Config) - super().__init__(lexer.filename, lexer.blockname) + super().__init__(lexer.language, lexer.filename, lexer.blockname) self.cfg = cfg self.pos = 0 self.tokens = [] self.mh = lexer.mh self.lines = lexer.line_count() - self.comment_char = lexer.comment_char - self.octave_mode = lexer.octave_mode while True: tok = lexer.token() @@ -1429,7 +1409,8 @@ def replay(self): token.value += "\n" else: newline_added = True - new_tokens.append(m_ast.MATLAB_Token("NEWLINE", "\n", + new_tokens.append(m_ast.MATLAB_Token(self.language, + "NEWLINE", "\n", token.location, False, False, anonymous = True)) @@ -1542,7 +1523,8 @@ def sanity_test(mh, filename): with open(filename, "r") as fd: content = fd.read() try: - lexer = MATLAB_Lexer(mh, content, filename) + language = MATLAB_Latest_Language() + lexer = MATLAB_Lexer(language, mh, content, filename) lexer.debug_comma = True while True: tok = lexer.token() diff --git a/miss_hit_core/m_parser.py b/miss_hit_core/m_parser.py index a20feb21..d643196e 100644 --- a/miss_hit_core/m_parser.py +++ b/miss_hit_core/m_parser.py @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2019-2021, Florian Schanda ## +## Copyright (C) 2019-2022, Florian Schanda ## ## Copyright (C) 2019-2020, Zenuity AB ## ## ## ## This file is part of MISS_HIT. ## @@ -30,6 +30,7 @@ from miss_hit_core.config import Config, METRICS from miss_hit_core.errors import ICE, Message_Handler from miss_hit_core.m_ast import * +from miss_hit_core.m_language import Language from miss_hit_core.m_lexer import Token_Generator @@ -92,6 +93,7 @@ def __init__(self, mh, lexer, cfg): assert isinstance(cfg, Config) self.lexer = lexer + self.language = self.lexer.language self.mh = mh self.cfg = cfg @@ -207,7 +209,7 @@ def should_skip(token): break def match(self, kind, value=None): - assert kind in TOKEN_KINDS + assert kind in self.language.token_kinds self.skip() if self.ct is None: self.mh.error(self.lexer.get_file_loc(), @@ -233,7 +235,7 @@ def match(self, kind, value=None): (kind, value, self.ct.kind, self.ct.value)) def amatch(self, kind, value=None): - assert kind in TOKEN_KINDS + assert kind in self.language.token_kinds self.skip() if self.ct is None: self.mh.error(self.lexer.get_file_loc(), @@ -275,7 +277,7 @@ def peek_annotation(self): return self.nt and self.nt.annotation def peek(self, kind, value=None): - assert kind in TOKEN_KINDS + assert kind in self.language.token_kinds if self.nt and \ self.nt.kind == kind and \ not self.nt.annotation: @@ -287,7 +289,7 @@ def peek(self, kind, value=None): return False def peek2(self, kind, value=None): - assert kind in TOKEN_KINDS + assert kind in self.language.token_kinds if self.nnt and \ self.nnt.kind == kind and \ not self.nnt.annotation: @@ -299,7 +301,7 @@ def peek2(self, kind, value=None): return False def apeek(self, kind, value=None): - assert kind in TOKEN_KINDS + assert kind in self.language.token_kinds if self.nt and \ self.nt.kind == kind and \ self.nt.annotation: @@ -630,7 +632,7 @@ def parse_file(self): l_pragmas + l_more_pragmas) elif self.peek("KEYWORD", "classdef"): cunit = self.parse_class_file(l_pragmas) - elif self.lexer.octave_mode: + elif self.language.script_global_functions: cunit = self.parse_octave_script_file(l_pragmas) else: cunit = self.parse_matlab_script_file(l_pragmas) @@ -641,7 +643,7 @@ def parse_file(self): self.mh.error(cunit.l_functions[0].loc(), "script-global functions are an Octave-specific" " feature; move your functions to the end of" - " the script file or use the --octave mode") + " the script file or use an Octave language") if self.debug_tree: cunit.debug_parse_tree() @@ -718,7 +720,12 @@ def parse_class_file(self, l_pragmas): self.functions_require_end = True n_classdef = self.parse_classdef() - l_functions, l_more_pragmas = self.parse_function_list() + + if self.language.allow_classdef_subfunctions: + l_functions, l_more_pragmas = self.parse_function_list() + else: + l_functions = [] + l_more_pragmas = [] return Class_File(os.path.basename(self.lexer.filename), os.path.dirname( @@ -1869,7 +1876,7 @@ def parse_argument_list(self, n_ast): return args while True: - if not self.lexer.octave_mode and \ + if self.language.string_argument_pairs and \ self.peek("IDENTIFIER") and self.peek2("ASSIGNMENT"): # Special case for the 2021a MATLAB mis-feature of # name-value pairs in function calls diff --git a/miss_hit_core/mh_metric.py b/miss_hit_core/mh_metric.py index d0b67b9f..e9b71440 100644 --- a/miss_hit_core/mh_metric.py +++ b/miss_hit_core/mh_metric.py @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2020-2021, Florian Schanda ## +## Copyright (C) 2020-2022, Florian Schanda ## ## Copyright (C) 2020, Veoneer System Software GmbH ## ## ## ## This file is part of MISS_HIT. ## @@ -964,10 +964,11 @@ def process_wp(cls, wp): # Create lexer - lexer = MATLAB_Lexer(wp.mh, wp.get_content(), - wp.filename, wp.blockname) - if wp.cfg.octave: - lexer.set_octave_mode() + lexer = MATLAB_Lexer(wp.cfg.language, + wp.mh, + wp.get_content(), + wp.filename, + wp.blockname) if not wp.cfg.pragmas: lexer.process_pragmas = False diff --git a/miss_hit_core/mh_style.py b/miss_hit_core/mh_style.py index 9af1de12..d2e27e62 100644 --- a/miss_hit_core/mh_style.py +++ b/miss_hit_core/mh_style.py @@ -638,9 +638,10 @@ def stage_3_analysis(mh, cfg, tbuf, is_embedded, fixed, valid_code): # Ignore block comments pass - elif token.raw_text.strip() in ("%s%s" % (cc, cb) - for cc in tbuf.comment_char - for cb in "{}"): + elif token.raw_text.strip() in ( + "%s%s" % (cc, cb) + for cc in tbuf.language.comment_chars + for cb in "{}"): # Leave block comment indicators alone pass @@ -1015,9 +1016,11 @@ def process_wp(cls, wp): # Create lexer - lexer = MATLAB_Lexer(wp.mh, content, wp.filename, wp.blockname) - if wp.cfg.octave: - lexer.set_octave_mode() + lexer = MATLAB_Lexer(wp.cfg.language, + wp.mh, + content, + wp.filename, + wp.blockname) if not wp.cfg.pragmas: lexer.process_pragmas = False diff --git a/miss_hit_core/s_parser.py b/miss_hit_core/s_parser.py index 03861619..1624ba1c 100644 --- a/miss_hit_core/s_parser.py +++ b/miss_hit_core/s_parser.py @@ -3,7 +3,7 @@ ## ## ## MATLAB Independent, Small & Safe, High Integrity Tools ## ## ## -## Copyright (C) 2020, Florian Schanda ## +## Copyright (C) 2020-2022, Florian Schanda ## ## ## ## This file is part of MISS_HIT. ## ## ## @@ -38,6 +38,7 @@ from miss_hit_core.config import Config from miss_hit_core.s_ast import * from miss_hit_core.errors import Message_Handler, ICE +from miss_hit_core.m_language import MATLAB_Latest_Language # pylint: disable=invalid-name anatomy = {} @@ -484,7 +485,8 @@ def sanity_test(mh, filename, _): mh.info(n_block.loc(), "block contains %u lines of MATLAB" % len(n_block.get_text().splitlines())) - lexer = m_lexer.MATLAB_Lexer(mh, + lexer = m_lexer.MATLAB_Lexer(MATLAB_Latest_Language(), + mh, n_block.get_text(), filename, n_block.local_name()) diff --git a/tests/config_parser/language/invalid_1.cfg b/tests/config_parser/language/invalid_1.cfg new file mode 100644 index 00000000..3225898f --- /dev/null +++ b/tests/config_parser/language/invalid_1.cfg @@ -0,0 +1,11 @@ +octave: false +octave: "2017b" +octave: "3.0" +octave: "4.x" +octave: "99.0" + +matlab: false +matlab: "4.4" +matlab: "2017a" +matlab: "2017c" +matlab: "2099b" diff --git a/tests/config_parser/language/invalid_1.cfg.out b/tests/config_parser/language/invalid_1.cfg.out new file mode 100644 index 00000000..7c649f6a --- /dev/null +++ b/tests/config_parser/language/invalid_1.cfg.out @@ -0,0 +1,32 @@ +In invalid_1.cfg, line 1 +| octave: false +| ^^^^^ error: A value of 'false' makes no sense here; use "latest" or a specific version. +In invalid_1.cfg, line 2 +| octave: "2017b" +| ^^^^^^^ error: Octave version must be MAJOR.MINOR, e.g. 4.4 +In invalid_1.cfg, line 3 +| octave: "3.0" +| ^^^^^ error: earliest Octave language supported is 4.2 +In invalid_1.cfg, line 4 +| octave: "4.x" +| ^^^^^ error: Octave version must be MAJOR.MINOR, e.g. 4.4 +In invalid_1.cfg, line 5 +| octave: "99.0" +| ^^^^^^ error: latest Octave language supported is 7.2 +In invalid_1.cfg, line 7 +| matlab: false +| ^^^^^ error: A value of 'false' makes no sense here; use "latest" or a specific version. +In invalid_1.cfg, line 8 +| matlab: "4.4" +| ^^^^^ error: MATLAB version must be YEAR[ab], e.g. 2017b +In invalid_1.cfg, line 9 +| matlab: "2017a" +| ^^^^^^^ error: earliest MATLAB language supported is 2017b +In invalid_1.cfg, line 10 +| matlab: "2017c" +| ^^^^^^^ error: MATLAB version must be YEAR[ab], e.g. 2017b +In invalid_1.cfg, line 11 +| matlab: "2099b" +| ^^^^^^^ error: latest MATLAB language supported is 2022a +invalid_1.cfg: error: config file contains errors +MISS_HIT Debug Summary: 1 file(s) analysed, 11 error(s) diff --git a/tests/config_parser/language/valid_1.cfg b/tests/config_parser/language/valid_1.cfg new file mode 100644 index 00000000..bc48e454 --- /dev/null +++ b/tests/config_parser/language/valid_1.cfg @@ -0,0 +1,27 @@ +matlab: "latest" +octave: "latest" + +matlab: "2017b" +matlab: "2018a" +matlab: "2018b" +matlab: "2019a" +matlab: "2019b" +matlab: "2020a" +matlab: "2020b" +matlab: "2021a" +matlab: "2021b" +matlab: "2022a" +# matlab: "2022b" + +octave: "4.2" +octave: "4.3" +octave: "4.4" +octave: "5.1" +octave: "5.2" +octave: "6.1" +octave: "6.2" +octave: "6.3" +octave: "6.4" +octave: "7.1" +octave: "7.2" +# octave: "7.3" diff --git a/tests/config_parser/language/valid_1.cfg.out b/tests/config_parser/language/valid_1.cfg.out new file mode 100644 index 00000000..16faf771 --- /dev/null +++ b/tests/config_parser/language/valid_1.cfg.out @@ -0,0 +1,25 @@ +MISS_HIT configuration file + Language: MATLAB (MATLAB 2021a) + Language: Octave (Octave 4.4) + Language: MATLAB 2017b (MATLAB 2017b) + Language: MATLAB 2018a (MATLAB 2017b) + Language: MATLAB 2018b (MATLAB 2017b) + Language: MATLAB 2019a (MATLAB 2017b) + Language: MATLAB 2019b (MATLAB 2017b) + Language: MATLAB 2020a (MATLAB 2017b) + Language: MATLAB 2020b (MATLAB 2020b) + Language: MATLAB 2021a (MATLAB 2021a) + Language: MATLAB 2021b (MATLAB 2021a) + Language: MATLAB 2022a (MATLAB 2021a) + Language: Octave 4.2 (Octave 4.2) + Language: Octave 4.3 (Octave 4.2) + Language: Octave 4.4 (Octave 4.4) + Language: Octave 5.1 (Octave 4.4) + Language: Octave 5.2 (Octave 4.4) + Language: Octave 6.1 (Octave 4.4) + Language: Octave 6.2 (Octave 4.4) + Language: Octave 6.3 (Octave 4.4) + Language: Octave 6.4 (Octave 4.4) + Language: Octave 7.1 (Octave 4.4) + Language: Octave 7.2 (Octave 4.4) +MISS_HIT Debug Summary: 1 file(s) analysed, everything seems fine diff --git a/tests/copyright/octave/cmdline b/tests/copyright/octave/cmdline index 87c79ea6..7ca07716 100644 --- a/tests/copyright/octave/cmdline +++ b/tests/copyright/octave/cmdline @@ -1,4 +1,4 @@ ---octave +--octave=latest --update-year --year=2021 --primary-entity=Florian Schanda diff --git a/tests/parser/argument_validation/invalid_05.m.octave.out b/tests/parser/argument_validation/invalid_05.m.octave.out new file mode 100644 index 00000000..fe3fb38d --- /dev/null +++ b/tests/parser/argument_validation/invalid_05.m.octave.out @@ -0,0 +1,16 @@ +In invalid_05.m, line 9 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In invalid_05.m, line 10 +| a uint32 = b * c +| ^ style: end statement with a semicolon +In invalid_05.m, line 11 +| b uint32 +| ^^^^^^ style: end statement with a semicolon +In invalid_05.m, line 12 +| c uint32 +| ^^^^^^ style: end statement with a semicolon +In invalid_05.m, line 16 +| end +| ^^^ error: expected end of file, found KEYWORD instead +MISS_HIT Debug Summary: 1 file(s) analysed, 4 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_01.m.octave.out b/tests/parser/argument_validation/test_01.m.octave.out new file mode 100644 index 00000000..47009907 --- /dev/null +++ b/tests/parser/argument_validation/test_01.m.octave.out @@ -0,0 +1,7 @@ +In test_01.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_01.m, line 5 +| x (1, 1) single {mustBePositive, mustBeFinite} +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_02.m.octave.out b/tests/parser/argument_validation/test_02.m.octave.out new file mode 100644 index 00000000..3dfe6b39 --- /dev/null +++ b/tests/parser/argument_validation/test_02.m.octave.out @@ -0,0 +1,7 @@ +In test_02.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_02.m, line 5 +| A (1,1) string +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_03.m.octave.out b/tests/parser/argument_validation/test_03.m.octave.out new file mode 100644 index 00000000..de837d47 --- /dev/null +++ b/tests/parser/argument_validation/test_03.m.octave.out @@ -0,0 +1,16 @@ +In test_03.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_03.m, line 5 +| a double +| ^^^^^^ style: end statement with a semicolon +In test_03.m, line 6 +| b char +| ^^^^ style: end statement with a semicolon +In test_03.m, line 7 +| c SpeedEnum +| ^^^^^^^^^ style: end statement with a semicolon +In test_03.m, line 11 +| disp(class(a)); +| ^^^^ error: expected end of file, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 4 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_04.m.octave.out b/tests/parser/argument_validation/test_04.m.octave.out new file mode 100644 index 00000000..a56ca9c7 --- /dev/null +++ b/tests/parser/argument_validation/test_04.m.octave.out @@ -0,0 +1,13 @@ +In test_04.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_04.m, line 5 +| x (1,:) {mustBeNumeric,mustBeReal} +| ^ style: end statement with a semicolon +In test_04.m, line 6 +| v (1,:) {mustBeNumeric,mustBeReal,mustBeEqualSize(v,x)} +| ^ style: end statement with a semicolon +In test_04.m, line 7 +| method (1,:) char {mustBeMember(method,{'linear','cubic','spline'})} = 'linear' +| ^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 3 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_05.m.octave.out b/tests/parser/argument_validation/test_05.m.octave.out new file mode 100644 index 00000000..20d3799d --- /dev/null +++ b/tests/parser/argument_validation/test_05.m.octave.out @@ -0,0 +1,7 @@ +In test_05.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_05.m, line 5 +| x (1,:) double +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_07.m.octave.out b/tests/parser/argument_validation/test_07.m.octave.out new file mode 100644 index 00000000..1a8ca6de --- /dev/null +++ b/tests/parser/argument_validation/test_07.m.octave.out @@ -0,0 +1,7 @@ +In test_07.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_07.m, line 5 +| ~ +| ^ error: expected IDENTIFIER, found NEWLINE instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_09.m.octave.out b/tests/parser/argument_validation/test_09.m.octave.out new file mode 100644 index 00000000..75b04e64 --- /dev/null +++ b/tests/parser/argument_validation/test_09.m.octave.out @@ -0,0 +1,7 @@ +In test_09.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_09.m, line 5 +| ~ +| ^ error: expected IDENTIFIER, found NEWLINE instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_10.m.octave.out b/tests/parser/argument_validation/test_10.m.octave.out new file mode 100644 index 00000000..1070c6da --- /dev/null +++ b/tests/parser/argument_validation/test_10.m.octave.out @@ -0,0 +1,16 @@ +In test_10.m, line 4 +| arguments (Repeating) +| ^ style: end statement with a semicolon +In test_10.m, line 5 +| x double +| ^^^^^^ style: end statement with a semicolon +In test_10.m, line 6 +| y double +| ^^^^^^ style: end statement with a semicolon +In test_10.m, line 7 +| option {mustBeMember(option,["linear","cubic"])} +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ style: end statement with a semicolon +In test_10.m, line 12 +| xCell = x; +| ^^^^^ error: expected end of file, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 4 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_12.m.octave.out b/tests/parser/argument_validation/test_12.m.octave.out new file mode 100644 index 00000000..d1d75f34 --- /dev/null +++ b/tests/parser/argument_validation/test_12.m.octave.out @@ -0,0 +1,7 @@ +In test_12.m, line 4 +| arguments(Repeating) +| ^ style: end statement with a semicolon +In test_12.m, line 5 +| x (1,:) double +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_14.m.octave.out b/tests/parser/argument_validation/test_14.m.octave.out new file mode 100644 index 00000000..e0c8163f --- /dev/null +++ b/tests/parser/argument_validation/test_14.m.octave.out @@ -0,0 +1,13 @@ +In test_14.m, line 15 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_14.m, line 16 +| a uint32 +| ^^^^^^ style: end statement with a semicolon +In test_14.m, line 17 +| b uint32 +| ^^^^^^ style: end statement with a semicolon +In test_14.m, line 19 +| arguments (Repeating) +| ^^^^^^^^^ error: expected end of file, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 3 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_15.m.octave.out b/tests/parser/argument_validation/test_15.m.octave.out new file mode 100644 index 00000000..8008bfcf --- /dev/null +++ b/tests/parser/argument_validation/test_15.m.octave.out @@ -0,0 +1,13 @@ +In test_15.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_15.m, line 5 +| NameValueArgs.Name1 +| ^^^^^ style: end statement with a semicolon +In test_15.m, line 6 +| NameValueArgs.Name2 +| ^^^^^ style: end statement with a semicolon +In test_15.m, line 10 +| result = NameValueArgs.Name1 * NameValueArgs.Name2; +| ^^^^^^ error: expected end of file, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 3 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_17.m.octave.out b/tests/parser/argument_validation/test_17.m.octave.out new file mode 100644 index 00000000..7ab5b90f --- /dev/null +++ b/tests/parser/argument_validation/test_17.m.octave.out @@ -0,0 +1,13 @@ +In test_17.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_17.m, line 5 +| width double +| ^^^^^^ style: end statement with a semicolon +In test_17.m, line 6 +| height double +| ^^^^^^ style: end statement with a semicolon +In test_17.m, line 7 +| options.LineStyle (1,1) string = "-" +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 3 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_19.m.octave.out b/tests/parser/argument_validation/test_19.m.octave.out new file mode 100644 index 00000000..f1201cea --- /dev/null +++ b/tests/parser/argument_validation/test_19.m.octave.out @@ -0,0 +1,7 @@ +In test_19.m, line 4 +| arguments(Repeating) +| ^ style: end statement with a semicolon +In test_19.m, line 5 +| x (1,:) double +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_21.m.octave.out b/tests/parser/argument_validation/test_21.m.octave.out new file mode 100644 index 00000000..a136d3a2 --- /dev/null +++ b/tests/parser/argument_validation/test_21.m.octave.out @@ -0,0 +1,13 @@ +In test_21.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_21.m, line 5 +| width double +| ^^^^^^ style: end statement with a semicolon +In test_21.m, line 6 +| height double +| ^^^^^^ style: end statement with a semicolon +In test_21.m, line 7 +| lineOptions.LineStyle (1,1) string = "-" +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 3 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_22.m.octave.out b/tests/parser/argument_validation/test_22.m.octave.out new file mode 100644 index 00000000..c8310492 --- /dev/null +++ b/tests/parser/argument_validation/test_22.m.octave.out @@ -0,0 +1,7 @@ +In test_22.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_22.m, line 5 +| x (:,:) double +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_24.m.octave.out b/tests/parser/argument_validation/test_24.m.octave.out new file mode 100644 index 00000000..9c21143b --- /dev/null +++ b/tests/parser/argument_validation/test_24.m.octave.out @@ -0,0 +1,7 @@ +In test_24.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_24.m, line 5 +| x (:,:) double +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_26.m.octave.out b/tests/parser/argument_validation/test_26.m.octave.out new file mode 100644 index 00000000..41f09dd2 --- /dev/null +++ b/tests/parser/argument_validation/test_26.m.octave.out @@ -0,0 +1,16 @@ +In test_26.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_26.m, line 5 +| a uint32 +| ^^^^^^ style: end statement with a semicolon +In test_26.m, line 6 +| b uint32 +| ^^^^^^ style: end statement with a semicolon +In test_26.m, line 7 +| c uint32 = a .* b +| ^ style: end statement with a semicolon +In test_26.m, line 11 +| end +| ^^^ error: expected end of file, found KEYWORD instead +MISS_HIT Debug Summary: 1 file(s) analysed, 4 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_28.m.octave.out b/tests/parser/argument_validation/test_28.m.octave.out new file mode 100644 index 00000000..7535f6fa --- /dev/null +++ b/tests/parser/argument_validation/test_28.m.octave.out @@ -0,0 +1,7 @@ +In test_28.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_28.m, line 5 +| a (:,:) double +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_30.m.octave.out b/tests/parser/argument_validation/test_30.m.octave.out new file mode 100644 index 00000000..15670e6d --- /dev/null +++ b/tests/parser/argument_validation/test_30.m.octave.out @@ -0,0 +1,13 @@ +In test_30.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_30.m, line 5 +| a {mustBeA(a,'double'), mustBeDims(a,2)} +| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ style: end statement with a semicolon +In test_30.m, line 6 +| b {mustBeSize(b,[5,3])} +| ^^^^^^^^^^^^^^^^^^^^^ style: end statement with a semicolon +In test_30.m, line 10 +| end +| ^^^ error: expected end of file, found KEYWORD instead +MISS_HIT Debug Summary: 1 file(s) analysed, 3 style issue(s), 1 error(s) diff --git a/tests/parser/argument_validation/test_31.m.octave.out b/tests/parser/argument_validation/test_31.m.octave.out new file mode 100644 index 00000000..0b34f242 --- /dev/null +++ b/tests/parser/argument_validation/test_31.m.octave.out @@ -0,0 +1,7 @@ +In test_31.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_31.m, line 5 +| a (1,1) double +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/arguments_as_identifier/test.m.octave.out b/tests/parser/arguments_as_identifier/test.m.octave.out new file mode 100644 index 00000000..3709dd70 --- /dev/null +++ b/tests/parser/arguments_as_identifier/test.m.octave.out @@ -0,0 +1,10 @@ +In test.m, line 2 +| arguments % keyword +| ^^^^^^^^^ style: end statement with a semicolon +In test.m, line 3 +| x uint +| ^^^^ style: end statement with a semicolon +In test.m, line 5 +| try +| ^^^ error: expected end of file, found KEYWORD instead +MISS_HIT Debug Summary: 1 file(s) analysed, 2 style issue(s), 1 error(s) diff --git a/tests/parser/property_arguments/test_1.m.octave.out b/tests/parser/property_arguments/test_1.m.octave.out new file mode 100644 index 00000000..0c3a680d --- /dev/null +++ b/tests/parser/property_arguments/test_1.m.octave.out @@ -0,0 +1,7 @@ +In test_1.m, line 14 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_1.m, line 15 +| x (:,:) double +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/property_arguments/test_3.m.octave.out b/tests/parser/property_arguments/test_3.m.octave.out new file mode 100644 index 00000000..43a0d8f7 --- /dev/null +++ b/tests/parser/property_arguments/test_3.m.octave.out @@ -0,0 +1,7 @@ +In test_3.m, line 19 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In test_3.m, line 20 +| x (:,:) double +| ^^^^^^ error: expected end of statement, found IDENTIFIER instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/parser/scripts/bar.m.out b/tests/parser/scripts/bar.m.out index c5181ccc..76f85e2c 100644 --- a/tests/parser/scripts/bar.m.out +++ b/tests/parser/scripts/bar.m.out @@ -1,4 +1,4 @@ In bar.m, line 3 | function y = foo(x) -| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use the --octave mode +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language MISS_HIT Debug Summary: 1 file(s) analysed, 1 error(s) diff --git a/tests/parser/spmd/test_01.m.octave.out b/tests/parser/spmd/test_01.m.octave.out new file mode 100644 index 00000000..7ce95521 --- /dev/null +++ b/tests/parser/spmd/test_01.m.octave.out @@ -0,0 +1,7 @@ +In test_01.m, line 4 +| spmd +| ^^^^ style: end statement with a semicolon +In test_01.m, line 8 +| end +| ^^^ error: expected end of file, found KEYWORD instead +MISS_HIT Debug Summary: 1 file(s) analysed, 1 style issue(s), 1 error(s) diff --git a/tests/projects/language/matlab_2017b/cdef_subfun.m b/tests/projects/language/matlab_2017b/cdef_subfun.m new file mode 100644 index 00000000..9cf43ca6 --- /dev/null +++ b/tests/projects/language/matlab_2017b/cdef_subfun.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +classdef cdef_subfun + +end + +function y = Potato(x) + y = x; +end diff --git a/tests/projects/language/matlab_2017b/comments.m b/tests/projects/language/matlab_2017b/comments.m new file mode 100644 index 00000000..16742989 --- /dev/null +++ b/tests/projects/language/matlab_2017b/comments.m @@ -0,0 +1 @@ +# (c) Copyright 2022 Florian Schanda diff --git a/tests/projects/language/matlab_2017b/fun_contract.m b/tests/projects/language/matlab_2017b/fun_contract.m new file mode 100644 index 00000000..32024630 --- /dev/null +++ b/tests/projects/language/matlab_2017b/fun_contract.m @@ -0,0 +1,7 @@ +% (c) Copyright 2022 Florian Schanda + +function fun_contract(x) + arguments + x uint32 + end +end diff --git a/tests/projects/language/matlab_2017b/hexlit.m b/tests/projects/language/matlab_2017b/hexlit.m new file mode 100644 index 00000000..6363976c --- /dev/null +++ b/tests/projects/language/matlab_2017b/hexlit.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = 0x5; diff --git a/tests/projects/language/matlab_2017b/ident_with_underscore.m b/tests/projects/language/matlab_2017b/ident_with_underscore.m new file mode 100644 index 00000000..843d33a8 --- /dev/null +++ b/tests/projects/language/matlab_2017b/ident_with_underscore.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +_x = 12; diff --git a/tests/projects/language/matlab_2017b/miss_hit.cfg b/tests/projects/language/matlab_2017b/miss_hit.cfg new file mode 100644 index 00000000..682bd48b --- /dev/null +++ b/tests/projects/language/matlab_2017b/miss_hit.cfg @@ -0,0 +1 @@ +matlab: "2017b" diff --git a/tests/projects/language/matlab_2017b/negation.m b/tests/projects/language/matlab_2017b/negation.m new file mode 100644 index 00000000..6d218cb5 --- /dev/null +++ b/tests/projects/language/matlab_2017b/negation.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = (1 != 2); diff --git a/tests/projects/language/matlab_2017b/sa_pair.m b/tests/projects/language/matlab_2017b/sa_pair.m new file mode 100644 index 00000000..c557ca55 --- /dev/null +++ b/tests/projects/language/matlab_2017b/sa_pair.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +foo(value = 2); diff --git a/tests/projects/language/matlab_2017b/script_global.m b/tests/projects/language/matlab_2017b/script_global.m new file mode 100644 index 00000000..7827690c --- /dev/null +++ b/tests/projects/language/matlab_2017b/script_global.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +x = Foo(10); + +function rv = Foo(potato) + rv = potato + 1; +end + +x = x + 1; diff --git a/tests/projects/language/matlab_2017b/shellescape.m b/tests/projects/language/matlab_2017b/shellescape.m new file mode 100644 index 00000000..0f7fdf36 --- /dev/null +++ b/tests/projects/language/matlab_2017b/shellescape.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +! ls diff --git a/tests/projects/language/matlab_2020b/cdef_subfun.m b/tests/projects/language/matlab_2020b/cdef_subfun.m new file mode 100644 index 00000000..9cf43ca6 --- /dev/null +++ b/tests/projects/language/matlab_2020b/cdef_subfun.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +classdef cdef_subfun + +end + +function y = Potato(x) + y = x; +end diff --git a/tests/projects/language/matlab_2020b/comments.m b/tests/projects/language/matlab_2020b/comments.m new file mode 100644 index 00000000..16742989 --- /dev/null +++ b/tests/projects/language/matlab_2020b/comments.m @@ -0,0 +1 @@ +# (c) Copyright 2022 Florian Schanda diff --git a/tests/projects/language/matlab_2020b/fun_contract.m b/tests/projects/language/matlab_2020b/fun_contract.m new file mode 100644 index 00000000..32024630 --- /dev/null +++ b/tests/projects/language/matlab_2020b/fun_contract.m @@ -0,0 +1,7 @@ +% (c) Copyright 2022 Florian Schanda + +function fun_contract(x) + arguments + x uint32 + end +end diff --git a/tests/projects/language/matlab_2020b/hexlit.m b/tests/projects/language/matlab_2020b/hexlit.m new file mode 100644 index 00000000..6363976c --- /dev/null +++ b/tests/projects/language/matlab_2020b/hexlit.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = 0x5; diff --git a/tests/projects/language/matlab_2020b/ident_with_underscore.m b/tests/projects/language/matlab_2020b/ident_with_underscore.m new file mode 100644 index 00000000..843d33a8 --- /dev/null +++ b/tests/projects/language/matlab_2020b/ident_with_underscore.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +_x = 12; diff --git a/tests/projects/language/matlab_2020b/miss_hit.cfg b/tests/projects/language/matlab_2020b/miss_hit.cfg new file mode 100644 index 00000000..7842b0b9 --- /dev/null +++ b/tests/projects/language/matlab_2020b/miss_hit.cfg @@ -0,0 +1 @@ +matlab: "2020b" diff --git a/tests/projects/language/matlab_2020b/negation.m b/tests/projects/language/matlab_2020b/negation.m new file mode 100644 index 00000000..6d218cb5 --- /dev/null +++ b/tests/projects/language/matlab_2020b/negation.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = (1 != 2); diff --git a/tests/projects/language/matlab_2020b/sa_pair.m b/tests/projects/language/matlab_2020b/sa_pair.m new file mode 100644 index 00000000..c557ca55 --- /dev/null +++ b/tests/projects/language/matlab_2020b/sa_pair.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +foo(value = 2); diff --git a/tests/projects/language/matlab_2020b/script_global.m b/tests/projects/language/matlab_2020b/script_global.m new file mode 100644 index 00000000..7827690c --- /dev/null +++ b/tests/projects/language/matlab_2020b/script_global.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +x = Foo(10); + +function rv = Foo(potato) + rv = potato + 1; +end + +x = x + 1; diff --git a/tests/projects/language/matlab_2020b/shellescape.m b/tests/projects/language/matlab_2020b/shellescape.m new file mode 100644 index 00000000..0f7fdf36 --- /dev/null +++ b/tests/projects/language/matlab_2020b/shellescape.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +! ls diff --git a/tests/projects/language/matlab_2021a/cdef_subfun.m b/tests/projects/language/matlab_2021a/cdef_subfun.m new file mode 100644 index 00000000..9cf43ca6 --- /dev/null +++ b/tests/projects/language/matlab_2021a/cdef_subfun.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +classdef cdef_subfun + +end + +function y = Potato(x) + y = x; +end diff --git a/tests/projects/language/matlab_2021a/comments.m b/tests/projects/language/matlab_2021a/comments.m new file mode 100644 index 00000000..16742989 --- /dev/null +++ b/tests/projects/language/matlab_2021a/comments.m @@ -0,0 +1 @@ +# (c) Copyright 2022 Florian Schanda diff --git a/tests/projects/language/matlab_2021a/fun_contract.m b/tests/projects/language/matlab_2021a/fun_contract.m new file mode 100644 index 00000000..32024630 --- /dev/null +++ b/tests/projects/language/matlab_2021a/fun_contract.m @@ -0,0 +1,7 @@ +% (c) Copyright 2022 Florian Schanda + +function fun_contract(x) + arguments + x uint32 + end +end diff --git a/tests/projects/language/matlab_2021a/hexlit.m b/tests/projects/language/matlab_2021a/hexlit.m new file mode 100644 index 00000000..6363976c --- /dev/null +++ b/tests/projects/language/matlab_2021a/hexlit.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = 0x5; diff --git a/tests/projects/language/matlab_2021a/ident_with_underscore.m b/tests/projects/language/matlab_2021a/ident_with_underscore.m new file mode 100644 index 00000000..843d33a8 --- /dev/null +++ b/tests/projects/language/matlab_2021a/ident_with_underscore.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +_x = 12; diff --git a/tests/projects/language/matlab_2021a/miss_hit.cfg b/tests/projects/language/matlab_2021a/miss_hit.cfg new file mode 100644 index 00000000..cd0b36dc --- /dev/null +++ b/tests/projects/language/matlab_2021a/miss_hit.cfg @@ -0,0 +1 @@ +matlab: "2021a" diff --git a/tests/projects/language/matlab_2021a/negation.m b/tests/projects/language/matlab_2021a/negation.m new file mode 100644 index 00000000..6d218cb5 --- /dev/null +++ b/tests/projects/language/matlab_2021a/negation.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = (1 != 2); diff --git a/tests/projects/language/matlab_2021a/sa_pair.m b/tests/projects/language/matlab_2021a/sa_pair.m new file mode 100644 index 00000000..c557ca55 --- /dev/null +++ b/tests/projects/language/matlab_2021a/sa_pair.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +foo(value = 2); diff --git a/tests/projects/language/matlab_2021a/script_global.m b/tests/projects/language/matlab_2021a/script_global.m new file mode 100644 index 00000000..7827690c --- /dev/null +++ b/tests/projects/language/matlab_2021a/script_global.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +x = Foo(10); + +function rv = Foo(potato) + rv = potato + 1; +end + +x = x + 1; diff --git a/tests/projects/language/matlab_2021a/shellescape.m b/tests/projects/language/matlab_2021a/shellescape.m new file mode 100644 index 00000000..0f7fdf36 --- /dev/null +++ b/tests/projects/language/matlab_2021a/shellescape.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +! ls diff --git a/tests/projects/language/mh_trace.json b/tests/projects/language/mh_trace.json new file mode 100644 index 00000000..b450dc94 --- /dev/null +++ b/tests/projects/language/mh_trace.json @@ -0,0 +1,29 @@ +{ + "cdef_subfun.m::Potato": { + "source": { + "col_start": 13, + "filename": "octave_4_4/cdef_subfun.m", + "line": 7 + }, + "tags": [], + "test": false + }, + "fun_contract": { + "source": { + "col_start": 9, + "filename": "matlab_2021a/fun_contract.m", + "line": 3 + }, + "tags": [], + "test": false + }, + "script_global.m::Foo": { + "source": { + "col_start": 14, + "filename": "octave_4_4/script_global.m", + "line": 5 + }, + "tags": [], + "test": false + } +} \ No newline at end of file diff --git a/tests/projects/language/miss_hit.cfg b/tests/projects/language/miss_hit.cfg new file mode 100644 index 00000000..a3442726 --- /dev/null +++ b/tests/projects/language/miss_hit.cfg @@ -0,0 +1,4 @@ +project_root +suppress_rule: "naming_scripts" +suppress_rule: "naming_classes" +suppress_rule: "naming_functions" \ No newline at end of file diff --git a/tests/projects/language/octave_4_2/cdef_subfun.m b/tests/projects/language/octave_4_2/cdef_subfun.m new file mode 100644 index 00000000..9cf43ca6 --- /dev/null +++ b/tests/projects/language/octave_4_2/cdef_subfun.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +classdef cdef_subfun + +end + +function y = Potato(x) + y = x; +end diff --git a/tests/projects/language/octave_4_2/comments.m b/tests/projects/language/octave_4_2/comments.m new file mode 100644 index 00000000..16742989 --- /dev/null +++ b/tests/projects/language/octave_4_2/comments.m @@ -0,0 +1 @@ +# (c) Copyright 2022 Florian Schanda diff --git a/tests/projects/language/octave_4_2/fun_contract.m b/tests/projects/language/octave_4_2/fun_contract.m new file mode 100644 index 00000000..32024630 --- /dev/null +++ b/tests/projects/language/octave_4_2/fun_contract.m @@ -0,0 +1,7 @@ +% (c) Copyright 2022 Florian Schanda + +function fun_contract(x) + arguments + x uint32 + end +end diff --git a/tests/projects/language/octave_4_2/hexlit.m b/tests/projects/language/octave_4_2/hexlit.m new file mode 100644 index 00000000..6363976c --- /dev/null +++ b/tests/projects/language/octave_4_2/hexlit.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = 0x5; diff --git a/tests/projects/language/octave_4_2/ident_with_underscore.m b/tests/projects/language/octave_4_2/ident_with_underscore.m new file mode 100644 index 00000000..843d33a8 --- /dev/null +++ b/tests/projects/language/octave_4_2/ident_with_underscore.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +_x = 12; diff --git a/tests/projects/language/octave_4_2/miss_hit.cfg b/tests/projects/language/octave_4_2/miss_hit.cfg new file mode 100644 index 00000000..3223a17d --- /dev/null +++ b/tests/projects/language/octave_4_2/miss_hit.cfg @@ -0,0 +1 @@ +octave: "4.2" diff --git a/tests/projects/language/octave_4_2/negation.m b/tests/projects/language/octave_4_2/negation.m new file mode 100644 index 00000000..6d218cb5 --- /dev/null +++ b/tests/projects/language/octave_4_2/negation.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = (1 != 2); diff --git a/tests/projects/language/octave_4_2/sa_pair.m b/tests/projects/language/octave_4_2/sa_pair.m new file mode 100644 index 00000000..c557ca55 --- /dev/null +++ b/tests/projects/language/octave_4_2/sa_pair.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +foo(value = 2); diff --git a/tests/projects/language/octave_4_2/script_global.m b/tests/projects/language/octave_4_2/script_global.m new file mode 100644 index 00000000..7827690c --- /dev/null +++ b/tests/projects/language/octave_4_2/script_global.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +x = Foo(10); + +function rv = Foo(potato) + rv = potato + 1; +end + +x = x + 1; diff --git a/tests/projects/language/octave_4_2/shellescape.m b/tests/projects/language/octave_4_2/shellescape.m new file mode 100644 index 00000000..0f7fdf36 --- /dev/null +++ b/tests/projects/language/octave_4_2/shellescape.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +! ls diff --git a/tests/projects/language/octave_4_4/cdef_subfun.m b/tests/projects/language/octave_4_4/cdef_subfun.m new file mode 100644 index 00000000..9cf43ca6 --- /dev/null +++ b/tests/projects/language/octave_4_4/cdef_subfun.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +classdef cdef_subfun + +end + +function y = Potato(x) + y = x; +end diff --git a/tests/projects/language/octave_4_4/comments.m b/tests/projects/language/octave_4_4/comments.m new file mode 100644 index 00000000..16742989 --- /dev/null +++ b/tests/projects/language/octave_4_4/comments.m @@ -0,0 +1 @@ +# (c) Copyright 2022 Florian Schanda diff --git a/tests/projects/language/octave_4_4/fun_contract.m b/tests/projects/language/octave_4_4/fun_contract.m new file mode 100644 index 00000000..32024630 --- /dev/null +++ b/tests/projects/language/octave_4_4/fun_contract.m @@ -0,0 +1,7 @@ +% (c) Copyright 2022 Florian Schanda + +function fun_contract(x) + arguments + x uint32 + end +end diff --git a/tests/projects/language/octave_4_4/hexlit.m b/tests/projects/language/octave_4_4/hexlit.m new file mode 100644 index 00000000..6363976c --- /dev/null +++ b/tests/projects/language/octave_4_4/hexlit.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = 0x5; diff --git a/tests/projects/language/octave_4_4/ident_with_underscore.m b/tests/projects/language/octave_4_4/ident_with_underscore.m new file mode 100644 index 00000000..843d33a8 --- /dev/null +++ b/tests/projects/language/octave_4_4/ident_with_underscore.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +_x = 12; diff --git a/tests/projects/language/octave_4_4/miss_hit.cfg b/tests/projects/language/octave_4_4/miss_hit.cfg new file mode 100644 index 00000000..341fe564 --- /dev/null +++ b/tests/projects/language/octave_4_4/miss_hit.cfg @@ -0,0 +1 @@ +octave: "4.4" diff --git a/tests/projects/language/octave_4_4/negation.m b/tests/projects/language/octave_4_4/negation.m new file mode 100644 index 00000000..6d218cb5 --- /dev/null +++ b/tests/projects/language/octave_4_4/negation.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +x = (1 != 2); diff --git a/tests/projects/language/octave_4_4/sa_pair.m b/tests/projects/language/octave_4_4/sa_pair.m new file mode 100644 index 00000000..c557ca55 --- /dev/null +++ b/tests/projects/language/octave_4_4/sa_pair.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +foo(value = 2); diff --git a/tests/projects/language/octave_4_4/script_global.m b/tests/projects/language/octave_4_4/script_global.m new file mode 100644 index 00000000..7827690c --- /dev/null +++ b/tests/projects/language/octave_4_4/script_global.m @@ -0,0 +1,9 @@ +% (c) Copyright 2022 Florian Schanda + +x = Foo(10); + +function rv = Foo(potato) + rv = potato + 1; +end + +x = x + 1; diff --git a/tests/projects/language/octave_4_4/shellescape.m b/tests/projects/language/octave_4_4/shellescape.m new file mode 100644 index 00000000..0f7fdf36 --- /dev/null +++ b/tests/projects/language/octave_4_4/shellescape.m @@ -0,0 +1,3 @@ +% (c) Copyright 2022 Florian Schanda + +! ls diff --git a/tests/projects/language/output.txt b/tests/projects/language/output.txt new file mode 100644 index 00000000..28f568bd --- /dev/null +++ b/tests/projects/language/output.txt @@ -0,0 +1,717 @@ +=== STYLE === +In matlab_2017b/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2017b/hexlit.m, line 3 +| x = 0x5; +| ^^ error: expected end of statement, found IDENTIFIER instead +In matlab_2017b/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2017b/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2017b/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In matlab_2017b/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In matlab_2020b/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2020b/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2020b/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2020b/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In matlab_2020b/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In matlab_2021a/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2021a/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2021a/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2021a/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In octave_4_2/cdef_subfun.m, line 7 +| function y = Potato(x) +| ^^^^^^^^ error: expected end of file, found KEYWORD instead +In octave_4_2/fun_contract.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In octave_4_2/fun_contract.m, line 5 +| x uint32 +| ^^^^^^ style: end statement with a semicolon +In octave_4_2/fun_contract.m, line 7 +| end +| ^^^ error: expected end of file, found KEYWORD instead +In octave_4_2/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In octave_4_2/shellescape.m, line 3 +| ! ls +| ^ style: unary operator must not be followed by whitespace +In octave_4_2/shellescape.m, line 3 +| ! ls +| ^^ style: end statement with a semicolon +In octave_4_4/fun_contract.m, line 4 +| arguments +| ^^^^^^^^^ style: end statement with a semicolon +In octave_4_4/fun_contract.m, line 5 +| x uint32 +| ^^^^^^ style: end statement with a semicolon +In octave_4_4/fun_contract.m, line 7 +| end +| ^^^ error: expected end of file, found KEYWORD instead +In octave_4_4/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In octave_4_4/shellescape.m, line 3 +| ! ls +| ^ style: unary operator must not be followed by whitespace +In octave_4_4/shellescape.m, line 3 +| ! ls +| ^^ style: end statement with a semicolon +MISS_HIT Style Summary: 45 file(s) analysed, 8 style issue(s), 20 error(s) +=== LINT === +In matlab_2017b/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2017b/hexlit.m, line 3 +| x = 0x5; +| ^^ error: expected end of statement, found IDENTIFIER instead +In matlab_2017b/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2017b/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2017b/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In matlab_2017b/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In matlab_2020b/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2020b/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2020b/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2020b/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In matlab_2020b/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In matlab_2021a/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2021a/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2021a/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2021a/sa_pair.m, line 3 +| foo(value = 2); +| ^ check (low): name-value pairs have extremely confusing semantics and should be avoided, use two arguments instead +In matlab_2021a/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In octave_4_2/cdef_subfun.m, line 7 +| function y = Potato(x) +| ^^^^^^^^ error: expected end of file, found KEYWORD instead +In octave_4_2/fun_contract.m, line 7 +| end +| ^^^ error: expected end of file, found KEYWORD instead +In octave_4_2/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In octave_4_4/fun_contract.m, line 7 +| end +| ^^^ error: expected end of file, found KEYWORD instead +In octave_4_4/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +MISS_HIT Lint Summary: 45 file(s) analysed, 1 check(s), 20 error(s) +=== METRICS === +In matlab_2017b/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2017b/hexlit.m, line 3 +| x = 0x5; +| ^^ error: expected end of statement, found IDENTIFIER instead +In matlab_2017b/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2017b/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2017b/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In matlab_2017b/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In matlab_2020b/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2020b/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2020b/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2020b/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In matlab_2020b/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In matlab_2021a/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2021a/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2021a/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2021a/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In octave_4_2/cdef_subfun.m, line 7 +| function y = Potato(x) +| ^^^^^^^^ error: expected end of file, found KEYWORD instead +In octave_4_2/fun_contract.m, line 7 +| end +| ^^^ error: expected end of file, found KEYWORD instead +In octave_4_2/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In octave_4_4/fun_contract.m, line 7 +| end +| ^^^ error: expected end of file, found KEYWORD instead +In octave_4_4/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +=== Code metric by file: + +* Code metrics for file matlab_2017b/cdef_subfun.m: + File lines: 9 + + Code metrics for function cdef_subfun.m::Potato: + Control nesting : 0 + Cyclomatic complexity: 1 + Function lines : 3 + Globals : 0 + Number of paths : 1 + Parameters : 2 + Persistents : 0 + +* Code metrics for file matlab_2017b/comments.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2017b/fun_contract.m: + File lines: 7 + + Code metrics for function fun_contract: + Control nesting : 0 + Cyclomatic complexity: 1 + Function lines : 5 + Globals : 0 + Number of paths : 1 + Parameters : 1 + Persistents : 0 + +* Code metrics for file matlab_2017b/hexlit.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2017b/ident_with_underscore.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2017b/negation.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2017b/sa_pair.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2017b/script_global.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2017b/shellescape.m: + File lines: 3 + + Code metrics for function shellescape: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file matlab_2020b/cdef_subfun.m: + File lines: 9 + + Code metrics for function cdef_subfun.m::Potato: + Control nesting : 0 + Cyclomatic complexity: 1 + Function lines : 3 + Globals : 0 + Number of paths : 1 + Parameters : 2 + Persistents : 0 + +* Code metrics for file matlab_2020b/comments.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2020b/fun_contract.m: + File lines: 7 + + Code metrics for function fun_contract: + Control nesting : 0 + Cyclomatic complexity: 1 + Function lines : 5 + Globals : 0 + Number of paths : 1 + Parameters : 1 + Persistents : 0 + +* Code metrics for file matlab_2020b/hexlit.m: + File lines: 3 + + Code metrics for function hexlit: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file matlab_2020b/ident_with_underscore.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2020b/negation.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2020b/sa_pair.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2020b/script_global.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2020b/shellescape.m: + File lines: 3 + + Code metrics for function shellescape: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file matlab_2021a/cdef_subfun.m: + File lines: 9 + + Code metrics for function cdef_subfun.m::Potato: + Control nesting : 0 + Cyclomatic complexity: 1 + Function lines : 3 + Globals : 0 + Number of paths : 1 + Parameters : 2 + Persistents : 0 + +* Code metrics for file matlab_2021a/comments.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2021a/fun_contract.m: + File lines: 7 + + Code metrics for function fun_contract: + Control nesting : 0 + Cyclomatic complexity: 1 + Function lines : 5 + Globals : 0 + Number of paths : 1 + Parameters : 1 + Persistents : 0 + +* Code metrics for file matlab_2021a/hexlit.m: + File lines: 3 + + Code metrics for function hexlit: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file matlab_2021a/ident_with_underscore.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2021a/negation.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2021a/sa_pair.m: + File lines: 3 + + Code metrics for function sa_pair: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file matlab_2021a/script_global.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file matlab_2021a/shellescape.m: + File lines: 3 + + Code metrics for function shellescape: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_2/cdef_subfun.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file octave_4_2/comments.m: + File lines: 1 + + Code metrics for function comments: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_2/fun_contract.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file octave_4_2/hexlit.m: + File lines: 3 + + Code metrics for function hexlit: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_2/ident_with_underscore.m: + File lines: 3 + + Code metrics for function ident_with_underscore: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_2/negation.m: + File lines: 3 + + Code metrics for function negation: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_2/sa_pair.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file octave_4_2/script_global.m: + File lines: 9 + + Code metrics for function script_global: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + + Code metrics for function script_global.m::Foo: + Control nesting : 0 + Cyclomatic complexity: 1 + Function lines : 3 + Globals : 0 + Number of paths : 1 + Parameters : 2 + Persistents : 0 + +* Code metrics for file octave_4_2/shellescape.m: + File lines: 3 + + Code metrics for function shellescape: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_4/cdef_subfun.m: + File lines: 9 + + Code metrics for function cdef_subfun.m::Potato: + Control nesting : 0 + Cyclomatic complexity: 1 + Function lines : 3 + Globals : 0 + Number of paths : 1 + Parameters : 2 + Persistents : 0 + +* Code metrics for file octave_4_4/comments.m: + File lines: 1 + + Code metrics for function comments: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_4/fun_contract.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file octave_4_4/hexlit.m: + File lines: 3 + + Code metrics for function hexlit: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_4/ident_with_underscore.m: + File lines: 3 + + Code metrics for function ident_with_underscore: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_4/negation.m: + File lines: 3 + + Code metrics for function negation: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +* Code metrics for file octave_4_4/sa_pair.m: + Contains syntax or semantics errors, + no metrics collected. + +* Code metrics for file octave_4_4/script_global.m: + File lines: 9 + + Code metrics for function script_global: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + + Code metrics for function script_global.m::Foo: + Control nesting : 0 + Cyclomatic complexity: 1 + Function lines : 3 + Globals : 0 + Number of paths : 1 + Parameters : 2 + Persistents : 0 + +* Code metrics for file octave_4_4/shellescape.m: + File lines: 3 + + Code metrics for function shellescape: + Control nesting : 0 + Cyclomatic complexity: 1 + Globals : 0 + Number of paths : 1 + Parameters : 0 + Persistents : 0 + +=== Global summary of worst offenders by metric: + +* File metric 'File lines': + 1. 9 (octave_4_4/script_global.m) + 2. 9 (octave_4_4/cdef_subfun.m) + 3. 9 (octave_4_2/script_global.m) + 4. 9 (matlab_2021a/cdef_subfun.m) + 5. 9 (matlab_2020b/cdef_subfun.m) + 6. 9 (matlab_2017b/cdef_subfun.m) + 7. 7 (matlab_2021a/fun_contract.m) + 8. 7 (matlab_2020b/fun_contract.m) + 9. 7 (matlab_2017b/fun_contract.m) + 10. 3 (octave_4_4/shellescape.m) + +* Function metric 'Cyclomatic complexity': + 1. 1 (octave_4_4/shellescape.m, function shellescape) + 2. 1 (octave_4_4/script_global.m, function script_global.m::Foo) + 3. 1 (octave_4_4/script_global.m, function script_global) + 4. 1 (octave_4_4/negation.m, function negation) + 5. 1 (octave_4_4/ident_with_underscore.m, function ident_with_underscore) + 6. 1 (octave_4_4/hexlit.m, function hexlit) + 7. 1 (octave_4_4/comments.m, function comments) + 8. 1 (octave_4_4/cdef_subfun.m, function cdef_subfun.m::Potato) + 9. 1 (octave_4_2/shellescape.m, function shellescape) + 10. 1 (octave_4_2/script_global.m, function script_global.m::Foo) + +* Function metric 'Function lines': + 1. 5 (matlab_2021a/fun_contract.m, function fun_contract) + 2. 5 (matlab_2020b/fun_contract.m, function fun_contract) + 3. 5 (matlab_2017b/fun_contract.m, function fun_contract) + 4. 3 (octave_4_4/script_global.m, function script_global.m::Foo) + 5. 3 (octave_4_4/cdef_subfun.m, function cdef_subfun.m::Potato) + 6. 3 (octave_4_2/script_global.m, function script_global.m::Foo) + 7. 3 (matlab_2021a/cdef_subfun.m, function cdef_subfun.m::Potato) + 8. 3 (matlab_2020b/cdef_subfun.m, function cdef_subfun.m::Potato) + 9. 3 (matlab_2017b/cdef_subfun.m, function cdef_subfun.m::Potato) + +* Function metric 'Number of paths': + 1. 1 (octave_4_4/shellescape.m, function shellescape) + 2. 1 (octave_4_4/script_global.m, function script_global.m::Foo) + 3. 1 (octave_4_4/script_global.m, function script_global) + 4. 1 (octave_4_4/negation.m, function negation) + 5. 1 (octave_4_4/ident_with_underscore.m, function ident_with_underscore) + 6. 1 (octave_4_4/hexlit.m, function hexlit) + 7. 1 (octave_4_4/comments.m, function comments) + 8. 1 (octave_4_4/cdef_subfun.m, function cdef_subfun.m::Potato) + 9. 1 (octave_4_2/shellescape.m, function shellescape) + 10. 1 (octave_4_2/script_global.m, function script_global.m::Foo) + +* Function metric 'Parameters': + 1. 2 (octave_4_4/script_global.m, function script_global.m::Foo) + 2. 2 (octave_4_4/cdef_subfun.m, function cdef_subfun.m::Potato) + 3. 2 (octave_4_2/script_global.m, function script_global.m::Foo) + 4. 2 (matlab_2021a/cdef_subfun.m, function cdef_subfun.m::Potato) + 5. 2 (matlab_2020b/cdef_subfun.m, function cdef_subfun.m::Potato) + 6. 2 (matlab_2017b/cdef_subfun.m, function cdef_subfun.m::Potato) + 7. 1 (matlab_2021a/fun_contract.m, function fun_contract) + 8. 1 (matlab_2020b/fun_contract.m, function fun_contract) + 9. 1 (matlab_2017b/fun_contract.m, function fun_contract) + +MISS_HIT Metric Summary: 45 file(s) analysed, 20 error(s) +=== TRACING === +In matlab_2017b/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2017b/hexlit.m, line 3 +| x = 0x5; +| ^^ error: expected end of statement, found IDENTIFIER instead +In matlab_2017b/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2017b/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2017b/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In matlab_2017b/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In matlab_2020b/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2020b/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2020b/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2020b/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In matlab_2020b/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In matlab_2021a/comments.m, line 1 +| # (c) Copyright 2022 Florian Schanda +| ^ lex error: unexpected character '#' +In matlab_2021a/ident_with_underscore.m, line 3 +| _x = 12; +| ^ lex error: unexpected character '_' +In matlab_2021a/negation.m, line 3 +| x = (1 != 2); +| ^^^^^^ error: expected KET, found BANG instead +In matlab_2021a/script_global.m, line 5 +| function rv = Foo(potato) +| ^^^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language +In octave_4_2/cdef_subfun.m, line 7 +| function y = Potato(x) +| ^^^^^^^^ error: expected end of file, found KEYWORD instead +In octave_4_2/fun_contract.m, line 7 +| end +| ^^^ error: expected end of file, found KEYWORD instead +In octave_4_2/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +In octave_4_4/fun_contract.m, line 7 +| end +| ^^^ error: expected end of file, found KEYWORD instead +In octave_4_4/sa_pair.m, line 3 +| foo(value = 2); +| ^ error: expected IDENTIFIER, found ASSIGNMENT instead +MISS_HIT Trace Summary: 45 file(s) analysed, 20 error(s) diff --git a/tests/style/bug_199_parse_errors_and_style/expected_out.html b/tests/style/bug_199_parse_errors_and_style/expected_out.html index a0ce357a..b7810f58 100644 --- a/tests/style/bug_199_parse_errors_and_style/expected_out.html +++ b/tests/style/bug_199_parse_errors_and_style/expected_out.html @@ -12,7 +12,7 @@

Issues identified

test_1.m

-
test_1.m: line 5: error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use the --octave mode
+
test_1.m: line 5: error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language

test_2.m

test_2.m: style: violates naming scheme for scripts
test_2.m: line 1: style: No copyright notice found in docstring
diff --git a/tests/style/bug_199_parse_errors_and_style/expected_out.txt b/tests/style/bug_199_parse_errors_and_style/expected_out.txt index 5d5a2ee0..817c66bf 100644 --- a/tests/style/bug_199_parse_errors_and_style/expected_out.txt +++ b/tests/style/bug_199_parse_errors_and_style/expected_out.txt @@ -2,7 +2,7 @@ test_1.m: error: file is not auto-fixed because it contains parse errors In test_1.m, line 5 | function z = f(x, a) -| ^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use the --octave mode +| ^ error: script-global functions are an Octave-specific feature; move your functions to the end of the script file or use an Octave language test_2.m: style: violates naming scheme for scripts In test_2.m, line 1 | % Taken from issue #199 (by alvinseville7cf) diff --git a/tests/style/program_order/octave/Not_Valid_1.m b/tests/style/program_order/octave/Not_Valid_1.m index 1fb62b49..ef714da6 100644 --- a/tests/style/program_order/octave/Not_Valid_1.m +++ b/tests/style/program_order/octave/Not_Valid_1.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_1 (x) - arguments - x uint32 - end - persistent z if isempty(z) global y diff --git a/tests/style/program_order/octave/Not_Valid_1.m_fixed b/tests/style/program_order/octave/Not_Valid_1.m_fixed index 1fb62b49..ef714da6 100644 --- a/tests/style/program_order/octave/Not_Valid_1.m_fixed +++ b/tests/style/program_order/octave/Not_Valid_1.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_1 (x) - arguments - x uint32 - end - persistent z if isempty(z) global y diff --git a/tests/style/program_order/octave/Not_Valid_2.m b/tests/style/program_order/octave/Not_Valid_2.m index e2fd61cf..6cdade23 100644 --- a/tests/style/program_order/octave/Not_Valid_2.m +++ b/tests/style/program_order/octave/Not_Valid_2.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_2 (x) - arguments - x uint32 - end - persistent z global y persistent w diff --git a/tests/style/program_order/octave/Not_Valid_2.m_fixed b/tests/style/program_order/octave/Not_Valid_2.m_fixed index e2fd61cf..6cdade23 100644 --- a/tests/style/program_order/octave/Not_Valid_2.m_fixed +++ b/tests/style/program_order/octave/Not_Valid_2.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_2 (x) - arguments - x uint32 - end - persistent z global y persistent w diff --git a/tests/style/program_order/octave/Not_Valid_4.m b/tests/style/program_order/octave/Not_Valid_4.m index 10aabfb4..727b60e0 100644 --- a/tests/style/program_order/octave/Not_Valid_4.m +++ b/tests/style/program_order/octave/Not_Valid_4.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_4 (x) - arguments - x uint32 - end - rv = x; global y diff --git a/tests/style/program_order/octave/Not_Valid_4.m_fixed b/tests/style/program_order/octave/Not_Valid_4.m_fixed index 10aabfb4..727b60e0 100644 --- a/tests/style/program_order/octave/Not_Valid_4.m_fixed +++ b/tests/style/program_order/octave/Not_Valid_4.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_4 (x) - arguments - x uint32 - end - rv = x; global y diff --git a/tests/style/program_order/octave/Not_Valid_5.m b/tests/style/program_order/octave/Not_Valid_5.m index 544695ae..e3b4c659 100644 --- a/tests/style/program_order/octave/Not_Valid_5.m +++ b/tests/style/program_order/octave/Not_Valid_5.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_5 (x) - arguments - x uint32 - end - persistent y if isempty(y) diff --git a/tests/style/program_order/octave/Not_Valid_5.m_fixed b/tests/style/program_order/octave/Not_Valid_5.m_fixed index 544695ae..e3b4c659 100644 --- a/tests/style/program_order/octave/Not_Valid_5.m_fixed +++ b/tests/style/program_order/octave/Not_Valid_5.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_5 (x) - arguments - x uint32 - end - persistent y if isempty(y) diff --git a/tests/style/program_order/octave/Not_Valid_6.m b/tests/style/program_order/octave/Not_Valid_6.m index 856a24d2..60a4ad76 100644 --- a/tests/style/program_order/octave/Not_Valid_6.m +++ b/tests/style/program_order/octave/Not_Valid_6.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_6 (x) - arguments - x uint32 - end - global y persistent z global w diff --git a/tests/style/program_order/octave/Not_Valid_6.m_fixed b/tests/style/program_order/octave/Not_Valid_6.m_fixed index 856a24d2..60a4ad76 100644 --- a/tests/style/program_order/octave/Not_Valid_6.m_fixed +++ b/tests/style/program_order/octave/Not_Valid_6.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Not_Valid_6 (x) - arguments - x uint32 - end - global y persistent z global w diff --git a/tests/style/program_order/octave/Valid_1.m b/tests/style/program_order/octave/Valid_1.m index 83b4b77b..7b188ba2 100644 --- a/tests/style/program_order/octave/Valid_1.m +++ b/tests/style/program_order/octave/Valid_1.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_1 (x) - arguments - x uint32 - end - global y persistent z diff --git a/tests/style/program_order/octave/Valid_1.m_fixed b/tests/style/program_order/octave/Valid_1.m_fixed index 83b4b77b..7b188ba2 100644 --- a/tests/style/program_order/octave/Valid_1.m_fixed +++ b/tests/style/program_order/octave/Valid_1.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_1 (x) - arguments - x uint32 - end - global y persistent z diff --git a/tests/style/program_order/octave/Valid_2.m b/tests/style/program_order/octave/Valid_2.m index 3db598b9..666ebf1d 100644 --- a/tests/style/program_order/octave/Valid_2.m +++ b/tests/style/program_order/octave/Valid_2.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_2 (x) - arguments - x uint32 - end - persistent z global y diff --git a/tests/style/program_order/octave/Valid_2.m_fixed b/tests/style/program_order/octave/Valid_2.m_fixed index 3db598b9..666ebf1d 100644 --- a/tests/style/program_order/octave/Valid_2.m_fixed +++ b/tests/style/program_order/octave/Valid_2.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_2 (x) - arguments - x uint32 - end - persistent z global y diff --git a/tests/style/program_order/octave/Valid_4.m b/tests/style/program_order/octave/Valid_4.m index ab14688b..26f3c340 100644 --- a/tests/style/program_order/octave/Valid_4.m +++ b/tests/style/program_order/octave/Valid_4.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_4 (x) - arguments - x uint32 - end - global y rv = x + y; diff --git a/tests/style/program_order/octave/Valid_4.m_fixed b/tests/style/program_order/octave/Valid_4.m_fixed index ab14688b..26f3c340 100644 --- a/tests/style/program_order/octave/Valid_4.m_fixed +++ b/tests/style/program_order/octave/Valid_4.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_4 (x) - arguments - x uint32 - end - global y rv = x + y; diff --git a/tests/style/program_order/octave/Valid_5.m b/tests/style/program_order/octave/Valid_5.m index 4726a5cd..160a44d1 100644 --- a/tests/style/program_order/octave/Valid_5.m +++ b/tests/style/program_order/octave/Valid_5.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_5 (x) - arguments - x uint32 - end - persistent z if isempty(z) diff --git a/tests/style/program_order/octave/Valid_5.m_fixed b/tests/style/program_order/octave/Valid_5.m_fixed index 4726a5cd..160a44d1 100644 --- a/tests/style/program_order/octave/Valid_5.m_fixed +++ b/tests/style/program_order/octave/Valid_5.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_5 (x) - arguments - x uint32 - end - persistent z if isempty(z) diff --git a/tests/style/program_order/octave/Valid_6.m b/tests/style/program_order/octave/Valid_6.m index 461e0d96..6871fbed 100644 --- a/tests/style/program_order/octave/Valid_6.m +++ b/tests/style/program_order/octave/Valid_6.m @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_6 (x) - arguments - x uint32 - end - import Potato.Kitten global y diff --git a/tests/style/program_order/octave/Valid_6.m_fixed b/tests/style/program_order/octave/Valid_6.m_fixed index 461e0d96..6871fbed 100644 --- a/tests/style/program_order/octave/Valid_6.m_fixed +++ b/tests/style/program_order/octave/Valid_6.m_fixed @@ -1,10 +1,6 @@ % (c) Copyright 2021 Florian Schanda function rv = Valid_6 (x) - arguments - x uint32 - end - import Potato.Kitten global y