diff --git a/platform/lang-api/src/com/intellij/execution/filters/CompositeInputFilter.java b/platform/lang-api/src/com/intellij/execution/filters/CompositeInputFilter.java new file mode 100644 index 000000000000..7ba812f9e8d7 --- /dev/null +++ b/platform/lang-api/src/com/intellij/execution/filters/CompositeInputFilter.java @@ -0,0 +1,64 @@ +/* + * Copyright 2000-2012 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.execution.ui.ConsoleViewContentType; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; +import com.intellij.util.containers.ContainerUtilRt; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class CompositeInputFilter implements InputFilter { + private static final Logger LOG = Logger.getInstance(CompositeInputFilter.class); + + private final List> myFilters = ContainerUtilRt.newArrayList(); + private final DumbService myDumbService; + + public CompositeInputFilter(@NotNull Project project) { + myDumbService = DumbService.getInstance(project); + } + + @Override + @Nullable + public Pair applyFilter(final String text, final ConsoleViewContentType contentType) { + boolean dumb = myDumbService.isDumb(); + for (Pair pair : myFilters) { + if (!dumb || pair.second == Boolean.TRUE) { + long t0 = System.currentTimeMillis(); + InputFilter filter = pair.first; + Pair result = filter.applyFilter(text, contentType); + t0 = System.currentTimeMillis() - t0; + if (t0 > 100) { + LOG.warn(filter.getClass().getSimpleName() + ".applyFilter() took " + t0 + " ms on '''" + text + "'''"); + } + if (result != null) { + return result; + } + } + } + return null; + } + + public void addFilter(@NotNull final InputFilter filter) { + myFilters.add(Pair.create(filter, DumbService.isDumbAware(filter))); + } +} diff --git a/platform/lang-api/src/com/intellij/execution/filters/ConsoleInputFilterProvider.java b/platform/lang-api/src/com/intellij/execution/filters/ConsoleInputFilterProvider.java new file mode 100644 index 000000000000..078fe82245d9 --- /dev/null +++ b/platform/lang-api/src/com/intellij/execution/filters/ConsoleInputFilterProvider.java @@ -0,0 +1,29 @@ +/* + * Copyright 2000-2012 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.extensions.ExtensionPointName; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +public interface ConsoleInputFilterProvider { + ExtensionPointName INPUT_FILTER_PROVIDERS = + ExtensionPointName.create("com.intellij.consoleInputFilterProvider"); + + @NotNull + InputFilter[] getDefaultFilters(@NotNull Project project); +} diff --git a/platform/lang-api/src/com/intellij/execution/filters/InputFilter.java b/platform/lang-api/src/com/intellij/execution/filters/InputFilter.java new file mode 100644 index 000000000000..648b1ee037c5 --- /dev/null +++ b/platform/lang-api/src/com/intellij/execution/filters/InputFilter.java @@ -0,0 +1,32 @@ +/* + * Copyright 2000-2012 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.execution.ui.ConsoleViewContentType; +import com.intellij.openapi.util.Pair; +import org.jetbrains.annotations.Nullable; + +public interface InputFilter { + + /** + * @param text the text to be filtered. + * @param contentType the content type of filtered text + * @return null, if there was no match, otherwise, a pair of ('string to use', 'content type to use') + */ + @Nullable + Pair applyFilter(String text, ConsoleViewContentType contentType); + +} diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index cebb3189b24f..f8fcc58cc41c 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -241,6 +241,8 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo protected final CompositeFilter myPredefinedMessageFilter; protected final CompositeFilter myCustomFilter; + @Nullable private final InputFilter myInputMessageFilter; + private final Alarm myFoldingAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, this); private final List myPendingFoldRegions = new ArrayList(); @@ -264,7 +266,11 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo this(project, GlobalSearchScope.allScope(project), viewer, fileType); } - public ConsoleViewImpl(@NotNull final Project project, @NotNull GlobalSearchScope searchScope, boolean viewer, @Nullable FileType fileType) { + public ConsoleViewImpl(@NotNull final Project project, + @NotNull GlobalSearchScope searchScope, + boolean viewer, + @Nullable FileType fileType) + { this(project, searchScope, viewer, fileType, new ConsoleState.NotStartedStated() { @Override @@ -278,7 +284,8 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo @NotNull GlobalSearchScope searchScope, boolean viewer, @Nullable FileType fileType, - @NotNull final ConsoleState initialState) { + @NotNull final ConsoleState initialState) + { super(new BorderLayout()); isViewer = viewer; myState = initialState; @@ -299,6 +306,21 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo myHeavyUpdateTicket = 0; myHeavyAlarm = myPredefinedMessageFilter.isAnyHeavy() ? new Alarm(Alarm.ThreadToUse.SHARED_THREAD, this) : null; + ConsoleInputFilterProvider[] inputFilters = Extensions.getExtensions(ConsoleInputFilterProvider.INPUT_FILTER_PROVIDERS); + if (inputFilters.length > 0) { + CompositeInputFilter compositeInputFilter = new CompositeInputFilter(project); + myInputMessageFilter = compositeInputFilter; + for (ConsoleInputFilterProvider eachProvider : inputFilters) { + InputFilter[] filters = eachProvider.getDefaultFilters(project); + for (InputFilter filter : filters) { + compositeInputFilter.addFilter(filter); + } + } + } + else { + myInputMessageFilter = null; + } + Disposer.register(project, this); myFinishProgress = new Runnable() { @Override @@ -338,6 +360,7 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo if (myEditor == null || myFlushAlarm.isDisposed()) return; class ScrollRunnable extends MyFlushRunnable { private final int myOffset = offset; + @Override public void doRun() { flushDeferredText(); @@ -510,7 +533,20 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo @Override public void print(String s, final ConsoleViewContentType contentType) { - printHyperlink(s, contentType, null); + if (myInputMessageFilter == null) { + printHyperlink(s, contentType, null); + return; + } + + Pair result = myInputMessageFilter.applyFilter(s, contentType); + if (result == null) { + printHyperlink(s, contentType, null); + } + else { + if (result.first != null) { + printHyperlink(result.first, result.second == null ? contentType : result.second, null); + } + } } private void printHyperlink(String s, ConsoleViewContentType contentType, HyperlinkInfo info) { diff --git a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml index fb33b8ae8652..cd3494f4c2c2 100644 --- a/platform/platform-resources/src/META-INF/LangExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/LangExtensionPoints.xml @@ -294,6 +294,7 @@ area="IDEA_PROJECT"/> +