Skip to content

Commit ecae18c

Browse files
committed
Refactor primary extractor in type checker extractor
1 parent 2a582bb commit ecae18c

File tree

5 files changed

+106
-77
lines changed

5 files changed

+106
-77
lines changed

src/types/ast/astExtractor/expression-extractor.ts

Lines changed: 86 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,45 @@
11
import {
22
ArgumentListCtx,
3+
ArrayAccessSuffixCtx,
34
BaseJavaCstVisitorWithDefaults,
45
BinaryExpressionCtx,
5-
ClassOrInterfaceTypeToInstantiateCtx,
66
BooleanLiteralCtx,
7+
ClassOrInterfaceTypeToInstantiateCtx,
78
ExpressionCstNode,
89
ExpressionCtx,
910
FloatingPointLiteralCtx,
1011
FqnOrRefTypeCtx,
1112
FqnOrRefTypePartCommonCtx,
1213
FqnOrRefTypePartFirstCtx,
1314
FqnOrRefTypePartRestCtx,
14-
IToken,
1515
IntegerLiteralCtx,
16+
IToken,
1617
LiteralCtx,
1718
MethodInvocationSuffixCtx,
1819
NewExpressionCtx,
1920
ParenthesisExpressionCtx,
2021
PrimaryCtx,
2122
PrimaryPrefixCtx,
23+
PrimarySuffixCstNode,
2224
PrimarySuffixCtx,
2325
TernaryExpressionCtx,
2426
UnaryExpressionCstNode,
2527
UnaryExpressionCtx,
26-
UnqualifiedClassInstanceCreationExpressionCtx,
27-
ArrayAccessSuffixCtx
28+
UnqualifiedClassInstanceCreationExpressionCtx
2829
} from 'java-parser'
29-
import { Location } from '../types/ast'
3030
import {
31+
ArgumentList,
3132
ArrayAccess,
3233
Assignment,
3334
BinaryExpression,
3435
ClassInstanceCreationExpression,
3536
Expression,
3637
ExpressionName,
37-
MethodInvocation,
38+
FieldAccess,
3839
Primary
3940
} from '../types/blocks-and-statements'
41+
import { Location } from '../types/ast'
42+
import { getLocation } from './utils'
4043

4144
export class ExpressionExtractor extends BaseJavaCstVisitorWithDefaults {
4245
private location: Location
@@ -194,72 +197,71 @@ export class ExpressionExtractor extends BaseJavaCstVisitorWithDefaults {
194197
}
195198

196199
primary(ctx: PrimaryCtx): Primary {
197-
let primary = this.visit(ctx.primaryPrefix)
198200
if (ctx.primarySuffix) {
199201
const lastSuffix = ctx.primarySuffix[ctx.primarySuffix.length - 1]
200-
if (lastSuffix.children.arrayAccessSuffix) {
201-
const newPrimaryCtx: PrimaryCtx = { primaryPrefix: ctx.primaryPrefix }
202-
if (ctx.primarySuffix.length - 1 > 0) {
203-
const newSuffixArray = ctx.primarySuffix.filter(
204-
(_, index) => index !== ctx.primarySuffix!.length - 1
205-
)
206-
newPrimaryCtx.primarySuffix = newSuffixArray
207-
}
208-
return {
209-
...this.visit(lastSuffix.children.arrayAccessSuffix),
210-
primary: this.primary(newPrimaryCtx)
211-
}
212-
}
213-
214-
for (const s of ctx.primarySuffix.filter(s => !s.children.methodInvocationSuffix)) {
215-
primary += '.' + this.visit(s)
216-
}
217-
218-
if (ctx.primarySuffix[ctx.primarySuffix.length - 1].children.methodInvocationSuffix) {
202+
const newPrimaryCtx: PrimaryCtx = { primaryPrefix: ctx.primaryPrefix }
203+
const primarySuffix: PrimarySuffixCstNode[] = []
204+
for (let i = 0; i < ctx.primarySuffix.length - 1; i++)
205+
primarySuffix.push(ctx.primarySuffix[i])
206+
if (primarySuffix.length > 0) newPrimaryCtx.primarySuffix = primarySuffix
207+
const primary = this.primary(newPrimaryCtx)
208+
const primaryRest = this.visit(lastSuffix)
209+
if (!primaryRest) return {} as Primary // Temporary
210+
if (primary.kind === 'FieldAccess' && primaryRest.kind === 'MethodInvocation') {
211+
// example.test() -> primary: example.test, primaryRest: ()
219212
return {
220-
kind: 'MethodInvocation',
221-
identifier: primary,
222-
argumentList: this.visit(ctx.primarySuffix[ctx.primarySuffix.length - 1]),
223-
location: this.location
224-
} as MethodInvocation
213+
...primaryRest,
214+
identifier: primary.identifier,
215+
location: primary.location,
216+
primary: primary.primary
217+
} as Primary
225218
}
219+
return { ...primaryRest, primary }
226220
}
227-
228-
if (ctx.primaryPrefix[0].children.fqnOrRefType || ctx.primaryPrefix[0].children.This) {
229-
return {
230-
kind: 'ExpressionName',
231-
name: primary,
232-
location: this.location
233-
} as ExpressionName
234-
}
235-
236-
return primary
221+
return this.visit(ctx.primaryPrefix) as Primary
237222
}
238223

239224
primaryPrefix(ctx: PrimaryPrefixCtx) {
240-
if (ctx.literal) {
241-
return this.visit(ctx.literal)
242-
} else if (ctx.parenthesisExpression) {
243-
return this.visit(ctx.parenthesisExpression)
225+
if (ctx.This) {
226+
return { kind: 'This' }
227+
} else if (ctx.Void) {
228+
return { kind: 'Void' }
229+
} else if (ctx.castExpression) {
230+
throw new Error('not implemented')
244231
} else if (ctx.fqnOrRefType) {
245232
return this.visit(ctx.fqnOrRefType)
233+
} else if (ctx.literal) {
234+
return this.visit(ctx.literal)
246235
} else if (ctx.newExpression) {
247236
return this.visit(ctx.newExpression)
248-
} else if (ctx.This) {
249-
return ctx.This[0].image
237+
} else if (ctx.parenthesisExpression) {
238+
return this.visit(ctx.parenthesisExpression)
239+
} else if (ctx.switchStatement) {
240+
throw new Error('not implemented')
241+
} else if (ctx.unannPrimitiveTypeWithOptionalDimsSuffix) {
242+
throw new Error('not implemented')
250243
}
251244
}
252245

253246
primarySuffix(ctx: PrimarySuffixCtx) {
254247
if (ctx.methodInvocationSuffix) {
255248
return this.visit(ctx.methodInvocationSuffix)
256-
} else if (ctx.Identifier) {
257-
return ctx.Identifier[0].image
249+
} else if (ctx.Dot && ctx.Identifier) {
250+
return {
251+
kind: 'FieldAccess',
252+
identifier: ctx.Identifier[0].image,
253+
location: getLocation(ctx.Identifier[0])
254+
}
255+
} else if (ctx.arrayAccessSuffix) {
256+
return this.visit(ctx.arrayAccessSuffix)
258257
}
259258
}
260259

261260
methodInvocationSuffix(ctx: MethodInvocationSuffixCtx) {
262-
return ctx.argumentList ? this.visit(ctx.argumentList) : []
261+
return {
262+
kind: 'MethodInvocation',
263+
argumentList: ctx.argumentList ? this.visit(ctx.argumentList) : []
264+
}
263265
}
264266

265267
newExpression(ctx: NewExpressionCtx) {
@@ -281,30 +283,52 @@ export class ExpressionExtractor extends BaseJavaCstVisitorWithDefaults {
281283
return ctx.Identifier[0].image
282284
}
283285

284-
argumentList(ctx: ArgumentListCtx) {
285-
const expressionExtractor = new ExpressionExtractor()
286-
return ctx.expression.map(e => expressionExtractor.extract(e))
286+
argumentList(ctx: ArgumentListCtx): ArgumentList {
287+
const argumentList: Expression[] = []
288+
ctx.expression.forEach(expression => {
289+
const expressionExtractor = new ExpressionExtractor()
290+
const argumentExpression = expressionExtractor.extract(expression)
291+
argumentList.push(argumentExpression)
292+
})
293+
return argumentList
287294
}
288295

289296
fqnOrRefType(ctx: FqnOrRefTypeCtx) {
290-
let fqn = this.visit(ctx.fqnOrRefTypePartFirst)
291-
if (ctx.fqnOrRefTypePartRest) {
292-
for (const r of ctx.fqnOrRefTypePartRest) {
293-
fqn += '.' + this.visit(r)
294-
}
297+
const firstPart = this.visit(ctx.fqnOrRefTypePartFirst)
298+
if (ctx.Dot && ctx.fqnOrRefTypePartRest) {
299+
const expressionName = this.visit(ctx.fqnOrRefTypePartRest) as ExpressionName
300+
return {
301+
kind: 'FieldAccess',
302+
identifier: expressionName.name,
303+
primary: firstPart,
304+
location: expressionName.location
305+
} as FieldAccess
295306
}
296-
return fqn
307+
return firstPart
297308
}
298309

299310
fqnOrRefTypePartFirst(ctx: FqnOrRefTypePartFirstCtx) {
311+
if (ctx.annotation) throw new Error('not implemented')
300312
return this.visit(ctx.fqnOrRefTypePartCommon)
301313
}
302314

303315
fqnOrRefTypePartCommon(ctx: FqnOrRefTypePartCommonCtx) {
304-
return ctx.Identifier && ctx.Identifier[0].image
316+
if (ctx.Identifier) {
317+
return {
318+
kind: 'ExpressionName',
319+
name: ctx.Identifier[0].image,
320+
location: getLocation(ctx.Identifier[0])
321+
} as Primary
322+
}
323+
throw new Error('not implemented')
305324
}
306325

307326
fqnOrRefTypePartRest(ctx: FqnOrRefTypePartRestCtx) {
327+
if (ctx.annotation) {
328+
throw new Error('not implemented')
329+
} else if (ctx.typeArguments) {
330+
throw new Error('not implemented')
331+
}
308332
return this.visit(ctx.fqnOrRefTypePartCommon)
309333
}
310334

@@ -416,7 +440,8 @@ export class ExpressionExtractor extends BaseJavaCstVisitorWithDefaults {
416440
const expresionExtractor = new ExpressionExtractor()
417441
return {
418442
kind: 'ArrayAccess',
419-
expression: expresionExtractor.extract(ctx.expression[0])
443+
expression: expresionExtractor.extract(ctx.expression[0]),
444+
location: getLocation(ctx.LSquare[0])
420445
}
421446
}
422447
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { Location } from '../types/ast'
2+
3+
export const getLocation = (object: Location): Location => ({
4+
startLine: object.startLine,
5+
startOffset: object.startOffset,
6+
endColumn: object.endColumn,
7+
endLine: object.endLine,
8+
endOffset: object.endOffset,
9+
startColumn: object.startColumn
10+
})

src/types/ast/types/blocks-and-statements.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,14 +127,15 @@ export interface Void extends BaseNode {
127127
}
128128

129129
export type Primary =
130+
| ArrayAccess
131+
| Assignment // TODO: Check JLS for this
132+
| ClassInstanceCreationExpression
130133
| Expression
131-
| Literal
132134
| ExpressionName
133-
| Assignment
134-
| MethodInvocation
135-
| ArrayAccess
136135
| FieldAccess
137-
| ClassInstanceCreationExpression
136+
| Literal
137+
| MethodInvocation
138+
| This
138139

139140
export interface ClassInstanceCreationExpression extends BaseNode {
140141
kind: 'ClassInstanceCreationExpression'
@@ -277,3 +278,7 @@ export interface TernaryExpression extends BaseNode {
277278
consequent: Expression
278279
alternate: Expression
279280
}
281+
282+
export interface This extends BaseNode {
283+
kind: 'This'
284+
}

src/types/checker/__tests__/arrays.test.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,16 +80,6 @@ const testcases: {
8080
`,
8181
result: { type: null, errors: [] }
8282
},
83-
84-
{
85-
input: `
86-
int i = numbers.length; // Accessing array length
87-
int j = numbers.hashCode(length).test(); // Checking difference
88-
`,
89-
result: { type: null, errors: [] },
90-
only: true
91-
},
92-
9383
{
9484
input: `
9585
char[] chars = new char[5];

src/types/checker/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,6 @@ export const check = (node: Node, frame: Frame = Frame.globalFrame()): Result =>
452452
return OK_RESULT
453453
}
454454
default:
455-
console.log(node)
456455
throw new Error(`Check is not implemented for this type of node ${node.kind}.`)
457456
}
458457
}

0 commit comments

Comments
 (0)