/*
* Copyright 2005-2016 Sixth and Red River Software, Bas Leijdekkers
*
* 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.sixrr.metrics.metricModel;
import com.intellij.analysis.AnalysisScope;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiCompiledElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.sixrr.metrics.Metric;
import com.sixrr.metrics.MetricCalculator;
import com.sixrr.metrics.MetricsExecutionContext;
import com.sixrr.metrics.MetricsResultsHolder;
import com.sixrr.metrics.profile.MetricInstance;
import com.sixrr.metrics.profile.MetricsProfile;
import com.sixrr.metrics.utils.MetricsReloadedBundle;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MetricsExecutionContextImpl implements MetricsExecutionContext {
private final Project project;
private final AnalysisScope scope;
public MetricsExecutionContextImpl(Project project, AnalysisScope scope) {
this.project = project;
this.scope = scope;
}
public final void execute(final MetricsProfile profile, final MetricsResultsHolder resultsHolder) {
final Task.Backgroundable task = new Task.Backgroundable(project,
MetricsReloadedBundle.message("calculating.metrics"), true) {
@Override
public void run(@NotNull final ProgressIndicator indicator) {
calculateMetrics(profile, resultsHolder);
}
@Override
public void onSuccess() {
onFinish();
}
@Override
public void onCancel() {
MetricsExecutionContextImpl.this.onCancel();
}
};
task.queue();
}
public void calculateMetrics(MetricsProfile profile, final MetricsResultsHolder resultsHolder) {
final ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
final List<MetricInstance> metrics = profile.getMetricInstances();
indicator.setText(MetricsReloadedBundle.message("initializing.progress.string"));
final int numFiles = scope.getFileCount();
final int numMetrics = metrics.size();
final List<MetricCalculator> calculators = new ArrayList<MetricCalculator>(numMetrics);
for (final MetricInstance metricInstance : metrics) {
indicator.checkCanceled();
if (!metricInstance.isEnabled()) {
continue;
}
final Metric metric = metricInstance.getMetric();
final MetricCalculator calculator = metric.createCalculator();
calculators.add(calculator);
calculator.beginMetricsRun(metric, resultsHolder, this);
}
scope.accept(new PsiElementVisitor() {
private int mainTraversalProgress = 0;
@Override
public void visitFile(PsiFile file) {
super.visitFile(file);
if (file instanceof PsiCompiledElement) {
return;
}
final FileType fileType = file.getFileType();
if (fileType.isBinary()) {
return;
}
final VirtualFile virtualFile = file.getVirtualFile();
final ProjectRootManager rootManager = ProjectRootManager.getInstance(file.getProject());
final ProjectFileIndex fileIndex = rootManager.getFileIndex();
if (fileIndex.isExcluded(virtualFile) || !fileIndex.isInContent(virtualFile)) {
return;
}
final String fileName = file.getName();
indicator.setText(MetricsReloadedBundle.message("analyzing.progress.string", fileName));
mainTraversalProgress++;
for (MetricCalculator calculator : calculators) {
calculator.processFile(file);
}
indicator.setFraction((double) mainTraversalProgress / (double) numFiles);
}
});
indicator.setText(MetricsReloadedBundle.message("tabulating.results.progress.string"));
for (MetricCalculator calculator : calculators) {
indicator.checkCanceled();
calculator.endMetricsRun();
}
}
public void onFinish() {}
public void onCancel() {}
@Override
public final Project getProject() {
return project;
}
@Override
public final AnalysisScope getScope() {
return scope;
}
private Map userData = new HashMap();
@Override
public final <T> T getUserData(@NotNull Key<T> key) {
return (T) userData.get(key);
}
@Override
public final <T> void putUserData(@NotNull Key<T> key, T t) {
userData.put(key, t);
}
}