1
0
mirror of https://github.com/sasjs/lint.git synced 2025-12-10 09:34:34 +00:00
Files
lint/src/utils/parseMacros.ts

91 lines
2.7 KiB
TypeScript

import { LintConfig } from '../types/LintConfig'
import { LineEndings } from '../types/LineEndings'
import { trimComments } from './trimComments'
interface Macro {
name: string
startLineNumber: number | null
endLineNumber: number | null
declaration: string
termination: string
parentMacro: string
hasMacroNameInMend: boolean
hasParentheses: boolean
mismatchedMendMacroName: string
}
export const parseMacros = (text: string, config?: LintConfig): Macro[] => {
const lineEnding = config?.lineEndings === LineEndings.CRLF ? '\r\n' : '\n'
const lines: string[] = text ? text.split(lineEnding) : []
const macros: Macro[] = []
let isCommentStarted = false
let macroStack: Macro[] = []
lines.forEach((line, index) => {
const { statement: trimmedLine, commentStarted } = trimComments(
line,
isCommentStarted
)
isCommentStarted = commentStarted
const statements: string[] = trimmedLine ? trimmedLine.split(';') : []
statements.forEach((statement) => {
const { statement: trimmedStatement, commentStarted } = trimComments(
statement,
isCommentStarted
)
isCommentStarted = commentStarted
if (trimmedStatement.startsWith('%macro')) {
const startLineNumber = index + 1
const name = trimmedStatement
.slice(7, trimmedStatement.length)
.trim()
.split('(')[0]
macroStack.push({
name,
startLineNumber,
endLineNumber: null,
parentMacro: macroStack.length
? macroStack[macroStack.length - 1].name
: '',
hasParentheses: trimmedStatement.endsWith('()'),
hasMacroNameInMend: false,
mismatchedMendMacroName: '',
declaration: line,
termination: ''
})
} else if (trimmedStatement.startsWith('%mend')) {
if (macroStack.length) {
const macro = macroStack.pop() as Macro
const mendMacroName =
trimmedStatement.split(' ').filter((s: string) => !!s)[1] || ''
macro.endLineNumber = index + 1
macro.hasMacroNameInMend = trimmedStatement.includes(macro.name)
macro.mismatchedMendMacroName = macro.hasMacroNameInMend
? ''
: mendMacroName
macro.termination = line
macros.push(macro)
} else {
macros.push({
name: '',
startLineNumber: null,
endLineNumber: index + 1,
parentMacro: '',
hasParentheses: false,
hasMacroNameInMend: false,
mismatchedMendMacroName: '',
declaration: '',
termination: line
})
}
}
})
})
macros.push(...macroStack)
return macros
}