-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(strictMacroDefinition): moved from lineRules to fileRules
- Loading branch information
1 parent
af2d2c1
commit f793eb3
Showing
8 changed files
with
351 additions
and
232 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
import { LintConfig, Severity } from '../../types' | ||
import { strictMacroDefinition } from './strictMacroDefinition' | ||
|
||
describe('strictMacroDefinition', () => { | ||
it('should return an empty array when the content has correct macro definition syntax', () => { | ||
const content = '%macro somemacro;' | ||
expect(strictMacroDefinition.test(content)).toEqual([]) | ||
|
||
const content2 = '%macro somemacro();' | ||
expect(strictMacroDefinition.test(content2)).toEqual([]) | ||
|
||
const content3 = '%macro somemacro(var1);' | ||
expect(strictMacroDefinition.test(content3)).toEqual([]) | ||
|
||
const content4 = '%macro somemacro/minoperator;' | ||
expect(strictMacroDefinition.test(content4)).toEqual([]) | ||
|
||
const content5 = '%macro somemacro /minoperator;' | ||
expect(strictMacroDefinition.test(content5)).toEqual([]) | ||
|
||
const content6 = '%macro somemacro(var1, var2)/minoperator;' | ||
expect(strictMacroDefinition.test(content6)).toEqual([]) | ||
|
||
const content7 = | ||
' /* Some Comment */ %macro somemacro(var1, var2) /minoperator ; /* Some Comment */' | ||
expect(strictMacroDefinition.test(content7)).toEqual([]) | ||
|
||
const content8 = | ||
'%macro macroName( arr, arr/* / store source */3 ) /* / store source */;/* / store source */' | ||
expect(strictMacroDefinition.test(content8)).toEqual([]) | ||
|
||
const content9 = '%macro macroName(var1, var2=with space, var3=);' | ||
expect(strictMacroDefinition.test(content9)).toEqual([]) | ||
|
||
const content10 = '%macro macroName()/ /* some comment */ store source;' | ||
expect(strictMacroDefinition.test(content10)).toEqual([]) | ||
|
||
const content11 = '`%macro macroName() /* / store source */;' | ||
expect(strictMacroDefinition.test(content11)).toEqual([]) | ||
}) | ||
|
||
it('should return an array with a single diagnostic when Macro definition has space in param', () => { | ||
const content = '%macro somemacro(va r1);' | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Param 'va r1' cannot have space`, | ||
lineNumber: 1, | ||
startColumnNumber: 18, | ||
endColumnNumber: 22, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
|
||
it('should return an array with a two diagnostics when Macro definition has space in params', () => { | ||
const content = '%macro somemacro(var1, var 2, v ar3, var4);' | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Param 'var 2' cannot have space`, | ||
lineNumber: 1, | ||
startColumnNumber: 24, | ||
endColumnNumber: 28, | ||
severity: Severity.Warning | ||
}, | ||
{ | ||
message: `Param 'v ar3' cannot have space`, | ||
lineNumber: 1, | ||
startColumnNumber: 31, | ||
endColumnNumber: 35, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
|
||
it('should return an array with a two diagnostics when Macro definition has space in params - special case', () => { | ||
const content = | ||
'%macro macroName( arr, ar r/* / store source */ 3 ) /* / store source */;/* / store source */' | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Param 'ar r 3' cannot have space`, | ||
lineNumber: 1, | ||
startColumnNumber: 24, | ||
endColumnNumber: 49, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
|
||
it('should return an array with a single diagnostic when Macro definition has invalid option', () => { | ||
const content = '%macro somemacro(var1, var2)/minXoperator;' | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Option 'minXoperator' is not valid`, | ||
lineNumber: 1, | ||
startColumnNumber: 30, | ||
endColumnNumber: 41, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
|
||
it('should return an array with a two diagnostics when Macro definition has invalid options', () => { | ||
const content = | ||
'%macro somemacro(var1, var2)/ store invalidoption secure ;' | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Option 'invalidoption' is not valid`, | ||
lineNumber: 1, | ||
startColumnNumber: 39, | ||
endColumnNumber: 51, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
|
||
describe('multi-content macro declarations', () => { | ||
it('should return an array with a single diagnostic when Macro definition has space in param', () => { | ||
const content = `%macro | ||
somemacro(va r1);` | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Param 'va r1' cannot have space`, | ||
lineNumber: 2, | ||
startColumnNumber: 18, | ||
endColumnNumber: 22, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
|
||
it('should return an array with a two diagnostics when Macro definition has space in params', () => { | ||
const content = `%macro somemacro( | ||
var1, | ||
var 2, | ||
v ar3, | ||
var4);` | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Param 'var 2' cannot have space`, | ||
lineNumber: 3, | ||
startColumnNumber: 7, | ||
endColumnNumber: 11, | ||
severity: Severity.Warning | ||
}, | ||
{ | ||
message: `Param 'v ar3' cannot have space`, | ||
lineNumber: 4, | ||
startColumnNumber: 7, | ||
endColumnNumber: 11, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
|
||
it('should return an array with a two diagnostics when Macro definition has space in params - special case', () => { | ||
const content = `%macro macroName( | ||
arr, | ||
ar r/* / store source */ 3 | ||
) /* / store source */;/* / store source */` | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Param 'ar r 3' cannot have space`, | ||
lineNumber: 3, | ||
startColumnNumber: 7, | ||
endColumnNumber: 32, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
|
||
it('should return an array with a single diagnostic when Macro definition has invalid option', () => { | ||
const content = `%macro somemacro(var1, var2) | ||
/minXoperator;` | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Option 'minXoperator' is not valid`, | ||
lineNumber: 2, | ||
startColumnNumber: 8, | ||
endColumnNumber: 19, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
|
||
it('should return an array with a two diagnostics when Macro definition has invalid options', () => { | ||
const content = `%macro | ||
somemacro( | ||
var1, var2 | ||
) | ||
/ store | ||
invalidoption | ||
secure ;` | ||
expect(strictMacroDefinition.test(content)).toEqual([ | ||
{ | ||
message: `Option 'invalidoption' is not valid`, | ||
lineNumber: 6, | ||
startColumnNumber: 16, | ||
endColumnNumber: 28, | ||
severity: Severity.Warning | ||
} | ||
]) | ||
}) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
import { Diagnostic } from '../../types/Diagnostic' | ||
import { LintConfig } from '../../types' | ||
import { FileLintRule } from '../../types/LintRule' | ||
import { LintRuleType } from '../../types/LintRuleType' | ||
import { Severity } from '../../types/Severity' | ||
import { parseMacros } from '../../utils/parseMacros' | ||
|
||
const name = 'strictMacroDefinition' | ||
const description = 'Enforce strictly rules of macro definition syntax.' | ||
const message = 'Incorrent Macro Definition Syntax' | ||
|
||
const validOptions = [ | ||
'CMD', | ||
'DES', | ||
'MINDELIMITER', | ||
'MINOPERATOR', | ||
'NOMINOPERATOR', | ||
'PARMBUFF', | ||
'SECURE', | ||
'NOSECURE', | ||
'STMT', | ||
'SOURCE', | ||
'SRC', | ||
'STORE' | ||
] | ||
|
||
const test = (value: string, config?: LintConfig) => { | ||
const diagnostics: Diagnostic[] = [] | ||
|
||
const macros = parseMacros(value, config) | ||
|
||
macros.forEach((macro) => { | ||
const declaration = macro.declaration | ||
|
||
const regExpParams = new RegExp(/\((.*?)\)/) | ||
const regExpParamsResult = regExpParams.exec(declaration) | ||
|
||
let _declaration = declaration | ||
if (regExpParamsResult) { | ||
const paramsPresent = regExpParamsResult[1] | ||
|
||
const paramsTrimmed = paramsPresent.trim() | ||
const params = paramsTrimmed.split(',') | ||
params.forEach((param) => { | ||
const trimedParam = param.split('=')[0].trim() | ||
|
||
let paramLineNumber: number = 1, | ||
paramStartIndex: number = 1, | ||
paramEndIndex: number = value.length | ||
|
||
if ( | ||
macro.declarationLines.findIndex( | ||
(dl) => dl.indexOf(trimedParam) !== -1 | ||
) === -1 | ||
) { | ||
const comment = '/\\*(.*?)\\*/' | ||
for (let i = 1; i < trimedParam.length; i++) { | ||
const paramWithComment = | ||
trimedParam.slice(0, i) + comment + trimedParam.slice(i) | ||
const regEx = new RegExp(paramWithComment) | ||
|
||
const declarationLineIndex = macro.declarationLines.findIndex( | ||
(dl) => !!regEx.exec(dl) | ||
) | ||
|
||
if (declarationLineIndex !== -1) { | ||
const declarationLine = | ||
macro.declarationLines[declarationLineIndex] | ||
const partFound = regEx.exec(declarationLine)![0] | ||
|
||
paramLineNumber = macro.startLineNumbers[declarationLineIndex] | ||
paramStartIndex = declarationLine.indexOf(partFound) | ||
paramEndIndex = | ||
declarationLine.indexOf(partFound) + partFound.length | ||
break | ||
} | ||
} | ||
} else { | ||
const declarationLineIndex = macro.declarationLines.findIndex( | ||
(dl) => dl.indexOf(trimedParam) !== -1 | ||
) | ||
const declarationLine = macro.declarationLines[declarationLineIndex] | ||
paramLineNumber = macro.startLineNumbers[declarationLineIndex] | ||
|
||
paramStartIndex = declarationLine.indexOf(trimedParam) | ||
paramEndIndex = | ||
declarationLine.indexOf(trimedParam) + trimedParam.length | ||
} | ||
|
||
if (trimedParam.includes(' ')) { | ||
diagnostics.push({ | ||
message: `Param '${trimedParam}' cannot have space`, | ||
lineNumber: paramLineNumber, | ||
startColumnNumber: paramStartIndex + 1, | ||
endColumnNumber: paramEndIndex, | ||
severity: Severity.Warning | ||
}) | ||
} | ||
}) | ||
|
||
_declaration = declaration.split(`(${paramsPresent})`)[1] | ||
} | ||
|
||
const optionsPresent = _declaration.split('/')?.[1]?.trim().split(' ') | ||
|
||
optionsPresent | ||
?.filter((o) => !!o) | ||
.forEach((option) => { | ||
const trimmedOption = option.trim() | ||
if (!validOptions.includes(trimmedOption.toUpperCase())) { | ||
const declarationLineIndex = macro.declarationLines.findIndex( | ||
(dl) => dl.indexOf(trimmedOption) !== -1 | ||
) | ||
const declarationLine = macro.declarationLines[declarationLineIndex] | ||
|
||
diagnostics.push({ | ||
message: `Option '${trimmedOption}' is not valid`, | ||
lineNumber: macro.startLineNumbers[declarationLineIndex], | ||
startColumnNumber: declarationLine.indexOf(trimmedOption) + 1, | ||
endColumnNumber: | ||
declarationLine.indexOf(trimmedOption) + trimmedOption.length, | ||
severity: Severity.Warning | ||
}) | ||
} | ||
}) | ||
}) | ||
|
||
return diagnostics | ||
} | ||
|
||
/** | ||
* Lint rule that checks if a line has followed syntax for macro definition | ||
*/ | ||
export const strictMacroDefinition: FileLintRule = { | ||
type: LintRuleType.File, | ||
name, | ||
description, | ||
message, | ||
test | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.