Skip to content

Enhanced blocks logic#491

Open
buzzia2001 wants to merge 8 commits intocodefori:mainfrom
buzzia2001:main
Open

Enhanced blocks logic#491
buzzia2001 wants to merge 8 commits intocodefori:mainfrom
buzzia2001:main

Conversation

@buzzia2001
Copy link
Copy Markdown

@buzzia2001 buzzia2001 commented Mar 25, 2026

Changes

This release improves block logic. Specifically, support has been added for highlighting different functional blocks, including the start and end of each block. Support has also been added for folding blocks and for displaying information within the navigation bar.

image image image image

The support works for:

  • { open: ['if', 'ifeq', 'ifne', 'ifgt', 'iflt', 'ifge', 'ifle'], close: ['endif'], middle: ['else', 'elseif'] }
  • { open: ['dow', 'doweq', 'downe', 'dowgt', 'dowlt', 'dowge', 'dowle'], close: ['enddo'] }
  • { open: ['dou', 'doueq', 'doune', 'dougt', 'doult', 'douge', 'doule'], close: ['enddo'] }
  • { open: ['do'], close: ['enddo'] }
  • { open: ['for', 'for-each'], close: ['endfor'] }
  • { open: ['select'], close: ['endsl'], middle: ['when', 'wheneq', 'whenne', 'whengt', 'whenlt', 'whenge', 'whenle', 'when-is', 'when-in', 'other'] }
  • { open: ['monitor'], close: ['endmon'], middle: ['on-error', 'on-excp'] }
  • { open: ['dcl-proc'], close: ['end-proc'] }
  • { open: ['dcl-ds'], close: ['end-ds'] }
  • { open: ['dcl-pr'], close: ['end-pr'] }
  • { open: ['dcl-pi'], close: ['end-pi'] }
  • { open: ['dcl-enum'], close: ['end-enum'] }
  • { open: ['begsr'], close: ['endsr'] }
  • { open: ['casxx', 'caseq', 'casne', 'casgt', 'caslt', 'casge', 'casle'], close: ['endcs'] }

Checklist

  • have tested my change
  • Remove any/all console.logs I added
  • have added myself to the contributors' list in the README
  • for feature PRs: PR only includes one feature enhancement.

closes #486

@bobcozzi
Copy link
Copy Markdown
Contributor

bobcozzi commented Apr 7, 2026

You have for listed as supported, can you confirm if this includes support for the for-each opcode as well?

@buzzia2001
Copy link
Copy Markdown
Author

You have for listed as supported, can you confirm if this includes support for the for-each opcode as well?

Hi @bobcozzi,
supported keywords are the following:

  • { open: ['if', 'ifeq', 'ifne', 'ifgt', 'iflt', 'ifge', 'ifle'], close: ['endif'], middle: ['else', 'elseif'] }
  • { open: ['dow', 'doweq', 'downe', 'dowgt', 'dowlt', 'dowge', 'dowle'], close: ['enddo'] }
  • { open: ['dou', 'doueq', 'doune', 'dougt', 'doult', 'douge', 'doule'], close: ['enddo'] }
  • { open: ['do'], close: ['enddo'] }
  • { open: ['for', 'for-each'], close: ['endfor'] }
  • { open: ['select'], close: ['endsl'], middle: ['when', 'wheneq', 'whenne', 'whengt', 'whenlt', 'whenge', 'whenle', 'when-is', 'when-in', 'other'] }
  • { open: ['monitor'], close: ['endmon'], middle: ['on-error', 'on-excp'] }
  • { open: ['dcl-proc'], close: ['end-proc'] }
  • { open: ['dcl-ds'], close: ['end-ds'] }
  • { open: ['dcl-pr'], close: ['end-pr'] }
  • { open: ['dcl-pi'], close: ['end-pi'] }
  • { open: ['dcl-enum'], close: ['end-enum'] }
  • { open: ['begsr'], close: ['endsr'] }
  • { open: ['casxx', 'caseq', 'casne', 'casgt', 'caslt', 'casge', 'casle'], close: ['endcs'] }

Let me know if I missed anything.
Thank you

@bobcozzi
Copy link
Copy Markdown
Contributor

bobcozzi commented Apr 8, 2026

Thank you! I see that now.

Are you supporting fixed-format as well? I am asking because this line:
{ open: ['if', 'ifeq', 'ifne', 'ifgt', 'iflt', 'ifge', 'ifle'], close: ['endif'] },

contains fixed-format opcode. Thus replicating the open:['if']... on a new line--wondering if that plays nice with the other entires.

Also, have you considered seeing if you can support RPG IV Conditional Compiler Directive?
/IF
/ELSEIF
/ELSE
/ENDIF

https://www.ibm.com/docs/en/i/7.4.0?topic=statements-conditional-directives-within-free-form-statement

@buzzia2001
Copy link
Copy Markdown
Author

buzzia2001 commented Apr 8, 2026

Thank you! I see that now.

Are you supporting fixed-format as well? I am asking because this line: { open: ['if', 'ifeq', 'ifne', 'ifgt', 'iflt', 'ifge', 'ifle'], close: ['endif'] },

contains fixed-format opcode. Thus replicating the open:['if']... on a new line--wondering if that plays nice with the other entires.

Also, have you considered seeing if you can support RPG IV Conditional Compiler Directive? /IF /ELSEIF /ELSE /ENDIF

https://www.ibm.com/docs/en/i/7.4.0?topic=statements-conditional-directives-within-free-form-statement

Hi @bobcozzi
My idea is to cover FIXED and FREE rpg without differences.

I didn't unserstand what you mean with "Thus replicating the open:['if']... on a new line--wondering if that plays nice with the other entires."

For /IF and so on, I see that highlighting and foldinf is already supported:
image

I'm pushing also the support for breadcrumb
image

@charles-slc
Copy link
Copy Markdown

Just poking around, so I may be way off base. But don't you need to consider end by itself as a possible closure for fixed-format CASxx, DO, DOU, DOUxx, DOW, DOWxx, FOR, IF, IFxx, or SELECT group

@bobcozzi
Copy link
Copy Markdown
Contributor

Just poking around, so I may be way off base. But don't you need to consider end by itself as a possible closure for fixed-format CASxx, DO, DOU, DOUxx, DOW, DOWxx, FOR, IF, IFxx, or SELECT group

I suppose if Developers still have that old System/38 RPG III "END" opcode, then yes, it should potentially be there. If there's still using it, I see no reason to put any extra effort into supporting it, however.

@charles-slc
Copy link
Copy Markdown

I suppose if Developers still have that old System/38 RPG III "END" opcode, then yes, it should potentially be there. If there's still using it, I see no reason to put any extra effort into supporting it, however.

I'd agree it's not worth a lot of extra effort. I was pointing it out incase it was simply a matter of having close: ['endif', 'end']

I still run into it once and a while. Some may have originated in RPG III, but just as likely to have come from a (lazy?) RPG IV developer. It is valid fixed format, may consider how not supporting it would break the new functionality.

@buzzia2001
Copy link
Copy Markdown
Author

I suppose if Developers still have that old System/38 RPG III "END" opcode, then yes, it should potentially be there. If there's still using it, I see no reason to put any extra effort into supporting it, however.

I'd agree it's not worth a lot of extra effort. I was pointing it out incase it was simply a matter of having close: ['endif', 'end']

I still run into it once and a while. Some may have originated in RPG III, but just as likely to have come from a (lazy?) RPG IV developer. It is valid fixed format, may consider how not supporting it would break the new functionality.

@bobcozzi @charles-slc

Help me understand this—I’ll admit I’m by no means an expert on fixed-length RPGs…
Does END let me close all those blocks mentioned above? If so, I can try adding it to see if the algorithm I used for nesting calculations needs to be modified or if it’s already fine as is, but I don’t expect any major issues.
Let me know

@charles-slc
Copy link
Copy Markdown

@bobcozzi @charles-slc

Help me understand this—I’ll admit I’m by no means an expert on fixed-length RPGs… Does END let me close all those blocks mentioned above? If so, I can try adding it to see if the algorithm I used for nesting calculations needs to be modified or if it’s already fine as is, but I don’t expect any major issues. Let me know

Yes, https://www.ibm.com/docs/en/i/7.6.0?topic=codes-endyy-end-structured-group

image

@buzzia2001
Copy link
Copy Markdown
Author

@bobcozzi @charles-slc
Help me understand this—I’ll admit I’m by no means an expert on fixed-length RPGs… Does END let me close all those blocks mentioned above? If so, I can try adding it to see if the algorithm I used for nesting calculations needs to be modified or if it’s already fine as is, but I don’t expect any major issues. Let me know

Yes, https://www.ibm.com/docs/en/i/7.6.0?topic=codes-endyy-end-structured-group

Okay, I was immediately proven wrong... Adding “END” isn't as straightforward as I'd hoped; it's causing quite a few issues when trying to identify the block that the generic keyword belongs to. In fact, there could be several possibilities, especially when blocks are nested... I quickly tried changing the data structure for storing the block structure, but even in this case there are errors... which I hadn't noticed before, since it was unique

I'll try to look into it again in the next few days, but I can't guarantee that it will be feasible in the short term...

@bobcozzi @charles-slc I'd like to know if this issue with the generic END is a recurring problem (in which case it would be worth the effort to completely overhaul the logic) or if it's a fairly isolated case

@charles-slc
Copy link
Copy Markdown

charles-slc commented Apr 17, 2026

@bobcozzi @charles-slc I'd like to know if this issue with the generic END is a recurring problem (in which case it would be worth the effort to completely overhaul the logic) or if it's a fairly isolated case

Not sure I understand the question. Do you mean:

  1. are there any other "generic" op-codes like END.
  2. is the generic END commonly used.

For 1, I can't think of anything similar. For 2, as Bob pointed out it's a relic from RPG III. But it is still valid RPG IV. A quick search of our codebase turned up about 3% of our programs using it at least once. (high score was 193 occurrences)

@bobcozzi
Copy link
Copy Markdown
Contributor

bobcozzi commented Apr 18, 2026

The "END" opcode in fixed format:
Originated on System/38 RPG III. It was used to end the original IFxx, DO, DOWxx, DOUxx, CASxx, and SELCT/WHEN opcodes.
Originally there were no ENDIF, ENDDO, ENDCS, ENDSL opcodes.
Then IBM added them to RPG III to help with obvious things, readability and validation during compiling.

"END" was deprecated about 10 years prior to RPG IV being released. It was included in RPG IV to enable simpler CVTRPGSRC conversion; so that conversion tool could simply convert (i.e., reformat) RPGIII into RPG IV without maintaining context during conversion. It is not now, nor has it ever been advocated as a thing--kind of like using an Input field "status" indicator where if blank then set on indicator 71. Sure it is supported in the compiler, but should it be used?

So in summary, "END" is used in place of any of the following:
ENDDO
ENDIF
ENDCS
ENDSL

So when "END" is detected, it matches the most recently detected conditional statement above it.

@buzzia2001
Copy link
Copy Markdown
Author

@bobcozzi @charles-slc

ok, I think I’ve managed it—at least it worked in all the test cases I generated.
I also realized I hadn’t handled “enddo” properly, since that’s a generic keyword too.
Unfortunately, I can’t upload the VSIX here, but if you could test it by building the extension from my branch, I’d really appreciate it—that way, we’d all have peace of mind.

@charles-slc
Copy link
Copy Markdown

I'll give it a shot this week. I don't know if it helps or hurts, but note that END or ENDxx always closes the most recent block. If the xx doesn't match the start of the block it's a syntax/compile issue. Maybe this is covered in your code, I didn't look very hard at it. But the impression I got was that when you hit and endif you were looking for the that prior matching if. But for instance:

  * valid
C        dow ...
C        if ...
C        ...
C        end;
C        end;
  * not valid syntax error
C        dow ...
C        if ...
C        ...
C        end;
C        endif;

Think of it as a stack, pushing the condition op-codes (and line nbr), popping when you hit ENDxx the popped op-code needs to match the xx unless it's one that accepts just END and that's what you've just gotten.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Show block nesting" in VS Code

3 participants