blob: 9d532e8d78b628057faaf7d15142b2b007ccf824 [file] [log] [blame]
/*
* Copyright 2003-2005 Dave Griffith
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ig.classmetrics;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.LibraryUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
class CouplingVisitor extends JavaRecursiveElementVisitor {
private boolean m_inClass = false;
private final PsiClass m_class;
private final boolean m_includeJavaClasses;
private final boolean m_includeLibraryClasses;
private final Set<String> m_dependencies = new HashSet<String>(10);
CouplingVisitor(PsiClass aClass, boolean includeJavaClasses,
boolean includeLibraryClasses) {
super();
m_class = aClass;
m_includeJavaClasses = includeJavaClasses;
m_includeLibraryClasses = includeLibraryClasses;
}
@Override
public void visitField(@NotNull PsiField field) {
super.visitField(field);
final PsiType type = field.getType();
addDependency(type);
}
@Override
public void visitLocalVariable(@NotNull PsiLocalVariable var) {
super.visitLocalVariable(var);
final PsiType type = var.getType();
addDependency(type);
}
@Override
public void visitMethod(@NotNull PsiMethod method) {
super.visitMethod(method);
final PsiType returnType = method.getReturnType();
addDependency(returnType);
addDependenciesForParameters(method);
addDependenciesForThrowsList(method);
}
private void addDependenciesForThrowsList(PsiMethod method) {
final PsiReferenceList throwsList = method.getThrowsList();
final PsiClassType[] throwsTypes = throwsList.getReferencedTypes();
for (PsiClassType throwsType : throwsTypes) {
addDependency(throwsType);
}
}
private void addDependenciesForParameters(PsiMethod method) {
final PsiParameterList parameterList = method.getParameterList();
final PsiParameter[] parameters = parameterList.getParameters();
for (PsiParameter parameter : parameters) {
final PsiType parameterType = parameter.getType();
addDependency(parameterType);
}
}
@Override
public void visitNewExpression(@NotNull PsiNewExpression exp) {
super.visitNewExpression(exp);
final PsiType classType = exp.getType();
addDependency(classType);
}
@Override
public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression exp) {
super.visitClassObjectAccessExpression(exp);
final PsiTypeElement operand = exp.getOperand();
final PsiType classType = operand.getType();
addDependency(classType);
}
@Override
public void visitClass(@NotNull PsiClass aClass) {
final boolean wasInClass = m_inClass;
if (!m_inClass) {
m_inClass = true;
super.visitClass(aClass);
}
m_inClass = wasInClass;
final PsiType[] superTypes = aClass.getSuperTypes();
for (PsiType superType : superTypes) {
addDependency(superType);
}
}
@Override
public void visitTryStatement(@NotNull PsiTryStatement statement) {
super.visitTryStatement(statement);
final PsiParameter[] catchBlockParameters = statement.getCatchBlockParameters();
for (PsiParameter catchBlockParameter : catchBlockParameters) {
final PsiType catchType = catchBlockParameter.getType();
addDependency(catchType);
}
}
@Override
public void visitInstanceOfExpression(@NotNull PsiInstanceOfExpression exp) {
super.visitInstanceOfExpression(exp);
final PsiTypeElement checkType = exp.getCheckType();
if (checkType == null) {
return;
}
final PsiType classType = checkType.getType();
addDependency(classType);
}
@Override
public void visitTypeCastExpression(@NotNull PsiTypeCastExpression exp) {
super.visitTypeCastExpression(exp);
final PsiTypeElement castType = exp.getCastType();
if (castType == null) {
return;
}
final PsiType classType = castType.getType();
addDependency(classType);
}
private void addDependency(PsiType type) {
if (type == null) {
return;
}
final PsiType baseType = type.getDeepComponentType();
if (ClassUtils.isPrimitive(type)) {
return;
}
final String qualifiedName = m_class.getQualifiedName();
if (qualifiedName == null) {
return;
}
if (baseType.equalsToText(qualifiedName)) {
return;
}
final String baseTypeName = baseType.getCanonicalText();
@NonNls final String javaPrefix = "java.";
@NonNls final String javaxPrefix = "javax.";
if (!m_includeJavaClasses &&
(baseTypeName.startsWith(javaPrefix) ||
baseTypeName.startsWith(javaxPrefix))) {
return;
}
if (!m_includeLibraryClasses) {
final Project project = m_class.getProject();
final GlobalSearchScope searchScope = GlobalSearchScope.allScope(project);
final PsiClass aClass = JavaPsiFacade.getInstance(project).findClass(baseTypeName, searchScope);
if (aClass == null) {
return;
}
if (LibraryUtil.classIsInLibrary(aClass)) {
return;
}
}
if (StringUtil.startsWithConcatenation(baseTypeName, qualifiedName, ".")) {
return;
}
m_dependencies.add(baseTypeName);
}
public int getNumDependencies() {
return m_dependencies.size();
}
}