-
-
Notifications
You must be signed in to change notification settings - Fork 10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Format implementation assignments, ifs #41
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi,
Sorry for the late reply, I was quite busy lately. Thanks for the first draft!
Some comments/ideas per file.
IfBlockStart
In IfBlockStart
it would be good to have a Tokenize
method to clean up the Format
method a bit. Now there is a lot going on in the format method, where it does both tokenizing and formatting. Maybe use a regex to put each statement as a separate item in a list? When you do this also clean them of all spaces. You could for example put them in a new struct Statement
which has three members leftOperand
, operand
and rightOperand
?
Currently you only check if the unformatted code + the indentation is longer than 88, but it can happen that the unformatted code contains double spaces or no spaces. I think it should be a two step process. For example you make a method FormatInSingleLine
which formats the if statement as a single line. Then it checks the length of that. if it is longer than 88, it will call FomatOverMultipleLines
.
Finally, this
IF len(str) > 0
AND len(str) > 0
AND len(str) > 0
AND len(str) > 0
AND len(str) > 0
AND len(str) > 0
THEN
should be
IF
len(str) > 0
AND len(str) > 0
AND len(str) > 0
AND len(str) > 0
AND len(str) > 0
AND len(str) > 0
THEN
ImplementationCode
I think it is a good idea to make a separate class as you did with ImplementationCode
. Then it would be a good idea to also make a DeclarationCode
class and move all declaration specific code to there from CompositeCode
. All the general code will remain in CompositeCode
class.
There is a lot of white space fixing in here. I think this isn't be necessary with my suggestions for IfBlockStart
.
.Tokenize() | ||
.Format(ref indents); | ||
string firstLine; | ||
if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this if statement here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is something I've started with my own projects. The first line of the implementation is always a comment //
or empty. This is because when doing git diffs on the xml it's easier to read if the first code line is not attached to the <![CDATA[
. This is separating the TwinCAT markup vs the actual user code.
For example
<Implementation>
<ST><![CDATA[
F_CreateHashTableHnd(ADR(table), SIZEOF(table), hTable);
]]></ST>
</Implementation>
vs
<Implementation>
<ST><![CDATA[F_CreateHashTableHnd(ADR(table), SIZEOF(table), hTable);
]]></ST>
</Implementation>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it even better that it always is an empty line? When putting a comment there you have the same issue as with code right?
I prefer either one of the following options:
- Always insert an empty line, but not an (empty) comment
- Remove all empty lines at the start.
If you choose option 1, then I guess it is also needed for the declaration part.
Finally I prefer if you just add an EmptyLine
class at the start when you loop over the lines in the Tokenize method.
src/TcBlack/VariableAssignment.cs
Outdated
public override string Format(ref uint indents) | ||
{ | ||
TcAssignment assign = Tokenize(); | ||
return _singleIndent.Repeat(indents) + assign.LeftOperand + " := " + assign.RightOperand; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use string interpolation for this https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/tokens/interpolated. Also at the other places.
So this becomes $"{_singleIndent.Repeat(indents)}{assign.LeftOperand} := {assign.RightOperand};"$
.
I've made the line ending and indentation into global variables (#42). This shortens the initialization of the different code types a lot. You can also add the line length as a global variable. |
All sounds good to me, I'll make the changes. One thing I'm unsure about is what to do with multi assignments.
Are these allowed? Or shall they be broken up into single lines? |
…Black into implementation-format
Multi line function calls inside an if don't work
Ok, now supports fixing multiline function calls (not inside an if though). Also fixed a bunch of other parsing issues. One major item that needs to be addressed is recursively setting types. This is why function calls inside an IF ... THEN don't work as it treats as plain text currently.
Becomes
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing I'm unsure about is what to do with multi assignments.
Personally I'm not a fan and would break them up, but Black for Python allows it so TcBlack will also allow it.
.Tokenize() | ||
.Format(ref indents); | ||
string firstLine; | ||
if ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it even better that it always is an empty line? When putting a comment there you have the same issue as with code right?
I prefer either one of the following options:
- Always insert an empty line, but not an (empty) comment
- Remove all empty lines at the start.
If you choose option 1, then I guess it is also needed for the declaration part.
Finally I prefer if you just add an EmptyLine
class at the start when you loop over the lines in the Tokenize method.
src/TcBlack/UnknownCodeType.cs
Outdated
@@ -12,7 +12,7 @@ string lineEnding | |||
|
|||
public override string Format(ref uint indents) | |||
{ | |||
return _unformattedCode; | |||
return _singleIndent.Repeat(indents) + _unformattedCode; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't this add extra spaces if the original code already has the correct spacing? Since there is no trim method used when the code is added to the CompositeCode.codeLines
list.
); | ||
} | ||
|
||
protected string FormatSingle(ref uint indents, TcVariablePassing func, bool multi) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you break this up into FormatIntoSingleLine
and FormatIntoMultiLine
methods? Then you do not need bool mutli
and all the if statements in the method. Plus the name conveys better what the method does.
formated += Global.lineEnding; | ||
} | ||
foreach( | ||
string ea |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does ea
stand for? Can you use non-abbreviated variable names?
|
||
public struct IfStatement | ||
{ | ||
public IfStatement( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also use non-abbreviated variable names here?
return formattedCode; | ||
} | ||
|
||
public override string Format(ref uint indents) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you move the Format
method above FormatSingle
? Then the code gets more detailed as you read along plus it is the natural order: first you tokenize, then format, which consists of the more detailed FormatSingle
and FormatMultiple
methods.
General comment. It would be a good idea to break up this PR into multiple ones. Like one for function calls, one for if statements, etc. It is becoming quite large now and difficult to review. Also it would be good to have unit tests from the start. |
Initial go ahead with formatting of the implementation. Works with assignments and IF statements.
Format this:
Into this:
I just want to stop here with a working example and go over any major changes to implementation before continuing on this path.