Skip to content

Commit

Permalink
Merge pull request #237 from sasjs/@sasjs/cli-issue-1338
Browse files Browse the repository at this point in the history
feat(compile): added validateDependency method
  • Loading branch information
YuryShkoda authored May 10, 2023
2 parents 127875d + 433bc4f commit b2ec9c6
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 8 deletions.
57 changes: 56 additions & 1 deletion src/compileTree/compileTree.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { CompileTree, Tree, removeHeader } from './'
import { readFile, deleteFile, fileExists } from '../'
import {
readFile,
deleteFile,
fileExists,
DependencyType,
DependencyHeader
} from '../'
import path from 'path'

describe('CompileTree', () => {
Expand Down Expand Up @@ -29,6 +35,55 @@ describe('CompileTree', () => {
JSON.stringify(tree, null, 2)
)
})

it('should validate dependencies', () => {
const testDepPath = 'test.sas'
const getTestContent = (header: DependencyHeader) => `/**
@file macroWithInclude.sas
@brief test macro
${header}
**/
proc sql;
create table areas as select distinct area
from mydb.springs;
`

const getExpectedError = (header: DependencyHeader) =>
new Error(
`Dependency '${header}' can not be used in artefact type '${DependencyType.Macro}'. Please remove it from '${testDepPath}'.`
)

expect(() =>
compileTree['validateDependency'](
getTestContent(DependencyHeader.Include),
testDepPath,
DependencyType.Macro
)
).toThrow(getExpectedError(DependencyHeader.Include))
expect(() =>
compileTree['validateDependency'](
getTestContent(DependencyHeader.Binary),
testDepPath,
DependencyType.Macro
)
).toThrow(getExpectedError(DependencyHeader.Binary))

expect(() =>
compileTree['validateDependency'](
getTestContent(DependencyHeader.Binary),
testDepPath
)
).not.toThrow()
expect(() =>
compileTree['validateDependency'](
getTestContent(DependencyHeader.Binary),
testDepPath,
DependencyType.Binary
)
).not.toThrow()
})
})

describe('removeHeader', () => {
Expand Down
48 changes: 44 additions & 4 deletions src/compileTree/compileTree.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import path from 'path'
import { createFile, readFile } from '../'
import { getList, DependencyHeader, getDeprecatedHeader } from '../sasjsCli'
import { newLine } from '../formatter'
import {
getList,
DependencyHeader,
getDeprecatedHeader,
DependencyType
} from '../sasjsCli'

export interface Leaf {
content: string
Expand Down Expand Up @@ -52,18 +56,54 @@ export class CompileTree {

// If leaf exists, returns it's content.
// Otherwise reads file, creates leaf and return content.
public async getDepContent(depPath: string) {
public async getDepContent(depPath: string, depType?: DependencyType) {
const leaf = this.getLeaf(depPath)

if (leaf) return leaf.content

const content = await readFile(depPath, undefined)

this.validateDependency(content, depPath, depType)

return this.addLeaf({
content: await readFile(depPath, undefined),
content,
dependencies: [],
location: depPath
}).content
}

// Throws an error if wrong dependencies have been used
private validateDependency(
content: string,
depPath: string,
depType?: DependencyType
) {
if (!depType) return

const getErrorMessage = (
header: DependencyHeader,
dependency: DependencyType,
depPath: string
) =>
`Dependency '${header}' can not be used in artefact type '${dependency}'. Please remove it from '${depPath}'.`

switch (depType) {
case DependencyType.Macro:
if (content.includes(DependencyHeader.Include)) {
throw new Error(
getErrorMessage(DependencyHeader.Include, depType, depPath)
)
} else if (content.includes(DependencyHeader.Binary)) {
throw new Error(
getErrorMessage(DependencyHeader.Binary, depType, depPath)
)
}

default:
break
}
}

// Returns file name based on file path
private getFileName(location: string) {
return location.split(path.sep)[location.split(path.sep).length - 1]
Expand Down
5 changes: 4 additions & 1 deletion src/sasjsCli/getDependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@ export const getDependencies = async (
Object.keys(compileTree).length &&
depType !== DependencyType.Binary
) {
encodedFileContent = await compileTree.getDepContent(filePaths[0])
encodedFileContent = await compileTree.getDepContent(
filePaths[0],
depType
)
} else {
encodedFileContent = await readFile(
filePaths[0],
Expand Down
11 changes: 9 additions & 2 deletions src/sasjsCli/getDependencyPaths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
prioritiseDependencyOverrides,
getList,
DependencyHeader,
getDeprecatedHeader
getDeprecatedHeader,
DependencyType
} from './'
import { CompileTree, Leaf } from '../compileTree'

Expand All @@ -19,10 +20,12 @@ export async function getDependencyPaths(
let dependencyPaths: string[] = []
const foundDependencies: string[] = []
const sourcePaths = [...macroFolders, macroCorePath]

const dependenciesHeader = getDeprecatedHeader(
fileContent,
DependencyHeader.Macro
)

const dependencies =
leaf?.dependencies ||
getList(dependenciesHeader, fileContent).filter((d) => d.endsWith('.sas'))
Expand All @@ -38,7 +41,11 @@ export async function getDependencyPaths(
let leaf: Leaf | undefined = undefined

if (compileTree && Object.keys(compileTree).length) {
fileContent = await compileTree.getDepContent(filePaths[0])
fileContent = await compileTree.getDepContent(
filePaths[0],
DependencyType.Macro
)

leaf = compileTree.getLeaf(filePaths[0])
} else {
fileContent = await readFile(filePaths[0])
Expand Down

0 comments on commit b2ec9c6

Please sign in to comment.