mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
-62
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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.LookupElement;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class AbstractBasicToClassNameDelegator extends CompletionContributor {
|
||||
protected abstract boolean isClassNameCompletionSupported(CompletionResultSet result, PsiFile file, PsiElement position);
|
||||
|
||||
protected void updateProperties(LookupElement lookupElement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(final CompletionParameters parameters, final CompletionResultSet result) {
|
||||
if (parameters.getCompletionType() != CompletionType.BASIC || parameters.getInvocationCount() == 0) return;
|
||||
|
||||
final PsiFile file = parameters.getOriginalFile();
|
||||
final PsiElement position = parameters.getPosition();
|
||||
if (!isClassNameCompletionSupported(result, file, position)) return;
|
||||
|
||||
final boolean empty = result.runRemainingContributors(parameters, true).isEmpty();
|
||||
|
||||
final CompletionParameters classParams;
|
||||
|
||||
final int invocationCount = parameters.getInvocationCount();
|
||||
if (empty) {
|
||||
classParams = parameters.withType(CompletionType.CLASS_NAME);
|
||||
}
|
||||
else if (invocationCount > 1) {
|
||||
classParams = parameters.withType(CompletionType.CLASS_NAME).withInvocationCount(invocationCount - 1);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
CompletionService.getCompletionService().getVariantsFromContributors(classParams, null, new Consumer<CompletionResult>() {
|
||||
public void consume(final CompletionResult lookupElement) {
|
||||
updateProperties(lookupElement.getLookupElement());
|
||||
result.passResult(lookupElement);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+23
-25
@@ -22,6 +22,7 @@ import com.intellij.lang.LangBundle;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.fileTypes.impl.CustomSyntaxTableFileType;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.patterns.PsiJavaElementPattern;
|
||||
@@ -30,7 +31,6 @@ import com.intellij.psi.filters.ClassFilter;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.filters.TrueFilter;
|
||||
import com.intellij.psi.filters.element.ExcludeDeclaredFilter;
|
||||
import com.intellij.psi.filters.types.AssignableFromFilter;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Consumer;
|
||||
@@ -52,10 +52,10 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet _result) {
|
||||
if (parameters.isExtendedCompletion()) {
|
||||
if (parameters.getCompletionType() == CompletionType.CLASS_NAME ||
|
||||
parameters.isExtendedCompletion() && mayContainClassName(parameters)) {
|
||||
CompletionResultSet result = _result.withPrefixMatcher(CompletionUtil.findReferenceOrAlphanumericPrefix(parameters));
|
||||
addAllClasses(parameters, parameters.getInvocationCount() <= 1,
|
||||
JavaCompletionSorting.addJavaSorting(parameters, result).getPrefixMatcher(), new Consumer<LookupElement>() {
|
||||
addAllClasses(parameters, parameters.getInvocationCount() <= 1, result.getPrefixMatcher(), new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
_result.addElement(element);
|
||||
@@ -64,28 +64,29 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean mayContainClassName(CompletionParameters parameters) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
PsiFile file = position.getContainingFile();
|
||||
if (file instanceof PsiPlainTextFile || file.getFileType() instanceof CustomSyntaxTableFileType) {
|
||||
return true;
|
||||
}
|
||||
if (SkipAutopopupInStrings.isInStringLiteral(position)) {
|
||||
return true;
|
||||
}
|
||||
if (PsiTreeUtil.getParentOfType(position, PsiComment.class, false) != null) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void addAllClasses(CompletionParameters parameters,
|
||||
final boolean filterByScope,
|
||||
@NotNull final PrefixMatcher matcher,
|
||||
@NotNull final Consumer<LookupElement> consumer) {
|
||||
final PsiElement insertedElement = parameters.getPosition();
|
||||
|
||||
final ElementFilter filter;
|
||||
if (JavaSmartCompletionContributor.AFTER_THROW_NEW.accepts(insertedElement) ||
|
||||
JavaCompletionContributor.INSIDE_METHOD_THROWS_CLAUSE.accepts(insertedElement) ||
|
||||
JavaCompletionContributor.IN_CATCH_TYPE.accepts(insertedElement) ||
|
||||
JavaCompletionContributor.IN_MULTI_CATCH_TYPE.accepts(insertedElement)) {
|
||||
filter = new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE);
|
||||
}
|
||||
else if (JavaCompletionContributor.IN_RESOURCE_TYPE.accepts(insertedElement)) {
|
||||
filter = new AssignableFromFilter(CommonClassNames.JAVA_LANG_AUTO_CLOSEABLE);
|
||||
}
|
||||
else if (IN_TYPE_PARAMETER.accepts(insertedElement)) {
|
||||
filter = new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class));
|
||||
}
|
||||
else {
|
||||
filter = TrueFilter.INSTANCE;
|
||||
}
|
||||
final ElementFilter filter =
|
||||
IN_TYPE_PARAMETER.accepts(insertedElement) ? new ExcludeDeclaredFilter(new ClassFilter(PsiTypeParameter.class)) : TrueFilter.INSTANCE;
|
||||
|
||||
final boolean inJavaContext = parameters.getPosition() instanceof PsiIdentifier;
|
||||
final boolean afterNew = AFTER_NEW.accepts(insertedElement);
|
||||
@@ -107,13 +108,10 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
|
||||
final boolean lookingForAnnotations = psiElement().afterLeaf("@").accepts(insertedElement);
|
||||
final boolean pkgContext = JavaCompletionUtil.inSomePackage(insertedElement);
|
||||
AllClassesGetter.processJavaClasses(parameters, matcher, filterByScope, new Consumer<PsiClass>() {
|
||||
@Override
|
||||
public void consume(PsiClass psiClass) {
|
||||
if (lookingForAnnotations && !psiClass.isAnnotationType()) return;
|
||||
|
||||
if (filter.isAcceptable(psiClass, insertedElement)) {
|
||||
if (!inJavaContext) {
|
||||
consumer.consume(AllClassesGetter.createLookupItem(psiClass, AllClassesGetter.TRY_SHORTENING));
|
||||
@@ -179,8 +177,8 @@ public class JavaClassNameCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
private static boolean shouldShowSecondSmartCompletionHint(final CompletionParameters parameters) {
|
||||
return parameters.getCompletionType() == CompletionType.CLASS_NAME &&
|
||||
parameters.getInvocationCount() == 1 &&
|
||||
return parameters.getCompletionType() == CompletionType.BASIC &&
|
||||
parameters.getInvocationCount() == 2 &&
|
||||
parameters.getOriginalFile().getLanguage().isKindOf(JavaLanguage.INSTANCE);
|
||||
}
|
||||
}
|
||||
|
||||
+26
-12
@@ -19,27 +19,41 @@ import com.intellij.codeInsight.lookup.AutoCompletionPolicy;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.lang.StdLanguages;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.util.Consumer;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class XmlBasicToClassNameDelegator extends AbstractBasicToClassNameDelegator {
|
||||
public class XmlBasicToClassNameDelegator extends CompletionContributor {
|
||||
|
||||
@Override
|
||||
protected boolean isClassNameCompletionSupported(CompletionResultSet result, PsiFile file, PsiElement position) {
|
||||
if (!JavaCompletionContributor.mayStartClassName(result)) return false;
|
||||
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) {
|
||||
PsiElement position = parameters.getPosition();
|
||||
if (parameters.getCompletionType() != CompletionType.BASIC ||
|
||||
!JavaCompletionContributor.mayStartClassName(result) ||
|
||||
!position.getContainingFile().getLanguage().isKindOf(StdLanguages.XML)) {
|
||||
return;
|
||||
}
|
||||
|
||||
return file.getLanguage().isKindOf(StdLanguages.XML);
|
||||
}
|
||||
final boolean empty = result.runRemainingContributors(parameters, true).isEmpty();
|
||||
|
||||
@Override
|
||||
protected void updateProperties(LookupElement lookupElement) {
|
||||
JavaPsiClassReferenceElement classElement = lookupElement.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
|
||||
if (classElement != null) {
|
||||
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
if (!empty && parameters.getInvocationCount() == 0) {
|
||||
result.restartCompletionWhenNothingMatches();
|
||||
}
|
||||
|
||||
if (empty || parameters.isExtendedCompletion()) {
|
||||
CompletionService.getCompletionService().getVariantsFromContributors(parameters.delegateToClassName(), null, new Consumer<CompletionResult>() {
|
||||
public void consume(final CompletionResult completionResult) {
|
||||
LookupElement lookupElement = completionResult.getLookupElement();
|
||||
JavaPsiClassReferenceElement classElement = lookupElement.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
|
||||
if (classElement != null) {
|
||||
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
}
|
||||
lookupElement.putUserData(XmlCompletionContributor.WORD_COMPLETION_COMPATIBLE, Boolean.TRUE); //todo think of a less dirty interaction
|
||||
result.passResult(completionResult);
|
||||
}
|
||||
});
|
||||
}
|
||||
lookupElement.putUserData(XmlCompletionContributor.WORD_COMPLETION_COMPATIBLE, Boolean.TRUE); //todo think of a less dirty interaction
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+60
-4
@@ -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() {
|
||||
|
||||
+1
-1
@@ -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";
|
||||
}
|
||||
|
||||
+10
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.codeInsight.lookup.LookupManager;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
@@ -64,6 +65,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
|
||||
String path = "/afterNewThrowable";
|
||||
|
||||
configureByFile(path + "/before1.java");
|
||||
myFixture.type('\n');
|
||||
checkResultByFile(path + "/after1.java");
|
||||
}
|
||||
|
||||
@@ -80,6 +82,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
|
||||
String path = "/afterNewThrowable";
|
||||
|
||||
configureByFile(path + "/before2.java");
|
||||
myFixture.type('\n');
|
||||
checkResultByFile(path + "/after2.java");
|
||||
}
|
||||
|
||||
@@ -94,6 +97,12 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
|
||||
checkResultByFile(getTestName(false) + "_after.txt");
|
||||
}
|
||||
|
||||
public void testInPropertiesFile() throws Exception {
|
||||
myFixture.configureByText("a.properties", "abc = StrinBui<caret>");
|
||||
complete();
|
||||
myFixture.checkResult("abc = java.lang.StringBuilder<caret>");
|
||||
}
|
||||
|
||||
public void testDoubleStringBuffer() throws Exception {
|
||||
createClass("package java.lang; public class StringBuffer {}");
|
||||
doTest();
|
||||
@@ -198,6 +207,7 @@ public class ClassNameCompletionTest extends LightFixtureCompletionTestCase {
|
||||
private void cleanupVfs() {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
FileDocumentManager.getInstance().saveAllDocuments();
|
||||
for (VirtualFile file : myFixture.getTempDirFixture().getFile("").getChildren()) {
|
||||
try {
|
||||
file.delete(this);
|
||||
|
||||
@@ -329,6 +329,9 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
final File file = new File(deleted);
|
||||
final RootDescriptor rd = pd.rootsIndex.getModuleAndRoot(file);
|
||||
if (rd != null) {
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Applying deleted path from fs event: " + file.getPath());
|
||||
}
|
||||
pd.fsState.registerDeleted(rd.module, file, rd.isTestRoot, timestamps);
|
||||
}
|
||||
else {
|
||||
@@ -341,6 +344,9 @@ final class BuildSession implements Runnable, CanceledStatus {
|
||||
final File file = new File(changed);
|
||||
final RootDescriptor rd = pd.rootsIndex.getModuleAndRoot(file);
|
||||
if (rd != null) {
|
||||
if (Utils.IS_TEST_MODE) {
|
||||
LOG.info("Applying dirty path from fs event: " + file.getPath());
|
||||
}
|
||||
pd.fsState.markDirty(file, rd, timestamps);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -44,6 +44,10 @@ public final class CompletionParameters {
|
||||
myLookup = lookup;
|
||||
}
|
||||
|
||||
public CompletionParameters delegateToClassName() {
|
||||
return withType(CompletionType.CLASS_NAME).withInvocationCount(myInvocationCount - 1);
|
||||
}
|
||||
|
||||
public CompletionParameters withType(CompletionType type) {
|
||||
return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount, myLookup);
|
||||
}
|
||||
@@ -100,6 +104,6 @@ public final class CompletionParameters {
|
||||
}
|
||||
|
||||
public boolean isExtendedCompletion() {
|
||||
return myCompletionType == CompletionType.CLASS_NAME || myCompletionType == CompletionType.BASIC && myInvocationCount >= 2;
|
||||
return myCompletionType == CompletionType.BASIC && myInvocationCount >= 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,5 +4,12 @@ package com.intellij.codeInsight.completion;
|
||||
* @author peter
|
||||
*/
|
||||
public enum CompletionType {
|
||||
BASIC, SMART, @Deprecated CLASS_NAME
|
||||
BASIC,
|
||||
SMART,
|
||||
|
||||
/**
|
||||
* Only to be passed to {@link CompletionService#getVariantsFromContributors(CompletionParameters, CompletionContributor, com.intellij.util.Consumer)}
|
||||
* to invoke special class-name providers for various file types where those class names are applicable (e.g. xml, txt, properties, custom)
|
||||
*/
|
||||
CLASS_NAME
|
||||
}
|
||||
|
||||
+12
-6
@@ -39,17 +39,23 @@ public class SkipAutopopupInStrings extends CompletionConfidence {
|
||||
@NotNull
|
||||
@Override
|
||||
public ThreeState shouldSkipAutopopup(@NotNull PsiElement contextElement, @NotNull PsiFile psiFile, int offset) {
|
||||
ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(PsiUtilBase.getLanguageAtOffset(psiFile, offset));
|
||||
if (definition != null) {
|
||||
if (isStringLiteral(contextElement, definition) || isStringLiteral(contextElement.getParent(), definition) ||
|
||||
isStringLiteralWithError(contextElement, definition) || isStringLiteralWithError(contextElement.getParent(), definition)) {
|
||||
return ThreeState.YES;
|
||||
}
|
||||
if (isInStringLiteral(contextElement)) {
|
||||
return ThreeState.YES;
|
||||
}
|
||||
|
||||
return ThreeState.UNSURE;
|
||||
}
|
||||
|
||||
public static boolean isInStringLiteral(PsiElement element) {
|
||||
ParserDefinition definition = LanguageParserDefinitions.INSTANCE.forLanguage(PsiUtilBase.findLanguageFromElement(element));
|
||||
if (definition == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isStringLiteral(element, definition) || isStringLiteral(element.getParent(), definition) ||
|
||||
isStringLiteralWithError(element, definition) || isStringLiteralWithError(element.getParent(), definition);
|
||||
}
|
||||
|
||||
private static boolean isStringLiteral(PsiElement element, ParserDefinition definition) {
|
||||
return PlatformPatterns.psiElement().withElementType(definition.getStringLiteralElements()).accepts(element);
|
||||
}
|
||||
|
||||
+96
@@ -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);
|
||||
}
|
||||
}
|
||||
+85
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -29,11 +29,11 @@ import org.jetbrains.annotations.NotNull;
|
||||
*/
|
||||
public class DependentSpacingRule {
|
||||
|
||||
enum Anchor {
|
||||
public enum Anchor {
|
||||
MIN_LINE_FEEDS, MAX_LINE_FEEDS
|
||||
}
|
||||
|
||||
enum Trigger {
|
||||
public enum Trigger {
|
||||
HAS_LINE_FEEDS, DOES_NOT_HAVE_LINE_FEEDS
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -86,6 +86,7 @@ public class CodeCompletionHandlerBase {
|
||||
|
||||
public CodeCompletionHandlerBase(CompletionType completionType, boolean invokedExplicitly, boolean autopopup, boolean synchronous) {
|
||||
myCompletionType = completionType;
|
||||
LOG.assertTrue(myCompletionType != CompletionType.CLASS_NAME, "Class name completion shouldn't be invoked directly");
|
||||
this.invokedExplicitly = invokedExplicitly;
|
||||
this.autopopup = autopopup;
|
||||
this.synchronous = synchronous;
|
||||
|
||||
-1
@@ -176,7 +176,6 @@ public class FilePathCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
};
|
||||
extend(CompletionType.CLASS_NAME, psiElement(), provider);
|
||||
extend(CompletionType.BASIC, psiElement(), provider);
|
||||
}
|
||||
|
||||
|
||||
+18
-7
@@ -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);
|
||||
}
|
||||
|
||||
@@ -232,6 +232,7 @@ public class GridCellImpl implements GridCell {
|
||||
return info.
|
||||
setIcon(content.getIcon()).
|
||||
setText(content.getDisplayName()).
|
||||
setTooltipText(content.getDescription()).
|
||||
setActionsContextComponent(content.getActionsContextComponent()).
|
||||
setActions(content.getActions(), content.getPlace());
|
||||
}
|
||||
|
||||
@@ -150,8 +150,10 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
getMemValueContainer(key).removeAssociatedValue(inputId);
|
||||
return;
|
||||
}
|
||||
|
||||
myMap.remove(key); //
|
||||
final ChangeTrackingValueContainer<Value> valueContainer = myMap.get(key);
|
||||
if (valueContainer != null) {
|
||||
valueContainer.dropMergedData();
|
||||
}
|
||||
|
||||
myBackendStorage.removeAllValues(key, inputId);
|
||||
}
|
||||
|
||||
@@ -119,30 +119,33 @@ public class ChangeListStorageImpl implements ChangeListStorage {
|
||||
isCompletelyBroken = true;
|
||||
}
|
||||
|
||||
notifyUser("Local History storage file has become corrupted and was rebuilt.");
|
||||
notifyUser("Local History storage file has become corrupted and will be rebuilt.");
|
||||
}
|
||||
|
||||
|
||||
public static void notifyUser(String message) {
|
||||
final String logFile = PathManager.getLogPath();
|
||||
String createIssuePart = "<br>" +
|
||||
"<br>" +
|
||||
"Please attach log files from <a href=\"file\">" + logFile + "</a><br>" +
|
||||
"to the <a href=\"url\">YouTrack issue</a>";
|
||||
|
||||
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID,
|
||||
"Local History is broken",
|
||||
message + "<br>" +
|
||||
"<br>" +
|
||||
"Please attach log files from <a href=\"file\">" + logFile + "</a><br>" +
|
||||
"to the <a href=\"url\">YouTrack issue</a>",
|
||||
message /*+ createIssuePart*/,
|
||||
NotificationType.ERROR,
|
||||
new NotificationListener() {
|
||||
@Override
|
||||
public void hyperlinkUpdate(@NotNull Notification notification,
|
||||
@NotNull HyperlinkEvent event) {
|
||||
if ("url".equals(event.getDescription())) {
|
||||
BrowserUtil.launchBrowser("http://youtrack.jetbrains.net/issue/IDEA-71270");
|
||||
}
|
||||
else {
|
||||
File file = new File(logFile);
|
||||
ShowFilePathAction.openFile(file);
|
||||
if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
|
||||
if ("url".equals(event.getDescription())) {
|
||||
BrowserUtil.launchBrowser("http://youtrack.jetbrains.net/issue/IDEA-71270");
|
||||
}
|
||||
else {
|
||||
File file = new File(logFile);
|
||||
ShowFilePathAction.openFile(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
}), null);
|
||||
|
||||
@@ -255,4 +255,6 @@ public interface IdeActions {
|
||||
String ACTION_REDO = "$Redo";
|
||||
String GROUP_REFACTOR = "RefactoringMenu";
|
||||
String CHANGES_VIEW_ROLLBACK = "ChangesView.Rollback";
|
||||
|
||||
String CONSOLE_CLEAR_ALL = "ConsoleView.ClearAll";
|
||||
}
|
||||
|
||||
+3
-4
@@ -149,12 +149,11 @@ public class ShowFeatureUsageStatisticsDialog extends DialogWrapper {
|
||||
long idleTime = app.getIdleTime();
|
||||
|
||||
final String uptimeS = FeatureStatisticsBundle.message("feature.statistics.application.uptime",
|
||||
ApplicationNamesInfo.getInstance().getProductName(),
|
||||
ApplicationNamesInfo.getInstance().getFullProductName(),
|
||||
DateFormatUtil.formatDuration(uptime));
|
||||
|
||||
final String idleTimeS = FeatureStatisticsBundle .message("feature.statistics.application.idle.time",
|
||||
ApplicationNamesInfo.getInstance().getProductName(),
|
||||
DateFormatUtil.formatDuration(idleTime));
|
||||
final String idleTimeS = FeatureStatisticsBundle.message("feature.statistics.application.idle.time",
|
||||
DateFormatUtil.formatDuration(idleTime));
|
||||
|
||||
String labelText = uptimeS + ", " + idleTimeS;
|
||||
CompletionStatistics stats = ((FeatureUsageTrackerImpl)FeatureUsageTracker.getInstance()).getCompletionStatistics();
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.intellij.openapi.ui.Messages;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
|
||||
import java.awt.event.InputEvent;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author yole
|
||||
@@ -50,8 +51,9 @@ public class ReopenProjectAction extends AnAction implements DumbAware {
|
||||
final int modifiers = e.getModifiers();
|
||||
final boolean forceOpenInNewFrame = (modifiers & InputEvent.CTRL_MASK) != 0 || (modifiers & InputEvent.SHIFT_MASK) != 0;
|
||||
Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext());
|
||||
if (!RecentProjectsManagerBase.isValidProjectPath(myProjectPath)) {
|
||||
Messages.showErrorDialog(project, "The project path " + FileUtil.toSystemDependentName(myProjectPath) + " does not exist.\n" +
|
||||
File file = new File(myProjectPath);
|
||||
if (!file.exists() || !file.isDirectory()) {
|
||||
Messages.showErrorDialog(project, "The directory " + FileUtil.toSystemDependentName(myProjectPath) + " does not exist.\n" +
|
||||
"If it is on a removable or network drive, please make sure that the drive is connected.",
|
||||
"Reopen Project");
|
||||
return;
|
||||
|
||||
@@ -88,10 +88,13 @@ class EventLogConsole {
|
||||
|
||||
((EditorMarkupModel)editor.getMarkupModel()).setErrorStripeVisible(true);
|
||||
|
||||
final ClearLog clearLog = new ClearLog();
|
||||
clearLog.registerCustomShortcutSet(ActionManager.getInstance().getAction(IdeActions.CONSOLE_CLEAR_ALL).getShortcutSet(), editor.getContentComponent());
|
||||
|
||||
editor.addEditorMouseListener(new EditorPopupHandler() {
|
||||
public void invokePopup(final EditorMouseEvent event) {
|
||||
final ActionManager actionManager = ActionManager.getInstance();
|
||||
final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, createPopupActions(actionManager));
|
||||
final ActionPopupMenu menu = actionManager.createActionPopupMenu(ActionPlaces.UNKNOWN, createPopupActions(actionManager, clearLog));
|
||||
final MouseEvent mouseEvent = event.getMouseEvent();
|
||||
menu.getComponent().show(mouseEvent.getComponent(), mouseEvent.getX(), mouseEvent.getY());
|
||||
}
|
||||
@@ -99,31 +102,12 @@ class EventLogConsole {
|
||||
return editor;
|
||||
}
|
||||
|
||||
private DefaultActionGroup createPopupActions(ActionManager actionManager) {
|
||||
private DefaultActionGroup createPopupActions(ActionManager actionManager, ClearLog action) {
|
||||
DefaultActionGroup group = new DefaultActionGroup();
|
||||
group.add(new EditorCopyAction());
|
||||
group.add(actionManager.getAction(IdeActions.ACTION_COMPARE_CLIPBOARD_WITH_SELECTION));
|
||||
group.addSeparator();
|
||||
group.add(new DumbAwareAction("Clear All") {
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
final boolean enabled = e.getData(PlatformDataKeys.EDITOR) != null;
|
||||
e.getPresentation().setEnabled(enabled);
|
||||
e.getPresentation().setVisible(enabled);
|
||||
}
|
||||
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
for (Notification notification : myProjectModel.getNotifications()) {
|
||||
notification.expire();
|
||||
myProjectModel.removeNotification(notification);
|
||||
}
|
||||
myProjectModel.setStatusMessage(null, 0);
|
||||
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
|
||||
if (editor != null) {
|
||||
editor.getDocument().deleteString(0, editor.getDocument().getTextLength());
|
||||
}
|
||||
}
|
||||
});
|
||||
group.add(action);
|
||||
return group;
|
||||
}
|
||||
|
||||
@@ -240,4 +224,28 @@ class EventLogConsole {
|
||||
document.insertString(document.getTextLength(), s);
|
||||
}
|
||||
|
||||
private class ClearLog extends DumbAwareAction {
|
||||
public ClearLog() {
|
||||
super("Clear All");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
final boolean enabled = e.getData(PlatformDataKeys.EDITOR) != null;
|
||||
e.getPresentation().setEnabled(enabled);
|
||||
e.getPresentation().setVisible(enabled);
|
||||
}
|
||||
|
||||
public void actionPerformed(final AnActionEvent e) {
|
||||
for (Notification notification : myProjectModel.getNotifications()) {
|
||||
notification.expire();
|
||||
myProjectModel.removeNotification(notification);
|
||||
}
|
||||
myProjectModel.setStatusMessage(null, 0);
|
||||
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
|
||||
if (editor != null) {
|
||||
editor.getDocument().deleteString(0, editor.getDocument().getTextLength());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ feature.statistics.not.applicable=N/A
|
||||
# {0} - application name (IntelliJ IDEA or Visual Fabrique or RubyMine or WebStorm or PhpStorm or PyCharm or CIDR)
|
||||
# {1} - formatted duration.
|
||||
feature.statistics.application.uptime={0} uptime: {1}
|
||||
feature.statistics.application.idle.time={0} idle time: {1}
|
||||
feature.statistics.application.idle.time=idle time: {0}
|
||||
|
||||
# Names of features in the feature statistics bundle
|
||||
navigation.popup.class=Go to class
|
||||
|
||||
@@ -377,6 +377,7 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
}
|
||||
|
||||
public void testMatchingDegree() {
|
||||
assertPreference("jscote", "JsfCompletionTest", "JSCompletionTest", NameUtil.MatchingCaseSensitivity.NONE);
|
||||
assertPreference("OCO", "OneCoolObject", "OCObject");
|
||||
assertPreference("MUp", "MavenUmlProvider", "MarkUp");
|
||||
assertPreference("MUP", "MarkUp", "MavenUmlProvider");
|
||||
@@ -400,6 +401,11 @@ public class NameUtilTest extends UsefulTestCase {
|
||||
assertPreference(" Boo", "boolean", "Boolean", NameUtil.MatchingCaseSensitivity.NONE);
|
||||
}
|
||||
|
||||
public void testPreferWordBoundaryMatch() {
|
||||
assertPreference("*les", "configureByFiles", "getLookupElementStrings", NameUtil.MatchingCaseSensitivity.FIRST_LETTER);
|
||||
assertPreference("*les", "configureByFiles", "getLookupElementStrings", NameUtil.MatchingCaseSensitivity.NONE);
|
||||
}
|
||||
|
||||
public void testPreferEarlyMatching() {
|
||||
assertPreference(" path", "getAbsolutePath", "findPath");
|
||||
}
|
||||
|
||||
@@ -264,7 +264,9 @@ public class MinusculeMatcher implements Matcher {
|
||||
if (p < 0) {
|
||||
break;
|
||||
}
|
||||
matchingCase += c == myPattern[p] ? 1 : 0;
|
||||
if (Character.isUpperCase(myPattern[p]) || i == range.getStartOffset()) {
|
||||
matchingCase += c == myPattern[p] ? 1 : 0;
|
||||
}
|
||||
}
|
||||
fragmentCount++;
|
||||
}
|
||||
|
||||
@@ -30,11 +30,9 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -441,13 +439,17 @@ public class PagedFileStorage implements Forceable {
|
||||
private static final int FILE_INDEX_SHIFT = 16;
|
||||
private final boolean checkThreadAccess;
|
||||
public final StorageLockContext myDefaultStorageLockContext;
|
||||
|
||||
private int myMappingChangeCount;
|
||||
private final LinkedHashMap<Integer, ByteBufferWrapper> myMap;
|
||||
private long mySizeLimit;
|
||||
private long mySize;
|
||||
private final ConcurrentHashMap<Integer, PagedFileStorage> myIndex2Storage = new ConcurrentHashMap<Integer, PagedFileStorage>();
|
||||
|
||||
private final LinkedHashMap<Integer, ByteBufferWrapper> mySegments;
|
||||
private final SequenceLock mySegmentsAccessLock = new SequenceLock(); // protects map operations of mySegments, needed for LRU order, mySize and myMappingChangeCount
|
||||
|
||||
private final SequenceLock mySegmentsAllocationLock = new SequenceLock();
|
||||
private final ConcurrentLinkedQueue<ByteBufferWrapper> mySegmentsToRemove = new ConcurrentLinkedQueue<ByteBufferWrapper>();
|
||||
private volatile long mySize;
|
||||
private volatile long mySizeLimit;
|
||||
private volatile int myMappingChangeCount;
|
||||
|
||||
public StorageLock() {
|
||||
this(true);
|
||||
}
|
||||
@@ -457,7 +459,7 @@ public class PagedFileStorage implements Forceable {
|
||||
myDefaultStorageLockContext = new StorageLockContext(this);
|
||||
|
||||
mySizeLimit = UPPER_LIMIT;
|
||||
myMap = new LinkedHashMap<Integer, ByteBufferWrapper>(10, 0.75f) {
|
||||
mySegments = new LinkedHashMap<Integer, ByteBufferWrapper>(10, 0.75f) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<Integer, ByteBufferWrapper> eldest) {
|
||||
return mySize > mySizeLimit;
|
||||
@@ -469,8 +471,9 @@ public class PagedFileStorage implements Forceable {
|
||||
// this method can be called after removeEldestEntry
|
||||
ByteBufferWrapper wrapper = super.remove(key);
|
||||
if (wrapper != null) {
|
||||
++myMappingChangeCount;
|
||||
mySegmentsToRemove.offer(wrapper);
|
||||
mySize -= wrapper.myLength;
|
||||
wrapper.dispose();
|
||||
}
|
||||
return wrapper;
|
||||
}
|
||||
@@ -502,33 +505,79 @@ public class PagedFileStorage implements Forceable {
|
||||
}
|
||||
|
||||
private ByteBufferWrapper get(Integer key) {
|
||||
ByteBufferWrapper wrapper = myMap.get(key);
|
||||
if (wrapper != null) {
|
||||
ByteBufferWrapper wrapper;
|
||||
try { // fast path
|
||||
mySegmentsAccessLock.lock();
|
||||
wrapper = mySegments.get(key);
|
||||
if (wrapper != null) return wrapper;
|
||||
}
|
||||
finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
mySegmentsAllocationLock.lock();
|
||||
try {
|
||||
// check if anybody cared about our segment
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
wrapper = mySegments.get(key);
|
||||
if (wrapper != null) return wrapper;
|
||||
} finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
long started = IOStatistics.DEBUG ? System.currentTimeMillis() : 0;
|
||||
wrapper = createValue(key);
|
||||
|
||||
if (IOStatistics.DEBUG) {
|
||||
long finished = System.currentTimeMillis();
|
||||
if (finished - started > IOStatistics.MIN_IO_TIME_TO_REPORT) {
|
||||
IOStatistics.dump(
|
||||
"Mapping " + wrapper.myLength + " from " + wrapper.myPosition + " file:" + wrapper.myFile + " for " + (finished - started));
|
||||
}
|
||||
}
|
||||
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
mySegments.put(key, wrapper);
|
||||
mySize += wrapper.myLength;
|
||||
}
|
||||
finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
ensureSize(mySizeLimit);
|
||||
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
long started = IOStatistics.DEBUG ? System.currentTimeMillis() : 0;
|
||||
wrapper = createValue(key);
|
||||
mySize += wrapper.myLength;
|
||||
|
||||
if (IOStatistics.DEBUG) {
|
||||
long finished = System.currentTimeMillis();
|
||||
if (finished - started > IOStatistics.MIN_IO_TIME_TO_REPORT) {
|
||||
IOStatistics.dump(
|
||||
"Mapping " + wrapper.myLength + " from " + wrapper.myPosition + " file:" + wrapper.myFile + " for " + (finished - started));
|
||||
}
|
||||
finally {
|
||||
mySegmentsAllocationLock.unlock();
|
||||
}
|
||||
myMap.put(key, wrapper);
|
||||
}
|
||||
|
||||
ensureSize(mySizeLimit);
|
||||
return wrapper;
|
||||
private void disposeRemovedSegments() {
|
||||
assert mySegmentsAllocationLock.isHeldByCurrentThread();
|
||||
Iterator<ByteBufferWrapper> iterator = mySegmentsToRemove.iterator();
|
||||
while(iterator.hasNext()) {
|
||||
iterator.next().dispose();
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
private void ensureSize(long sizeLimit) {
|
||||
while (mySize > sizeLimit) {
|
||||
// we still have to drop something
|
||||
myMap.doRemoveEldestEntry();
|
||||
assert mySegmentsAllocationLock.isHeldByCurrentThread();
|
||||
|
||||
try {
|
||||
mySegmentsAccessLock.lock();
|
||||
while (mySize > sizeLimit) {
|
||||
// we still have to drop something
|
||||
mySegments.doRemoveEldestEntry();
|
||||
}
|
||||
} finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
disposeRemovedSegments();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -541,7 +590,7 @@ public class PagedFileStorage implements Forceable {
|
||||
if (off > owner.length()) {
|
||||
throw new IndexOutOfBoundsException("off=" + off + " key.owner.length()=" + owner.length());
|
||||
}
|
||||
++myMappingChangeCount;
|
||||
|
||||
int min = Math.min((int)(owner.length() - off), owner.myPageSize);
|
||||
ByteBufferWrapper wrapper = ByteBufferWrapper.readWriteDirect(owner.myFile, off, min);
|
||||
IOException oome = null;
|
||||
@@ -586,30 +635,49 @@ public class PagedFileStorage implements Forceable {
|
||||
}
|
||||
|
||||
private @Nullable Map<Integer, ByteBufferWrapper> getBuffersOrderedForOwner(int index, StorageLockContext storageLockContext) {
|
||||
checkThreadAccess(storageLockContext);
|
||||
Map<Integer, ByteBufferWrapper> mineBuffers = null;
|
||||
for (Map.Entry<Integer, ByteBufferWrapper> entry : myMap.entrySet()) {
|
||||
if ((entry.getKey() & FILE_INDEX_MASK) == index) {
|
||||
if (mineBuffers == null) {
|
||||
mineBuffers = new TreeMap<Integer, ByteBufferWrapper>(new Comparator<Integer>() {
|
||||
@Override
|
||||
public int compare(Integer o1, Integer o2) {
|
||||
return o1 - o2;
|
||||
}
|
||||
});
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
checkThreadAccess(storageLockContext);
|
||||
Map<Integer, ByteBufferWrapper> mineBuffers = null;
|
||||
for (Map.Entry<Integer, ByteBufferWrapper> entry : mySegments.entrySet()) {
|
||||
if ((entry.getKey() & FILE_INDEX_MASK) == index) {
|
||||
if (mineBuffers == null) {
|
||||
mineBuffers = new TreeMap<Integer, ByteBufferWrapper>(new Comparator<Integer>() {
|
||||
@Override
|
||||
public int compare(Integer o1, Integer o2) {
|
||||
return o1 - o2;
|
||||
}
|
||||
});
|
||||
}
|
||||
mineBuffers.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
mineBuffers.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return mineBuffers;
|
||||
}
|
||||
finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
return mineBuffers;
|
||||
}
|
||||
|
||||
private void unmapBuffersForOwner(int index, StorageLockContext storageLockContext) {
|
||||
final Map<Integer, ByteBufferWrapper> buffers = getBuffersOrderedForOwner(index, storageLockContext);
|
||||
|
||||
if (buffers != null) {
|
||||
for (Integer key : buffers.keySet()) {
|
||||
myMap.remove(key);
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
for (Integer key : buffers.keySet()) {
|
||||
mySegments.remove(key);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
|
||||
mySegmentsAllocationLock.lock();
|
||||
try {
|
||||
disposeRemovedSegments();
|
||||
} finally {
|
||||
mySegmentsAllocationLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -618,14 +686,32 @@ public class PagedFileStorage implements Forceable {
|
||||
Map<Integer, ByteBufferWrapper> buffers = getBuffersOrderedForOwner(index, storageLockContext);
|
||||
|
||||
if (buffers != null) {
|
||||
for(ByteBufferWrapper buffer:buffers.values()) {
|
||||
buffer.flush();
|
||||
mySegmentsAllocationLock.lock();
|
||||
try {
|
||||
for(ByteBufferWrapper buffer:buffers.values()) {
|
||||
buffer.flush();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
mySegmentsAllocationLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void invalidateBuffer(int page) {
|
||||
myMap.remove(page);
|
||||
mySegmentsAccessLock.lock();
|
||||
try {
|
||||
mySegments.remove(page);
|
||||
} finally {
|
||||
mySegmentsAccessLock.unlock();
|
||||
}
|
||||
mySegmentsAllocationLock.lock();
|
||||
try {
|
||||
disposeRemovedSegments();
|
||||
}
|
||||
finally {
|
||||
mySegmentsAllocationLock.unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,6 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="java-i18n" />
|
||||
<orderEntry type="module" module-name="properties" />
|
||||
<orderEntry type="module" module-name="openapi" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
<orderEntry type="module" module-name="compiler-impl" />
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
<resource-bundle>messages.AndroidDesignerBundle</resource-bundle>
|
||||
|
||||
<depends>com.intellij.java-i18n</depends>
|
||||
<depends>com.intellij.properties</depends>
|
||||
<depends>org.jetbrains.android</depends>
|
||||
<depends>com.intellij.ui-designer-new</depends>
|
||||
|
||||
|
||||
+10
@@ -31,6 +31,7 @@ import com.intellij.designer.designSurface.selection.NonResizeSelectionDecorator
|
||||
import com.intellij.designer.designSurface.tools.ComponentCreationFactory;
|
||||
import com.intellij.designer.designSurface.tools.ComponentPasteFactory;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.model.WrapInProvider;
|
||||
import com.intellij.designer.palette.DefaultPaletteItem;
|
||||
import com.intellij.designer.palette.PaletteGroup;
|
||||
import com.intellij.designer.palette.PaletteItem;
|
||||
@@ -77,6 +78,7 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
|
||||
private volatile RenderSession mySession;
|
||||
private boolean myParseTime;
|
||||
private int myProfileLastVersion;
|
||||
private WrapInProvider myWrapInProvider;
|
||||
|
||||
public AndroidDesignerEditorPanel(@NotNull DesignerEditor editor,
|
||||
@NotNull Project project,
|
||||
@@ -464,6 +466,14 @@ public final class AndroidDesignerEditorPanel extends DesignerEditorPanel {
|
||||
return myTreeDecorator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WrapInProvider getWrapInProvider() {
|
||||
if (myWrapInProvider == null) {
|
||||
myWrapInProvider = new AndroidWrapInProvider(getProject());
|
||||
}
|
||||
return myWrapInProvider;
|
||||
}
|
||||
|
||||
private static final ComponentDecorator NON_RESIZE_DECORATOR = new NonResizeSelectionDecorator(Color.RED, 2);
|
||||
|
||||
@Override
|
||||
|
||||
+48
@@ -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 com.intellij.android.designer.model;
|
||||
|
||||
import com.intellij.designer.model.MetaModel;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.model.WrapInProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public final class AndroidWrapInProvider extends WrapInProvider<RadViewComponent> {
|
||||
public AndroidWrapInProvider(Project project) {
|
||||
super(ViewsMetaManager.getInstance(project));
|
||||
}
|
||||
|
||||
@Override
|
||||
public RadComponent wrapIn(RadViewComponent parent, List<RadViewComponent> components, MetaModel target) throws Exception {
|
||||
RadViewComponent newParent = ModelParser.createComponent(null, target);
|
||||
|
||||
ModelParser.addComponent(parent, newParent, components.get(0));
|
||||
|
||||
for (RadViewComponent component : components) {
|
||||
ModelParser.moveComponent(newParent, component, null);
|
||||
}
|
||||
|
||||
RadViewLayout layout = (RadViewLayout)parent.getLayout();
|
||||
layout.wrapIn(newParent, components);
|
||||
|
||||
return newParent;
|
||||
}
|
||||
}
|
||||
@@ -43,4 +43,7 @@ public class RadViewLayout extends RadLayout {
|
||||
JComponent shortcuts,
|
||||
List<RadComponent> selection) {
|
||||
}
|
||||
|
||||
public void wrapIn(RadViewComponent newParent, List<RadViewComponent> components) throws Exception {
|
||||
}
|
||||
}
|
||||
@@ -1447,6 +1447,15 @@
|
||||
</creation>
|
||||
</meta>
|
||||
|
||||
<wrap-in>
|
||||
<item tag="FrameLayout"/>
|
||||
<item tag="LinearLayout"/>
|
||||
<item tag="TableLayout"/>
|
||||
<item tag="TableRow"/>
|
||||
<item tag="GridLayout"/>
|
||||
<item tag="RelativeLayout"/>
|
||||
</wrap-in>
|
||||
|
||||
<!-- ================= Palette ================= -->
|
||||
|
||||
<palette>
|
||||
|
||||
@@ -29,9 +29,10 @@ import com.intellij.openapi.vcs.changes.ChangeListManager;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import git4idea.GitBranch;
|
||||
import git4idea.GitUtil;
|
||||
import git4idea.repo.GitRemote;
|
||||
import git4idea.repo.GitRepository;
|
||||
import git4idea.repo.GitRepositoryManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.plugins.github.ui.GithubLoginDialog;
|
||||
|
||||
import static org.jetbrains.plugins.github.GithubUtil.*;
|
||||
@@ -106,8 +107,7 @@ public class GithubOpenInBrowserAction extends DumbAwareAction {
|
||||
}
|
||||
final GitRepository gitRepository = manager.getRepositoryForFile(root);
|
||||
// Check that given repository is properly configured git repository
|
||||
final GitRemote gitRemote = findGitHubRemoteBranch(gitRepository);
|
||||
final String pushUrl = getGithubUrl(gitRemote);
|
||||
final String githubRemoteUrl = findGithubRemoteUrl(gitRepository);
|
||||
|
||||
final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE);
|
||||
final String rootPath = root.getPath();
|
||||
@@ -117,38 +117,84 @@ public class GithubOpenInBrowserAction extends DumbAwareAction {
|
||||
return;
|
||||
}
|
||||
|
||||
String userAndRepository = getUserAndRepositoryOrShowError(project, pushUrl);
|
||||
String branch = getBranchNameOnRemote(project, root);
|
||||
if (branch == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current tracked branch
|
||||
String relativePath = path.substring(rootPath.length());
|
||||
String urlToOpen = makeUrlToOpen(e, relativePath, branch, githubRemoteUrl);
|
||||
BrowserUtil.launchBrowser(urlToOpen);
|
||||
}
|
||||
|
||||
private static String makeUrlToOpen(@NotNull AnActionEvent e, @NotNull String relativePath, @NotNull String branch,
|
||||
@NotNull String githubRemoteUrl) {
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append(makeGithubRepoUrlFromRemoteUrl(githubRemoteUrl)).append("/blob/").append(branch).append(relativePath);
|
||||
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
|
||||
if (editor != null) {
|
||||
final int line = editor.getCaretModel().getLogicalPosition().line + 1; // lines are counted internally from 0, but from 1 on github
|
||||
builder.append("#L").append(line);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String makeGithubRepoUrlFromRemoteUrl(@NotNull String remoteUrl) {
|
||||
remoteUrl = removeEndingDotGit(remoteUrl);
|
||||
if (remoteUrl.startsWith("http")) {
|
||||
return remoteUrl;
|
||||
}
|
||||
if (remoteUrl.startsWith("git://")) {
|
||||
return "https" + remoteUrl.substring(3);
|
||||
}
|
||||
return convertFromSshToHttp(remoteUrl);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String convertFromSshToHttp(@NotNull String remoteUrl) {
|
||||
// Format: git@github.com:account/repository
|
||||
int indexOfAt = remoteUrl.indexOf("@");
|
||||
if (indexOfAt < 0) {
|
||||
throw new IllegalStateException("Invalid remote Github SSH url: " + remoteUrl);
|
||||
}
|
||||
String withoutPrefix = remoteUrl.substring(indexOfAt + 1, remoteUrl.length());
|
||||
return "https://" + withoutPrefix.replace(':', '/');
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String removeEndingDotGit(@NotNull String url) {
|
||||
final String DOT_GIT = ".git";
|
||||
if (url.endsWith(DOT_GIT)) {
|
||||
return url.substring(0, url.length() - DOT_GIT.length());
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String getBranchNameOnRemote(@NotNull Project project, @NotNull VirtualFile root) {
|
||||
final GitBranch tracked;
|
||||
try {
|
||||
final GitBranch current = GitBranch.current(project, root);
|
||||
if (current == null) {
|
||||
Messages.showErrorDialog(project, "Cannot find local branch", CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
tracked = current.tracked(project, root);
|
||||
if (tracked == null || !tracked.isRemote()) {
|
||||
Messages.showErrorDialog(project, "Cannot find tracked branch for branch: " + current.getFullName(), CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
catch (VcsException e1) {
|
||||
Messages.showErrorDialog(project, "Error occurred while inspecting branches: " + e1, CANNOT_OPEN_IN_BROWSER);
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
String branch = tracked.getName();
|
||||
if (branch.startsWith("origin/")) {
|
||||
branch = branch.substring(7);
|
||||
}
|
||||
|
||||
final StringBuilder builder = new StringBuilder();
|
||||
builder.append("https://github.com/").append(userAndRepository).append("/blob/").append(branch).append(path.substring(rootPath.length()));
|
||||
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
|
||||
if (editor != null) {
|
||||
final int line = editor.getCaretModel().getLogicalPosition().line;
|
||||
builder.append("#L").append(line);
|
||||
}
|
||||
BrowserUtil.launchBrowser(builder.toString());
|
||||
return branch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -450,6 +450,7 @@ public class GithubUtil {
|
||||
final String host = githubSettings.getHost();
|
||||
final String username = githubSettings.getLogin();
|
||||
|
||||
// TODO this doesn't work with organizational accounts
|
||||
final String userRepoMarkerSSHProtocol = host + ":" + username + "/";
|
||||
final String userRepoMarkerOtherProtocols = host + "/" + username + "/";
|
||||
for (String pushUrl : gitRemote.getUrls()) {
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
+3
-63
@@ -34,10 +34,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
import com.intellij.psi.filters.FilterPositionUtil;
|
||||
import com.intellij.psi.filters.TrueFilter;
|
||||
import com.intellij.psi.filters.types.AssignableFromFilter;
|
||||
import com.intellij.psi.impl.source.tree.LeafPsiElement;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
@@ -177,8 +174,8 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
|
||||
private static final ElementPattern<PsiElement> AFTER_NUMBER_LITERAL = psiElement().afterLeaf(
|
||||
psiElement().withElementType(elementType().oneOf(mNUM_DOUBLE, mNUM_INT, mNUM_LONG, mNUM_FLOAT, mNUM_BIG_INT, mNUM_BIG_DECIMAL)));
|
||||
private static final ElementPattern<PsiElement> AFTER_AT = psiElement().afterLeaf("@");
|
||||
private static final ElementPattern<PsiElement> IN_CATCH_TYPE = psiElement().afterLeaf(psiElement().withText("(").withParent(GrCatchClause.class));
|
||||
public static final ElementPattern<PsiElement> AFTER_AT = psiElement().afterLeaf("@");
|
||||
public static final ElementPattern<PsiElement> IN_CATCH_TYPE = psiElement().afterLeaf(psiElement().withText("(").withParent(GrCatchClause.class));
|
||||
|
||||
|
||||
private static void addAllClasses(CompletionParameters parameters, final CompletionResultSet result, final InheritorsHolder inheritors) {
|
||||
@@ -194,7 +191,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
final Consumer<LookupElement> consumer,
|
||||
final InheritorsHolder inheritors, final PrefixMatcher matcher) {
|
||||
final PsiElement position = parameters.getPosition();
|
||||
final ElementFilter filter = getClassFilter(position);
|
||||
final boolean afterNew = JavaClassNameCompletionContributor.AFTER_NEW.accepts(position);
|
||||
AllClassesGetter.processJavaClasses(parameters, matcher, parameters.getInvocationCount() <= 1, new Consumer<PsiClass>() {
|
||||
@Override
|
||||
@@ -203,7 +199,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
.createClassLookupItems(psiClass, afterNew, new GroovyClassNameInsertHandler(), new Condition<PsiClass>() {
|
||||
@Override
|
||||
public boolean value(PsiClass psiClass) {
|
||||
return !inheritors.alreadyProcessed(psiClass) && filter.isAcceptable(psiClass, position);
|
||||
return !inheritors.alreadyProcessed(psiClass);
|
||||
}
|
||||
})) {
|
||||
consumer.consume(element);
|
||||
@@ -212,16 +208,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
});
|
||||
}
|
||||
|
||||
private static ElementFilter getClassFilter(PsiElement position) {
|
||||
if (AFTER_AT.accepts(position)) {
|
||||
return new AssignableFromFilter(CommonClassNames.JAVA_LANG_ANNOTATION_ANNOTATION);
|
||||
}
|
||||
if (IN_CATCH_TYPE.accepts(position)) {
|
||||
return new AssignableFromFilter(CommonClassNames.JAVA_LANG_THROWABLE);
|
||||
}
|
||||
return TrueFilter.INSTANCE;
|
||||
}
|
||||
|
||||
public GroovyCompletionContributor() {
|
||||
//provide 'this' and 'super' completions in ClassName.<caret>
|
||||
extend(CompletionType.BASIC, AFTER_DOT, new CompletionProvider<CompletionParameters>() {
|
||||
@@ -261,20 +247,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
MapKeysCompletionProvider.register(this);
|
||||
GroovyDocCompletionProvider.register(this);
|
||||
|
||||
// class name stuff
|
||||
|
||||
extend(CompletionType.CLASS_NAME, psiElement().withParent(GrReferenceElement.class), new GlobalStaticMembersProvider());
|
||||
|
||||
extend(CompletionType.CLASS_NAME, psiElement(), new CompletionProvider<CompletionParameters>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
ProcessingContext context,
|
||||
@NotNull CompletionResultSet result) {
|
||||
result.stopHere();
|
||||
addAllClasses(parameters, result.withPrefixMatcher(CompletionUtil.findJavaIdentifierPrefix(parameters)), new InheritorsHolder(parameters.getPosition(), result));
|
||||
}
|
||||
});
|
||||
|
||||
extend(CompletionType.BASIC, STATEMENT_START, new CompletionProvider<CompletionParameters>() {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
@@ -392,10 +364,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
public static boolean isClassNamePossible(PsiElement position) {
|
||||
if (PsiJavaPatterns.psiElement().inside(GrImportStatement.class).accepts(position)) {
|
||||
return false;
|
||||
}
|
||||
if (position instanceof PsiComment) return false;
|
||||
PsiElement parent = position.getParent();
|
||||
if (parent instanceof GrReferenceElement) {
|
||||
return ((GrReferenceElement)parent).getQualifier() == null;
|
||||
@@ -445,8 +413,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
};
|
||||
|
||||
final PsiElement position = parameters.getPosition();
|
||||
|
||||
final Map<PsiModifierListOwner, LookupElement> staticMembers = hashMap();
|
||||
final PsiElement qualifier = reference.getQualifier();
|
||||
final PsiType qualifierType = qualifier instanceof GrExpression ? ((GrExpression)qualifier).getType() : null;
|
||||
@@ -469,8 +435,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
unresolvedProps = Collections.emptySet();
|
||||
}
|
||||
|
||||
final ElementFilter classFilter = getClassFilter(position);
|
||||
|
||||
final List<LookupElement> zeroPriority = arrayList();
|
||||
reference.processVariants(matcher, parameters, new Consumer<LookupElement>() {
|
||||
public void consume(LookupElement lookupElement) {
|
||||
@@ -503,9 +467,6 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
staticMembers.put(CompletionUtil.getOriginalOrSelf((PsiModifierListOwner)object), lookupElement);
|
||||
}
|
||||
}
|
||||
if (object instanceof PsiClass && !classFilter.isAcceptable(object, position)) {
|
||||
return;
|
||||
}
|
||||
|
||||
PrioritizedLookupElement prio = lookupElement.as(PrioritizedLookupElement.CLASS_CONDITION_KEY);
|
||||
if (prio == null || prio.getPriority() == 0) {
|
||||
@@ -829,25 +790,4 @@ public class GroovyCompletionContributor extends CompletionContributor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class GlobalStaticMembersProvider extends CompletionProvider<CompletionParameters> {
|
||||
@Override
|
||||
protected void addCompletions(@NotNull CompletionParameters parameters,
|
||||
ProcessingContext context,
|
||||
@NotNull final CompletionResultSet result) {
|
||||
if (!parameters.isExtendedCompletion()) return;
|
||||
|
||||
final PsiElement position = parameters.getPosition();
|
||||
if (((GrReferenceElement)position.getParent()).getQualifier() != null) return;
|
||||
|
||||
if (StringUtil.isEmpty(result.getPrefixMatcher().getPrefix())) return;
|
||||
|
||||
completeStaticMembers(parameters).processStaticMethodsGlobally(result.getPrefixMatcher(), new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
result.addElement(element);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-2
@@ -21,11 +21,13 @@ import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.light.LightElement;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.util.containers.CollectionFactory;
|
||||
import com.intellij.util.containers.hash.HashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
|
||||
import org.jetbrains.plugins.groovy.lang.completion.GroovyCompletionContributor;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
|
||||
@@ -86,6 +88,15 @@ public class GrKindWeigher extends CompletionWeigher {
|
||||
|
||||
if (isPriorityKeyword(o)) return NotQualifiedKind.local;
|
||||
if (isLightElement(o)) return NotQualifiedKind.unknown;
|
||||
if (o instanceof PsiClass) {
|
||||
if (((PsiClass)o).isAnnotationType() && GroovyCompletionContributor.AFTER_AT.accepts(position)) {
|
||||
return NotQualifiedKind.restrictedClass;
|
||||
}
|
||||
if (GroovyCompletionContributor.IN_CATCH_TYPE.accepts(position) &&
|
||||
InheritanceUtil.isInheritor((PsiClass)o, CommonClassNames.JAVA_LANG_THROWABLE)) {
|
||||
return NotQualifiedKind.restrictedClass;
|
||||
}
|
||||
}
|
||||
if (o instanceof PsiMember) {
|
||||
final PsiClass containingClass = ((PsiMember)o).getContainingClass();
|
||||
if (isAccessor((PsiMember)o)) return NotQualifiedKind.accessor;
|
||||
@@ -145,18 +156,19 @@ public class GrKindWeigher extends CompletionWeigher {
|
||||
return qualifier.getManager().areElementsEquivalent(member.getContainingClass(), psiClass);
|
||||
}
|
||||
|
||||
private static enum NotQualifiedKind {
|
||||
private enum NotQualifiedKind {
|
||||
arrayType,
|
||||
innerClass,
|
||||
unknown,
|
||||
accessor,
|
||||
member,
|
||||
currentClassMember,
|
||||
restrictedClass,
|
||||
local,
|
||||
onTop
|
||||
}
|
||||
|
||||
private static enum QualifiedKind {
|
||||
private enum QualifiedKind {
|
||||
innerClass,
|
||||
unknown,
|
||||
accessor,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+48
@@ -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;
|
||||
}
|
||||
}
|
||||
+9
-8
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -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() {
|
||||
|
||||
+3
-1
@@ -231,7 +231,9 @@ public abstract class GroovyCompilerTestCase extends JavaCodeInsightFixtureTestC
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
VfsUtil.saveText(ObjectUtils.assertNotNull(file.getVirtualFile()), barText);
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
System.out.println("Changing file text: psiFile= " + file + "; vFile= " + virtualFile);
|
||||
VfsUtil.saveText(ObjectUtils.assertNotNull(virtualFile), barText);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
|
||||
+2
-2
@@ -226,14 +226,14 @@ new Fxoo()<caret>\n"""
|
||||
myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}"
|
||||
myFixture.configureByText "a.groovy", "@Abcd<caret>"
|
||||
complete()
|
||||
myFixture.checkResult "@AbcdAnno<caret>"
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdAnno'
|
||||
}
|
||||
|
||||
public void testOnlyExceptionsInCatch() {
|
||||
myFixture.addClass "class AbcdClass {}; class AbcdException extends Throwable {}"
|
||||
myFixture.configureByText "a.groovy", "try {} catch (Abcd<caret>"
|
||||
complete()
|
||||
myFixture.checkResult "try {} catch (AbcdException<caret>"
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdException'
|
||||
}
|
||||
|
||||
public void testClassNameInMultilineString() {
|
||||
|
||||
+5
-3
@@ -712,17 +712,17 @@ format(<caret>)"""
|
||||
}
|
||||
|
||||
public void testOnlyAnnotationsAfterAt() {
|
||||
myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}"
|
||||
myFixture.addClass "class AbcdClass {}; @interface AbcdXAnno {}"
|
||||
myFixture.configureByText "a.groovy", "@Abcd<caret> class A {}"
|
||||
myFixture.completeBasic()
|
||||
myFixture.checkResult "@AbcdAnno<caret> class A {}"
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdXAnno'
|
||||
}
|
||||
|
||||
public void testOnlyAnnotationsAfterAtInMethodParameters() {
|
||||
myFixture.addClass "class AbcdClass {}; @interface AbcdAnno {}"
|
||||
myFixture.configureByText "a.groovy", "def foo(@Abcd<caret> ) {}"
|
||||
myFixture.completeBasic()
|
||||
myFixture.checkResult "def foo(@AbcdAnno<caret> ) {}"
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdAnno'
|
||||
}
|
||||
|
||||
public void testNoCompletionInClassBodyComments() {
|
||||
@@ -767,6 +767,8 @@ try {} catch (AbcdException"""
|
||||
myFixture.addClass "class AbcdClass {}; class AbcdException extends Throwable {}"
|
||||
myFixture.configureByText "a.groovy", "try {} catch (Abcd<caret> e) {}"
|
||||
myFixture.completeBasic()
|
||||
assert myFixture.lookupElementStrings[0] == 'AbcdException'
|
||||
myFixture.type('\n')
|
||||
myFixture.checkResult "try {} catch (AbcdException<caret> e) {}"
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
+13
-3
@@ -15,16 +15,26 @@
|
||||
*/
|
||||
package com.intellij.lang.properties;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionContributor;
|
||||
import com.intellij.codeInsight.completion.CompletionInitializationContext;
|
||||
import com.intellij.codeInsight.completion.CompletionUtil;
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.lang.properties.psi.PropertiesFile;
|
||||
import com.intellij.util.Consumer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class PropertiesCompletionContributor extends CompletionContributor {
|
||||
@Override
|
||||
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) {
|
||||
if (parameters.isExtendedCompletion()) {
|
||||
CompletionService.getCompletionService().getVariantsFromContributors(parameters.delegateToClassName(), null, new Consumer<CompletionResult>() {
|
||||
public void consume(final CompletionResult completionResult) {
|
||||
result.passResult(completionResult);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeCompletion(@NotNull CompletionInitializationContext context) {
|
||||
if (context.getFile() instanceof PropertiesFile) {
|
||||
|
||||
@@ -24,7 +24,7 @@ import org.tmatesoft.svn.core.SVNException;
|
||||
* Time: 3:45 PM
|
||||
*/
|
||||
public abstract class RepeatSvnActionThroughBusy {
|
||||
public static final int REPEAT = 3;
|
||||
public static final int REPEAT = 10;
|
||||
protected int myCnt = REPEAT;
|
||||
protected long myTimeout = 50;
|
||||
protected abstract void executeImpl() throws SVNException;
|
||||
|
||||
@@ -163,7 +163,10 @@ public class SvnVcs extends AbstractVcs<CommittedChangeList> {
|
||||
@Override
|
||||
public boolean process(Exception e) {
|
||||
if (e instanceof SVNException) {
|
||||
if (SVNErrorCode.SQLITE_ERROR.equals(((SVNException)e).getErrorMessage().getErrorCode())) {
|
||||
final SVNErrorCode errorCode = ((SVNException)e).getErrorMessage().getErrorCode();
|
||||
if (SVNErrorCode.WC_LOCKED.equals(errorCode)) {
|
||||
return true;
|
||||
} else if (SVNErrorCode.SQLITE_ERROR.equals(errorCode)) {
|
||||
Throwable cause = ((SVNException)e).getErrorMessage().getCause();
|
||||
if (cause instanceof SqlJetException) {
|
||||
return SqlJetErrorCode.BUSY.equals(((SqlJetException)cause).getErrorCode());
|
||||
|
||||
@@ -144,7 +144,7 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
}
|
||||
}
|
||||
catch (VcsException e1) {
|
||||
//
|
||||
exception[0] = e1;
|
||||
}
|
||||
catch (SVNException e1) {
|
||||
exception[0] = new VcsException(e);
|
||||
@@ -215,7 +215,11 @@ public class SvnAnnotationProvider implements AnnotationProvider, VcsCacheableAn
|
||||
if (wcRootInfo == null || wcRootInfo.getURL() == null) {
|
||||
throw new VcsException("Can not find relative path for " + wasFile.getPath() + "@" + revision.getRevisionNumber().asString());
|
||||
}
|
||||
final SVNURL wasUrl = wcRootInfo.getURL().appendPath(relativePath, true);
|
||||
SVNURL wasUrl = wcRootInfo.getURL();
|
||||
final String[] strings = relativePath.replace('\\','/').split("/");
|
||||
for (String string : strings) {
|
||||
wasUrl = wasUrl.appendPath(string, true);
|
||||
}
|
||||
|
||||
final ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||
final SVNRevision svnRevision = ((SvnRevisionNumber)revision.getRevisionNumber()).getRevision();
|
||||
|
||||
@@ -5,8 +5,7 @@
|
||||
|
||||
<resource-bundle>messages.DesignerBundle</resource-bundle>
|
||||
|
||||
<depends>com.intellij.java-i18n</depends>
|
||||
<depends>com.intellij.properties</depends>
|
||||
<depends>com.intellij.modules.lang</depends>
|
||||
|
||||
<project-components>
|
||||
<component>
|
||||
|
||||
+1
@@ -177,6 +177,7 @@ public class DesignerActionPanel implements DataProvider {
|
||||
myDynamicPopupGroup.removeAll();
|
||||
}
|
||||
|
||||
WrapInAction.fill(myDesigner, myDynamicPopupGroup, area);
|
||||
MorphingAction.fill(myDesigner, myDynamicPopupGroup, area);
|
||||
|
||||
return myPopupGroup;
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.designer.actions;
|
||||
|
||||
import com.intellij.designer.designSurface.DesignerEditorPanel;
|
||||
import com.intellij.designer.designSurface.EditableArea;
|
||||
import com.intellij.designer.model.MetaModel;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.model.RadLayout;
|
||||
import com.intellij.designer.model.WrapInProvider;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.AnActionEvent;
|
||||
import com.intellij.openapi.actionSystem.DefaultActionGroup;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public class WrapInAction extends AnAction {
|
||||
private final DesignerEditorPanel myDesigner;
|
||||
private final EditableArea myArea;
|
||||
private final WrapInProvider myProvider;
|
||||
private final RadComponent myParent;
|
||||
private final List<RadComponent> myComponents;
|
||||
private final MetaModel myTarget;
|
||||
|
||||
public WrapInAction(DesignerEditorPanel designer,
|
||||
EditableArea area,
|
||||
WrapInProvider provider,
|
||||
RadComponent parent,
|
||||
List<RadComponent> components,
|
||||
MetaModel target) {
|
||||
super(target.getTag(), null, target.getIcon());
|
||||
myDesigner = designer;
|
||||
myArea = area;
|
||||
myProvider = provider;
|
||||
myParent = parent;
|
||||
myComponents = components;
|
||||
myTarget = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
myDesigner.getToolProvider().execute(new ThrowableRunnable<Exception>() {
|
||||
@Override
|
||||
public void run() throws Exception {
|
||||
myArea.select(myProvider.wrapIn(myParent, myComponents, myTarget));
|
||||
}
|
||||
}, "Run Wrap In action", true);
|
||||
}
|
||||
|
||||
public static void fill(DesignerEditorPanel designer, DefaultActionGroup group, EditableArea area) {
|
||||
List<RadComponent> selection = area.getSelection();
|
||||
if (selection.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Set<RadComponent> parents = RadComponent.getParents(selection);
|
||||
if (parents.size() != 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
RadComponent parent = parents.iterator().next();
|
||||
RadLayout layout = parent.getLayout();
|
||||
if (layout != null && !layout.isWrapIn(selection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
WrapInProvider provider = designer.getWrapInProvider();
|
||||
if (provider == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<MetaModel> models = provider.getModels();
|
||||
if (models.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DefaultActionGroup wrapGroup = new DefaultActionGroup("Wrap In", true);
|
||||
for (MetaModel wrapModel : models) {
|
||||
wrapGroup.add(new WrapInAction(designer, area, provider, parent, selection, wrapModel));
|
||||
}
|
||||
|
||||
group.add(wrapGroup);
|
||||
}
|
||||
}
|
||||
+6
@@ -24,6 +24,7 @@ import com.intellij.designer.componentTree.TreeComponentDecorator;
|
||||
import com.intellij.designer.designSurface.tools.*;
|
||||
import com.intellij.designer.model.FindComponentVisitor;
|
||||
import com.intellij.designer.model.RadComponent;
|
||||
import com.intellij.designer.model.WrapInProvider;
|
||||
import com.intellij.designer.palette.PaletteGroup;
|
||||
import com.intellij.designer.palette.PaletteItem;
|
||||
import com.intellij.designer.palette.PaletteToolWindowManager;
|
||||
@@ -729,6 +730,11 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
|
||||
Disposer.dispose(myProgressIcon);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public WrapInProvider getWrapInProvider() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public RadComponent getRootComponent() {
|
||||
return myRootComponent;
|
||||
}
|
||||
|
||||
@@ -43,12 +43,14 @@ public abstract class MetaManager {
|
||||
private static final String NAME = "name";
|
||||
private static final String ITEM = "item";
|
||||
private static final String TAG = "tag";
|
||||
private static final String WRAP_IN = "wrap-in";
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.designer.model.MetaManager");
|
||||
|
||||
private final Map<String, MetaModel> myTag2Model = new HashMap<String, MetaModel>();
|
||||
private final Map<String, MetaModel> myTarget2Model = new HashMap<String, MetaModel>();
|
||||
private final List<PaletteGroup> myPaletteGroups = new ArrayList<PaletteGroup>();
|
||||
private final List<MetaModel> myWrapModels = new ArrayList<MetaModel>();
|
||||
|
||||
private PropertyChangeSupport myPaletteChangeSupport;
|
||||
|
||||
@@ -73,6 +75,14 @@ public abstract class MetaManager {
|
||||
loadGroup((Element)element);
|
||||
}
|
||||
|
||||
Element wrapInElement = rootElement.getChild(WRAP_IN);
|
||||
if (wrapInElement != null) {
|
||||
for (Object element : wrapInElement.getChildren(ITEM)) {
|
||||
Element item = (Element)element;
|
||||
myWrapModels.add(myTag2Model.get(item.getAttributeValue("tag")));
|
||||
}
|
||||
}
|
||||
|
||||
for (Map.Entry<MetaModel, List<String>> entry : modelToMorphing.entrySet()) {
|
||||
MetaModel meta = entry.getKey();
|
||||
List<MetaModel> morphingModels = new ArrayList<MetaModel>();
|
||||
@@ -209,6 +219,10 @@ public abstract class MetaManager {
|
||||
return myTarget2Model.get(target);
|
||||
}
|
||||
|
||||
public List<MetaModel> getWrapInModels() {
|
||||
return myWrapModels;
|
||||
}
|
||||
|
||||
public List<PaletteGroup> getPaletteGroups() {
|
||||
return myPaletteGroups;
|
||||
}
|
||||
|
||||
@@ -265,6 +265,11 @@ public abstract class RadComponent {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public RadComponent wrapIn(MetaModel target) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Utils
|
||||
|
||||
@@ -62,4 +62,8 @@ public abstract class RadLayout {
|
||||
public ICaption getCaption(RadComponent component) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isWrapIn(List<RadComponent> components) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.designer.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Alexander Lobas
|
||||
*/
|
||||
public abstract class WrapInProvider<T extends RadComponent> {
|
||||
private final List<MetaModel> myModels;
|
||||
|
||||
public WrapInProvider(MetaManager metaManager) {
|
||||
myModels = metaManager.getWrapInModels();
|
||||
}
|
||||
|
||||
public List<MetaModel> getModels() {
|
||||
return myModels;
|
||||
}
|
||||
|
||||
public abstract RadComponent wrapIn(T parent, List<T> components, MetaModel target) throws Exception;
|
||||
}
|
||||
@@ -14,7 +14,6 @@
|
||||
<orderEntry type="module" module-name="execution-impl" />
|
||||
<orderEntry type="module" module-name="execution-openapi" />
|
||||
<orderEntry type="module" module-name="icons" />
|
||||
<orderEntry type="module" module-name="java-i18n" />
|
||||
<orderEntry type="module" module-name="idea-ui" />
|
||||
<orderEntry type="module" module-name="java-impl" />
|
||||
<orderEntry type="module" module-name="platform-api" />
|
||||
|
||||
Reference in New Issue
Block a user