/* * SonarLint for Eclipse * Copyright (C) 2015-2017 SonarSource SA * sonarlint@sonarsource.com * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 3 of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package org.sonarlint.eclipse.core.internal.resources; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Objects; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IResourceVisitor; import org.sonarlint.eclipse.core.internal.adapter.Adapters; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.team.core.RepositoryProvider; import org.eclipse.team.core.TeamException; import org.eclipse.team.core.subscribers.Subscriber; import org.eclipse.team.core.synchronize.SyncInfo; import org.sonarlint.eclipse.core.SonarLintLogger; import org.sonarlint.eclipse.core.internal.SonarLintCorePlugin; import org.sonarlint.eclipse.core.internal.utils.SonarLintUtils; import org.sonarlint.eclipse.core.resource.ISonarLintFile; import org.sonarlint.eclipse.core.resource.ISonarLintProject; public class DefaultSonarLintProjectAdapter implements ISonarLintProject { private static final String UNABLE_TO_ANALYZE_CHANGED_FILES = "Unable to collect changed files"; private final IProject project; public DefaultSonarLintProjectAdapter(IProject project) { this.project = project; } @Override public String getName() { return project.getName(); } @Override public Path getWorkingDir() { return project.getWorkingLocation(SonarLintCorePlugin.PLUGIN_ID).toFile().toPath(); } @Override public boolean exists(String relativeFilePath) { return project.getFile(relativeFilePath).exists(); } @Override public Object getObjectToNotify() { return project; } @Override public Collection<ISonarLintFile> files() { List<ISonarLintFile> result = new ArrayList<>(); try { project.accept(new IResourceVisitor() { @Override public boolean visit(IResource resource) throws CoreException { if (!SonarLintUtils.shouldAnalyze(resource)) { return false; } ISonarLintFile sonarLintFile = Adapters.adapt(resource, ISonarLintFile.class); if (sonarLintFile != null) { result.add(sonarLintFile); } return true; } }); } catch (CoreException e) { SonarLintLogger.get().error("Error collecting files in project " + project.getName(), e); } return result; } public String getNoScmSupportCause() { RepositoryProvider provider = RepositoryProvider.getProvider(project); if (provider == null) { return "No SCM for project '" + project.getName() + "'"; } else if (provider.getSubscriber() == null) { return "Unsupported SCM for project '" + project.getName() + "'"; } else { return null; } } public Collection<ISonarLintFile> getScmChangedFiles(IProgressMonitor monitor) { List<ISonarLintFile> result = new ArrayList<>(); RepositoryProvider provider = RepositoryProvider.getProvider(project); if (provider == null) { SonarLintLogger.get().debug("Project " + project.getName() + " doesn't have any RepositoryProvider"); return result; } Subscriber subscriber = provider.getSubscriber(); if (subscriber == null) { // Some providers (like Clear Case SCM Adapter) don't provide a Subscriber. SonarLintLogger.get().debug("No Subscriber for provider " + provider.getID() + " on project " + project.getName()); return result; } try { IResource[] roots = subscriber.roots(); if (Arrays.asList(roots).contains(project)) { // Refresh subscriber.refresh(new IResource[] {project}, IResource.DEPTH_INFINITE, monitor); // Collect all the synchronization states and print collect(subscriber, project, result); } else { SonarLintLogger.get().debug("Project " + project.getName() + " is not part of Subscriber roots"); } } catch (TeamException e) { throw new IllegalStateException(UNABLE_TO_ANALYZE_CHANGED_FILES, e); } return result; } private static void collect(Subscriber subscriber, IResource resource, Collection<ISonarLintFile> changedFiles) throws TeamException { IFile file = Adapters.adapt(resource, IFile.class); if (file != null) { ISonarLintFile sonarLintFile = Adapters.adapt(file, ISonarLintFile.class); if (sonarLintFile != null) { SyncInfo syncInfo = subscriber.getSyncInfo(resource); if (syncInfo != null && !SyncInfo.isInSync(syncInfo.getKind())) { changedFiles.add(sonarLintFile); } } } else { for (IResource child : subscriber.members(resource)) { collect(subscriber, child, changedFiles); } } } @Override public ISonarLintProject getProject() { return this; } @Override public IResource getResource() { return project; } @Override public int hashCode() { return project.hashCode(); } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } DefaultSonarLintProjectAdapter other = (DefaultSonarLintProjectAdapter) obj; return Objects.equals(project, other.project); } }