Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 163b79939d7069f51c867e38224c904d0639fa66 (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
149
/*******************************************************************************
 * Copyright (c) 2000, 2014 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
 *     Stephan Herrmann - Contributions for
 *								bug 349326 - [1.7] new warning for missing try-with-resources
 *								bug 392384 - [1.8][compiler][null] Restore nullness info from type annotations in class files
 *								Bug 392099 - [1.8][compiler][null] Apply null annotation on types for null analysis
 *******************************************************************************/
package org.eclipse.jdt.internal.compiler.lookup;

import org.eclipse.jdt.core.compiler.CharOperation;

public class UnresolvedReferenceBinding extends ReferenceBinding {

ReferenceBinding resolvedType;
TypeBinding[] wrappers;
UnresolvedReferenceBinding prototype;

UnresolvedReferenceBinding(char[][] compoundName, PackageBinding packageBinding) {
	this.compoundName = compoundName;
	this.sourceName = compoundName[compoundName.length - 1]; // reasonable guess
	this.fPackage = packageBinding;
	this.wrappers = null;
	this.prototype = this;
	computeId();
}

public UnresolvedReferenceBinding(UnresolvedReferenceBinding prototype) {
	super(prototype);
	this.resolvedType = prototype.resolvedType;
	this.wrappers = null;
	this.prototype = prototype.prototype;
}

public TypeBinding clone(TypeBinding outerType) {
	if (this.resolvedType != null || this.depth() > 0)
		throw new IllegalStateException();
	UnresolvedReferenceBinding copy = new UnresolvedReferenceBinding(this);
	this.addWrapper(copy, null);
	return copy;
}

void addWrapper(TypeBinding wrapper, LookupEnvironment environment) {
	if (this.resolvedType != null) {
		// the type reference B<B<T>.M> means a signature of <T:Ljava/lang/Object;>LB<LB<TT;>.M;>;
		// when the ParameterizedType for Unresolved B is created with args B<T>.M, the Unresolved B is resolved before the wrapper is added
		wrapper.swapUnresolved(this, this.resolvedType, environment);
		return;
	}
	if (this.wrappers == null) {
		this.wrappers = new TypeBinding[] {wrapper};
	} else {
		int length = this.wrappers.length;
		System.arraycopy(this.wrappers, 0, this.wrappers = new TypeBinding[length + 1], 0, length);
		this.wrappers[length] = wrapper;
	}
}
public boolean isUnresolvedType() {
	return true;
}
public String debugName() {
	return toString();
}
public int depth() {
	// we don't yet have our enclosing types wired, but we know the nesting depth from our compoundName:
	int last = this.compoundName.length-1;
	return CharOperation.occurencesOf('$', this.compoundName[last]);
}
public boolean hasTypeBit(int bit) {
	// shouldn't happen since we are not called before analyseCode(), but play safe:
	return false;
}

public TypeBinding prototype() {
	return this.prototype;
}

ReferenceBinding resolve(LookupEnvironment environment, boolean convertGenericToRawType) {
	ReferenceBinding targetType;
	if (this != this.prototype) { //$IDENTITY-COMPARISON$
		targetType = this.prototype.resolve(environment, convertGenericToRawType);
		if (convertGenericToRawType && targetType != null && targetType.isRawType()) {
			targetType = (ReferenceBinding) environment.createAnnotatedType(targetType, this.typeAnnotations);
		} else {
			targetType = this.resolvedType;
		}
		return targetType;
	}
	targetType = this.resolvedType;
	if (targetType == null) {
		targetType = this.fPackage.getType0(this.compoundName[this.compoundName.length - 1]);
		if (targetType == this) { //$IDENTITY-COMPARISON$
			targetType = environment.askForType(this.compoundName);
		}
		if (targetType == null || targetType == this) { // could not resolve any better, error was already reported against it //$IDENTITY-COMPARISON$
			// report the missing class file first - only if not resolving a previously missing type
			if ((this.tagBits & TagBits.HasMissingType) == 0 && !environment.mayTolerateMissingType) {
				environment.problemReporter.isClassPathCorrect(
					this.compoundName,
					environment.unitBeingCompleted,
					environment.missingClassFileLocation);
			}
			// create a proxy for the missing BinaryType
			targetType = environment.createMissingType(null, this.compoundName);
		}
		setResolvedType(targetType, environment);
	}
	if (convertGenericToRawType) {
		targetType = (ReferenceBinding) environment.convertUnresolvedBinaryToRawType(targetType);
	}
	return targetType;
}
void setResolvedType(ReferenceBinding targetType, LookupEnvironment environment) {
	if (this.resolvedType == targetType) return; // already resolved //$IDENTITY-COMPARISON$

	// targetType may be a source or binary type
	this.resolvedType = targetType;
	environment.updateCaches(this, targetType);
	// must ensure to update any other type bindings that can contain the resolved type
	// otherwise we could create 2 : 1 for this unresolved type & 1 for the resolved type
	if (this.wrappers != null)
		for (int i = 0, l = this.wrappers.length; i < l; i++)
			this.wrappers[i].swapUnresolved(this, targetType, environment);
}

public void swapUnresolved(UnresolvedReferenceBinding unresolvedType, ReferenceBinding unannotatedType, LookupEnvironment environment) {
	if (this.resolvedType != null) return;
	ReferenceBinding annotatedType = (ReferenceBinding) unannotatedType.clone(null);
	this.resolvedType = annotatedType;
	annotatedType.setTypeAnnotations(getTypeAnnotations(), environment.globalOptions.isAnnotationBasedNullAnalysisEnabled);
	annotatedType.id = unannotatedType.id = this.id;
	environment.updateCaches(this, annotatedType);
	if (this.wrappers != null)
		for (int i = 0, l = this.wrappers.length; i < l; i++)
			this.wrappers[i].swapUnresolved(this, annotatedType, environment);
}

public String toString() {
	if (this.hasTypeAnnotations())
		return super.annotatedDebugName() + "(unresolved)"; //$NON-NLS-1$
	return "Unresolved type " + ((this.compoundName != null) ? CharOperation.toString(this.compoundName) : "UNNAMED"); //$NON-NLS-1$ //$NON-NLS-2$
}
}

Back to the top