discuss@lists.openscad.org

OpenSCAD general discussion Mailing-list

View all threads

Static Code Analysis for OpenSCAD

L
lar3ry
Fri, Nov 20, 2020 8:07 PM

Just a few things I have noticed.
I ran it against an OpenSCAD file designed to be run through the customizer,
and saw a few things.

parsing publicDomainGearV1.1.scad
publicDomainGearV1.1.scad:63:2: W2002: Overwriting mm_per_tooth variable
from a lower scope.
publicDomainGearV1.1.scad:65:2: W2002: Overwriting thickness variable from
a lower scope.
publicDomainGearV1.1.scad:74:47: W2008: Variable pi used but never
defined.
publicDomainGearV1.1.scad:75:14: W2008: Variable p used but never defined.
...
publicDomainGearV1.1.scad:79:9: W1001: Overly complicated argument contains
9 tokens.

I wrote a small test program to check a few of these, and got:

parsing Test.scad
Test.scad:2:15: W2002: Overwriting x variable from a lower scope.

Test1 illustrates the first problem. In a module, a parameter can have a
default value.
Test2 does not duplicate the errors shown for lines 74 and 75 of
publicDomainGearV1.1.scad

About the line 79:9 "Overly complicated argument", I'm not sure that's a
problem. I admit I am not an expert OpenSCAD user, but it seems to me that a
valid startement using any number of arguments should not generate a warning
or error.

publicDomainGearV1.scad
http://forum.openscad.org/file/t2121/publicDomainGearV1.scad
Test.scad http://forum.openscad.org/file/t2121/Test.scad

Nice work.

--
Sent from: http://forum.openscad.org/

Just a few things I have noticed. I ran it against an OpenSCAD file designed to be run through the customizer, and saw a few things. parsing publicDomainGearV1.1.scad publicDomainGearV1.1.scad:63:2: W2002: Overwriting `mm_per_tooth` variable from a lower scope. publicDomainGearV1.1.scad:65:2: W2002: Overwriting `thickness` variable from a lower scope. publicDomainGearV1.1.scad:74:47: W2008: Variable `pi` used but never defined. publicDomainGearV1.1.scad:75:14: W2008: Variable `p` used but never defined. ... publicDomainGearV1.1.scad:79:9: W1001: Overly complicated argument contains 9 tokens. I wrote a small test program to check a few of these, and got: parsing Test.scad Test.scad:2:15: W2002: Overwriting `x` variable from a lower scope. Test1 illustrates the first problem. In a module, a parameter can have a default value. Test2 does not duplicate the errors shown for lines 74 and 75 of publicDomainGearV1.1.scad About the line 79:9 "Overly complicated argument", I'm not sure that's a problem. I admit I am not an expert OpenSCAD user, but it seems to me that a valid startement using any number of arguments should not generate a warning or error. publicDomainGearV1.scad <http://forum.openscad.org/file/t2121/publicDomainGearV1.scad> Test.scad <http://forum.openscad.org/file/t2121/Test.scad> Nice work. -- Sent from: http://forum.openscad.org/
J
julianstirling
Fri, Nov 20, 2020 11:10 PM

Yeah exactly what rules we put in are an interesting question and there will
always be differences of opinion, and the best way to deal with this is to
make them customisable.

For context of the microscope we are looking to move the microscope design
towards something that could be medically certified. For this we need a lot
of confidence that every piece of code behaves as expected.

Overwriting a variable from a lower scope can cause a piece of code to
change behaviour unexpectedly or to confuse someone on which variable is
being used. It is then safer to pass in arguments than overwrite a variable.
We are also likely to warn that include in itself is dangerous. So in the
example of Test.scad if you remove line 1 then it doesn't warn. So it is
fine to override the the default input, but it warns if a variable in that
scope has the same name as one defined in the lower scope. These warnings
are annoying to a lot of people. So we may perhaps turn them off by default
and have a mode that is more like
sca2d --strict file.scad

The same logic goes for overly complicated argument. It is again for
readability and understandability of out code. The idea is to try get
someone to change:

cube([17*2+0.1*25.4*2+35, 17*2+0.1*25.4*2+75, 17*2+0.1*25.4*2+45]);

To:

wall_thickness = 17;
inch = 25.4;
//clearance is 1/10 of an inch as recommended by the manufacturer on p19
clearance = 0.1*inch;
inner_dimensions = [35, 75, 45];
extra_size = (wall_thickness+clearance)*2*[1,1,1];
cube(inner_dimensions + extra_size);

Both should be identical. But one is more understandable. Of course, the
analyser can only go so far. There are always ways just define a pointless
badly named variable just to reduce the number of tokens. But the analyser
is to help you identify confusing code. Most statements the analyser picks
up will be valid code, they just are things that may confuse someone else
reading it.

The key to this has to be configurability so a project can decide what the
want to allow. It would be interesting to get feedback from the community
about what dangerous/confusing code they would want to be warned about.

--
Sent from: http://forum.openscad.org/

Yeah exactly what rules we put in are an interesting question and there will always be differences of opinion, and the best way to deal with this is to make them customisable. For context of the microscope we are looking to move the microscope design towards something that could be medically certified. For this we need a lot of confidence that every piece of code behaves as expected. Overwriting a variable from a lower scope can cause a piece of code to change behaviour unexpectedly or to confuse someone on which variable is being used. It is then safer to pass in arguments than overwrite a variable. We are also likely to warn that include in itself is dangerous. So in the example of `Test.scad` if you remove line 1 then it doesn't warn. So it is fine to override the the default input, but it warns if a variable in that scope has the same name as one defined in the lower scope. These warnings are annoying to a lot of people. So we may perhaps turn them off by default and have a mode that is more like sca2d --strict file.scad The same logic goes for overly complicated argument. It is again for readability and understandability of out code. The idea is to try get someone to change: cube([17*2+0.1*25.4*2+35, 17*2+0.1*25.4*2+75, 17*2+0.1*25.4*2+45]); To: wall_thickness = 17; inch = 25.4; //clearance is 1/10 of an inch as recommended by the manufacturer on p19 clearance = 0.1*inch; inner_dimensions = [35, 75, 45]; extra_size = (wall_thickness+clearance)*2*[1,1,1]; cube(inner_dimensions + extra_size); Both should be identical. But one is more understandable. Of course, the analyser can only go so far. There are always ways just define a pointless badly named variable just to reduce the number of tokens. But the analyser is to help you identify confusing code. Most statements the analyser picks up will be valid code, they just are things that may confuse someone else reading it. The key to this has to be configurability so a project can decide what the want to allow. It would be interesting to get feedback from the community about what dangerous/confusing code they would want to be warned about. -- Sent from: http://forum.openscad.org/
A
adrianv
Fri, Nov 20, 2020 11:28 PM

julianstirling wrote

Yeah exactly what rules we put in are an interesting question and there
will
always be differences of opinion, and the best way to deal with this is to
make them customisable.

For context of the microscope we are looking to move the microscope design
towards something that could be medically certified. For this we need a
lot
of confidence that every piece of code behaves as expected.

Overwriting a variable from a lower scope can cause a piece of code to
change behaviour unexpectedly or to confuse someone on which variable is
being used.

I haven't tried the analyzer, but I think that in a case like this:

function myfunc(parm1, parm2) =
let(
parm2 = is_undef(parm2) ? parm1 : parm2,
....
)

it is more clear to define parm2 in the lower scope as I do above than it
would be to do something like

function myfunction(parm1, parm2_temp)
let(
parm2 = is_undef(parm2_temp) ? parm1: parm2_temp,
....
)

It is then safer to pass in arguments than overwrite a variable.

Technically speaking it's impossible to overwrite a "variable" in OpenSCAD.
You can only define new ones.

--
Sent from: http://forum.openscad.org/

julianstirling wrote > Yeah exactly what rules we put in are an interesting question and there > will > always be differences of opinion, and the best way to deal with this is to > make them customisable. > > > For context of the microscope we are looking to move the microscope design > towards something that could be medically certified. For this we need a > lot > of confidence that every piece of code behaves as expected. > > Overwriting a variable from a lower scope can cause a piece of code to > change behaviour unexpectedly or to confuse someone on which variable is > being used. I haven't tried the analyzer, but I think that in a case like this: function myfunc(parm1, parm2) = let( parm2 = is_undef(parm2) ? parm1 : parm2, .... ) it is more clear to define parm2 in the lower scope as I do above than it would be to do something like function myfunction(parm1, parm2_temp) let( parm2 = is_undef(parm2_temp) ? parm1: parm2_temp, .... ) > It is then safer to pass in arguments than overwrite a variable. Technically speaking it's impossible to overwrite a "variable" in OpenSCAD. You can only define new ones. -- Sent from: http://forum.openscad.org/
W
Whosawhatsis
Sat, Nov 21, 2020 12:14 AM

Has anyone tried OpenSCAD on any of the new Apple Silicon machines (MacBook
Air/Pro or Mac Mini with the M1 processor)?

The latest nightly doesn't appear to be compiled as Universal 2. Although
Rosetta 2 seems to be handling most things really well by all reports, I
can easily see the kind of stuff that OpenCSG is doing potentially having
bugs on the new GPUs.

I'm looking to upgrade soon, but I really need to be able to run OpenSCAD,
and its support for the new machines is currently my biggest question mark.

Has anyone tried OpenSCAD on any of the new Apple Silicon machines (MacBook Air/Pro or Mac Mini with the M1 processor)? The latest nightly doesn't appear to be compiled as Universal 2. Although Rosetta 2 seems to be handling most things really well by all reports, I can easily see the kind of stuff that OpenCSG is doing potentially having bugs on the new GPUs. I'm looking to upgrade soon, but I really need to be able to run OpenSCAD, and its support for the new machines is currently my biggest question mark.
TP
Torsten Paul
Sat, Nov 21, 2020 12:42 AM

On 21.11.20 01:14, Whosawhatsis wrote:

Has anyone tried OpenSCAD on any of the new Apple Silicon machines
(MacBook Air/Pro or Mac Mini with the M1 processor)?

Yep, that would be interesting to hear.

The latest nightly doesn't appear to be compiled as Universal 2.
Although Rosetta 2 seems to be handling most things really well
by all reports, I can easily see the kind of stuff that OpenCSG
is doing potentially having bugs on the new GPUs.

I don't know if it will be possible to do anytime soon. Right
now it's not clear how to support MacOS if more of the services
currently free for open source projects are closing down and/or
are limiting availability.

ciao,
Torsten.

On 21.11.20 01:14, Whosawhatsis wrote: > Has anyone tried OpenSCAD on any of the new Apple Silicon machines > (MacBook Air/Pro or Mac Mini with the M1 processor)? Yep, that would be interesting to hear. > The latest nightly doesn't appear to be compiled as Universal 2. > Although Rosetta 2 seems to be handling most things really well > by all reports, I can easily see the kind of stuff that OpenCSG > is doing potentially having bugs on the new GPUs. I don't know if it will be possible to do anytime soon. Right now it's not clear how to support MacOS if more of the services currently free for open source projects are closing down and/or are limiting availability. ciao, Torsten.
DM
Doug Moen
Sat, Nov 21, 2020 1:14 AM

Looks like Github Actions has a MacOS 11 build environment.
https://github.com/actions/virtual-environments/issues/1814
It is free for public repositories.

On Fri, Nov 20, 2020, at 7:42 PM, Torsten Paul wrote:

On 21.11.20 01:14, Whosawhatsis wrote:

Has anyone tried OpenSCAD on any of the new Apple Silicon machines
(MacBook Air/Pro or Mac Mini with the M1 processor)?

Yep, that would be interesting to hear.

The latest nightly doesn't appear to be compiled as Universal 2.
Although Rosetta 2 seems to be handling most things really well
by all reports, I can easily see the kind of stuff that OpenCSG
is doing potentially having bugs on the new GPUs.

I don't know if it will be possible to do anytime soon. Right
now it's not clear how to support MacOS if more of the services
currently free for open source projects are closing down and/or
are limiting availability.

ciao,
Torsten.


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

Looks like Github Actions has a MacOS 11 build environment. https://github.com/actions/virtual-environments/issues/1814 It is free for public repositories. On Fri, Nov 20, 2020, at 7:42 PM, Torsten Paul wrote: > On 21.11.20 01:14, Whosawhatsis wrote: > > Has anyone tried OpenSCAD on any of the new Apple Silicon machines > > (MacBook Air/Pro or Mac Mini with the M1 processor)? > > Yep, that would be interesting to hear. > > > The latest nightly doesn't appear to be compiled as Universal 2. > > Although Rosetta 2 seems to be handling most things really well > > by all reports, I can easily see the kind of stuff that OpenCSG > > is doing potentially having bugs on the new GPUs. > > I don't know if it will be possible to do anytime soon. Right > now it's not clear how to support MacOS if more of the services > currently free for open source projects are closing down and/or > are limiting availability. > > ciao, > Torsten. > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
L
lar3ry
Sat, Nov 21, 2020 4:06 AM

julianstirling wrote

Yeah exactly what rules we put in are an interesting question and there
will
always be differences of opinion, and the best way to deal with this is to
make them customisable.

Agreed.

Overwriting a variable from a lower scope can cause a piece of code to
change behaviour unexpectedly or to confuse someone on which variable is
being used. It is then safer to pass in arguments than overwrite a
variable.
We are also likely to warn that include in itself is dangerous. So in the
example of Test.scad if you remove line 1 then it doesn't warn. So it is
fine to override the the default input, but it warns if a variable in that
scope has the same name as one defined in the lower scope. These warnings
are annoying to a lot of people. So we may perhaps turn them off by
default
and have a mode that is more like
sca2d --strict file.scad

Sounds good. I see a LOT of people using defaults for variables, and using
the same names. I can understand the reasoning on both sides. Some want to
name it the same as the external one so it is clear what its purpose is, and
to supply a default value. Others (possibly those that see variables in
openSCAD as being actual variables), as being redefined. Both sides might
see the opposite as confusing.

You did not mention it, but what about the "variable used but never
defined"?

publicDomainGearV1.1.scad:74:47: W2008: Variable pi used but never
defined.
publicDomainGearV1.1.scad:75:14: W2008: Variable p used but never defined.

I see that when I remove the assign() (which is deprecated), it no longer
gets flagged, so that may be the reason for it.

The same logic goes for overly complicated argument. It is again for
readability and understandability of out code. The idea is to try get
someone to change:

 cube([17*2+0.1*25.4*2+35, 17*2+0.1*25.4*2+75, 17*2+0.1*25.4*2+45]);

To:

 wall_thickness = 17;
 inch = 25.4;
 //clearance is 1/10 of an inch as recommended by the manufacturer on

p19
clearance = 0.1*inch;
inner_dimensions = [35, 75, 45];
extra_size = (wall_thickness+clearance)2[1,1,1];
cube(inner_dimensions + extra_size);

Fair enough, but there are things that simply can't be reduced, so where
would you set the limit?
In the file I referenced, line 123:7 is a good case in point. All those
variables are used in the module.

Both should be identical. But one is more understandable. Of course, the
analyser can only go so far. There are always ways just define a pointless
badly named variable just to reduce the number of tokens. But the analyser
is to help you identify confusing code. Most statements the analyser picks
up will be valid code, they just are things that may confuse someone else
reading it.

The key to this has to be configurability so a project can decide what the
want to allow. It would be interesting to get feedback from the community
about what dangerous/confusing code they would want to be warned about.

Well, this has been feedback for you, and I am happy that you see the
desirability of allowing preferences to be set.

I do like the "Function defined but never used" and the "Semicolon not
required" reporting.

Again, nice work.

--
Sent from: http://forum.openscad.org/

julianstirling wrote > Yeah exactly what rules we put in are an interesting question and there > will > always be differences of opinion, and the best way to deal with this is to > make them customisable. Agreed. > Overwriting a variable from a lower scope can cause a piece of code to > change behaviour unexpectedly or to confuse someone on which variable is > being used. It is then safer to pass in arguments than overwrite a > variable. > We are also likely to warn that include in itself is dangerous. So in the > example of `Test.scad` if you remove line 1 then it doesn't warn. So it is > fine to override the the default input, but it warns if a variable in that > scope has the same name as one defined in the lower scope. These warnings > are annoying to a lot of people. So we may perhaps turn them off by > default > and have a mode that is more like > sca2d --strict file.scad Sounds good. I see a LOT of people using defaults for variables, and using the same names. I can understand the reasoning on both sides. Some want to name it the same as the external one so it is clear what its purpose is, and to supply a default value. Others (possibly those that see variables in openSCAD as being actual variables), as being redefined. Both sides might see the opposite as confusing. You did not mention it, but what about the "variable used but never defined"? publicDomainGearV1.1.scad:74:47: W2008: Variable `pi` used but never defined. publicDomainGearV1.1.scad:75:14: W2008: Variable `p` used but never defined. I see that when I remove the assign() (which is deprecated), it no longer gets flagged, so that may be the reason for it. > The same logic goes for overly complicated argument. It is again for > readability and understandability of out code. The idea is to try get > someone to change: > > cube([17*2+0.1*25.4*2+35, 17*2+0.1*25.4*2+75, 17*2+0.1*25.4*2+45]); > > To: > > wall_thickness = 17; > inch = 25.4; > //clearance is 1/10 of an inch as recommended by the manufacturer on > p19 > clearance = 0.1*inch; > inner_dimensions = [35, 75, 45]; > extra_size = (wall_thickness+clearance)*2*[1,1,1]; > cube(inner_dimensions + extra_size); Fair enough, but there are things that simply can't be reduced, so where would you set the limit? In the file I referenced, line 123:7 is a good case in point. All those variables are used in the module. > Both should be identical. But one is more understandable. Of course, the > analyser can only go so far. There are always ways just define a pointless > badly named variable just to reduce the number of tokens. But the analyser > is to help you identify confusing code. Most statements the analyser picks > up will be valid code, they just are things that may confuse someone else > reading it. > > The key to this has to be configurability so a project can decide what the > want to allow. It would be interesting to get feedback from the community > about what dangerous/confusing code they would want to be warned about. Well, this has been feedback for you, and I am happy that you see the desirability of allowing preferences to be set. I do like the "Function defined but never used" and the "Semicolon not required" reporting. Again, nice work. -- Sent from: http://forum.openscad.org/
J
julianstirling
Sat, Nov 21, 2020 12:37 PM

@lar3ry
"You did not mention it, but what about the "variable used but never
defined"? "

So used but never defined, should catch an error, that will happen in some
paths of the code. I can well believe there is a bug in how I count it at
the moment. The program is less than a week old :)

The "X defined but never used" warnings need a bit of nuance. A library of
modules/functions that are for others to "use", or a library of variables
for others to "include". They are defined but not used for a very good
reason! At the moment SCA2D just shouts about all of them. I think that
defining something in a module/control scope and never using should generate
a warning. In the outer-scope, it probably should not for libraries.

I say "it should not for libraries" but obviously any file can be used as a
library. I think this is where again we may for our specific purposes have a
strict mode where we somehow divide files into libraries that define modules
and functions but don't use them. And geometry files that use everything
they declare. This is a useful separation for our purposes but not a sane
default I would want to "impose" on others.

"Fair enough, but there are things that simply can't be reduced, so where
would you set the limit?" This I think is the key question. One thing I am
starting to do now is recategorise the warnings more sensibly. Using
something before it is defined is an Error and should have an E code, not
using something within a module scope is a Warning and should have a W code.
Complexity should be listed under "consider refactoring" with an R code.

I think the important thing about code analysis is that there is always the
option to ignore the message. So when I program PyLint tells me off when a
class has too many attributes, or when a method is too complex. Sometime I
will look at the Class/Method and go "Eh, you know, it is fine as it is.".
Other times I will look at it and go "Wow that is getting out of hand, I
should tidy it up.". The code analysis is a great way to locate potentially
confusing things and then deciding if you want to fix them. However, if you
think it is fine, then the right thing to do is ignore the analysis. In
PyLint I used to put in little codes to disable a specific warning in a
specific place. I have stopped doing this now because as the code mature
these things grow until I really should look at them again.

Looking now at your specific example it is a long array... And a very clear
long array. I think I do really need a better way to calculate the
complexity of arrays because clearly the expression you flagged is a very
very clearly laid out expression. I have made a note of this and will fix
it. It won't be a quick fix because my complexity calculation is very overly
simplistic right now. Thanks for flagging this!

@adrianv

That example with the "let" is very interesting. I had not appreciated that
let could be used in that way. In fact, none of our code uses let in any way
so I just bashed it into the lexer/parser without much further thought.
Reading in more detail I do actually need to give it significantly more
thought as it is a very powerful new feature. Thanks for bringing my
attention to this :)

--
Sent from: http://forum.openscad.org/

@lar3ry "You did not mention it, but what about the "variable used but never defined"? " So used but never defined, should catch an error, that will happen in some paths of the code. I can well believe there is a bug in how I count it at the moment. The program is less than a week old :) The "X defined but never used" warnings need a bit of nuance. A library of modules/functions that are for others to "use", or a library of variables for others to "include". They are defined but not used for a very good reason! At the moment SCA2D just shouts about all of them. I think that defining something in a module/control scope and never using should generate a warning. In the outer-scope, it probably should not for libraries. I say "it should not for libraries" but obviously any file can be used as a library. I think this is where again we may for our specific purposes have a strict mode where we somehow divide files into libraries that define modules and functions but don't use them. And geometry files that use everything they declare. This is a useful separation for our purposes but not a sane default I would want to "impose" on others. "Fair enough, but there are things that simply can't be reduced, so where would you set the limit?" This I think is the key question. One thing I am starting to do now is recategorise the warnings more sensibly. Using something before it is defined is an Error and should have an E code, not using something within a module scope is a Warning and should have a W code. Complexity should be listed under "consider refactoring" with an R code. I think the important thing about code analysis is that there is always the option to ignore the message. So when I program PyLint tells me off when a class has too many attributes, or when a method is too complex. Sometime I will look at the Class/Method and go "Eh, you know, it is fine as it is.". Other times I will look at it and go "Wow that is getting out of hand, I should tidy it up.". The code analysis is a great way to locate potentially confusing things and then deciding if you want to fix them. However, if you think it is fine, then the right thing to do is ignore the analysis. In PyLint I used to put in little codes to disable a specific warning in a specific place. I have stopped doing this now because as the code mature these things grow until I really should look at them again. Looking now at your specific example it is a long array... And a very clear long array. I think I do really need a better way to calculate the complexity of arrays because clearly the expression you flagged is a very very clearly laid out expression. I have made a note of this and will fix it. It won't be a quick fix because my complexity calculation is very overly simplistic right now. Thanks for flagging this! @adrianv That example with the "let" is very interesting. I had not appreciated that let could be used in that way. In fact, none of our code uses let in any way so I just bashed it into the lexer/parser without much further thought. Reading in more detail I do actually need to give it significantly more thought as it is a very powerful new feature. Thanks for bringing my attention to this :) -- Sent from: http://forum.openscad.org/
AC
A. Craig West
Sat, Nov 21, 2020 12:43 PM

I'm not sure how useful complexity warnings are in OpenScad. The nature of
the language requires some very complex syntax to accomplish almost any
non-trivial task...

On Sat, 21 Nov 2020, 07:37 julianstirling, julian@julianstirling.co.uk
wrote:

@lar3ry
"You did not mention it, but what about the "variable used but never
defined"? "

So used but never defined, should catch an error, that will happen in some
paths of the code. I can well believe there is a bug in how I count it at
the moment. The program is less than a week old :)

The "X defined but never used" warnings need a bit of nuance. A library of
modules/functions that are for others to "use", or a library of variables
for others to "include". They are defined but not used for a very good
reason! At the moment SCA2D just shouts about all of them. I think that
defining something in a module/control scope and never using should
generate
a warning. In the outer-scope, it probably should not for libraries.

I say "it should not for libraries" but obviously any file can be used as a
library. I think this is where again we may for our specific purposes have
a
strict mode where we somehow divide files into libraries that define
modules
and functions but don't use them. And geometry files that use everything
they declare. This is a useful separation for our purposes but not a sane
default I would want to "impose" on others.

"Fair enough, but there are things that simply can't be reduced, so where
would you set the limit?" This I think is the key question. One thing I am
starting to do now is recategorise the warnings more sensibly. Using
something before it is defined is an Error and should have an E code, not
using something within a module scope is a Warning and should have a W
code.
Complexity should be listed under "consider refactoring" with an R code.

I think the important thing about code analysis is that there is always the
option to ignore the message. So when I program PyLint tells me off when a
class has too many attributes, or when a method is too complex. Sometime I
will look at the Class/Method and go "Eh, you know, it is fine as it is.".
Other times I will look at it and go "Wow that is getting out of hand, I
should tidy it up.". The code analysis is a great way to locate potentially
confusing things and then deciding if you want to fix them. However, if you
think it is fine, then the right thing to do is ignore the analysis. In
PyLint I used to put in little codes to disable a specific warning in a
specific place. I have stopped doing this now because as the code mature
these things grow until I really should look at them again.

Looking now at your specific example it is a long array... And a very clear
long array. I think I do really need a better way to calculate the
complexity of arrays because clearly the expression you flagged is a very
very clearly laid out expression. I have made a note of this and will fix
it. It won't be a quick fix because my complexity calculation is very
overly
simplistic right now. Thanks for flagging this!

@adrianv

That example with the "let" is very interesting. I had not appreciated that
let could be used in that way. In fact, none of our code uses let in any
way
so I just bashed it into the lexer/parser without much further thought.
Reading in more detail I do actually need to give it significantly more
thought as it is a very powerful new feature. Thanks for bringing my
attention to this :)

--
Sent from: http://forum.openscad.org/


OpenSCAD mailing list
Discuss@lists.openscad.org
http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org

I'm not sure how useful complexity warnings are in OpenScad. The nature of the language requires some very complex syntax to accomplish almost any non-trivial task... On Sat, 21 Nov 2020, 07:37 julianstirling, <julian@julianstirling.co.uk> wrote: > @lar3ry > "You did not mention it, but what about the "variable used but never > defined"? " > > So used but never defined, should catch an error, that will happen in some > paths of the code. I can well believe there is a bug in how I count it at > the moment. The program is less than a week old :) > > The "X defined but never used" warnings need a bit of nuance. A library of > modules/functions that are for others to "use", or a library of variables > for others to "include". They are defined but not used for a very good > reason! At the moment SCA2D just shouts about all of them. I think that > defining something in a module/control scope and never using should > generate > a warning. In the outer-scope, it probably should not for libraries. > > I say "it should not for libraries" but obviously any file can be used as a > library. I think this is where again we may for our specific purposes have > a > strict mode where we somehow divide files into libraries that define > modules > and functions but don't use them. And geometry files that use everything > they declare. This is a useful separation for our purposes but not a sane > default I would want to "impose" on others. > > "Fair enough, but there are things that simply can't be reduced, so where > would you set the limit?" This I think is the key question. One thing I am > starting to do now is recategorise the warnings more sensibly. Using > something before it is defined is an Error and should have an E code, not > using something within a module scope is a Warning and should have a W > code. > Complexity should be listed under "consider refactoring" with an R code. > > I think the important thing about code analysis is that there is always the > option to ignore the message. So when I program PyLint tells me off when a > class has too many attributes, or when a method is too complex. Sometime I > will look at the Class/Method and go "Eh, you know, it is fine as it is.". > Other times I will look at it and go "Wow that is getting out of hand, I > should tidy it up.". The code analysis is a great way to locate potentially > confusing things and then deciding if you want to fix them. However, if you > think it is fine, then the right thing to do is ignore the analysis. In > PyLint I used to put in little codes to disable a specific warning in a > specific place. I have stopped doing this now because as the code mature > these things grow until I really should look at them again. > > Looking now at your specific example it is a long array... And a very clear > long array. I think I do really need a better way to calculate the > complexity of arrays because clearly the expression you flagged is a very > very clearly laid out expression. I have made a note of this and will fix > it. It won't be a quick fix because my complexity calculation is very > overly > simplistic right now. Thanks for flagging this! > > > @adrianv > > That example with the "let" is very interesting. I had not appreciated that > let could be used in that way. In fact, none of our code uses let in any > way > so I just bashed it into the lexer/parser without much further thought. > Reading in more detail I do actually need to give it significantly more > thought as it is a very powerful new feature. Thanks for bringing my > attention to this :) > > > > > > -- > Sent from: http://forum.openscad.org/ > > _______________________________________________ > OpenSCAD mailing list > Discuss@lists.openscad.org > http://lists.openscad.org/mailman/listinfo/discuss_lists.openscad.org >
J
julianstirling
Sat, Nov 21, 2020 6:34 PM

I have pushed out v0.0.4. You can get the newest version by running:
pip install sca2d --upgrade

Thanks to the the helpful feedback of @lar3ry I have realised I was handling
assign statements incorrectly. This is fixed so they throw a sensible
depreciation message not a variable used before definition error.

Also thanks to @adrianv, I have now implemented let expressions in the form
he mentioned. It does still throw the variable overwritten from lower scope
warning. I need to think about this some more.

I have also recategorised the warnings into Errors, Warnings, Depreciation
warnings, and Information. These have E, W, D and I codes. If you run:
sca2 --colour file.scad
it will colourise the errors (not checked this on Windows!). The Fatal
warnings when files cannot be read still sit outside my normal messaging
system so they are still just standard in colour.

I still haven't managed to get to some of the other errors that @nophead
found. But I have added the problems to the README.

Finally to @acwest. I think that the nature of OpenSCAD is that it is a
low-level language. While you need to do quite a number of commands to
accomplish tasks, there is nothing stopping you breaking these up into
variable, smaller functions and modules. The concepts of cognitive
complexity and cyclotomic complexity have been for programming date back to
the 1980s or before, back when almost all languages were low level and
required a large number of commands to perform a simple task. The idea is to
break things down into managable chunks that can be digested.

--
Sent from: http://forum.openscad.org/

I have pushed out v0.0.4. You can get the newest version by running: pip install sca2d --upgrade Thanks to the the helpful feedback of @lar3ry I have realised I was handling assign statements incorrectly. This is fixed so they throw a sensible depreciation message not a variable used before definition error. Also thanks to @adrianv, I have now implemented let expressions in the form he mentioned. It does still throw the variable overwritten from lower scope warning. I need to think about this some more. I have also recategorised the warnings into Errors, Warnings, Depreciation warnings, and Information. These have E, W, D and I codes. If you run: sca2 --colour file.scad it will colourise the errors (not checked this on Windows!). The Fatal warnings when files cannot be read still sit outside my normal messaging system so they are still just standard in colour. I still haven't managed to get to some of the other errors that @nophead found. But I have added the problems to the README. Finally to @acwest. I think that the nature of OpenSCAD is that it is a low-level language. While you need to do quite a number of commands to accomplish tasks, there is nothing stopping you breaking these up into variable, smaller functions and modules. The concepts of cognitive complexity and cyclotomic complexity have been for programming date back to the 1980s or before, back when almost all languages were low level and required a large number of commands to perform a simple task. The idea is to break things down into managable chunks that can be digested. -- Sent from: http://forum.openscad.org/