1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/*******************************************************************************
* Copyright (c) 2000, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
* Jesper S Moller - Contributions for
* Bug 378674 - "The method can be declared as static" is wrong
* Stephan Herrmann - Contribution for
* Bug 400874 - [1.8][compiler] Inference infrastructure should evolve to meet JLS8 18.x (Part G of JSR335 spec)
*******************************************************************************/
package org.eclipse.jdt.internal.eval;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
import org.eclipse.jdt.internal.compiler.impl.Constant;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
import org.eclipse.jdt.internal.compiler.lookup.InferenceContext18;
import org.eclipse.jdt.internal.compiler.lookup.InvocationSite;
import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
/**
* A this reference inside a code snippet denotes a remote
* receiver object (that is, the receiver of the context in the stack frame)
*/
public class CodeSnippetThisReference extends ThisReference implements EvaluationConstants, InvocationSite {
EvaluationContext evaluationContext;
FieldBinding delegateThis;
boolean isImplicit;
/**
* CodeSnippetThisReference constructor comment.
* @param s int
* @param sourceEnd int
*/
public CodeSnippetThisReference(int s, int sourceEnd, EvaluationContext evaluationContext, boolean isImplicit) {
super(s, sourceEnd);
this.evaluationContext = evaluationContext;
this.isImplicit = isImplicit;
}
@Override
public boolean checkAccess(BlockScope scope, ReferenceBinding thisType) {
// this/super cannot be used in constructor call
MethodScope methodScope = scope.methodScope();
if (this.evaluationContext.isConstructorCall) {
methodScope.problemReporter().fieldsOrThisBeforeConstructorInvocation(this);
return false;
}
// static may not refer to this/super
if (this.evaluationContext.declaringTypeName == null || this.evaluationContext.isStatic) {
methodScope.problemReporter().errorThisSuperInStatic(this);
return false;
}
scope.tagAsAccessingEnclosingInstanceStateOf(thisType, false /* type variable access */);
return true;
}
@Override
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
int pc = codeStream.position;
if (valueRequired) {
codeStream.aload_0();
codeStream.fieldAccess(Opcodes.OPC_getfield, this.delegateThis, null /* default declaringClass */); // delegate field access
}
codeStream.recordPositionsFrom(pc, this.sourceStart);
}
/**
* @see org.eclipse.jdt.internal.compiler.lookup.InvocationSite#genericTypeArguments()
*/
@Override
public TypeBinding[] genericTypeArguments() {
return null;
}
@Override
public InferenceContext18 freshInferenceContext(Scope scope) {
return null;
}
@Override
public boolean isSuperAccess(){
return false;
}
@Override
public boolean isTypeAccess(){
return false;
}
@Override
public StringBuffer printExpression(int indent, StringBuffer output){
char[] declaringType = this.evaluationContext.declaringTypeName;
output.append('(');
if (declaringType == null)
output.append("<NO DECLARING TYPE>"); //$NON-NLS-1$
else
output.append(declaringType);
return output.append(")this"); //$NON-NLS-1$
}
@Override
public TypeBinding resolveType(BlockScope scope) {
// implicit this
this.constant = Constant.NotAConstant;
ReferenceBinding snippetType = scope.enclosingSourceType();
MethodScope methodScope = scope.methodScope();
if (!this.isImplicit && !checkAccess(scope, snippetType)) {
return null;
}
this.delegateThis = scope.getField(snippetType, DELEGATE_THIS, this);
if (this.delegateThis == null || !this.delegateThis.isValidBinding()) {
// should not happen
// if this happen we should report illegal access to this in a static context
methodScope.problemReporter().errorThisSuperInStatic(this);
return null;
}
return this.resolvedType = this.delegateThis.type;
}
@Override
public void setActualReceiverType(ReferenceBinding receiverType) {
// ignored
}
@Override
public void setDepth(int depth){
// ignored
}
@Override
public void setFieldIndex(int index){
// ignored
}
}
|