blob: fb782db28cd472fdff6028a9b62d78c73ef3ee1a [file] [log] [blame]
/*
* Copyright 2000-2013 JetBrains s.r.o.
*
* 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.intellij.execution.filters;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("ForLoopReplaceableByForEach")
public class CompositeFilter implements Filter, FilterMixin {
private static final Logger LOG = Logger.getInstance(CompositeFilter.class);
private final List<Filter> myFilters = new ArrayList<Filter>();
private boolean myIsAnyHeavy;
private boolean forceUseAllFilters = false;
private final DumbService myDumbService;
public CompositeFilter(@NotNull Project project) {
myDumbService = DumbService.getInstance(project);
}
protected CompositeFilter(DumbService dumbService) {
myDumbService = dumbService;
}
@Override
@Nullable
public Result applyFilter(final String line, final int entireLength) {
final boolean dumb = myDumbService.isDumb();
List<Filter> filters = myFilters;
int count = filters.size();
List<ResultItem> resultItems = null;
for (int i = 0; i < count; i++) {
Filter filter = filters.get(i);
if (!dumb || DumbService.isDumbAware(filter)) {
long t0 = System.currentTimeMillis();
Result result;
try {
result = filter.applyFilter(line, entireLength);
}
catch (Throwable t) {
throw new RuntimeException("Error while applying " + filter + " to '" + line + "'", t);
}
resultItems = merge(resultItems, result);
t0 = System.currentTimeMillis() - t0;
if (t0 > 1000) {
LOG.warn(filter.getClass().getSimpleName() + ".applyFilter() took " + t0 + " ms on '''" + line + "'''");
}
if (shouldStopFiltering(result)) {
break;
}
}
}
return createFinalResult(resultItems);
}
@Nullable
private static Result createFinalResult(@Nullable List<ResultItem> resultItems) {
if (resultItems == null) {
return null;
}
if (resultItems.size() == 1) {
ResultItem resultItem = resultItems.get(0);
return new Result(resultItem.getHighlightStartOffset(), resultItem.getHighlightEndOffset(), resultItem.getHyperlinkInfo(),
resultItem.getHighlightAttributes());
}
return new Result(resultItems);
}
private boolean shouldStopFiltering(@Nullable Result result) {
return result != null && result.getNextAction() == NextAction.EXIT && !forceUseAllFilters;
}
@Nullable
protected List<ResultItem> merge(@Nullable List<ResultItem> resultItems, @Nullable Result newResult) {
if (newResult != null) {
if (resultItems == null) {
resultItems = new ArrayList<ResultItem>();
}
List<ResultItem> newItems = newResult.getResultItems();
for (int i = 0; i < newItems.size(); i++) {
ResultItem item = newItems.get(i);
if (item.getHyperlinkInfo() == null || !intersects(resultItems, item)) {
resultItems.add(item);
}
}
}
return resultItems;
}
protected boolean intersects(List<ResultItem> items, ResultItem newItem) {
TextRange newItemTextRange = null;
for (int i = 0; i < items.size(); i++) {
ResultItem item = items.get(i);
if (item.getHyperlinkInfo() != null) {
if (newItemTextRange == null) {
newItemTextRange = new TextRange(newItem.highlightStartOffset, newItem.highlightEndOffset);
}
if (newItemTextRange.intersectsStrict(item.highlightStartOffset, item.highlightEndOffset)) {
return true;
}
}
}
return false;
}
@Override
public boolean shouldRunHeavy() {
for (Filter filter : myFilters) {
if (filter instanceof FilterMixin && ((FilterMixin)filter).shouldRunHeavy()) return true;
}
return false;
}
@Override
public void applyHeavyFilter(Document copiedFragment, int startOffset, int startLineNumber, Consumer<AdditionalHighlight> consumer) {
final boolean dumb = myDumbService.isDumb();
List<Filter> filters = myFilters;
int count = filters.size();
for (int i = 0; i < count; i++) {
Filter filter = filters.get(i);
if (!(filter instanceof FilterMixin) || !((FilterMixin)filter).shouldRunHeavy()) continue;
if (!dumb || DumbService.isDumbAware(filter)) {
((FilterMixin)filter).applyHeavyFilter(copiedFragment, startOffset, startLineNumber, consumer);
}
}
}
@Override
public String getUpdateMessage() {
final boolean dumb = myDumbService.isDumb();
List<Filter> filters = myFilters;
final List<String> updateMessage = new ArrayList<String>();
int count = filters.size();
for (int i = 0; i < count; i++) {
Filter filter = filters.get(i);
if (!(filter instanceof FilterMixin) || !((FilterMixin)filter).shouldRunHeavy()) continue;
if (!dumb || DumbService.isDumbAware(filter)) {
updateMessage.add(((FilterMixin)filter).getUpdateMessage());
}
}
return updateMessage.size() == 1 ? updateMessage.get(0) : "Updating...";
}
public boolean isEmpty() {
return myFilters.isEmpty();
}
public boolean isAnyHeavy() {
return myIsAnyHeavy;
}
public void addFilter(final Filter filter) {
myFilters.add(filter);
myIsAnyHeavy |= filter instanceof FilterMixin;
}
public void setForceUseAllFilters(boolean forceUseAllFilters) {
this.forceUseAllFilters = forceUseAllFilters;
}
}