package ru.naumen.gintonic.guice.analyzer; import java.util.Arrays; import java.util.List; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.IPackageBinding; import org.eclipse.jdt.core.dom.ITypeBinding; import ru.naumen.gintonic.GinTonicPlugin; import ru.naumen.gintonic.guice.GuiceModule; import ru.naumen.gintonic.guice.statements.BindingDefinition; import ru.naumen.gintonic.guice.statements.GuiceStatement; import ru.naumen.gintonic.guice.statements.InstallModuleStatement; import ru.naumen.gintonic.project.source.references.SourceCodeReference; import ru.naumen.gintonic.utils.ASTParserUtils; import ru.naumen.gintonic.utils.ICompilationUnitUtils; import ru.naumen.gintonic.utils.SetUtils; public class GuiceAnalyzer { //@formatter:off private static Set<String> supportedGuiceTypes = SetUtils.immutableSetOf( "AbstractModule", "PrivateModule", "AbstractGinModule"); //@formatter:on /** * Analyzes the given file it is a Guice Module (see {@link ITypeBindingUtils#isGuiceModuleType(ITypeBinding)). * * @return the {@link GuiceModule} or null if it is not a guice module. */ public GuiceModule index(IProject project, IFile file) { if (!file.exists()) { return null; } String filename = file.getName(); /* * We have to reject non java files (like binary .class files). Note to * the developer: If you remove this check the following call to * * <pre> ICompilationUnit compilationUnit = (ICompilationUnit) * JavaCore.create(file); </pre> * * can fail with a ClassCastException. */ if (!filename.endsWith(ICompilationUnitUtils.JAVA_EXTENSION)) { return null; } try { ICompilationUnit compilationUnit = JavaCore.createCompilationUnitFrom(file); if (compilationUnit == null) { return null; } IType primaryType = compilationUnit.findPrimaryType(); if (primaryType == null) { return null; } String superclassName = primaryType.getSuperclassName(); if (superclassName == null) { return null; } if (supportedGuiceTypes.contains(superclassName)) { return parseGuiceModule(compilationUnit, project); } // TODO Maybe slow IType[] allClasses = primaryType.newSupertypeHierarchy(null).getAllClasses(); for(IType clazz : allClasses) { if(supportedGuiceTypes.contains(clazz.getElementName())) { return parseGuiceModule(compilationUnit, project); } } } catch (Exception e) { GinTonicPlugin.logException("Error analyzing " + filename, e); } return null; } private GuiceModule parseGuiceModule(ICompilationUnit compilationUnit, IProject project) { CompilationUnit cu = ASTParserUtils.parseCompilationUnitAst3(compilationUnit, true, true); /* * No need to fail if there are errors in the compilationUnit, as it * works also with some errors (tested multiple times and sure it * depends on the type of the error). */ GuiceAnalyzerAstVisitor astVisitor = new GuiceAnalyzerAstVisitor(); try { cu.accept(astVisitor); } catch (Exception exception) { String message = "Unable to analyze '" + compilationUnit.getElementName() + "'"; GinTonicPlugin.logException(message, exception); return null; } ITypeBinding guiceModuleAsTypeBinding = astVisitor.getGuiceModuleTypeBinding(); IPackageBinding packageBinding = guiceModuleAsTypeBinding.getPackage(); String[] packageFullyQualified = packageBinding.getNameComponents(); String guiceModuleName = guiceModuleAsTypeBinding.getName(); String projectName = project.getName(); List<String> srcFolderPath = ICompilationUnitUtils.getSrcFolderPathComponents(compilationUnit); SourceCodeReference sourceCodeReferenceToGuiceModule = new SourceCodeReference(); sourceCodeReferenceToGuiceModule.setProjectName(projectName); sourceCodeReferenceToGuiceModule.setPackageNameComponents(Arrays.asList(packageFullyQualified)); sourceCodeReferenceToGuiceModule.setSrcFolderPathComponents(srcFolderPath); sourceCodeReferenceToGuiceModule.setPrimaryTypeName(guiceModuleName); List<BindingDefinition> bindingStatements = astVisitor.getBindingStatements(); for (BindingDefinition bindingStatement : bindingStatements) { copyInfo(sourceCodeReferenceToGuiceModule, bindingStatement); } List<InstallModuleStatement> installModuleStatements = astVisitor.getInstallModuleStatements(); for (InstallModuleStatement installModuleStatement : installModuleStatements) { copyInfo(sourceCodeReferenceToGuiceModule, installModuleStatement); } return new GuiceModule(sourceCodeReferenceToGuiceModule, installModuleStatements, bindingStatements); } private void copyInfo(SourceCodeReference guiceModule, GuiceStatement statement) { SourceCodeReference statementReference = statement.getSourceCodeReference(); statementReference.setProjectName(guiceModule.getProjectName()); statementReference.setPackageNameComponents(guiceModule.getPackageNameComponents()); statementReference.setSrcFolderPathComponents(guiceModule.getSrcFolderPathComponents()); statementReference.setPrimaryTypeName(guiceModule.getPrimaryTypeName()); } }