Skip to content

Commit

Permalink
Merge pull request #283 from richardm90/add_lowercase_directives
Browse files Browse the repository at this point in the history
Add lowercase directives
  • Loading branch information
worksofliam authored Jan 22, 2024
2 parents 5f4eec2 + 7ed6c66 commit 40e3c89
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 20 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,4 @@ Thanks so much to everyone [who has contributed](https://github.com/codefori/vsc
- [@p-behr](https://github.com/p-behr)
- [@chrjorgensen](https://github.com/chrjorgensen)
- [@sebjulliand](https://github.com/sebjulliand)
- [@richardm90](https://github.com/richardm90)
3 changes: 2 additions & 1 deletion extension/server/src/providers/linter/documentFormatting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ export default async function documentFormattingProvider(params: DocumentFormatt
// Need to fetch the docs again incase comments were added
// as part of RequiresProcedureDescription
docs = await parser.getDocs(document.uri, document.getText(), {
ignoreCache: true
ignoreCache: true,
withIncludes: true
});

// Next up, let's fix all the other things!
Expand Down
3 changes: 2 additions & 1 deletion extension/server/src/providers/linter/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,7 @@ export function getActions(document: TextDocument, errors: IssueRange[]) {

case `SpecificCasing`:
case `IncorrectVariableCase`:
case `DirectiveCasing`:
case `UppercaseDirectives`:
if (error.newValue) {
action = CodeAction.create(`Correct casing to '${error.newValue}'`, CodeActionKind.QuickFix);
Expand Down Expand Up @@ -342,7 +343,7 @@ export function getActions(document: TextDocument, errors: IssueRange[]) {

case `RequireBlankSpecial`:
if (error.newValue) {
action = CodeAction.create(`Convert constant name to uppercase`, CodeActionKind.QuickFix);
action = CodeAction.create(`Convert empty string literal to *BLANK`, CodeActionKind.QuickFix);
action.edit = {
changes: {
[document.uri]: [
Expand Down
51 changes: 39 additions & 12 deletions language/linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ const errorText = {
'StringLiteralDupe': `Same string literal used more than once. Consider using a constant instead.`,
'RequireBlankSpecial': `\`*BLANK\` should be used over empty string literals.`,
'CopybookDirective': `Directive does not match requirement.`,
'UppercaseDirectives': `Directives must be in uppercase.`,
'DirectiveCasing': `Does not match required case.`,
'UppercaseDirectives': `Directives must be in uppercase. UppercaseDirectives option is deprecated, consider using DirectiveCasing.`,
'NoSQLJoins': `SQL joins are not allowed. Consider creating a view instead.`,
'NoGlobalsInProcedures': `Global variables should not be referenced in procedures.`,
'NoCTDATA': `\`CTDATA\` is not allowed.`,
Expand Down Expand Up @@ -203,15 +204,6 @@ export default class Linter {

case `directive`:
value = statement[0].value;
if (rules.UppercaseDirectives) {
if (value !== value.toUpperCase()) {
errors.push({
offset: { position: statement[0].range.start, end: statement[0].range.end },
type: `UppercaseDirectives`,
newValue: value.toUpperCase()
});
}
}

if (rules.CopybookDirective || rules.IncludeMustBeRelative) {
if ([`/COPY`, `/INCLUDE`].includes(value.toUpperCase())) {
Expand Down Expand Up @@ -291,8 +283,13 @@ export default class Linter {
}

if (rules.CopybookDirective) {
const correctDirective = `/${rules.CopybookDirective.toUpperCase()}`;
if (value.toUpperCase() !== correctDirective) {
let correctDirective = `/${rules.CopybookDirective.toUpperCase()}`;
let correctValue = value.toUpperCase();
if (rules.DirectiveCasing === `lower`) {
correctDirective = correctDirective.toLowerCase();
correctValue = value.toLowerCase();
}
if (correctValue !== correctDirective) {
errors.push({
offset: { position: statement[0].range.start, end: statement[0].range.end },
type: `CopybookDirective`,
Expand All @@ -302,6 +299,36 @@ export default class Linter {
}
}
}

if (rules.DirectiveCasing === `lower`) {
if (value !== value.toLowerCase()) {
errors.push({
offset: { position: statement[0].range.start, end: statement[0].range.end },
type: `DirectiveCasing`,
newValue: value.toLowerCase()
});
}
}

if (rules.DirectiveCasing === `upper`) {
if (value !== value.toUpperCase()) {
errors.push({
offset: { position: statement[0].range.start, end: statement[0].range.end },
type: `DirectiveCasing`,
newValue: value.toUpperCase()
});
}
}

if (rules.UppercaseDirectives) {
if (value !== value.toUpperCase()) {
errors.push({
offset: { position: statement[0].range.start, end: statement[0].range.end },
type: `UppercaseDirectives`,
newValue: value.toUpperCase()
});
}
}
break;

case `declare`:
Expand Down
1 change: 1 addition & 0 deletions language/parserTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export interface Rules {
literalMinimum?: number;
RequireBlankSpecial?: boolean;
CopybookDirective?: "copy"|"include";
DirectiveCasing?: "lower"|"upper";
UppercaseDirectives?: boolean;
NoSQLJoins?: boolean;
NoGlobalsInProcedures?: boolean;
Expand Down
14 changes: 12 additions & 2 deletions schemas/rpglint.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "http://json-schema.org/draft-07/schema",
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://github.com/halcyon-tech/vscode-ibmi",
"type": "object",
"description": "Available lint configuration for RPGLE",
Expand Down Expand Up @@ -85,10 +85,20 @@
],
"description": "Force which directive which must be used to include other source. (Copy or Include)"
},
"DirectiveCase": {
"$id": "#/properties/DirectiveCase",
"type": "string",
"enum": [
"lower",
"upper"
],
"description": "The expected casing of directives (lower or upper)."
},
"UppercaseDirectives": {
"$id": "#/properties/UppercaseDirectives",
"type": "boolean",
"description": "Directives must be in uppercase."
"description": "Directives must be in uppercase.",
"deprecated": true
},
"NoSQLJoins": {
"$id": "#/properties/NoSQLJoins",
Expand Down
3 changes: 3 additions & 0 deletions tests/rpgle/copy3.rpgle
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
**FREE

Dcl-S CustomerName_t varchar(40) template;
139 changes: 139 additions & 0 deletions tests/suite/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,5 +463,144 @@ module.exports = {

const someDs = cache.find(`someDs`);
assert.strictEqual(someDs.keyword[`BASED`], undefined);
},

variable_case1: async () => {
const lines = [
`**FREE`,
`Ctl-Opt DftActGrp(*No);`,
`/copy './tests/rpgle/copy3.rpgle'`,
`Dcl-S MyCustomerName1 like(customername_t);`,
`Dcl-S MyCustomerName2 like(CustomerName_t);`,
`Dcl-S MyCustomerName3 like(CUSTOMERNAME_t);`,
`Dcl-S MyCustomerName4 like(CUSTOMERNAME_T);`,
`MyCustomerName1 = 'John Smith';`,
`dsply MyCustomerName1;`,
`Return;`
].join(`\n`);

const cache = await parser.getDocs(uri, lines, {withIncludes: true, ignoreCache: true});
const { errors } = Linter.getErrors({ uri, content: lines }, {
IncorrectVariableCase: true
}, cache);

assert.strictEqual(errors.length, 3, `Expect length of 3`);

assert.deepStrictEqual(errors[0], {
offset: { position: 92, end: 106 },
type: `IncorrectVariableCase`,
newValue: `CustomerName_t`
});

assert.deepStrictEqual(errors[1], {
offset: { position: 180, end: 194 },
type: `IncorrectVariableCase`,
newValue: `CustomerName_t`
});

assert.deepStrictEqual(errors[2], {
offset: { position: 224, end: 238 },
type: `IncorrectVariableCase`,
newValue: `CustomerName_t`
});
},

uppercase1: async () => {
const lines = [
`**FREE`,
`Ctl-Opt DftActGrp(*No);`,
`/copy './tests/rpgle/copy1.rpgle'`,
`/Copy './tests/rpgle/copy2.rpgle'`,
`/COPY './tests/rpgle/copy3.rpgle'`,
`Dcl-S MyCustomerName1 like(CustomerName_t);`,
`MyCustomerName1 = 'John Smith';`,
`dsply MyCustomerName1;`,
`Return;`
].join(`\n`);

const cache = await parser.getDocs(uri, lines, {withIncludes: true, ignoreCache: true});
const { errors } = Linter.getErrors({ uri, content: lines }, {
DirectiveCasing: `upper`
}, cache);

assert.strictEqual(errors.length, 2, `Expect length of 2`);

assert.deepStrictEqual(errors[0], {
offset: { position: 31, end: 36 },
type: `DirectiveCasing`,
newValue: `/COPY`
});

assert.deepStrictEqual(errors[1], {
offset: { position: 65, end: 70 },
type: `DirectiveCasing`,
newValue: `/COPY`
});
},

uppercase2: async () => {
const lines = [
`**FREE`,
`Ctl-Opt DftActGrp(*No);`,
`/copy './tests/rpgle/copy1.rpgle'`,
`/Copy './tests/rpgle/copy2.rpgle'`,
`/COPY './tests/rpgle/copy3.rpgle'`,
`Dcl-S MyCustomerName1 like(CustomerName_t);`,
`MyCustomerName1 = 'John Smith';`,
`dsply MyCustomerName1;`,
`Return;`
].join(`\n`);

const cache = await parser.getDocs(uri, lines, {withIncludes: true, ignoreCache: true});
const { errors } = Linter.getErrors({ uri, content: lines }, {
UppercaseDirectives: true
}, cache);

assert.strictEqual(errors.length, 2, `Expect length of 2`);

assert.deepStrictEqual(errors[0], {
offset: { position: 31, end: 36 },
type: `UppercaseDirectives`,
newValue: `/COPY`
});

assert.deepStrictEqual(errors[1], {
offset: { position: 65, end: 70 },
type: `UppercaseDirectives`,
newValue: `/COPY`
});
},

lowercase1: async () => {
const lines = [
`**FREE`,
`Ctl-Opt DftActGrp(*No);`,
`/copy './tests/rpgle/copy1.rpgle'`,
`/Copy './tests/rpgle/copy2.rpgle'`,
`/COPY './tests/rpgle/copy3.rpgle'`,
`Dcl-S MyCustomerName1 like(CustomerName_t);`,
`MyCustomerName1 = 'John Smith';`,
`dsply MyCustomerName1;`,
`Return;`
].join(`\n`);

const cache = await parser.getDocs(uri, lines, {withIncludes: true, ignoreCache: true});
const { errors } = Linter.getErrors({ uri, content: lines }, {
DirectiveCasing: `lower`
}, cache);

assert.strictEqual(errors.length, 2, `Expect length of 2`);

assert.deepStrictEqual(errors[0], {
offset: { position: 65, end: 70 },
type: `DirectiveCasing`,
newValue: `/copy`
});

assert.deepStrictEqual(errors[1], {
offset: { position: 99, end: 104 },
type: `DirectiveCasing`,
newValue: `/copy`
});
}
}
8 changes: 4 additions & 4 deletions tests/suite/linter.js
Original file line number Diff line number Diff line change
Expand Up @@ -1269,14 +1269,14 @@ exports.linter15 = async () => {

assert.deepStrictEqual(errors[0], {
offset: { position: 36, end: 38 },
type: 'PrettyComments',
newValue: '// '
type: `PrettyComments`,
newValue: `// `
});

assert.deepStrictEqual(errors[1], {
offset: { position: 207, end: 209 },
type: 'PrettyComments',
newValue: '// '
type: `PrettyComments`,
newValue: `// `
});
};

Expand Down

0 comments on commit 40e3c89

Please sign in to comment.