Skip to content

Commit f1c3ce5

Browse files
gigasecond: Initial analyzer (#38)
## Statistics | Status | Count | Comments | Unique | Avg | Median | Total | | --------------------:| -----:| --------:| ------:| ------:|-------:|--------:| | Approve | 89 | 29 | 4 | 515ms | 605ms | 4s | | Disapprove | 234 | 44 | 12 | 482ms | 508ms | 11s | | Refer to mentor | 176 | 37 | 4 | 466ms | 485ms | 8s | | Total | 499 | 92 | 14 | 482ms | 504ms | 24s |
1 parent fd1ac9a commit f1c3ce5

30 files changed

Lines changed: 6299 additions & 403 deletions

src/analyze.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const { exercise, options, input, logger } = Bootstrap.call()
1616

1717
logger.log('=> DEBUG mode is on')
1818
logger.log(`=> exercise: ${exercise.slug}`)
19+
logger.log(`=> options: ${options.pretty ? 'pretty ' : ''}${options.noTemplates ? 'no-templates' : 'templates'} ${options.dry ? 'dry ' : ''}`)
1920

2021
// The autoloader knows where an analyzer should live and tries to require it
2122
// so it can be instantiated here. This allows us to add new analyzers without
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { getProcessLogger as getLogger, Logger } from '~src/utils/logger'
2+
3+
import { IsolatedAnalyzerOutput, EarlyFinalization } from '~src/output/IsolatedAnalyzerOutput';
4+
5+
export abstract class IsolatedAnalyzerImpl implements Analyzer {
6+
protected readonly logger: Logger
7+
8+
/**
9+
* Creates an instance of an analyzer
10+
*/
11+
constructor() {
12+
this.logger = getLogger()
13+
}
14+
15+
/**
16+
* Runs the analyzer
17+
*
18+
* This is defined as a property instead of a method, so that it can not be
19+
* overriddden in a subclass. Subclasses should override @see execute instead.
20+
*
21+
* @returns The promise that resolves the analyzer output.
22+
*
23+
* @memberof BaseAnalyzer
24+
*/
25+
public async run(input: Input): Promise<Output> {
26+
const output = new IsolatedAnalyzerOutput()
27+
await this.execute(input, output)
28+
.catch((err): void | never => {
29+
if (err instanceof EarlyFinalization) {
30+
this.logger.log(`=> early finialization (${output.status})`)
31+
} else {
32+
throw err
33+
}
34+
})
35+
36+
return output
37+
}
38+
39+
/**
40+
* Execute the analyzer
41+
*/
42+
protected abstract execute(input: Input, output: WritableOutput): Promise<void>
43+
}

src/analyzers/SourceImpl.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { TSESTree, AST_NODE_TYPES } from "@typescript-eslint/typescript-estree";
2+
3+
type NodeWithLocation = TSESTree.Node & {
4+
range?: TSESTree.Range;
5+
loc?: TSESTree.SourceLocation;
6+
}
7+
8+
interface Source {
9+
get(node: NodeWithLocation): string;
10+
}
11+
12+
class SourceImpl implements Source {
13+
private readonly lines: string[]
14+
15+
constructor(source: string) {
16+
this.lines = source.split("\n")
17+
}
18+
19+
public get(node: NodeWithLocation): string {
20+
const start = this.lines[node.loc.start.line - 1]
21+
const end = this.lines[node.loc.end.line - 1]
22+
if (start === end) {
23+
return start.substring(node.loc.start.column, node.loc.end.column)
24+
}
25+
26+
return [
27+
start.substring(node.loc.start.column),
28+
...this.lines.slice(node.loc.start.line, node.loc.end.line - 2),
29+
end.substring(0, node.loc.end.column)
30+
].join("\n")
31+
}
32+
33+
public getOuter(node: NodeWithLocation): string {
34+
switch (node.type) {
35+
case AST_NODE_TYPES.ArrowFunctionExpression: {
36+
return this.get(node).replace(this.get(node.body), '...')
37+
}
38+
case AST_NODE_TYPES.FunctionDeclaration: {
39+
return this.get(node).replace(node.body && this.get(node.body) || '...', '...')
40+
}
41+
case AST_NODE_TYPES.FunctionExpression: {
42+
return this.get(node).replace(node.body && this.get(node.body) || '...', '...')
43+
}
44+
case AST_NODE_TYPES.VariableDeclaration: {
45+
const first = node.declarations[0].init
46+
return this.get(node).replace(first && this.get(first) || '...', first && this.getOuter(first) || '...')
47+
}
48+
default: {
49+
return this.get(node)
50+
}
51+
}
52+
}
53+
}
54+
55+
export { SourceImpl as Source }

0 commit comments

Comments
 (0)