Merge branch 'master' of git.labs.intellij.net:idea/community

This commit is contained in:
Dmitry Trofimov
2010-11-17 21:13:49 +03:00
18 changed files with 540 additions and 342 deletions
@@ -56,7 +56,7 @@ class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<L
if (item.getUserData(LookupItem.BRACKETS_COUNT_ATTR) == null && !inAnonymous) {
if (((PsiClass)item.getObject()).hasModifierProperty(PsiModifier.ABSTRACT)) {
if (mySmart) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.anonymous");
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW_ANONYMOUS);
}
PostprocessReformattingAspect.getInstance(context.getProject()).doPostponedFormatting(context.getFile().getViewProvider());
@@ -77,7 +77,7 @@ class ConstructorInsertHandler implements InsertHandler<LookupElementDecorator<L
}
}
if (mySmart) {
FeatureUsageTracker.getInstance().triggerFeatureUsed("editing.completion.smarttype.afternew");
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
}
}
}
@@ -0,0 +1,69 @@
/*
* Copyright 2000-2010 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.codeInsight.completion;
import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* @author peter
*/
public class InheritorsHolder implements Consumer<LookupElement> {
private final PsiElement myPosition;
private final Set<String> myAddedClasses = new HashSet<String>();
private final CompletionResultSet myResult;
public InheritorsHolder(PsiElement position, CompletionResultSet result) {
myPosition = position;
myResult = result;
}
@Override
public void consume(LookupElement lookupElement) {
final Object object = lookupElement.getObject();
if (object instanceof PsiClass) {
final PsiClass psiClass = (PsiClass)object;
if (JavaCompletionUtil.hasAccessibleInnerClass(psiClass, myPosition)) return;
ContainerUtil.addIfNotNull(myAddedClasses, psiClass.getQualifiedName());
}
myResult.addElement(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(lookupElement));
}
public boolean alreadyProcessed(@NotNull LookupElement element) {
final Object object = element.getObject();
if (object instanceof PsiClass) {
if (alreadyProcessed((PsiClass)object)) return true;
}
return false;
}
public boolean alreadyProcessed(@NotNull PsiClass object) {
final String qualifiedName = object.getQualifiedName();
if (qualifiedName == null || myAddedClasses.contains(qualifiedName)) {
return true;
}
return false;
}
}
@@ -48,8 +48,6 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.util.Consumer;
import com.intellij.util.PairConsumer;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -185,25 +183,12 @@ public class JavaCompletionContributor extends CompletionContributor {
return;
}
final Set<String> addedClasses = new THashSet<String>();
final InheritorsHolder inheritors = new InheritorsHolder(position, result);
if (JavaSmartCompletionContributor.AFTER_NEW.accepts(position)) {
final JavaInheritorsGetter getter = new JavaInheritorsGetter(ConstructorInsertHandler.BASIC_INSTANCE);
getter.generateVariants(parameters, result.getPrefixMatcher(), new Consumer<LookupElement>() {
@Override
public void consume(LookupElement lookupElement) {
final Object object = lookupElement.getObject();
if (object instanceof PsiClass) {
final PsiClass psiClass = (PsiClass)object;
if (JavaCompletionUtil.hasAccessibleInnerClass(psiClass, position)) return;
ContainerUtil.addIfNotNull(addedClasses, psiClass.getQualifiedName());
}
result.addElement(AutoCompletionPolicy.NEVER_AUTOCOMPLETE.applyPolicy(lookupElement));
}
});
new JavaInheritorsGetter(ConstructorInsertHandler.BASIC_INSTANCE).generateVariants(parameters, result.getPrefixMatcher(), inheritors);
}
addReferenceVariants(parameters, result, addedClasses);
addReferenceVariants(parameters, result, inheritors);
addKeywords(parameters, result);
@@ -213,7 +198,7 @@ public class JavaCompletionContributor extends CompletionContributor {
new Consumer<LookupElement>() {
@Override
public void consume(LookupElement lookupElement) {
if (!isAlreadyAdded(lookupElement, addedClasses)) {
if (!inheritors.alreadyProcessed(lookupElement)) {
result.addElement(lookupElement);
}
}
@@ -222,7 +207,7 @@ public class JavaCompletionContributor extends CompletionContributor {
result.stopHere();
}
private static void addReferenceVariants(final CompletionParameters parameters, CompletionResultSet result, final Set<String> addedClasses) {
private static void addReferenceVariants(final CompletionParameters parameters, CompletionResultSet result, final InheritorsHolder inheritors) {
final PsiElement position = parameters.getPosition();
final boolean checkAccess = parameters.getInvocationCount() <= 1;
LegacyCompletionContributor.processReferences(parameters, result, new PairConsumer<PsiReference, CompletionResultSet>() {
@@ -237,7 +222,7 @@ public class JavaCompletionContributor extends CompletionContributor {
new ElementExtractorFilter(filter),
checkAccess,
result.getPrefixMatcher(), parameters)) {
if (isAlreadyAdded(element, addedClasses)) {
if (inheritors.alreadyProcessed(element)) {
continue;
}
@@ -267,14 +252,12 @@ public class JavaCompletionContributor extends CompletionContributor {
if (completion == null) {
LOG.error("Position=" + position + "\n;Reference=" + reference + "\n;variants=" + Arrays.toString(variants));
}
if (completion instanceof LookupElement && !isAlreadyAdded((LookupElement)completion, addedClasses)) {
if (completion instanceof LookupElement && !inheritors.alreadyProcessed((LookupElement)completion)) {
result.addElement((LookupElement)completion);
}
else if (completion instanceof PsiClass) {
final PsiClass psiClass = (PsiClass)completion;
final String qname = psiClass.getQualifiedName();
if (qname == null || !addedClasses.contains(qname)) {
result.addElement(JavaClassNameCompletionContributor.createClassLookupItem(psiClass, true));
if (!inheritors.alreadyProcessed((PsiClass)completion)) {
result.addElement(JavaClassNameCompletionContributor.createClassLookupItem((PsiClass)completion, true));
}
}
else {
@@ -285,17 +268,6 @@ public class JavaCompletionContributor extends CompletionContributor {
});
}
private static boolean isAlreadyAdded(LookupElement element, Set<String> addedClasses) {
final Object object = element.getObject();
if (object instanceof PsiClass) {
final String qualifiedName = ((PsiClass)object).getQualifiedName();
if (qualifiedName != null && addedClasses.contains(qualifiedName)) {
return true;
}
}
return false;
}
private static void addKeywords(CompletionParameters parameters, CompletionResultSet result) {
PsiElement position = parameters.getPosition();
final Set<LookupElement> lookupSet = new LinkedHashSet<LookupElement>();
@@ -595,5 +567,4 @@ public class JavaCompletionContributor extends CompletionContributor {
}
return null;
}
}
@@ -26,4 +26,6 @@ public interface JavaCompletionFeatures {
@NonNls String SECOND_SMART_COMPLETION_ASLIST = "editing.completion.second.smarttype.aslist";
@NonNls String SECOND_SMART_COMPLETION_ARRAY_MEMBER = "editing.completion.second.smarttype.array.member";
@NonNls String IMPORT_STATIC = "editing.completion.import.static";
@NonNls String AFTER_NEW = "editing.completion.smarttype.afternew";
@NonNls String AFTER_NEW_ANONYMOUS = "editing.completion.smarttype.afternew";
}
@@ -108,6 +108,10 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
}
public void invokeCompletion(final Project project, final Editor editor, final PsiFile psiFile, int time) {
if (CompletionAutoPopupHandler.ourTestingAutopopup) {
System.out.println("CodeCompletionHandlerBase.doComplete");
}
if (!ApplicationManager.getApplication().isUnitTestMode()) {
assert !ApplicationManager.getApplication().isWriteAccessAllowed() : "Completion should not be invoked inside write action";
}
@@ -252,6 +256,9 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
}
private void doComplete(final int invocationCount, CompletionInitializationContext initContext) {
if (CompletionAutoPopupHandler.ourTestingAutopopup) {
System.out.println("CodeCompletionHandlerBase.doComplete");
}
final Editor editor = initContext.getEditor();
final CompletionParameters parameters = createCompletionParameters(invocationCount, initContext);
@@ -37,6 +37,9 @@ public class CreateDirectoryOrPackageAction extends AnAction implements DumbAwar
IdeView view = e.getData(LangDataKeys.IDE_VIEW);
Project project = e.getData(PlatformDataKeys.PROJECT);
if (view == null) {
return;
}
PsiDirectory directory = DirectoryChooserUtil.getOrChooseDirectory(view);
if (directory == null) return;
@@ -51,7 +54,7 @@ public class CreateDirectoryOrPackageAction extends AnAction implements DumbAwar
Messages.getQuestionIcon(), "", validator);
final PsiElement result = validator.getCreatedElement();
if (result != null && view != null) {
if (result != null) {
view.selectElement(result);
}
}
@@ -24,6 +24,7 @@ import com.intellij.openapi.roots.ProjectFileIndex;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.psi.PsiDirectory;
import com.intellij.refactoring.RefactoringBundle;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
@@ -34,7 +35,7 @@ public class DirectoryChooserUtil {
}
@Nullable
public static PsiDirectory getOrChooseDirectory(IdeView view) {
public static PsiDirectory getOrChooseDirectory(@NotNull IdeView view) {
PsiDirectory[] dirs = view.getDirectories();
if (dirs.length == 0) return null;
if (dirs.length == 1) {
@@ -90,6 +90,7 @@ public class ModuleManagerImpl extends ModuleManager implements ProjectComponent
@NonNls private static final String ATTRIBUTE_GROUP = "group";
private long myModificationCount;
private final MessageBusConnection myConnection;
private final ProgressManager myProgressManager;
private final MessageBus myMessageBus;
public static ModuleManagerImpl getInstanceImpl(Project project) {
@@ -101,8 +102,9 @@ public class ModuleManagerImpl extends ModuleManager implements ProjectComponent
myCachedSortedModules = null;
}
public ModuleManagerImpl(Project project, MessageBus bus) {
public ModuleManagerImpl(Project project, ProgressManager progressManager, MessageBus bus) {
myProject = project;
myProgressManager = progressManager;
myMessageBus = bus;
myConnection = bus.connect(project);
@@ -568,7 +570,7 @@ public class ModuleManagerImpl extends ModuleManager implements ProjectComponent
}
};
ProgressManager.getInstance().runProcessWithProgressSynchronously(runnableWithProgress, "Loading modules", false, myProject);
myProgressManager.runProcessWithProgressSynchronously(runnableWithProgress, "Loading modules", false, myProject);
myModuleModel.projectOpened();
}
@@ -39,12 +39,14 @@ import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.ProjectScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.PsiTreeUtil;
@@ -109,8 +111,13 @@ public class VariableInplaceRenamer {
if (InjectedLanguageUtil.isInInjectedLanguagePrefixSuffix(myElementToRename)) {
return false;
}
final Collection<PsiReference> refs = ReferencesSearch.search(myElementToRename).findAll();
VirtualFile vFile = myElementToRename.getContainingFile().getVirtualFile();
SearchScope referencesSearchScope = vFile == null || ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(vFile)
? ProjectScope.getProjectScope(myElementToRename.getProject())
: new LocalSearchScope(myElementToRename.getContainingFile());
final Collection<PsiReference> refs = ReferencesSearch.search(myElementToRename, referencesSearchScope, false).findAll();
addReferenceAtCaret(refs);
@@ -27,8 +27,10 @@ import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
public class TestResultsXmlFormatter {
@@ -37,16 +39,16 @@ public class TestResultsXmlFormatter {
private static final String ELEM_SUITE = "suite";
private static final String ATTR_NAME = "name";
private static final String ATTR_DURATION = "duration";
private static final String ATTR_TOTAL = "total";
private static final String ATTR_PASSED = "passed";
private static final String ATTR_FAILED = "failed";
private static final String ELEM_COUNT = "count";
private static final String ATTR_VALUE = "value";
private static final String ELEM_OUTPUT = "output";
private static final String ATTR_OUTPUT_TYPE = "type";
private static final String ATTR_STATUS = "status";
private static final String TOTAL_STATUS = "total";
private final RuntimeConfiguration myRuntimeConfiguration;
private final ContentHandler myResultHandler;
private final AbstractTestProxy myTestRoot;
private static final String ELEM_OUTPUT = "output";
private static final String ATTR_OUTPUT_TYPE = "type";
public static void execute(AbstractTestProxy root, RuntimeConfiguration runtimeConfiguration, ContentHandler resultHandler)
throws SAXException {
@@ -62,24 +64,37 @@ public class TestResultsXmlFormatter {
private void execute() throws SAXException {
myResultHandler.startDocument();
int total = 0;
int passed = 0;
TreeMap<String, Integer> counts = new TreeMap<String, Integer>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
if (TOTAL_STATUS.equals(o1) && !TOTAL_STATUS.equals(o2)) return -1;
if (TOTAL_STATUS.equals(o2) && !TOTAL_STATUS.equals(o1)) return 1;
return o1.compareTo(o2);
}
});
for (AbstractTestProxy node : myTestRoot.getAllTests()) {
if (!node.isLeaf()) continue;
total++;
if (node.isPassed()) passed++;
String status = getStatusString(node);
increment(counts, status);
increment(counts, TOTAL_STATUS);
}
Map<String, String> attrs = new HashMap<String, String>();
attrs.put(ATTR_NAME, myRuntimeConfiguration.getName());
Map<String, String> runAttrs = new HashMap<String, String>();
runAttrs.put(ATTR_NAME, myRuntimeConfiguration.getName());
Integer duration = myTestRoot.getDuration();
if (duration != null) {
attrs.put(ATTR_DURATION, String.valueOf(duration));
runAttrs.put(ATTR_DURATION, String.valueOf(duration));
}
attrs.put(ATTR_TOTAL, String.valueOf(total));
attrs.put(ATTR_PASSED, String.valueOf(passed));
attrs.put(ATTR_FAILED, String.valueOf(total - passed));
startElement(ELEM_RUN, attrs);
startElement(ELEM_RUN, runAttrs);
for (Map.Entry<String, Integer> entry : counts.entrySet()) {
Map<String, String> a = new HashMap<String, String>();
a.put(ATTR_NAME, entry.getKey());
a.put(ATTR_VALUE, String.valueOf(entry.getValue()));
startElement(ELEM_COUNT, a);
endElement(ELEM_COUNT);
}
if (myTestRoot.shouldSkipRootNodeForExport()) {
for (AbstractTestProxy node : myTestRoot.getChildren()) {
processNode(node);
@@ -92,6 +107,11 @@ public class TestResultsXmlFormatter {
myResultHandler.endDocument();
}
private static void increment(Map<String, Integer> counts, String status) {
Integer count = counts.get(status);
counts.put(status, count != null ? count + 1 : 1);
}
private void processNode(AbstractTestProxy node) throws SAXException {
Map<String, String> attrs = new HashMap<String, String>();
attrs.put(ATTR_NAME, node.getName());
@@ -145,7 +165,7 @@ public class TestResultsXmlFormatter {
}
if (buffer.length() > 0) {
Map<String, String> a = new HashMap<String, String>();
a.put(ATTR_OUTPUT_TYPE, lastType.toString());
a.put(ATTR_OUTPUT_TYPE, getTypeString(lastType.get()));
startElement(ELEM_OUTPUT, a);
writeText(buffer.toString());
endElement(ELEM_OUTPUT);
@@ -160,12 +180,26 @@ public class TestResultsXmlFormatter {
}
private static String getTypeString(ConsoleViewContentType type) {
return type == ConsoleViewContentType.ERROR_OUTPUT ? "error" : "normal";
return type == ConsoleViewContentType.ERROR_OUTPUT ? "stderr" : "stdout";
}
private static String getStatusString(AbstractTestProxy node) {
if (node.isPassed()) return "passed";
return "failed"; // TODO
int magnitude = node.getMagnitude();
// TODO enumeration!
switch (magnitude) {
case 0:
return "skipped";
case 5:
return "ignored";
case 1:
return "passed";
case 6:
return "failed";
case 8:
return "error";
default:
return node.isPassed() ? "passed" : "failed";
}
}
private void startElement(String name, Map<String, String> attributes) throws SAXException {
@@ -61,6 +61,7 @@
h1 {
color: #151515;
font-size: 180%;
line-height: 1.1em;
font-weight: bold;
}
@@ -88,10 +89,22 @@
color: #ff0000
}
span.success {
span.error {
color: #ff0000
}
span.passed {
color: #1d9d01
}
span.ignored {
color: #f8d216
}
span.skipped {
color: #f8d216
}
hr {
background-color: blue
}
@@ -101,31 +114,32 @@
}
#header {
padding: 1.3em 0 1em 0;
padding: 0;
position: fixed;
width: 100%;
height: 2em;
z-index: 10;
background-color: #c7ceda;
}
#header h1.title {
margin-top: 1em;
margin-bottom: 0;
}
#header h1 {
margin: 0 3em 0 1.7em;
margin: 0 3em 1em 1.7em;
}
#header .time {
margin-right: 3em;
margin-top: 2.2em;
margin-right: 3.4em;
float: right;
}
#treecontrol {
margin: 0;
padding: 1em 3em .5em 0;
position: fixed;
top: 4em;
right: 0;
padding: .5em 3em .5em 0;
text-align: right;
width: 100%;
background-color: #fff;
}
@@ -136,7 +150,7 @@
}
#content {
padding: 7em 2.5em 2em 1.7em;
padding: 0 2.5em 2em 1.7em;
}
#content ul {
@@ -158,7 +172,7 @@
}
#content ul li.level.top > span {
padding: .5em 0 .5em 1em;
padding: .5em .4em .5em 1em;
font-size: 120%;
color: #151515;
background-color: #f2f2f2;
@@ -169,6 +183,10 @@
border-left: solid 10px #f02525;
}
#content ul li.level.top.ignored > span {
border-left: solid 10px #f8d216;
}
#content ul li.level.suite > span {
margin-bottom: .8em;
padding: 0 0 0 .8em;
@@ -183,6 +201,10 @@
border-left: solid 15px #f02525;
}
#content ul li.level.suite.ignored > span {
border-left: solid 15px #f8d216;
}
#content ul li.level.suite > ul {
margin-bottom: 1.5em;
}
@@ -191,15 +213,19 @@
padding: .3em 0 .3em 1em;
color: #0046b0;
font-size: 100%;
border-left: solid 3px #93e078;
border-left: solid 6px #93e078;
border-bottom: solid 1px #dbdbdb;
}
#content ul li.level.test.failed > span {
border-left: solid 3px #f02525;
border-left: solid 6px #f02525;
}
#content ul li.text span {
#content ul li.level.test.ignored > span {
border-left: solid 6px #f8d216;
}
#content ul li.text p, #content ul li.text span {
margin-bottom: 1.5em;
color: #151515 !important;
font-size: 90% !important;
@@ -210,16 +236,24 @@
border: none !important;
}
#content ul li.text span {
margin-bottom: 0;
display: block;
}
#content ul li.text span.stderr {
color: #8b0000 !important;
}
#content ul li .time {
margin-right: .5em;
width: 5em;
text-align: right;
font-size: 90%;
font-size: 13px;
color: #151515;
font-style: normal;
font-weight: normal;
float: right;
background-color: #fff;
}
#content ul li span .status {
@@ -235,6 +269,11 @@
#content ul li.failed > span .status {
color: #ff0000;
}
#content ul li.ignored > span .status {
color: #f8d216;
}
</style>
<xsl:text disable-output-escaping="yes"><![CDATA[
@@ -525,8 +564,9 @@ jQuery.cookie = function(name, value, options) {
window.console && console.log("%o was toggled", this);
}
});
});
$("#content").css("padding-top", $("#header").height());
});
</script>
]]></xsl:text>
@@ -535,19 +575,22 @@ jQuery.cookie = function(name, value, options) {
<div id="container">
<div id="header">
<xsl:call-template name="duration"/>
<h1>
<h1 class="title">
<xsl:value-of select="@name"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="@total"/>
<xsl:text> total, </xsl:text>
<span class="success">
<xsl:value-of select="@passed"/>
<xsl:text> passed, </xsl:text>
</span>
<span class="failed">
<xsl:value-of select="@failed"/>
<xsl:text> failed</xsl:text>
</span>
</h1>
<h1>
<xsl:for-each select="count">
<xsl:variable name="status" select="@name"/>
<span class="{$status}">
<xsl:value-of select="@value"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$status"/>
<xsl:if test="count(../count) > position()">
<xsl:text>, </xsl:text>
</xsl:if>
</span>
</xsl:for-each>
</h1>
</div>
<div id="treecontrol">
@@ -571,6 +614,108 @@ jQuery.cookie = function(name, value, options) {
</html>
</xsl:template>
<xsl:template match="suite">
<xsl:variable name="class">
<xsl:text>level </xsl:text>
<xsl:choose>
<xsl:when test="parent::suite">
<xsl:text>suite</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>top</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:call-template name="get-node-class"/>
</xsl:variable>
<xsl:element name="li">
<xsl:attribute name="class">
<xsl:value-of select="$class"/>
</xsl:attribute>
<span>
<em class="time">
<xsl:call-template name="duration"/>
</em>
<xsl:value-of select="@name"/>
</span>
<ul>
<xsl:apply-templates/>
</ul>
</xsl:element>
</xsl:template>
<xsl:template match="test">
<xsl:variable name="class">
<xsl:text>level test</xsl:text>
<xsl:call-template name="get-node-class"/>
</xsl:variable>
<li class="{$class}">
<span>
<em class="time">
<xsl:call-template name="duration"/>
</em>
<em class="status">
<xsl:value-of select="@status"/>
</em>
<xsl:value-of select="@name"/>
</span>
<ul>
<xsl:for-each select="output">
<xsl:variable name="displayText">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="text()"/>
<xsl:with-param name="replace" select="'&#10;'"/>
<xsl:with-param name="by" select="'&lt;br/>'"/>
</xsl:call-template>
</xsl:variable>
<li class="text">
<xsl:variable name="output-type" select="@type"/>
<span class="{$output-type}">
<xsl:value-of disable-output-escaping="yes" select="$displayText"/>
</span>
</li>
</xsl:for-each>
</ul>
</li>
</xsl:template>
<xsl:template name="get-node-class">
<xsl:choose>
<xsl:when test="@status='failed' or @status='error'">
<xsl:text> failed open</xsl:text>
</xsl:when>
<xsl:when test="@status='ignored' or @status='skipped'">
<xsl:text> ignored open</xsl:text>
</xsl:when>
<xsl:when test="@status='passed'">
<xsl:if test="name(.) != 'test' and count(parent::*) = 1">
<xsl:text> open</xsl:text>
</xsl:if>
</xsl:when>
</xsl:choose>
</xsl:template>
<xsl:template name="string-replace-all">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$by"/>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="duration">
<xsl:if test="@duration">
<xsl:variable name="msec" select="number(@duration)"/>
@@ -613,100 +758,4 @@ jQuery.cookie = function(name, value, options) {
</xsl:if>
</xsl:template>
<xsl:template match="suite">
<xsl:variable name="class">
<xsl:text>level </xsl:text>
<xsl:choose>
<xsl:when test="parent::suite">
<xsl:text>suite</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text>top</xsl:text>
</xsl:otherwise>
</xsl:choose>
<xsl:choose>
<xsl:when test="@status!='passed'">
<xsl:text> failed open</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:if test="count(parent::*) = 1">
<xsl:text> open</xsl:text>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:element name="li">
<xsl:attribute name="class">
<xsl:value-of select="$class"/>
</xsl:attribute>
<span>
<em class="time">
<xsl:call-template name="duration"/>
</em>
<xsl:value-of select="@name"/>
</span>
<ul>
<xsl:apply-templates/>
</ul>
</xsl:element>
</xsl:template>
<xsl:template match="test">
<xsl:variable name="class">
<xsl:text>level test</xsl:text>
<xsl:if test="@status!='passed'">
<xsl:text> failed open</xsl:text>
</xsl:if>
</xsl:variable>
<li class="{$class}">
<span>
<em class="time">
<xsl:call-template name="duration"/>
</em>
<em class="status">
<xsl:value-of select="@status"/>
</em>
<xsl:value-of select="@name"/>
</span>
<ul>
<xsl:for-each select="output">
<xsl:variable name="displayText">
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="text()"/>
<xsl:with-param name="replace" select="'&#10;'"/>
<xsl:with-param name="by" select="'&lt;br/>'"/>
</xsl:call-template>
</xsl:variable>
<li class="text">
<span>
<xsl:value-of disable-output-escaping="yes" select="$displayText"/>
</span>
</li>
</xsl:for-each>
</ul>
</li>
</xsl:template>
<xsl:template name="string-replace-all">
<xsl:param name="text"/>
<xsl:param name="replace"/>
<xsl:param name="by"/>
<xsl:choose>
<xsl:when test="contains($text, $replace)">
<xsl:value-of select="substring-before($text,$replace)"/>
<xsl:value-of select="$by"/>
<xsl:call-template name="string-replace-all">
<xsl:with-param name="text" select="substring-after($text,$replace)"/>
<xsl:with-param name="replace" select="$replace"/>
<xsl:with-param name="by" select="$by"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$text"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
@@ -215,7 +215,7 @@ public class UpdateInfoTree extends PanelWithActionsAndCloseButton implements Di
}
public Object getData(String dataId) {
if (myTreeBrowser.isVisible()) {
if (myTreeBrowser != null && myTreeBrowser.isVisible()) {
return null;
}
if (PlatformDataKeys.NAVIGATABLE.is(dataId)) {
@@ -229,7 +229,7 @@ public class UpdateInfoTree extends PanelWithActionsAndCloseButton implements Di
return getFileArray();
} else if (PlatformDataKeys.TREE_EXPANDER.is(dataId)) {
if (myGroupByChangeList) {
return myTreeBrowser.getTreeExpander();
return myTreeBrowser != null ? myTreeBrowser.getTreeExpander() : null;
}
else {
return myTreeExpander;
+1
View File
@@ -35,6 +35,7 @@
<orderEntry type="module" module-name="IntelliLang" />
<orderEntry type="module" module-name="ant" />
<orderEntry type="module" module-name="testFramework-java" scope="TEST" />
<orderEntry type="library" name="Guava" level="project" />
</component>
</module>
@@ -53,9 +53,9 @@ public class GroovyClassNameInsertHandler implements InsertHandler<JavaPsiClassR
final boolean inNew = position != null && isReferenceInNewExpression(position.getParent());
final PsiClass psiClass = item.getObject();
if (isInVariable(position) || GroovyCompletionContributor.isInClosurePropertyParameters(position)) {
Project project = context.getProject();
PsiClass psiClass = item.getObject();
String qname = psiClass.getQualifiedName();
String shortName = psiClass.getName();
if (qname == null) return;
@@ -71,8 +71,8 @@ public class GroovyClassNameInsertHandler implements InsertHandler<JavaPsiClassR
}
AllClassesGetter.TRY_SHORTENING.handleInsert(context, item);
if (inNew) {
JavaCompletionUtil.insertParentheses(context, item, false, GroovyCompletionUtil.hasConstructorParameters(item.getObject()));
if (inNew && !JavaCompletionUtil.hasAccessibleInnerClass(psiClass, position)) {
JavaCompletionUtil.insertParentheses(context, item, false, GroovyCompletionUtil.hasConstructorParameters(psiClass));
}
}
@@ -200,92 +200,27 @@ public class GroovyCompletionContributor extends CompletionContributor {
}
};
private static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritors) {
result.stopHere();
AllClassesGetter.processJavaClasses(parameters, result.getPrefixMatcher(), parameters.getInvocationCount() <= 1, new Consumer<PsiClass>() {
@Override
public void consume(PsiClass psiClass) {
if (!inheritors.alreadyProcessed(psiClass)) {
result.addElement(GroovyCompletionUtil.createClassLookupItem(psiClass));
}
}
});
}
public GroovyCompletionContributor() {
extend(CompletionType.BASIC, psiElement(PsiElement.class), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull final CompletionResultSet result) {
final PsiElement position = parameters.getPosition();
final PsiElement reference = position.getParent();
final PsiElement reference = parameters.getPosition().getParent();
if (reference instanceof GrReferenceElement) {
final int invocationCount = parameters.getInvocationCount();
final boolean secondCompletionInvoked =
CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION ? invocationCount > 0 : invocationCount > 1;
final String prefix = result.getPrefixMatcher().getPrefix();
final boolean skipAccessors = !secondCompletionInvoked && !prefix.startsWith(GET_PREFIX) &&
!prefix.startsWith(SET_PREFIX) &&
!prefix.startsWith(IS_PREFIX);
result.restartCompletionOnPrefixChange(GET_PREFIX);
result.restartCompletionOnPrefixChange(SET_PREFIX);
result.restartCompletionOnPrefixChange(IS_PREFIX);
final Map<PsiModifierListOwner, LookupElement> staticMembers = hashMap();
((GrReferenceElement)reference).processVariants(new Consumer<Object>() {
public void consume(Object element) {
final LookupElement lookupElement = element instanceof PsiClass
? GroovyCompletionUtil.createClassLookupItem((PsiClass)element)
: GroovyCompletionUtil.getLookupElement(element);
Object object = lookupElement.getObject();
PsiSubstitutor substitutor = null;
if (object instanceof GroovyResolveResult) {
substitutor = ((GroovyResolveResult)object).getSubstitutor();
object = ((GroovyResolveResult)object).getElement();
}
//skip default groovy methods
if (!secondCompletionInvoked &&
object instanceof GrGdkMethod &&
GroovyCompletionUtil.skipDefGroovyMethod((GrGdkMethod)object, substitutor)) {
showInfo();
return;
}
//skip operator methods
if (!secondCompletionInvoked &&
object instanceof PsiMethod &&
GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(((PsiMethod)object).getName())) {
showInfo();
return;
}
//skip accessors if there is no get, set, is prefix
if (skipAccessors && object instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)object)) {
showInfo();
return;
}
if ((object instanceof PsiMethod || object instanceof PsiField) &&
((PsiModifierListOwner)object).hasModifierProperty(PsiModifier.STATIC)) {
if (lookupElement.getLookupString().equals(((PsiMember)object).getName())) {
staticMembers.put((PsiModifierListOwner)object, lookupElement);
return;
}
}
result.addElement(lookupElement);
}
});
if (((GrReferenceElement)reference).getQualifier() == null) {
completeStaticMembers(position).processMembersOfRegisteredClasses(null, new PairConsumer<PsiMember, PsiClass>() {
@Override
public void consume(PsiMember member, PsiClass psiClass) {
if (member instanceof GrAccessorMethod) {
member = ((GrAccessorMethod)member).getProperty();
}
final String name = member.getName();
if (name == null || !result.getPrefixMatcher().prefixMatches(name)) {
staticMembers.remove(member);
return;
}
staticMembers.put(member, new JavaGlobalMemberLookupElement(member, psiClass, QUALIFIED_METHOD_INSERT_HANDLER, STATIC_IMPORT_INSERT_HANDLER, true));
}
});
}
result.addAllElements(staticMembers.values());
completeReference(parameters, result, (GrReferenceElement)reference);
}
}
});
@@ -366,37 +301,113 @@ public class GroovyCompletionContributor extends CompletionContributor {
});
final CompletionProvider<CompletionParameters> classNameProvider = new CompletionProvider<CompletionParameters>() {
extend(CompletionType.CLASS_NAME, psiElement(), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull final CompletionResultSet result) {
result.stopHere();
AllClassesGetter
.processJavaClasses(parameters, result.getPrefixMatcher(), parameters.getInvocationCount() <= 1, new Consumer<PsiClass>() {
@Override
public void consume(PsiClass psiClass) {
result.addElement(GroovyCompletionUtil.createClassLookupItem(psiClass));
}
});
}
};
extend(CompletionType.CLASS_NAME, psiElement(), classNameProvider);
extend(CompletionType.BASIC, psiElement().withParent(GrReferenceElement.class), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
ProcessingContext context,
@NotNull final CompletionResultSet result) {
final PsiElement position = parameters.getPosition();
if (((GrReferenceElement)position.getParent()).getQualifier() != null) return;
final String s = result.getPrefixMatcher().getPrefix();
if (StringUtil.isEmpty(s) || !Character.isUpperCase(s.charAt(0))) return;
classNameProvider.addCompletionVariants(parameters, context, result);
@NotNull CompletionResultSet result) {
addAllClasses(parameters, result, new InheritorsHolder(parameters.getPosition(), result));
}
});
}
private static void completeReference(CompletionParameters parameters, final CompletionResultSet result, GrReferenceElement reference) {
PsiElement position = parameters.getPosition();
final InheritorsHolder inheritors = new InheritorsHolder(position, result);
if (GroovySmartCompletionContributor.AFTER_NEW.accepts(position)) {
GroovySmartCompletionContributor.generateInheritorVariants(parameters, result.getPrefixMatcher(), inheritors);
}
final int invocationCount = parameters.getInvocationCount();
final boolean secondCompletionInvoked = CodeInsightSettings.getInstance().AUTOCOMPLETE_ON_CODE_COMPLETION ? invocationCount > 0 : invocationCount > 1;
final String prefix = result.getPrefixMatcher().getPrefix();
final boolean skipAccessors = !secondCompletionInvoked && !prefix.startsWith(GET_PREFIX) &&
!prefix.startsWith(SET_PREFIX) &&
!prefix.startsWith(IS_PREFIX);
result.restartCompletionOnPrefixChange(GET_PREFIX);
result.restartCompletionOnPrefixChange(SET_PREFIX);
result.restartCompletionOnPrefixChange(IS_PREFIX);
final Map<PsiModifierListOwner, LookupElement> staticMembers = hashMap();
reference.processVariants(new Consumer<Object>() {
public void consume(Object element) {
if (element instanceof PsiClass && inheritors.alreadyProcessed((PsiClass)element)) {
return;
}
if (element instanceof LookupElement && inheritors.alreadyProcessed((LookupElement)element)) {
return;
}
final LookupElement lookupElement = element instanceof PsiClass
? GroovyCompletionUtil.createClassLookupItem((PsiClass)element)
: GroovyCompletionUtil.getLookupElement(element);
Object object = lookupElement.getObject();
PsiSubstitutor substitutor = null;
if (object instanceof GroovyResolveResult) {
substitutor = ((GroovyResolveResult)object).getSubstitutor();
object = ((GroovyResolveResult)object).getElement();
}
//skip default groovy methods
if (!secondCompletionInvoked &&
object instanceof GrGdkMethod &&
GroovyCompletionUtil.skipDefGroovyMethod((GrGdkMethod)object, substitutor)) {
showInfo();
return;
}
//skip operator methods
if (!secondCompletionInvoked &&
object instanceof PsiMethod &&
GroovyCompletionUtil.OPERATOR_METHOD_NAMES.contains(((PsiMethod)object).getName())) {
showInfo();
return;
}
//skip accessors if there is no get, set, is prefix
if (skipAccessors && object instanceof PsiMethod && GroovyPropertyUtils.isSimplePropertyAccessor((PsiMethod)object)) {
showInfo();
return;
}
if ((object instanceof PsiMethod || object instanceof PsiField) &&
((PsiModifierListOwner)object).hasModifierProperty(PsiModifier.STATIC)) {
if (lookupElement.getLookupString().equals(((PsiMember)object).getName())) {
staticMembers.put((PsiModifierListOwner)object, lookupElement);
return;
}
}
result.addElement(lookupElement);
}
});
if (reference.getQualifier() == null) {
completeStaticMembers(position).processMembersOfRegisteredClasses(null, new PairConsumer<PsiMember, PsiClass>() {
@Override
public void consume(PsiMember member, PsiClass psiClass) {
if (member instanceof GrAccessorMethod) {
member = ((GrAccessorMethod)member).getProperty();
}
final String name = member.getName();
if (name == null || !result.getPrefixMatcher().prefixMatches(name)) {
staticMembers.remove(member);
return;
}
staticMembers.put(member, new JavaGlobalMemberLookupElement(member, psiClass, QUALIFIED_METHOD_INSERT_HANDLER, STATIC_IMPORT_INSERT_HANDLER, true));
}
});
final String s = result.getPrefixMatcher().getPrefix();
if (!StringUtil.isEmpty(s) && Character.isUpperCase(s.charAt(0))) {
addAllClasses(parameters, result, inheritors);
}
}
result.addAllElements(staticMembers.values());
}
private static void showInfo() {
@@ -70,7 +70,7 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
GrAssignmentExpression.class),
psiElement(
GrVariable.class))));
private static final ElementPattern<PsiElement> AFTER_NEW =
static final ElementPattern<PsiElement> AFTER_NEW =
psiElement().afterLeaf(psiElement().withText(PsiKeyword.NEW).andNot(psiElement().afterLeaf(psiElement().withText(PsiKeyword.THROW))));
private static final TObjectHashingStrategy<TypeConstraint> EXPECTED_TYPE_INFO_STRATEGY =
new TObjectHashingStrategy<TypeConstraint>() {
@@ -191,38 +191,10 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
protected void addCompletions(@NotNull final CompletionParameters parameters,
final ProcessingContext matchingContext,
@NotNull final CompletionResultSet result) {
final PsiElement identifierCopy = parameters.getPosition();
final GrExpression expression = PsiTreeUtil.getParentOfType(identifierCopy, GrExpression.class);
if (expression == null) return;
final Set<PsiType> types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(expression);
for (PsiType type : types) {
if (type instanceof PsiArrayType) {
final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), identifierCopy);
if (item.getObject() instanceof PsiClass) {
JavaCompletionUtil.setShowFQN(item);
}
item.setInsertHandler(new ArrayInsertHandler());
result.addElement(item);
}
}
final List<PsiClassType> expectedClassTypes = new SmartList<PsiClassType>();
for (PsiType psiType : types) {
if (psiType instanceof PsiClassType) {
PsiType type = JavaCompletionUtil.eliminateWildcards(JavaCompletionUtil.originalize(psiType));
final PsiClassType classType = (PsiClassType)type;
if (classType.resolve() != null) {
expectedClassTypes.add(classType);
}
}
}
JavaInheritorsGetter.processInheritors(parameters, expectedClassTypes, result.getPrefixMatcher(), new Consumer<PsiType>() {
public void consume(final PsiType type) {
addExpectedType(result, type, identifierCopy);
generateInheritorVariants(parameters, result.getPrefixMatcher(), new Consumer<LookupElement>() {
@Override
public void consume(LookupElement lookupElement) {
result.addElement(lookupElement);
}
});
}
@@ -230,24 +202,65 @@ public class GroovySmartCompletionContributor extends CompletionContributor {
}
static void generateInheritorVariants(CompletionParameters parameters, PrefixMatcher matcher, final Consumer<LookupElement> consumer) {
final PsiElement identifierCopy = parameters.getPosition();
final GrExpression expression = PsiTreeUtil.getParentOfType(identifierCopy, GrExpression.class);
if (expression == null) return;
final Set<PsiType> types = GroovyExpectedTypesProvider.getDefaultExpectedTypes(expression);
for (PsiType type : types) {
if (type instanceof PsiArrayType) {
final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), identifierCopy);
if (item.getObject() instanceof PsiClass) {
JavaCompletionUtil.setShowFQN(item);
}
item.setInsertHandler(new ArrayInsertHandler());
consumer.consume(item);
}
}
final List<PsiClassType> expectedClassTypes = new SmartList<PsiClassType>();
for (PsiType psiType : types) {
if (psiType instanceof PsiClassType) {
PsiType type = JavaCompletionUtil.eliminateWildcards(JavaCompletionUtil.originalize(psiType));
final PsiClassType classType = (PsiClassType)type;
if (classType.resolve() != null) {
expectedClassTypes.add(classType);
}
}
}
JavaInheritorsGetter.processInheritors(parameters, expectedClassTypes, matcher, new Consumer<PsiType>() {
public void consume(final PsiType type) {
final LookupElement element = addExpectedType(type, identifierCopy);
if (element != null) {
consumer.consume(element);
}
}
});
}
@Override
public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) {
super.fillCompletionVariants(parameters, result);
}
private static void addExpectedType(final CompletionResultSet result, final PsiType type, final PsiElement place) {
if (!JavaCompletionUtil.hasAccessibleConstructor(type)) return;
@Nullable
private static LookupElement addExpectedType(final PsiType type, final PsiElement place) {
if (!JavaCompletionUtil.hasAccessibleConstructor(type)) return null;
final PsiClass psiClass = com.intellij.psi.util.PsiUtil.resolveClassInType(type);
if (psiClass == null) return;
if (psiClass == null) return null;
if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) return;
if (!checkForInnerClass(psiClass, place)) return;
if (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) return null;
if (!checkForInnerClass(psiClass, place)) return null;
final LookupItem item = PsiTypeLookupItem.createLookupItem(JavaCompletionUtil.eliminateWildcards(type), place);
JavaCompletionUtil.setShowFQN(item);
item.setInsertHandler(new AfterNewClassInsertHandler((PsiClassType)type, place));
result.addElement(item);
item.setInsertHandler(new AfterNewClassInsertHandler((PsiClassType)type, place, true));
return item;
}
private static boolean checkForInnerClass(PsiClass psiClass, PsiElement identifierCopy) {
@@ -19,8 +19,10 @@ package org.jetbrains.plugins.groovy.lang.completion.handlers;
import com.intellij.codeInsight.AutoPopupController;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.JavaCompletionFeatures;
import com.intellij.codeInsight.completion.util.ParenthesesInsertHandler;
import com.intellij.codeInsight.lookup.LookupItem;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.*;
import com.intellij.util.containers.ContainerUtil;
@@ -34,10 +36,12 @@ import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil;
public class AfterNewClassInsertHandler implements InsertHandler<LookupItem<PsiClassType>> {
private final PsiClassType myClassType;
private final PsiElement myPlace;
private final boolean myTriggerFeature;
public AfterNewClassInsertHandler(PsiClassType classType, PsiElement place) {
public AfterNewClassInsertHandler(PsiClassType classType, PsiElement place, boolean triggerFeature) {
myClassType = classType;
myPlace = place;
myTriggerFeature = triggerFeature;
}
public void handleInsert(InsertionContext context, LookupItem<PsiClassType> item) {
@@ -62,6 +66,10 @@ public class AfterNewClassInsertHandler implements InsertHandler<LookupItem<PsiC
}
});
if (myTriggerFeature) {
FeatureUsageTracker.getInstance().triggerFeatureUsed(JavaCompletionFeatures.AFTER_NEW);
}
if (hasParams) {
ParenthesesInsertHandler.WITH_PARAMETERS.handleInsert(context, item);
}
@@ -320,4 +320,24 @@ class A {
def getFileText(PsiFile file) {
return PsiDocumentManager.getInstance(project).getDocument(file).text
}
void configure(String text) {
myFixture.configureByText("a.groovy", text)
}
public void testGenericsAfterNew() {
configure "List<String> l = new ArrLi<caret>"
myFixture.completeBasic()
myFixture.type '\n'
myFixture.checkResult "List<String> l = new ArrayList<String>(<caret>)"
}
public void testAfterNewWithInner() {
myFixture.addClass """class Zzoo {
static class Impl {}
}"""
configure "Zzoo l = new Zz<caret>"
myFixture.completeBasic()
myFixture.checkResult "Zzoo l = new Zzoo<caret>"
}
}