Merge remote-tracking branch 'origin/master'

This commit is contained in:
Alexander Lobas
2012-07-02 16:21:32 +04:00
34 changed files with 476 additions and 96 deletions
+1 -1
View File
@@ -1 +1 @@
118.SNAPSHOT
120.SNAPSHOT
@@ -17,13 +17,20 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
@Override
public void registerFixes(PsiJavaCodeReferenceElement ref, QuickFixActionRegistrar registrar) {
@@ -37,15 +44,13 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
PsiReferenceExpression refExpr = (PsiReferenceExpression)ref;
registrar.register(fixRange, new CreateEnumConstantFromUsageFix(refExpr), null);
registrar.register(fixRange, new CreateConstantFieldFromUsageFix(refExpr), null);
registrar.register(fixRange, new CreateFieldFromUsageFix(refExpr), null);
registrar.register(new RenameWrongRefFix(refExpr));
if (!ref.isQualified()) {
registrar.register(fixRange, new BringVariableIntoScopeFix(refExpr), null);
registrar.register(fixRange, new CreateLocalFromUsageFix(refExpr), null);
registrar.register(fixRange, new CreateParameterFromUsageFix(refExpr), null);
}
registerPriorityActions(registrar,fixRange,refExpr);
}
registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.INTERFACE));
@@ -65,6 +70,57 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
}
}
private static void registerPriorityActions(@NotNull final QuickFixActionRegistrar registrar,
@NotNull final TextRange fixRange,
@NotNull final PsiReferenceExpression refExpr) {
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(refExpr.getProject());
final Map<VariableKind, IntentionAction> map = new HashMap<VariableKind, IntentionAction>() {
{
put(VariableKind.FIELD, new CreateFieldFromUsageFix(refExpr));
put(VariableKind.STATIC_FINAL_FIELD, new CreateConstantFieldFromUsageFix(refExpr));
if (!refExpr.isQualified()) {
put(VariableKind.LOCAL_VARIABLE, new CreateLocalFromUsageFix(refExpr));
put(VariableKind.PARAMETER, new CreateParameterFromUsageFix(refExpr));
}
}
};
final VariableKind kind = getKind(styleManager, refExpr);
if (map.containsKey(kind)){
map.put(kind, PriorityIntentionActionWrapper.highPriority(map.get(kind)));
}
for (IntentionAction action : map.values()){
registrar.register(fixRange, action, null);
}
}
@NotNull
private static VariableKind getKind(@NotNull JavaCodeStyleManager styleManager,
@NotNull PsiReferenceExpression refExpr) {
final String reference = refExpr.getText();
if (reference.toUpperCase().equals(reference)){
return VariableKind.STATIC_FINAL_FIELD;
}
for (VariableKind kind : VariableKind.values()) {
final String prefix = styleManager.getPrefixByVariableKind(kind);
final String suffix = styleManager.getSuffixByVariableKind(kind);
if (prefix.isEmpty() && suffix.isEmpty()) {
continue;
}
if (reference.startsWith(prefix) && reference.endsWith(suffix)) {
return kind;
}
}
return VariableKind.LOCAL_VARIABLE;
}
@Override
@NotNull
public Class<PsiJavaCodeReferenceElement> getReferenceClass() {
@@ -55,7 +55,7 @@ public class FileEqualsUsageInspection extends InternalInspection {
if (clazz == null) return;
String methodName = method.getName();
if ("java.io.File".equals(clazz.getQualifiedName())
if (CommonClassNames.JAVA_IO_FILE.equals(clazz.getQualifiedName())
&& ("equals".equals(methodName) || "compareTo".equals(methodName) || "hashCode".equals(methodName))) {
holder.registerProblem(methodExpression,
"Do not use File.equals/hashCode/compareTo as they don't honor case-sensitivity on MacOS. Use FileUtil.filesEquals/fileHashCode/compareFiles instead",
@@ -87,4 +87,5 @@ public interface CommonClassNames {
@NonNls String JAVA_LANG_INVOKE_MH_POLYMORPHIC = "java.lang.invoke.MethodHandle.PolymorphicSignature";
String TARGET_ANNOTATION_FQ_NAME = "java.lang.annotation.Target";
@NonNls String JAVA_LANG_RUNNABLE = "java.lang.Runnable";
@NonNls String JAVA_IO_FILE = "java.io.File";
}
@@ -0,0 +1,5 @@
class FooBar {
void foo(FooBar _fooBar) {
fb<caret>
}
}
@@ -1272,4 +1272,22 @@ class Foo {
myFixture.checkResult 'class Foo {{ boolean <caret> }}'
}
@Override
protected void tearDown() {
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.FIRST_LETTER
super.tearDown()
}
public void testBackspaceShouldShowPreviousVariants() {
CodeInsightSettings.instance.COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE
myFixture.addClass("class OuterX { static class TrueLine {} }")
myFixture.configureByText 'a.java', 'class Foo{ void foo(int truex) { return tr<caret> }}'
type 'ue'
assert myFixture.lookupElementStrings == ['true', 'truex']
type 'l'
assert myFixture.lookupElementStrings == ['TrueLine']
type '\b'
assert myFixture.lookupElementStrings == ['true', 'truex']
}
}
@@ -378,4 +378,9 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
assertPreferredItems(0, 'fooy', 'foox', 'fooAClass', 'fooBar');
}
public void testUnderscoresDontMakeMatchMiddle() {
CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE = CodeInsightSettings.NONE;
checkPreferredItems(0, '_fooBar', 'FooBar')
}
}
@@ -63,7 +63,7 @@ public abstract class CompletionTestCase extends DaemonAnalyzerTestCase {
}
protected void complete(final int time) {
new CodeCompletionHandlerBase(myType).invokeCompletion(myProject, myEditor, time, false);
new CodeCompletionHandlerBase(myType).invokeCompletion(myProject, myEditor, time);
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(myEditor);
myItems = lookup == null ? null : lookup.getItems().toArray(new LookupElement[lookup.getItems().size()]);
@@ -57,7 +57,7 @@ public abstract class LightCompletionTestCase extends LightCodeInsightTestCase {
}
protected void complete(final int time) {
new CodeCompletionHandlerBase(myType).invokeCompletion(getProject(), getEditor(), time, false);
new CodeCompletionHandlerBase(myType).invokeCompletion(getProject(), getEditor(), time);
LookupImpl lookup = (LookupImpl)LookupManager.getActiveLookup(myEditor);
myItems = lookup == null ? null : lookup.getItems().toArray(LookupElement.EMPTY_ARRAY);
@@ -0,0 +1,96 @@
/*
* 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.codeInsight.intention.impl;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
/**
* @author Danila Ponomarenko
*/
public abstract class PriorityIntentionActionWrapper implements IntentionAction {
private IntentionAction action;
private PriorityIntentionActionWrapper(@NotNull IntentionAction action) {
this.action = action;
}
@NotNull
@Override
public String getText() {
return action.getText();
}
@NotNull
@Override
public String getFamilyName() {
return action.getFamilyName();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return action.isAvailable(project, editor, file);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
action.invoke(project, editor, file);
}
@Override
public boolean startInWriteAction() {
return action.startInWriteAction();
}
private static class HighPriorityIntentionActionWrapper extends PriorityIntentionActionWrapper implements HighPriorityAction {
protected HighPriorityIntentionActionWrapper(@NotNull IntentionAction action) {
super(action);
}
}
private static class NormalPriorityIntentionActionWrapper extends PriorityIntentionActionWrapper {
protected NormalPriorityIntentionActionWrapper(@NotNull IntentionAction action) {
super(action);
}
}
private static class LowPriorityIntentionActionWrapper extends PriorityIntentionActionWrapper implements LowPriorityAction {
protected LowPriorityIntentionActionWrapper(@NotNull IntentionAction action) {
super(action);
}
}
@NotNull
public static IntentionAction highPriority(@NotNull IntentionAction action) {
return new HighPriorityIntentionActionWrapper(action);
}
@NotNull
public static IntentionAction normalPriority(@NotNull IntentionAction action) {
return new NormalPriorityIntentionActionWrapper(action);
}
@NotNull
public static IntentionAction lowPriority(@NotNull IntentionAction action) {
return new LowPriorityIntentionActionWrapper(action);
}
}
@@ -0,0 +1,85 @@
/*
* 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.codeInsight.intention.impl;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* @author Danila Ponomarenko
*/
public abstract class PriorityLocalQuickFixWrapper implements LocalQuickFix {
private LocalQuickFix fix;
private PriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) {
this.fix = fix;
}
@NotNull
@Override
public String getName() {
return fix.getName();
}
@NotNull
@Override
public String getFamilyName() {
return fix.getFamilyName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
fix.applyFix(project, descriptor);
}
private static class HighPriorityLocalQuickFixWrapper extends PriorityLocalQuickFixWrapper implements HighPriorityAction {
protected HighPriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) {
super(fix);
}
}
private static class NormalPriorityLocalQuickFixWrapper extends PriorityLocalQuickFixWrapper {
protected NormalPriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) {
super(fix);
}
}
private static class LowPriorityLocalQuickFixWrapper extends PriorityLocalQuickFixWrapper implements LowPriorityAction {
protected LowPriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) {
super(fix);
}
}
@NotNull
public static LocalQuickFix highPriority(@NotNull LocalQuickFix fix) {
return new HighPriorityLocalQuickFixWrapper(fix);
}
@NotNull
public static LocalQuickFix normalPriority(@NotNull LocalQuickFix fix) {
return new NormalPriorityLocalQuickFixWrapper(fix);
}
@NotNull
public static LocalQuickFix lowPriority(@NotNull LocalQuickFix fix) {
return new LowPriorityLocalQuickFixWrapper(fix);
}
}
@@ -121,7 +121,7 @@ public class AutoPopupController implements Disposable {
PsiFile file = PsiDocumentManager.getInstance(myProject).getPsiFile(editor.getDocument());
if (file != null && condition != null && !condition.value(file)) return;
CompletionAutoPopupHandler.invokeCompletion(CompletionType.BASIC, true, myProject, editor, 0);
CompletionAutoPopupHandler.invokeCompletion(CompletionType.BASIC, true, myProject, editor, 0, false);
}
});
}
@@ -100,14 +100,18 @@ public class CodeCompletionHandlerBase {
public final void invokeCompletion(final Project project, final Editor editor) {
try {
invokeCompletion(project, editor, 1, false);
invokeCompletion(project, editor, 1);
}
catch (IndexNotReadyException e) {
DumbService.getInstance(project).showDumbModeNotification("Code completion is not available here while indices are being built");
}
}
public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time, boolean hasModifiers) {
public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time) {
invokeCompletion(project, editor, time, false, false);
}
public final void invokeCompletion(@NotNull final Project project, @NotNull final Editor editor, int time, boolean hasModifiers, boolean restarted) {
final PsiFile psiFile = PsiUtilBase.getPsiFileInEditor(editor, project);
assert psiFile != null : "no PSI file: " + FileDocumentManager.getInstance().getFile(editor.getDocument());
@@ -210,22 +214,8 @@ public class CodeCompletionHandlerBase {
};
if (autopopup) {
CommandProcessor.getInstance().runUndoTransparentAction(initCmd);
int offset = editor.getCaretModel().getOffset();
int psiOffset = Math.max(0, offset - 1);
PsiElement elementAt = InjectedLanguageUtil.findInjectedElementNoCommit(psiFile, psiOffset);
if (elementAt == null) {
elementAt = psiFile.findElementAt(psiOffset);
}
if (elementAt == null) return;
Language language = PsiUtilBase.findLanguageFromElement(elementAt);
for (CompletionConfidence confidence : CompletionConfidenceEP.forLanguage(language)) {
final ThreeState result = confidence.shouldSkipAutopopup(elementAt, psiFile, offset);
if (result == ThreeState.YES) return;
if (result == ThreeState.NO) break;
if (!restarted && shouldSkipAutoPopup(editor, psiFile)) {
return;
}
} else {
CommandProcessor.getInstance().executeCommand(project, initCmd, null, null);
@@ -234,6 +224,30 @@ public class CodeCompletionHandlerBase {
insertDummyIdentifier(initializationContext[0], hasModifiers, time);
}
private static boolean shouldSkipAutoPopup(Editor editor, PsiFile psiFile) {
int offset = editor.getCaretModel().getOffset();
int psiOffset = Math.max(0, offset - 1);
PsiElement elementAt = InjectedLanguageUtil.findInjectedElementNoCommit(psiFile, psiOffset);
if (elementAt == null) {
elementAt = psiFile.findElementAt(psiOffset);
}
if (elementAt == null) return true;
Language language = PsiUtilBase.findLanguageFromElement(elementAt);
for (CompletionConfidence confidence : CompletionConfidenceEP.forLanguage(language)) {
final ThreeState result = confidence.shouldSkipAutopopup(elementAt, psiFile, offset);
if (result == ThreeState.YES) {
return true;
}
if (result == ThreeState.NO) {
return false;
}
}
return false;
}
@NotNull
private LookupImpl obtainLookup(Editor editor) {
LookupImpl existing = (LookupImpl)LookupManager.getActiveLookup(editor);
@@ -658,7 +658,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
if (phase.checkExpired()) return;
CompletionAutoPopupHandler.invokeCompletion(myParameters.getCompletionType(),
isAutopopupCompletion(), project, myEditor, myParameters.getInvocationCount());
isAutopopupCompletion(), project, myEditor, myParameters.getInvocationCount(), true);
}
});
}
@@ -47,7 +47,7 @@ public abstract class BaseCodeCompletionAction extends AnAction implements HintM
assert project != null;
assert editor != null;
InputEvent inputEvent = e.getInputEvent();
new CodeCompletionHandlerBase(type).invokeCompletion(project, editor, time, inputEvent != null && inputEvent.getModifiers() != 0);
new CodeCompletionHandlerBase(type).invokeCompletion(project, editor, time, inputEvent != null && inputEvent.getModifiers() != 0, false);
}
@Override
@@ -59,25 +59,22 @@ public class CamelHumpMatcher extends PrefixMatcher {
String prefix = applyMiddleMatching(myPrefix);
if (!caseSensitive) {
return NameUtil.buildCompletionMatcher(prefix, 0, true, true);
return NameUtil.buildMatcher(prefix, NameUtil.MatchingCaseSensitivity.NONE);
}
switch (CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE) {
case CodeInsightSettings.NONE:
return NameUtil.buildCompletionMatcher(prefix, 0, true, true);
return NameUtil.buildMatcher(prefix, NameUtil.MatchingCaseSensitivity.NONE);
case CodeInsightSettings.FIRST_LETTER:
int exactPrefixLen = prefix.startsWith("*") ? 0 : 1;
return NameUtil.buildCompletionMatcher(prefix, exactPrefixLen, true, true);
case CodeInsightSettings.ALL:
return NameUtil.buildCompletionMatcher(prefix, 1, false, false);
return NameUtil.buildMatcher(prefix, NameUtil.MatchingCaseSensitivity.FIRST_LETTER);
default:
return NameUtil.buildCompletionMatcher(prefix, 0, true, false);
return NameUtil.buildMatcher(prefix, NameUtil.MatchingCaseSensitivity.ALL);
}
}
public static String applyMiddleMatching(String prefix) {
if (Registry.is("ide.completion.middle.matching") && !prefix.isEmpty() && !ApplicationManager.getApplication().isUnitTestMode()) {
return " " + StringUtil.replace(prefix, ".", ". ").trim();
return "*" + StringUtil.replace(prefix, ".", ". ").trim();
}
return prefix;
}
@@ -147,10 +147,7 @@ public class CompletionServiceImpl extends CompletionService{
Iterable<TextRange> fragments = matcher.matchingFragments(ls);
if (fragments != null) {
Iterator<TextRange> iterator = fragments.iterator();
if (!ls.isEmpty() && prefix.charAt(0) == ls.charAt(0)) {
return false;
}
if (iterator.hasNext() && iterator.next().contains(0)) {
if (!iterator.hasNext() || MinusculeMatcher.isStartMatch(ls, iterator.next().getStartOffset())) {
return false;
}
}
@@ -79,7 +79,7 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate {
public static void invokeCompletion(CompletionType completionType,
boolean autopopup,
Project project, Editor editor, int time) {
Project project, Editor editor, int time, boolean restart) {
if (editor.isDisposed()) return;
// retrieve the injected file from scratch since our typing might have destroyed the old one completely
@@ -94,7 +94,7 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate {
}
Editor newEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(topLevelEditor, topLevelFile);
try {
new CodeCompletionHandlerBase(completionType, false, autopopup, false).invokeCompletion(project, newEditor, time, false);
new CodeCompletionHandlerBase(completionType, false, autopopup, false).invokeCompletion(project, newEditor, time, false, restart);
}
catch (IndexNotReadyException ignored) {
}
@@ -12,6 +12,7 @@ import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.text.CharArrayUtil;
@@ -20,6 +21,7 @@ import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.List;
/**
* @author yole
@@ -40,9 +42,9 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
Document document = editor.getDocument();
int selStartLine = document.getLineNumber(startOffsets[0]);
int selEndLine = document.getLineNumber(endOffsets[0]);
if (selStartLine == selEndLine) {
return null;
}
//if (selStartLine == selEndLine) {
// return null;
//}
// check that selection starts at or before the first non-whitespace character on a line
for (int offset = startOffsets[0] - 1; offset >= document.getLineStartOffset(selStartLine); offset--) {
if (!Character.isWhitespace(document.getCharsSequence().charAt(offset))) {
@@ -132,20 +134,29 @@ public class CopyPasteIndentProcessor implements CopyPastePostProcessor<IndentTr
@Override
public void run() {
String pastedText = document.getText(TextRange.create(bounds));
if (pastedText.trim().indexOf("\n") < 0) {
int startLine = document.getLineNumber(bounds.getStartOffset());
int endLine = document.getLineNumber(bounds.getEndOffset());
if (!pastedText.trim().contains("\n") && startLine == endLine) {
// don't indent single-line text
return;
}
int startLine = document.getLineNumber(bounds.getStartOffset());
int endLine = document.getLineNumber(bounds.getEndOffset());
int startLineStart = document.getLineStartOffset(startLine);
// don't indent first line if there's any text before it
final String textBeforeFirstLine = document.getText(new TextRange(startLineStart, bounds.getStartOffset()));
if (textBeforeFirstLine.trim().length() == 0) {
EditorActionUtil.indentLine(project, editor, startLine, -value.getFirstLineLeadingSpaces());
}
final List<String> strings = StringUtil.split(pastedText, "\n");
//if (strings.get(strings.size() - 1))
if (strings.get(0).trim().startsWith("def") ||
strings.get(0).trim().startsWith("class")) endLine -=1;
for (int i = startLine+1; i <= endLine; i++) {
EditorActionUtil.indentLine(project, editor, i, caretColumn - value.getIndent());
EditorActionUtil.indentLine(project, editor, i, value.getIndent());
}
indented.set(Boolean.TRUE);
}
@@ -1396,14 +1396,15 @@ public class LookupImpl extends LightweightHint implements LookupEx, Disposable
myScrollBarIncreaseButton.setPreferredSize(buttonSize);
myScrollBarIncreaseButton.setMinimumSize(buttonSize);
myScrollBarIncreaseButton.setMaximumSize(buttonSize);
myScrollPane.getVerticalScrollBar().revalidate();
myScrollPane.getVerticalScrollBar().repaint();
JScrollBar scrollBar = myScrollPane.getVerticalScrollBar();
scrollBar.revalidate();
scrollBar.repaint();
final Dimension iconSize = myProcessIcon.getPreferredSize();
myIconPanel.setBounds(getWidth() - iconSize.width, 0, iconSize.width, iconSize.height);
myIconPanel.setBounds(getWidth() - iconSize.width - (scrollBar.isVisible() ? scrollBar.getWidth() : 0), 0, iconSize.width, iconSize.height);
final Dimension sortSize = mySortingLabel.getPreferredSize();
final Point sbLocation = SwingUtilities.convertPoint(myScrollPane.getVerticalScrollBar(), 0, 0, myLayeredPane);
final Point sbLocation = SwingUtilities.convertPoint(scrollBar, 0, 0, myLayeredPane);
final int sortHeight = Math.max(adHeight, mySortingLabel.getPreferredSize().height);
mySortingLabel.setBounds(sbLocation.x, getHeight() - sortHeight, sortSize.width, sortHeight);
@@ -27,6 +27,6 @@ public class ClassNameCompleteMacro extends BaseCompleteMacro {
}
protected void invokeCompletionHandler(Project project, Editor editor) {
new CodeCompletionHandlerBase(CompletionType.BASIC, false, false, true).invokeCompletion(project, editor, 2, false);
new CodeCompletionHandlerBase(CompletionType.BASIC, false, false, true).invokeCompletion(project, editor, 2);
}
}
@@ -29,6 +29,6 @@ public class CompleteMacro extends BaseCompleteMacro {
protected void invokeCompletionHandler(Project project, Editor editor) {
new CodeCompletionHandlerBase(CompletionType.BASIC, ApplicationManager.getApplication().isUnitTestMode(), false, true)
.invokeCompletion(project, editor, 1, false);
.invokeCompletion(project, editor, 1);
}
}
@@ -27,6 +27,6 @@ public class CompleteSmartMacro extends BaseCompleteMacro {
}
protected void invokeCompletionHandler(Project project, Editor editor) {
new CodeCompletionHandlerBase(CompletionType.SMART).invokeCompletion(project, editor, 1, false);
new CodeCompletionHandlerBase(CompletionType.SMART).invokeCompletion(project, editor, 1);
}
}
@@ -300,7 +300,7 @@ public abstract class SpeedSearchBase<Comp extends JComponent> extends SpeedSear
if (!UIUtil.isReallyTypedEvent(e)) return;
char c = e.getKeyChar();
if (Character.isLetterOrDigit(c) || c == '_' || c == '*' || c == '/' || c == ':') {
if (Character.isLetterOrDigit(c) || c == '_' || c == '*' || c == '/' || c == ':' || c == '.' || c == '#') {
manageSearchPopup(new SearchPopup(String.valueOf(c)));
e.consume();
}
@@ -26,6 +26,7 @@ import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.CollectionFactory;
import com.intellij.util.text.Matcher;
import org.jetbrains.annotations.NonNls;
import java.util.ArrayList;
@@ -120,8 +121,13 @@ public class NameUtilTest extends UsefulTestCase {
assertMatches("foo bar", "fooGooBar");
assertMatches("foo bar", "fooGoo bar");
assertDoesntMatch(" b", "fbi");
assertTrue(NameUtil.buildCompletionMatcher(" us", 0, true, true).matches("getUsage"));
assertTrue(NameUtil.buildCompletionMatcher(" us", 0, true, true).matches("getMyUsage"));
assertDoesntMatch(" for", "performAction");
assertTrue(caseInsensitiveMatcher(" us").matches("getUsage"));
assertTrue(caseInsensitiveMatcher(" us").matches("getMyUsage"));
}
private static Matcher caseInsensitiveMatcher(String pattern) {
return NameUtil.buildMatcher(pattern, NameUtil.MatchingCaseSensitivity.NONE);
}
public void testStartDot() {
@@ -194,11 +200,11 @@ public class NameUtilTest extends UsefulTestCase {
}
public void testLowerCaseWords() throws Exception {
assertTrue(matches("uct", "unit_controller_test", true));
assertTrue(matches("unictest", "unit_controller_test", true));
assertTrue(matches("uc", "unit_controller_test", true));
assertFalse(matches("nc", "unit_controller_test", true));
assertFalse(matches("utc", "unit_controller_test", true));
assertTrue(matches("uct", "unit_controller_test"));
assertTrue(matches("unictest", "unit_controller_test"));
assertTrue(matches("uc", "unit_controller_test"));
assertFalse(matches("nc", "unit_controller_test"));
assertFalse(matches("utc", "unit_controller_test"));
}
public void testObjectiveCCases() throws Exception {
@@ -221,9 +227,9 @@ public class NameUtilTest extends UsefulTestCase {
assertMatches("*Git*", "AtpGenerationItem");
assertMatches("Collec*Util*", "CollectionUtils");
assertMatches("Collec*Util*", "CollectionUtilsTest");
assertTrue(NameUtil.buildCompletionMatcher("*us", 0, true, true).matches("usage"));
assertTrue(NameUtil.buildCompletionMatcher(" us", 0, true, true).matches("usage"));
assertTrue(NameUtil.buildCompletionMatcher(" fo. ba", 0, true, true).matches("getFoo.getBar"));
assertTrue(caseInsensitiveMatcher("*us").matches("usage"));
assertTrue(caseInsensitiveMatcher(" us").matches("usage"));
assertTrue(caseInsensitiveMatcher(" fo. ba").matches("getFoo.getBar"));
assertMatches(" File. sepa", "File.separator");
assertMatches(" File. sepa", "File._separator");
assertMatches(" File. _sepa", "File._separator");
@@ -231,32 +237,35 @@ public class NameUtilTest extends UsefulTestCase {
}
public void testMiddleMatchingFirstLetterSensitive() {
assertTrue(NameUtil.buildCompletionMatcher(" cl", 1, true, true).matches("getClass"));
assertTrue(NameUtil.buildCompletionMatcher(" EUC-", 1, true, true).matches("x-EUC-TW"));
assertTrue(NameUtil.buildCompletionMatcher(" a", 1, true, true).matches("aaa"));
assertFalse(NameUtil.buildCompletionMatcher(" a", 1, true, true).matches("Aaa"));
assertFalse(NameUtil.buildCompletionMatcher(" a", 1, true, true).matches("Aaa"));
assertFalse(NameUtil.buildCompletionMatcher(" _bl", 1, true, true).matches("_top"));
assertTrue(firstLetterMatcher(" cl").matches("getClass"));
assertTrue(firstLetterMatcher(" EUC-").matches("x-EUC-TW"));
assertTrue(firstLetterMatcher(" a").matches("aaa"));
assertFalse(firstLetterMatcher(" a").matches("Aaa"));
assertFalse(firstLetterMatcher(" a").matches("Aaa"));
assertFalse(firstLetterMatcher(" _bl").matches("_top"));
}
private static Matcher firstLetterMatcher(String pattern) {
return NameUtil.buildMatcher(pattern, NameUtil.MatchingCaseSensitivity.FIRST_LETTER);
}
public void testSpaceInCompletionPrefix() throws Exception {
assertTrue(NameUtil.buildCompletionMatcher("create ", 0, true, true).matches("create module"));
assertTrue(caseInsensitiveMatcher("create ").matches("create module"));
}
public void testLong() throws Exception {
assertTrue(matches("Product.findByDateAndNameGreaterThanEqualsAndQualityGreaterThanEqual", "Product.findByDateAndNameGreaterThanEqualsAndQualityGreaterThanEqualsIntellijIdeaRulezzz", false));
assertTrue(matches("Product.findByDateAndNameGreaterThanEqualsAndQualityGreaterThanEqual", "Product.findByDateAndNameGreaterThanEqualsAndQualityGreaterThanEqualsIntellijIdeaRulezzz"));
}
private static void assertMatches(@NonNls String pattern, @NonNls String name) {
assertTrue(matches(pattern, name, false));
assertTrue(matches(pattern, name));
}
private static void assertDoesntMatch(@NonNls String pattern, @NonNls String name) {
assertFalse(matches(pattern, name, false));
assertFalse(matches(pattern, name));
}
private static boolean matches(@NonNls final String pattern, @NonNls final String name, final boolean lowerCaseWords) {
//System.out.println("\n--- " + name + " " + lowerCaseWords);
return NameUtil.buildMatcher(pattern, 0, true, true, lowerCaseWords).matches(name);
private static boolean matches(@NonNls final String pattern, @NonNls final String name) {
return caseInsensitiveMatcher(pattern).matches(name);
}
public void testLowerCaseHumps() {
@@ -380,6 +389,7 @@ public class NameUtilTest extends UsefulTestCase {
}
public void testPreferStartMatchToMiddleMatch() {
assertPreference(" fb", "FooBar", "_fooBar", NameUtil.MatchingCaseSensitivity.NONE);
assertPreference("*foo", "barFoo", "foobar");
assertPreference("*f", "barfoo", "barFoo");
assertPreference("*f", "barfoo", "foo");
@@ -941,7 +941,7 @@ public class CodeInsightTestFixtureImpl extends BaseFixture implements CodeInsig
}
};
Editor editor = getCompletionEditor();
handler.invokeCompletion(getProject(), editor, invocationCount, false);
handler.invokeCompletion(getProject(), editor, invocationCount);
PsiDocumentManager.getInstance(getProject()).commitAllDocuments(); // to compare with file text
}
}, null, null);
@@ -269,18 +269,31 @@ public class MinusculeMatcher implements Matcher {
fragmentCount++;
}
if (first == null) {
return 0;
}
int commonStart = 0;
while (commonStart < name.length() && commonStart < myPattern.length && name.charAt(commonStart) == myPattern[commonStart]) {
commonStart++;
}
boolean prefixMatching = first != null && first.getStartOffset() == 0;
boolean middleWordStart = first != null && first.getStartOffset() > 0 && NameUtil.isWordStart(name, first.getStartOffset());
int startIndex = first != null ? first.getStartOffset() : 42;
int startIndex = first.getStartOffset();
boolean prefixMatching = isStartMatch(name, startIndex);
boolean middleWordStart = !prefixMatching && NameUtil.isWordStart(name, first.getStartOffset());
return -fragmentCount + matchingCase * 10 + commonStart - startIndex + (prefixMatching ? 2 : middleWordStart ? 1 : 0) * 100;
}
public static boolean isStartMatch(String name, int startIndex) {
for (int i = 0; i < startIndex; i++) {
if (!NameUtil.isWordSeparator(name.charAt(i))) {
return false;
}
}
return true;
}
@Override
public boolean matches(String name) {
return matchingFragments(name) != null;
@@ -358,7 +358,7 @@ public class NameUtil {
}
return i - 1;
}
while (i < text.length() && !isWordStart(text, i) && !!Character.isLetterOrDigit(text.charAt(i))) {
while (i < text.length() && !isWordStart(text, i) && Character.isLetterOrDigit(text.charAt(i))) {
i++;
}
return i;
@@ -384,6 +384,8 @@ public class NameUtil {
boolean matches(String name);
}
@SuppressWarnings("UnusedDeclaration")
@Deprecated
public static com.intellij.util.text.Matcher buildCompletionMatcher(String pattern, int exactPrefixLen, boolean allowToUpper, boolean allowToLower) {
MatchingCaseSensitivity options = !allowToLower && !allowToUpper ? MatchingCaseSensitivity.ALL : exactPrefixLen > 0 ? MatchingCaseSensitivity.FIRST_LETTER : MatchingCaseSensitivity.NONE;
return buildMatcher(pattern, options);
+1
View File
@@ -126,6 +126,7 @@
<membersContributor implementation="org.jetbrains.plugins.groovy.gant.GantMemberContributor"/>
<typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.GrContainerTypeConverter"/>
<typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.types.GrStringTypeConverter"/>
<typeConverter implementation="org.jetbrains.plugins.groovy.gpp.GppTypeConverter"/>
<expectedTypesContributor implementation="org.jetbrains.plugins.groovy.gpp.GppExpectedTypesContributor"/>
@@ -1,6 +1,8 @@
package org.jetbrains.plugins.groovy.lang.psi;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -19,4 +21,20 @@ public abstract class GrTypeConverter {
@Nullable
public abstract Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context);
protected static boolean resolvesTo(PsiType type, String fqn) {
if (type instanceof PsiClassType) {
final PsiClass resolved = ((PsiClassType)type).resolve();
return resolved != null && fqn.equals(resolved.getQualifiedName());
}
return false;
}
protected static boolean isEnum(PsiType type) {
if (type instanceof PsiClassType) {
final PsiClass resolved = ((PsiClassType)type).resolve();
return resolved != null && resolved.isEnum();
}
return false;
}
}
@@ -0,0 +1,48 @@
/*
* 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 org.jetbrains.plugins.groovy.lang.psi.impl.types;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.InheritanceUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import static com.intellij.psi.CommonClassNames.JAVA_LANG_BOOLEAN;
import static com.intellij.psi.CommonClassNames.JAVA_LANG_CLASS;
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_GSTRING;
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.JAVA_LANG_CHAR_SEQUENCE;
/**
* @author Max Medvedev
*/
public class GrStringTypeConverter extends GrTypeConverter {
@Override
public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
if (isMethodCallConversion(context)) return null;
if (!GroovyConfigUtils.getInstance().isVersionAtLeast(context, GroovyConfigUtils.GROOVY1_8)) return null;
if (!(InheritanceUtil.isInheritor(rType, JAVA_LANG_CHAR_SEQUENCE) || InheritanceUtil.isInheritor(rType, GROOVY_LANG_GSTRING))) {
return null;
}
if (lType == PsiType.BOOLEAN || resolvesTo(lType, JAVA_LANG_BOOLEAN)) return true;
if (resolvesTo(lType, JAVA_LANG_CLASS)) return true;
if (isEnum(lType)) return true;
return null;
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import java.util.Map;
import java.util.Set;
import static com.intellij.psi.CommonClassNames.JAVA_IO_FILE;
import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses;
/**
@@ -44,13 +45,13 @@ public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer {
simpleTypes.put("withDataOutputStream", "java.io.DataOutputStream");
simpleTypes.put("withDataInputStream", "java.io.DataInputStream");
simpleTypes.put("eachLine", "java.lang.String");
simpleTypes.put("eachFile", "java.io.File");
simpleTypes.put("eachDir", "java.io.File");
simpleTypes.put("eachFileRecurse", "java.io.File");
simpleTypes.put("traverse", "java.io.File");
simpleTypes.put("eachDirRecurse", "java.io.File");
simpleTypes.put("eachFileMatch", "java.io.File");
simpleTypes.put("eachDirMatch", "java.io.File");
simpleTypes.put("eachFile", JAVA_IO_FILE);
simpleTypes.put("eachDir", JAVA_IO_FILE);
simpleTypes.put("eachFileRecurse", JAVA_IO_FILE);
simpleTypes.put("traverse", JAVA_IO_FILE);
simpleTypes.put("eachDirRecurse", JAVA_IO_FILE);
simpleTypes.put("eachFileMatch", JAVA_IO_FILE);
simpleTypes.put("eachDirMatch", JAVA_IO_FILE);
simpleTypes.put("withReader", "java.io.Reader");
simpleTypes.put("withWriter", "java.io.Writer");
simpleTypes.put("withWriterAppend", "java.io.Writer");
@@ -259,7 +260,7 @@ public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer {
return res;
}
if (TypesUtil.isClassType(iterType, CommonClassNames.JAVA_LANG_STRING) || TypesUtil.isClassType(iterType, "java.io.File")) {
if (TypesUtil.isClassType(iterType, CommonClassNames.JAVA_LANG_STRING) || TypesUtil.isClassType(iterType, JAVA_IO_FILE)) {
return TypesUtil.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, context);
}
@@ -54,6 +54,7 @@ public final class GroovyCommonClassNames {
@NonNls public static final String GROOVY_TRANSFORM_COMPILE_STATIC = "groovy.transform.CompileStatic";
@NonNls public static final String GROOVY_TRANSFORM_TYPE_CHECKED = "groovy.transform.TypeChecked";
@NonNls public static final String GROOVY_TRANSFORM_TYPE_CHECKING_MODE = "groovy.transform.TypeCheckingMode";
@NonNls public static final String JAVA_LANG_CHAR_SEQUENCE = "java.lang.CharSequence";
private GroovyCommonClassNames() {
@@ -604,11 +604,11 @@ println new Bar().zzz
}
class GppProjectDescriptor extends DefaultLightProjectDescriptor {
static def instance = new GppProjectDescriptor()
public static final instance = new GppProjectDescriptor()
@Override
public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) {
final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary("GROOVY++").getModifiableModel();
final Library.ModifiableModel modifiableModel = model.moduleLibraryTable.createLibrary("GROOVY++").modifiableModel;
modifiableModel.addRoot(JarFileSystem.instance.refreshAndFindFileByPath(TestUtils.absoluteTestDataPath + "mockGroovypp/groovypp-0.9.0_1.8.2.jar!/"), OrderRootType.CLASSES)
modifiableModel.addRoot(JarFileSystem.instance.refreshAndFindFileByPath(TestUtils.mockGroovy1_7LibraryName + "!/"), OrderRootType.CLASSES);
modifiableModel.commit();