Skip to content

Commit fbacd31

Browse files
Merge pull request diffblue#314 from diffblue/feature/di-to-code
Add utility to convert DI config files to Java code
2 parents 850c824 + 9387006 commit fbacd31

File tree

19 files changed

+2659
-0
lines changed

19 files changed

+2659
-0
lines changed

env-model-generator/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
built
2+
node_modules
3+
.vscode
4+
output/src
5+
output/target

env-model-generator/README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# env-model-generator
2+
3+
Reads a DI configuration file and outputs Java code to reproduce the effects of the DI framework using that file.
4+
5+
## Usage
6+
7+
To install and run env-model-generator use the following commands:
8+
```bash
9+
yarn install
10+
yarn run build
11+
./env-model-generator benchmarks/GENUINE/sakai/edu-services/cm-service/cm-impl/hibernate-impl/impl/src/test/spring-test.xml \
12+
--input-file benchmarks/GENUINE/sakai/edu-services/cm-service/cm-impl/hibernate-impl/impl/src/test/spring-config-dataload.xml \
13+
--outputPath benchmarks/GENUINE/sakai/edu-services/cm-service/cm-impl/hibernate-impl/impl/src/test
14+
./env-model-generator regression/OWASP/BenchmarkTest00431/src/main/resources/context.xml --outputPath regression/OWASP/BenchmarkTest00431/src/main
15+
```
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash
2+
chmod a+x built/env-model-generator.js
3+
built/env-model-generator.js "$@"

env-model-generator/package.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"name": "@diffblue/env-model-generator",
3+
"description": "Reads a DI configuration file and outputs Java code to reproduce the effects of the DI framework using that file.",
4+
"version": "0.0.0",
5+
"private": true,
6+
"repository": "[email protected]:diffblue/security-scanner/env-model-generator",
7+
"author": {
8+
"name": "Nathan Phillips",
9+
"email": "[email protected]"
10+
},
11+
"main": "./built/env-model-generator.js",
12+
"bin": {
13+
"env-model-generator": "./built/env-model-generator.js"
14+
},
15+
"scripts": {
16+
"build": "tsc",
17+
"lint": "tslint src/**/*.ts",
18+
"fix-lint": "tslint src/**/*.ts --fix",
19+
"start": "node built/env-model-generator.js ../benchmarks/GENUINE/sakai/edu-services/cm-service/cm-impl/hibernate-impl/impl/src/test/spring-test.xml --outputPath output"
20+
},
21+
"dependencies": {
22+
"commander": "2.13.0",
23+
"fs-extra": "5.0.0",
24+
"iterable-ext": "1.0.4",
25+
"lodash": "4.17.4",
26+
"xml2js": "0.4.19"
27+
},
28+
"devDependencies": {
29+
"@types/fs-extra": "5.0.0",
30+
"@types/lodash": "4.14.68",
31+
"@types/node": "8.0.47",
32+
"@types/xml2js": "0.4.2",
33+
"tslint": "5.4.2",
34+
"tslint-language-service": "0.9.6",
35+
"typescript": "2.4.1"
36+
}
37+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// The error thrown when a configuration file can not be parsed
2+
3+
export class ConfigParseError extends Error {
4+
}

env-model-generator/src/JavaCode.ts

Lines changed: 280 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
import * as _ from "lodash";
2+
3+
const indent = " ";
4+
5+
export abstract class CodeElement {
6+
public elementType: string;
7+
8+
public abstract flatten(): string[];
9+
10+
public toString() {
11+
return this.flatten().join("\n");
12+
}
13+
}
14+
15+
export interface Expression {
16+
isExpression: true;
17+
flatten(): string[];
18+
}
19+
20+
export interface Statement {
21+
isStatement: true;
22+
flatten(): string[];
23+
}
24+
25+
export interface Member {
26+
isMember: true;
27+
flatten(): string[];
28+
}
29+
30+
export class FnCall extends CodeElement implements Expression {
31+
public isExpression: true = true;
32+
33+
private fnName: string;
34+
private args: Expression[];
35+
36+
public constructor(fnName: string, args: Expression[]) {
37+
super();
38+
this.fnName = fnName;
39+
this.args = args;
40+
}
41+
42+
public flatten(): string[] {
43+
const argsInLines = this.args.map((arg) => arg.flatten());
44+
for (let argNo = 0; argNo < argsInLines.length - 1; ++argNo) {
45+
const argInLines = argsInLines[argNo];
46+
argInLines[argInLines.length - 1] += ",";
47+
}
48+
const oneLine = this.fnName + "(" + argsInLines.join(" ") + ")";
49+
if (oneLine.length < 80)
50+
return [ oneLine ];
51+
return [
52+
this.fnName + "(",
53+
..._.flatten(argsInLines).map((arg) => indent + arg),
54+
")",
55+
];
56+
}
57+
}
58+
59+
export class BraceInitialiser extends CodeElement implements Expression {
60+
public isExpression: true = true;
61+
62+
private typename: string;
63+
private args: Expression[];
64+
65+
public constructor(typename: string, args: Expression[]) {
66+
super();
67+
this.typename = typename;
68+
this.args = args;
69+
}
70+
71+
public flatten(): string[] {
72+
const argsInLines = this.args.map((arg) => arg.flatten());
73+
for (const argInLines of argsInLines) {
74+
argInLines[argInLines.length - 1] += ",";
75+
}
76+
const oneLine = this.typename + " { " + argsInLines.join(" ") + " }";
77+
if (oneLine.length < 80)
78+
return [ oneLine ];
79+
return [
80+
this.typename + " {",
81+
..._.flatten(argsInLines).map((arg) => indent + arg),
82+
"}",
83+
];
84+
}
85+
}
86+
87+
export class StringConstant extends CodeElement implements Expression {
88+
public isExpression: true = true;
89+
90+
private value: string;
91+
92+
constructor(value: string) {
93+
super();
94+
this.value = value;
95+
}
96+
97+
public flatten(): string[] {
98+
return [ `"${this.value}"` ];
99+
}
100+
}
101+
102+
export class Symbol extends CodeElement implements Expression {
103+
public isExpression: true = true;
104+
105+
private name: string;
106+
107+
constructor(name: string) {
108+
super();
109+
this.name = name;
110+
}
111+
112+
public flatten(): string[] {
113+
return [ this.name ];
114+
}
115+
}
116+
117+
export class Assignment extends CodeElement implements Statement {
118+
public isStatement: true = true;
119+
120+
private lhs: string;
121+
private rhs: Expression;
122+
123+
public constructor(lhs: string, rhs: Expression) {
124+
super();
125+
this.lhs = lhs;
126+
this.rhs = rhs;
127+
}
128+
129+
public flatten(): string[] {
130+
const rhsInLines = this.rhs.flatten();
131+
if (rhsInLines.length !== 0)
132+
rhsInLines[rhsInLines.length - 1] += ";";
133+
if (rhsInLines.length === 1) {
134+
const oneLine = this.lhs + " = " + rhsInLines[0];
135+
if (oneLine.length < 100)
136+
return [ oneLine ];
137+
}
138+
return [
139+
this.lhs + " =",
140+
...rhsInLines.map((arg) => indent + arg),
141+
];
142+
}
143+
}
144+
145+
export class Declaration extends CodeElement implements Statement, Member {
146+
public isStatement: true = true;
147+
public isMember: true = true;
148+
149+
private modifiedType: string;
150+
private name: string;
151+
private rhs: Expression | undefined;
152+
153+
public constructor(modifiedType: string, name: string, rhs?: Expression) {
154+
super();
155+
this.modifiedType = modifiedType;
156+
this.name = name;
157+
this.rhs = rhs;
158+
}
159+
160+
public flatten(): string[] {
161+
const rhsInLines = this.rhs === undefined ? [] : this.rhs.flatten();
162+
if (rhsInLines.length !== 0)
163+
rhsInLines[rhsInLines.length - 1] += ";";
164+
const name = this.name + (rhsInLines.length === 0 ? ";" : " =");
165+
const oneLineLhs = `${this.modifiedType} ${name}`;
166+
if (oneLineLhs.length >= 80)
167+
return [
168+
this.modifiedType,
169+
indent + name,
170+
...rhsInLines.map((arg) => indent + indent + arg),
171+
];
172+
if (rhsInLines.length <= 1) {
173+
const oneLine = rhsInLines.length === 0 ? oneLineLhs : `${oneLineLhs} ${rhsInLines[0]}`;
174+
if (oneLine.length < 80)
175+
return [ oneLine ];
176+
}
177+
return [
178+
oneLineLhs,
179+
...rhsInLines.map((arg) => indent + arg),
180+
];
181+
}
182+
}
183+
184+
export class Return extends CodeElement implements Statement {
185+
public isStatement: true = true;
186+
187+
private value: Expression;
188+
189+
constructor(value: Expression) {
190+
super();
191+
this.value = value;
192+
}
193+
194+
public flatten(): string[] {
195+
const valueInLines = this.value.flatten();
196+
if (valueInLines.length !== 0)
197+
valueInLines[valueInLines.length - 1] += ";";
198+
if (valueInLines.length === 1) {
199+
const oneLine = "return " + valueInLines[0];
200+
if (oneLine.length < 100)
201+
return [ oneLine ];
202+
}
203+
return [
204+
"return",
205+
...valueInLines.map((arg) => indent + arg),
206+
];
207+
}
208+
}
209+
210+
export class FnStatement extends CodeElement implements Statement {
211+
public isStatement: true = true;
212+
213+
private expr: FnCall;
214+
215+
public constructor(expr: FnCall) {
216+
super();
217+
this.expr = expr;
218+
}
219+
220+
public flatten(): string[] {
221+
const stmt = this.expr.flatten();
222+
stmt[stmt.length - 1] += ";";
223+
return stmt;
224+
}
225+
}
226+
227+
export class BlankLine extends CodeElement implements Statement, Member {
228+
public isStatement: true = true;
229+
public isMember: true = true;
230+
231+
public flatten(): string[] {
232+
return [ "" ];
233+
}
234+
}
235+
236+
export class Braces extends CodeElement implements Statement, Member {
237+
public isStatement: true = true;
238+
public isMember: true = true;
239+
240+
private intro: string;
241+
private body: Statement[];
242+
243+
public constructor(intro: string, body: Statement[]) {
244+
super();
245+
this.intro = intro;
246+
this.body = body;
247+
}
248+
249+
public flatten(): string[] {
250+
return [
251+
this.intro + " {",
252+
..._.flatMap(this.body, (block) => block.flatten()).map((line) => indent + line),
253+
"}",
254+
];
255+
}
256+
}
257+
258+
export class Class extends CodeElement {
259+
private modifiers: string;
260+
private name: string;
261+
private members: Member[];
262+
263+
public constructor(modifiers: string, name: string, members: Member[]) {
264+
super();
265+
this.modifiers = modifiers;
266+
this.name = name;
267+
this.members = members;
268+
}
269+
270+
public flatten(): string[] {
271+
const members = _.flatMap(this.members, (value, index, array) =>
272+
index !== array.length - 1 && !(value instanceof BlankLine)
273+
? [ value, new BlankLine() ] : value);
274+
return [
275+
`${this.modifiers} class ${this.name} {`,
276+
..._.flatMap(members, (member) => member.flatten()).map((line) => indent + line),
277+
"}",
278+
];
279+
}
280+
}

0 commit comments

Comments
 (0)