Skip to main content
summaryrefslogtreecommitdiffstats
blob: be76447e59b7ff440213f1a535a29347122a6c91 (plain) (blame)
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
	}
}

Back to the top