1 /******************************************************************************* 2 * Copyright (c) 2008, 2013 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 package org.eclipse.pde.api.tools.internal.builder; 15 16 import java.util.Set; 17 18 import org.eclipse.core.runtime.CoreException; 19 import org.eclipse.jdt.core.Flags; 20 import org.eclipse.jdt.core.IField; 21 import org.eclipse.jdt.core.ISourceRange; 22 import org.eclipse.jdt.core.IType; 23 import org.eclipse.jface.text.BadLocationException; 24 import org.eclipse.jface.text.IDocument; 25 import org.eclipse.jface.text.Position; 26 import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin; 27 import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations; 28 import org.eclipse.pde.api.tools.internal.provisional.IApiDescription; 29 import org.eclipse.pde.api.tools.internal.provisional.RestrictionModifiers; 30 import org.eclipse.pde.api.tools.internal.provisional.builder.IReference; 31 import org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor; 32 import org.eclipse.pde.api.tools.internal.provisional.model.IApiField; 33 import org.eclipse.pde.api.tools.internal.provisional.model.IApiType; 34 import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblem; 35 import org.eclipse.pde.api.tools.internal.provisional.problems.IApiProblemTypes; 36 37 /** 38 * Detects leaked field declarations (declared type). 39 * 40 * @since 1.1 41 */ 42 public class LeakFieldProblemDetector extends AbstractTypeLeakDetector { 43 44 /** 45 * @param nonApiPackageNames 46 */ LeakFieldProblemDetector(Set<String> nonApiPackageNames)47 public LeakFieldProblemDetector(Set<String> nonApiPackageNames) { 48 super(nonApiPackageNames); 49 } 50 51 @Override isApplicable(IApiAnnotations annotations)52 protected boolean isApplicable(IApiAnnotations annotations) { 53 return super.isApplicable(annotations) && !RestrictionModifiers.isReferenceRestriction(annotations.getRestrictions()); 54 } 55 56 @Override getReferenceKinds()57 public int getReferenceKinds() { 58 return IReference.REF_FIELDDECL; 59 } 60 61 @Override getElementType(IReference reference)62 protected int getElementType(IReference reference) { 63 return IElementDescriptor.FIELD; 64 } 65 66 @Override getSeverityKey()67 protected String getSeverityKey() { 68 return IApiProblemTypes.LEAK_FIELD_DECL; 69 } 70 71 @Override getProblemFlags(IReference reference)72 protected int getProblemFlags(IReference reference) { 73 return IApiProblem.LEAK_FIELD; 74 } 75 76 @Override isProblem(IReference reference)77 protected boolean isProblem(IReference reference) { 78 if (super.isProblem(reference)) { 79 IApiField field = (IApiField) reference.getMember(); 80 if ((Flags.AccProtected & field.getModifiers()) > 0) { 81 // TODO: could do this check before resolution - it's a check on 82 // the source location 83 // ignore protected members if contained in a @noextend type 84 try { 85 IApiDescription description = field.getApiComponent().getApiDescription(); 86 IApiAnnotations annotations = description.resolveAnnotations(field.getHandle().getEnclosingType()); 87 if (annotations == null || RestrictionModifiers.isExtendRestriction(annotations.getRestrictions())) { 88 return false; 89 } 90 } catch (CoreException e) { 91 ApiPlugin.log(e); 92 } 93 } 94 return true; 95 } 96 return false; 97 } 98 99 @Override getMessageArgs(IReference reference)100 protected String[] getMessageArgs(IReference reference) throws CoreException { 101 IApiField field = (IApiField) reference.getMember(); 102 IApiType type = (IApiType) reference.getResolvedReference(); 103 return new String[] { 104 getSimpleTypeName(type), getSimpleTypeName(field), 105 field.getName() }; 106 } 107 108 @Override getQualifiedMessageArgs(IReference reference)109 protected String[] getQualifiedMessageArgs(IReference reference) throws CoreException { 110 IApiField field = (IApiField) reference.getMember(); 111 IApiType type = (IApiType) reference.getResolvedReference(); 112 return new String[] { 113 getQualifiedTypeName(type), getQualifiedTypeName(field), 114 field.getName() }; 115 } 116 117 @Override getSourceRange(IType type, IDocument doc, IReference reference)118 protected Position getSourceRange(IType type, IDocument doc, IReference reference) throws CoreException, BadLocationException { 119 IApiField field = (IApiField) reference.getMember(); 120 IField javaField = type.getField(field.getName()); 121 Position pos = null; 122 if (javaField.exists()) { 123 ISourceRange range = javaField.getNameRange(); 124 if (range != null) { 125 pos = new Position(range.getOffset(), range.getLength()); 126 } 127 } 128 if (pos == null) { 129 return defaultSourcePosition(type, reference); 130 } 131 return pos; 132 } 133 } 134