Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

All notable changes to the "vscode-rpgle" extension can be found in the
[Releases](https://github.com/codefori/vscode-rpgle/releases) section of the GitHub repository.

## [Unreleased]

### Added - OPM RPG Language Support
Expand Down Expand Up @@ -55,8 +54,6 @@ All notable changes to the "vscode-rpgle" extension can be found in the
- All language server providers now use `getParser(uri)` for dynamic parser selection
- Extension now supports both ILE RPG (`.rpgle`/`.sqlrpgle`) and OPM RPG (`.rpg`/`.sqlrpg`) language variants



### Added - Previous ILE RPG Enhancements

- **Input specification (`I` spec) parsing** (fixed-format ILE RPG): the parser now recognises and processes all four I spec sub-types — `programRecord`, `programField`, `externalRecord`, and `externalField`.
Expand All @@ -72,6 +69,23 @@ All notable changes to the "vscode-rpgle" extension can be found in the
### Fixed

- **Linter diagnostics not clearing when `**FREE` is removed**: previously, if a source file was opened as `**FREE` (activating the linter) and `**FREE` was later removed or the file was re-opened without it, stale linter diagnostics persisted indefinitely. `refreshLinterDiagnostics` now explicitly sends an empty diagnostics notification when the file is not `**FREE`, clearing any previously published warnings.
- **Shift+F4 ruler incorrectly shown on legacy embedded SQL lines**: the fixed-format spec ruler is no longer painted on C spec SQL continuation lines (column 7 = `+`, e.g. `.....C+ FROM qiws.qcustcdt;`), matching the existing behaviour for directive lines (column 7 = `/`).
- **Shift+F4 ruler persists when Cmd+Shift+F4 Column Assistant opens**: the ruler is now cleared immediately when the active editor changes (e.g. focus moves to the SEU-style Column Assistant webview panel), preventing it from staying frozen over the source until the next cursor move.
- **Shift+F4 ruler overlaps Source Change Date columns**: the opaque ruler background is now capped at 80 columns wide, so it no longer paints over the Source Change Date text that IBM i source physical files carry beyond column 80.
- Fixed type inference for fixed-format D-specifications when the data type position (40) is blank
- Correctly distinguishes between "no decimals specified" and "decimals = 0"
- Applies proper RPGLE type inference rules:
- Standalone fields (S) with decimals → Packed
- Standalone fields (S) without decimals → Char
- Subfields with decimals → Zoned
- Subfields without decimals → Char
- Resolves 5 failing test cases in fixed-format parser tests
- Fixed hover tooltips not displaying for data structure subfields
- Added support for qualified data structures (accessed as `DS.FIELD`)
- Added support for unqualified data structures (accessed as standalone `FIELD`)
- Hover text now displays parent structure context: `parent.field Type QUALIFIED` or `*UNQUALIFIED` or `*UNNAMED`
- Shows description tags from external file metadata when available
- Displays reference count in hover information

### Changed

Expand Down
37 changes: 34 additions & 3 deletions extension/client/src/language/columnAssist.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

import { commands, DecorationOptions, ExtensionContext, Range, Selection, TextDocument, ThemeColor, window } from 'vscode';
import { commands, DecorationOptions, ExtensionContext, Range, Selection, TextDocument, TextEditor, ThemeColor, window } from 'vscode';
import * as Configuration from "../configuration";
import { loadBase } from '../base';

Expand All @@ -17,12 +17,23 @@ const outlineBar = window.createTextEditorDecorationType({});

let rulerEnabled = Configuration.get(Configuration.RULER_ENABLED_BY_DEFAULT) || false
let currentEditorLine = -1;
// Tracks the last RPG fixed-format editor that had the ruler painted, so it can
// be cleared when focus moves to a webview (e.g. Ctrl+Shift+F4 prompter) or to
// a non-RPG file, where onDidChangeTextEditorSelection never fires.
let lastRpgleEditor: TextEditor | undefined = undefined;

import { SpecFieldDef, SpecFieldValue, SpecRulers, specs, opmSpecs, opmSpecRulers } from '../schemas/specs';

const getAreasForLine = (line: string, index: number, languageId: string = 'rpgle') => {
if (line.length < 6) return undefined;
if (line[6] === `*` || line[6] === `/`) return undefined;
// Skip comments (*), compiler directives (/), and legacy embedded SQL continuation lines (+).
// A `+` in column 7 marks a C spec SQL continuation (e.g. `C+ FROM qiws.qcustcdt;`)
// and should never trigger the spec ruler.
if (line[6] === `*` || line[6] === `/` || line[6] === `+`) return undefined;

// Use OPM specs for .rpg files, ILE specs for .rpgle files
const specDefinitions = languageId === 'rpg' ? opmSpecs : specs;
const rulerDefinitions = languageId === 'rpg' ? opmSpecRulers : SpecRulers;

// Use OPM specs for .rpg files, ILE specs for .rpgle files
const specDefinitions = languageId === 'rpg' ? opmSpecs : specs;
Expand Down Expand Up @@ -115,6 +126,19 @@ export function registerColumnAssist(context: ExtensionContext) {
clearRulers(editor);
}
}),

// Clear the ruler when the active editor changes (e.g. focus moves to a
// webview panel such as the Ctrl+Shift+F4 Column Assistant, or to a
// different file). onDidChangeTextEditorSelection does not fire in those
// cases, so the ruler would otherwise remain painted indefinitely.
window.onDidChangeActiveTextEditor(newEditor => {
if (lastRpgleEditor && newEditor !== lastRpgleEditor) {
clearRulers(lastRpgleEditor);
}
if (newEditor && rulerEnabled) {
updateRuler(newEditor);
}
}),
)
}

Expand Down Expand Up @@ -193,7 +217,10 @@ function updateRuler(editor = window.activeTextEditor) {
before: {
contentText: positionsData.outline,
color: new ThemeColor(`editorLineNumber.foreground`),
textDecoration: `none; position: absolute; top: -1.4em; background-color: var(--vscode-editor-background); width: 100vw;`,
// width is capped at 80ch (the fixed-format source width) so the
// opaque background does not paint over the Source Change Date
// columns that IBM i source physical files carry beyond column 80.
textDecoration: `none; position: absolute; top: -1.4em; background-color: var(--vscode-editor-background); width: 80ch;`,
}
}
},
Expand All @@ -203,6 +230,7 @@ function updateRuler(editor = window.activeTextEditor) {
}

currentEditorLine = lineNumber;
lastRpgleEditor = editor;
}
}
}
Expand All @@ -218,6 +246,9 @@ function clearRulers(editor = window.activeTextEditor) {
editor.setDecorations(notCurrentArea, []);
editor.setDecorations(outlineBar, []);
}
if (editor === lastRpgleEditor) {
lastRpgleEditor = undefined;
}
}

interface FieldBox {
Expand Down