Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: c03863f0ddd8efbae12f67213951caa2f083f5f9 (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
/*******************************************************************************
 * Copyright (c) 2007, 2010 Symbian Software Systems 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:
 *     Andrew Ferguson (Symbian) - Initial implementation
 *     Markus Schorn (Wind River Systems)
 *******************************************************************************/
package org.eclipse.cdt.internal.core.index.composite;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPSpecialization;
import org.eclipse.cdt.core.index.IIndexFileSet;
import org.eclipse.cdt.core.index.IIndexName;
import org.eclipse.cdt.internal.core.dom.parser.ProblemBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPCompositeBinding;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPUsingDeclaration;
import org.eclipse.cdt.internal.core.index.IIndexFragmentBinding;
import org.eclipse.cdt.internal.core.index.IIndexScope;

public abstract class CompositeScope implements IIndexScope {
	/**
	 * The factory used for obtaining further composite bindings
	 */
	protected final ICompositesFactory cf;
	/**
	 * The representative binding for this composite binding. Most cases are simple
	 * enough that this becomes a delegate, some need to use it as a search key over fragments,
	 * and some ignore it as a representative binding from each fragment is needed to meet interface
	 * contracts.
	 */
	protected final IIndexFragmentBinding rbinding;

	public CompositeScope(ICompositesFactory cf, IIndexFragmentBinding rbinding) {
		if (cf == null || rbinding == null)
			throw new NullPointerException();
		this.cf = cf;
		this.rbinding = rbinding;
	}
	
	@Override
	public IIndexScope getParent() {
		IIndexScope rscope = rbinding.getScope();
		if (rscope != null) {
			return cf.getCompositeScope(rscope);
		}
		return null;
	}

	@Override
	public IIndexName getScopeName() {
		if (rbinding instanceof IIndexScope)
			return ((IIndexScope) rbinding).getScopeName();
		if (rbinding instanceof ICPPClassType) 
			return (IIndexName) ((ICPPClassType) rbinding).getCompositeScope().getScopeName();
		return null;
	}

	protected final void fail() {
		throw new CompositingNotImplementedError();
	}
	
	
	public IBinding getRawScopeBinding() {
		return rbinding;
	}
	
	/**
	 * For bindings that are not known statically to be index bindings, we must decide how to
	 * process them by run-time type. This method processes a single binding accordingly.
	 * @param binding a binding from the fragment layer
	 * @return a suitable binding at the composite layer 
	 */
	protected final IBinding processUncertainBinding(IBinding binding) {
		if (binding instanceof IIndexFragmentBinding) {
			return cf.getCompositeBinding((IIndexFragmentBinding)binding);				
		} else if (binding instanceof ProblemBinding) {
			return binding;
		} else if (binding instanceof CPPCompositeBinding /* AST composite */) {
			return new CPPCompositeBinding(
				processUncertainBindings(((CPPCompositeBinding) binding).getBindings())
			);
		} else if (binding instanceof CPPUsingDeclaration) {
			return binding;
		} else if (binding == null) {
			return null;
		} else if (binding instanceof ICPPSpecialization) {
			return binding;
		}
		CCorePlugin.log("CompositeFactory unsure how to process: " + binding.getClass().getName()); //$NON-NLS-1$
		return binding;
	}
	
	/**
	 * A convenience method for processing an array of bindings with {@link CompositeScope#processUncertainBinding(IBinding)}
     * Returns an empty array if the input parameter is null
	 * @param frgBindings
	 * @return a non-null IBinding[] 
	 */
	protected final IBinding[] processUncertainBindings(IBinding[] frgBindings) {
		if (frgBindings != null) {
			IBinding[] result= new IBinding[frgBindings.length];
			for(int i= 0; i < result.length; i++) {
				result[i]= processUncertainBinding(frgBindings[i]);
			}
			return result;
		}
		return IBinding.EMPTY_BINDING_ARRAY;
	}

	@Override
	public final IBinding getBinding(IASTName name, boolean resolve) {
		return getBinding(name, resolve, IIndexFileSet.EMPTY);
	}

	@Override
	public final IBinding[] getBindings(IASTName name, boolean resolve, boolean prefix) {
		return getBindings(new ScopeLookupData(name, resolve, prefix));
	}
	
	/**
	 * The c++-name resolution stores scopes in hash-maps, we need to make sure equality is detected
	 * in order to prevent infinite loops.
	 */
	@Override
	public final boolean equals(Object other) {
		if (other instanceof CompositeScope) {
			return rbinding.equals(((CompositeScope)other).rbinding);
		}
		return false;
	}
	
	/**
	 * The c++-name resolution stores scopes in hash-maps, we need to make sure equality is detected
	 * in order to prevent infinite loops.
	 */
	@Override
	public final int hashCode() {
		return rbinding.hashCode();
	}
}

Back to the top