1 package com.stateofflow.eclipse.metrics.calculators.cohesion;
2
3 import org.eclipse.jdt.core.IJavaElement;
4 import org.eclipse.jdt.core.IMethod;
5 import org.eclipse.jdt.core.IType;
6 import org.eclipse.jdt.core.JavaModelException;
7
8 final class ReferencedFieldResultCollector extends FieldResultCollector {
9 private final DeclaredFieldResultCollector declaredFields;
10
11 public ReferencedFieldResultCollector(final String source, final DeclaredFieldResultCollector declaredFields) {
12 super(source);
13 this.declaredFields = declaredFields;
14 }
15
16 @Override
17 protected void acceptSearchMatch(final IJavaElement element, final int start, final int end) throws JavaModelException {
18 addReferencedField(element, start, end);
19 }
20
21 private void addReferencedField(final IJavaElement enclosingElement, final int start, final int end) {
22 if (!isInterestingFieldReference(start, end, enclosingElement, declaredFields)) {
23 return;
24 }
25
26 addField(findMethod(enclosingElement), start, end);
27 }
28
29 private IJavaElement findMethod(final IJavaElement enclosingElement) {
30 IJavaElement enclosingMethod = enclosingElement;
31 if (isMethod(enclosingElement)) {
32 enclosingMethod = enclosingElement.getAncestor(IJavaElement.METHOD);
33 }
34 return enclosingMethod;
35 }
36
37 private boolean isInterestingFieldReference(final int start, final int end, final IJavaElement enclosingElement, final DeclaredFieldResultCollector declaredFields) {
38 return isFieldAccessWithinMethod(start, end, enclosingElement, declaredFields) && isReferenceToDeclaredField(start);
39 }
40
41 private boolean isReferenceToDeclaredField(final int start) {
42 final int dot = getSource().findPreviousNonWhitespaceIndex(start - 1);
43 if (getSource().getCharAt(dot) != '.') {
44 return true;
45 }
46
47 final int thisEnd = getSource().findPreviousNonWhitespaceIndex(dot - 1);
48 return "this".equals(getSource().getSection(thisEnd - 4, thisEnd));
49 }
50
51 private boolean isFieldAccessWithinMethod(final int start, final int end, final IJavaElement enclosingElement, final DeclaredFieldResultCollector declaredFields) {
52 return isMethod(enclosingElement) && declaredFields.hasFieldInEnclosingType(enclosingElement, start, end);
53 }
54
55 private boolean isMethod(final IJavaElement enclosingElement) {
56 return enclosingElement.getElementType() == IJavaElement.METHOD;
57 }
58
59 public ClassComposition getFieldSets(final IType type) {
60 final ClassComposition composition = new ClassComposition();
61 for (final IJavaElement element : getKeys()) {
62 final IMethod method = (IMethod) element;
63 if (method.getAncestor(IJavaElement.TYPE).equals(type)) {
64 composition.addMethod(getFields(method));
65 }
66 }
67
68 return composition;
69 }
70 }
71