Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 93565319794cb2cd5020c00f765ae7ec803a62c4 (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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
/*******************************************************************************
 * Copyright (c) 2008 Institute for Software, HSR Hochschule fuer Technik  
 * Rapperswil, University of applied sciences 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: 
 * Institute for Software - initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.internal.ui.refactoring;

import org.eclipse.cdt.core.dom.ast.DOMException;
import org.eclipse.cdt.core.dom.ast.IASTName;
import org.eclipse.cdt.core.dom.ast.IASTNode;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IBinding;
import org.eclipse.cdt.core.dom.ast.IScope;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTQualifiedName;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTVisiblityLabel;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType;
import org.eclipse.cdt.core.dom.ast.cpp.ICPPMember;
import org.eclipse.cdt.ui.CUIPlugin;

import org.eclipse.cdt.internal.core.dom.parser.ASTInternal;
import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPASTVisibilityLabel;
import org.eclipse.cdt.internal.core.dom.parser.cpp.ICPPInternalBinding;

/**
 * Represents a function or method and adds some useful helper methods to
 * determine if methods are in the same class.
 *
 */
public class MethodContext {
	public enum ContextType{ NONE, FUNCTION, METHOD }

	private ContextType type;
	private IASTName declarationName;
	private ICPPASTQualifiedName qname;

	public ContextType getType() {
		return type;
	}

	public void setType(ContextType type) {
		this.type = type;
	}

	public void setMethodDeclarationName(IASTName tmpname) {
		this.declarationName=tmpname;
	}

	public IASTName getMethodDeclarationName(){
		return declarationName;
	}
	
	public IASTSimpleDeclaration getMethodDeclaration(){
		IASTNode parent = declarationName.getParent().getParent();
		if (parent instanceof IASTSimpleDeclaration) {
			return (IASTSimpleDeclaration) parent;
		}
		return null;
	}
	
	public ICPPASTVisiblityLabel getMethodDeclarationASTVisibility(){
		ICPPASTVisiblityLabel label = new CPPASTVisibilityLabel();
		ICPPMember member = ((ICPPMember)qname.resolveBinding());			

		try {
			label.setVisibility(member.getVisibility());
		} catch (DOMException e) {
			CUIPlugin.log(e);
		}
		return label;
	}
	
	public Visibility getMethodDeclarationVisibility(){
		return Visibility.getVisibility(declarationName);
	}

	public void setMethodQName(ICPPASTQualifiedName qname) {
		this.qname = qname;
	}
	
	public ICPPASTQualifiedName getMethodQName() {
		return qname;
	}
	
	public static boolean isSameClass(ICPPASTQualifiedName qname1, ICPPASTQualifiedName qname2) {
		ICPPInternalBinding bind1 = getClassBinding(qname1);
		ICPPInternalBinding bind2 = getClassBinding(qname2);
		return isSameClass(bind1,bind2);
	}
	
	public static boolean isSameOrSubClass(MethodContext context1, MethodContext contextOfSameOrSubclass) {
		ICPPInternalBinding bind1 = getICPPInternalBinding(context1);
		ICPPInternalBinding subclassBind = getICPPInternalBinding(contextOfSameOrSubclass);
		if(isSameClass(bind1,subclassBind)){
			return true;
		}
		return isSubclass(bind1,subclassBind);
	}
	
	private static boolean isSubclass(ICPPInternalBinding bind1, ICPPInternalBinding subclassBind) {
		if (subclassBind instanceof ICPPClassType) {
			ICPPClassType classType = (ICPPClassType) subclassBind;
			ICPPBase[] bases;
			try {
				bases = classType.getBases();
			} catch (DOMException e) {
				return false;
			}
			for (ICPPBase base : bases) {
				if(isSameClass(base,bind1)){
					return true;
				}
			}
		}
		return false;
	}

	public static boolean isSameClass(MethodContext context1, MethodContext context2) {
		ICPPInternalBinding bind1 = getICPPInternalBinding(context1);
		ICPPInternalBinding bind2 = getICPPInternalBinding(context2);

		return isSameClass(bind1,bind2);
	}
	
	private static boolean isSameClass(ICPPBase base, ICPPInternalBinding bind2) {
		try {
			IBinding bind1 = base.getBaseClass();
			IScope scope1 = bind1.getScope();
			if(scope1 == null)
				return false;
			IASTNode node1 = ASTInternal.getPhysicalNodeOfScope(scope1);
			
			IScope scope2 = bind2.getScope();
			if(scope2 == null)
				return false;
			IASTNode node2 = ASTInternal.getPhysicalNodeOfScope(scope2);
			
			if( node1.equals(node2) ){
				if (bind1 instanceof ICPPInternalBinding) {
					ICPPInternalBinding bind1int = (ICPPInternalBinding) bind1;
					return bind1int.getDefinition().equals(bind2.getDefinition());
				}
				return false;
			}
			return false;
		} catch (DOMException e) {
			return false;
		}	
	}
	
	private static boolean isSameClass(ICPPInternalBinding bind1, ICPPInternalBinding bind2) {
		try {
			IScope scope1 = bind1.getScope();
			if(scope1 == null)
				return false;
			IASTNode node1 = ASTInternal.getPhysicalNodeOfScope(scope1);
			
			IScope scope2 = bind2.getScope();
			if(scope2 == null)
				return false;
			IASTNode node2 = ASTInternal.getPhysicalNodeOfScope(scope2);
			
			if( node1.equals(node2) ){
				return bind1.getDefinition().equals(bind2.getDefinition());
			}
			return false;
		} catch (DOMException e) {
			return false;
		}	
	}
	
	public static ICPPInternalBinding getICPPInternalBinding(MethodContext context) {
		IASTName decl = context.getMethodDeclarationName();
		IASTNode node = decl;
		while(node != null){
			if (node instanceof ICPPASTCompositeTypeSpecifier) {
				ICPPASTCompositeTypeSpecifier type = (ICPPASTCompositeTypeSpecifier) node;
				IASTName classname = type.getName();
				ICPPInternalBinding bind = (ICPPInternalBinding)classname.resolveBinding();
				 
				return bind;
			}
			
			node = node.getParent();
		}
		
		return null;
	}
	
	private static ICPPInternalBinding getClassBinding(ICPPASTQualifiedName qname){
		IASTName classname = qname.getNames()[qname.getNames().length - 2];
		ICPPInternalBinding bind = (ICPPInternalBinding)classname.resolveBinding(); 
		return bind;
	}
}

Back to the top