Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: ff85297f87f1ca83f31f9fa962411a70c099b1b5 (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
/*******************************************************************************
 * Copyright (c) 2005, 2007 BEA Systems, Inc.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *    tyeung@bea.com - initial API and implementation
 *******************************************************************************/

package org.eclipse.jdt.apt.core.internal.util;

import org.eclipse.jdt.apt.core.internal.NonEclipseImplementationException;
import org.eclipse.jdt.apt.core.internal.declaration.DeclarationImpl;
import org.eclipse.jdt.apt.core.internal.declaration.EclipseDeclarationImpl;
import org.eclipse.jdt.apt.core.internal.declaration.EclipseMirrorObject;
import org.eclipse.jdt.apt.core.internal.declaration.MemberDeclarationImpl;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.IPackageBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
import org.eclipse.jdt.core.dom.Modifier;

import com.sun.mirror.declaration.MemberDeclaration;
import com.sun.mirror.declaration.MethodDeclaration;
import com.sun.mirror.util.Declarations;

public class DeclarationsUtil implements Declarations
{
    @Override
	public boolean hides(MemberDeclaration sub, MemberDeclaration sup) {
		
		// A declaration cannot hide itself
		if (sub == sup || sub.equals(sup))
			return false;
		
		if( ! ((EclipseDeclarationImpl)sub).isBindingBased() ||  
			! ((EclipseDeclarationImpl)sup).isBindingBased() )
			return false;
		
		MemberDeclarationImpl subImpl = (MemberDeclarationImpl)sub;
		MemberDeclarationImpl supImpl = (MemberDeclarationImpl)sup;
		
		IBinding subBinding = subImpl.getDeclarationBinding();
		IBinding supBinding = supImpl.getDeclarationBinding();
		
		
		// Hiding can only take place between declarations of the same kind and name,
		// and types, variables and methods
		int subKind = subBinding.getKind();
		int supKind = supBinding.getKind();
		if (subKind != supKind || subKind == IBinding.PACKAGE)
			return false;
		if (!subBinding.getName().equals(supBinding.getName()))
			return false;
		
		// Methods must be both static and the sub a subsignature of the sup
		if (subKind == IBinding.METHOD) {
			boolean allowed = false;
			int modifiers = subBinding.getModifiers();
			if ((modifiers & Modifier.STATIC) == Modifier.STATIC) {
				IMethodBinding methodBinding = (IMethodBinding)subBinding;
				if (methodBinding.isSubsignature((IMethodBinding)supBinding)) {
					allowed = true;
				}
			}
			if (!allowed)
				return false;
		}
		
		// sub's enclosing class must be a subclass of sup's
		ITypeBinding subClass = getDeclaringClass(subBinding);
		ITypeBinding supClass = getDeclaringClass(supBinding);
		if (subClass == null || supClass == null)
			return false;
		if (!subClass.isSubTypeCompatible(supClass))
			return false;
		
		// sup must be visible from sub
		if (!isVisibleForHiding(supClass, supClass, supBinding.getModifiers()))
			return false;
		
		return true;
    }
	
	/**
	 * Is a method, field, type visible from the viewer?
	 * That is, do accessibility rules allow it? (public, protected, etc.)<P>
	 * 
	 * Note that we make an assumption about protected here since
	 * its use in hides() already determines that the declaringTarget
	 * must be a subclass of the declaringViewer.
	 */
	private static boolean isVisibleForHiding(
			final ITypeBinding declaringTarget, 
			final ITypeBinding declaringViewer, 
			final int modifiers) {
		
		// Public is always visible
		if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC)
			return true;
		if ((modifiers & Modifier.PRIVATE) == Modifier.PRIVATE) {
			// Must be the same class
			if (declaringTarget.equals(declaringViewer))
				return true;
			else
				return false;
		}
		if ((modifiers & Modifier.PROTECTED) == Modifier.PROTECTED) {
			// We've already checked for subclassing
			return true;
		}
		// Package-friendly (no accessibility modifier)
		// Classes must be in the same package
		IPackageBinding targetPackage = declaringTarget.getPackage();
		IPackageBinding viewerPackage = declaringViewer.getPackage();
		return targetPackage.equals(viewerPackage);
	}

    @Override
	public boolean overrides(MethodDeclaration sub, MethodDeclaration sup) {
        final IMethodBinding subBinding = (IMethodBinding)getBinding(sub);
        final IMethodBinding supBinding = (IMethodBinding)getBinding(sup);
        if(subBinding == null || supBinding == null) return false;
        return subBinding.overrides(supBinding);
    }

    private static IBinding getBinding(MemberDeclaration memberDecl)
        throws NonEclipseImplementationException
    {
        if( memberDecl == null ) return null;
        if( memberDecl instanceof EclipseMirrorObject ){
        	if( memberDecl instanceof DeclarationImpl )
        		return ((DeclarationImpl)memberDecl).getDeclarationBinding();
        	else
        		return null;
        }
        throw new NonEclipseImplementationException("only applicable to eclipse type system objects." + //$NON-NLS-1$
                                                    " Found " + memberDecl.getClass().getName()); //$NON-NLS-1$
    }
	
	private static ITypeBinding getDeclaringClass(IBinding binding) {
		int kind = binding.getKind();
		if (kind == IBinding.TYPE)
			return ((ITypeBinding)binding).getDeclaringClass();
		if (kind == IBinding.METHOD)
			return ((IMethodBinding)binding).getDeclaringClass();
		if (kind == IBinding.VARIABLE)
			return ((IVariableBinding)binding).getDeclaringClass();
		
		// Package binding -- no declaring class
		return null;
	}
}

Back to the top