Skip to content
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

Add lowercase directives #283

Merged
merged 11 commits into from
Jan 22, 2024
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
richardm90 marked this conversation as resolved.
Show resolved Hide resolved
});

// 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 `LowercaseDirectives`:
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
40 changes: 29 additions & 11 deletions language/linter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ 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.`,
'LowercaseDirectives': `Directives must be in lowercase.`,
'UppercaseDirectives': `Directives must be in uppercase.`,
'NoSQLJoins': `SQL joins are not allowed. Consider creating a view instead.`,
'NoGlobalsInProcedures': `Global variables should not be referenced in procedures.`,
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.LowercaseDirectives) {
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,27 @@ export default class Linter {
}
}
}

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

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";
LowercaseDirectives?: boolean;
UppercaseDirectives?: boolean;
NoSQLJoins?: boolean;
NoGlobalsInProcedures?: boolean;
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions schemas/rpglint.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,11 @@
],
"description": "Force which directive which must be used to include other source. (Copy or Include)"
},
"LowercaseDirectives": {
richardm90 marked this conversation as resolved.
Show resolved Hide resolved
"$id": "#/properties/LowercaseDirectives",
"type": "boolean",
"description": "Directives must be in lowercase."
},
"UppercaseDirectives": {
richardm90 marked this conversation as resolved.
Show resolved Hide resolved
"$id": "#/properties/UppercaseDirectives",
"type": "boolean",
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;
106 changes: 106 additions & 0 deletions tests/suite/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -463,5 +463,111 @@ 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 }, {
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 }, {
LowercaseDirectives: true
}, cache);

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

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

assert.deepStrictEqual(errors[1], {
offset: { position: 99, end: 104 },
type: `LowercaseDirectives`,
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