Skip to content

Commit 2863d9d

Browse files
committed
Start of Analyzer for Bird Watcher
1 parent 010114e commit 2863d9d

File tree

2 files changed

+107
-0
lines changed

2 files changed

+107
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import {
2+
AstParser,
3+
extractExports,
4+
extractFunctions,
5+
} from '@exercism/static-analysis'
6+
import { TSESTree } from '@typescript-eslint/typescript-estree'
7+
import { readFileSync } from 'fs'
8+
import path from 'path'
9+
import { Source } from '~src/analyzers/SourceImpl'
10+
11+
export const TOTAL_BIRD_COUNT = 'totalBirdCount'
12+
export const BIRDS_IN_WEEK = 'birdsInWeek'
13+
export const FIX_BIRD_COUNT_LOG = 'fixBirdCountLog'
14+
15+
export class BirdWatcherSolution {
16+
private readonly source: Source
17+
18+
private exemplar!: Source
19+
20+
constructor(public readonly program: TSESTree.Program, source: string) {
21+
this.source = new Source(source)
22+
23+
const functions = extractFunctions(program)
24+
const exports = extractExports(program)
25+
}
26+
27+
public readExemplar(directory: string): void {
28+
const configPath = path.join(directory, '.meta', 'config.json')
29+
const config = JSON.parse(readFileSync(configPath).toString())
30+
31+
const exemplarPath = path.join(directory, config.files.exemplar[0])
32+
this.exemplar = new Source(readFileSync(exemplarPath).toString())
33+
}
34+
35+
public get isExemplar(): boolean {
36+
const sourceAst = AstParser.REPRESENTER.parseSync(this.source.toString())
37+
const exemplarAst = AstParser.REPRESENTER.parseSync(
38+
this.exemplar.toString()
39+
)
40+
41+
return (
42+
JSON.stringify(sourceAst[0].program) ===
43+
JSON.stringify(exemplarAst[0].program)
44+
)
45+
}
46+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import {
2+
AstParser,
3+
Input,
4+
NoExportError,
5+
NoMethodError,
6+
} from '@exercism/static-analysis'
7+
import { TSESTree } from '@typescript-eslint/typescript-estree'
8+
import {
9+
EXEMPLAR_SOLUTION,
10+
NO_METHOD,
11+
NO_NAMED_EXPORT,
12+
} from '../../../comments/shared'
13+
import { ExecutionOptions, WritableOutput } from '../../../interface'
14+
import { IsolatedAnalyzerImpl } from '../../IsolatedAnalyzerImpl'
15+
import { BirdWatcherSolution } from './BirdWatcherSolution'
16+
17+
type Program = TSESTree.Program
18+
19+
export class BirdWatcherAnalyzer extends IsolatedAnalyzerImpl {
20+
private solution!: BirdWatcherSolution
21+
22+
protected async execute(
23+
input: Input,
24+
output: WritableOutput,
25+
options: ExecutionOptions
26+
): Promise<void> {
27+
const [parsed] = await AstParser.ANALYZER.parse(input)
28+
29+
this.solution = this.checkStructure(parsed.program, parsed.source, output)
30+
this.solution.readExemplar(options.inputDir)
31+
32+
if (this.solution.isExemplar) {
33+
output.add(EXEMPLAR_SOLUTION())
34+
output.finish()
35+
}
36+
37+
output.finish()
38+
}
39+
40+
private checkStructure(
41+
program: Readonly<Program>,
42+
source: Readonly<string>,
43+
output: WritableOutput
44+
): BirdWatcherSolution | never {
45+
try {
46+
return new BirdWatcherSolution(program, source)
47+
} catch (error) {
48+
if (error instanceof NoMethodError) {
49+
output.add(NO_METHOD({ 'method.name': error.method }))
50+
output.finish()
51+
}
52+
53+
if (error instanceof NoExportError) {
54+
output.add(NO_NAMED_EXPORT({ 'export.name': error.namedExport }))
55+
}
56+
57+
throw error
58+
}
59+
}
60+
}
61+
export default BirdWatcherAnalyzer

0 commit comments

Comments
 (0)