Merge remote-tracking branch 'origin/master'

This commit is contained in:
Dmitry Jemerov
2012-07-02 19:43:27 +02:00
61 changed files with 990 additions and 327 deletions
@@ -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);
}
});
}
}
@@ -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);
}
}
@@ -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
}
}
@@ -17,13 +17,20 @@ package com.intellij.codeInsight.daemon.impl.quickfix;
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightMethodUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.impl.PriorityIntentionActionWrapper;
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.codeStyle.VariableKind;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider<PsiJavaCodeReferenceElement> {
@Override
public void registerFixes(PsiJavaCodeReferenceElement ref, QuickFixActionRegistrar registrar) {
@@ -37,15 +44,13 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
PsiReferenceExpression refExpr = (PsiReferenceExpression)ref;
registrar.register(fixRange, new CreateEnumConstantFromUsageFix(refExpr), null);
registrar.register(fixRange, new CreateConstantFieldFromUsageFix(refExpr), null);
registrar.register(fixRange, new CreateFieldFromUsageFix(refExpr), null);
registrar.register(new RenameWrongRefFix(refExpr));
if (!ref.isQualified()) {
registrar.register(fixRange, new BringVariableIntoScopeFix(refExpr), null);
registrar.register(fixRange, new CreateLocalFromUsageFix(refExpr), null);
registrar.register(fixRange, new CreateParameterFromUsageFix(refExpr), null);
}
registerPriorityActions(registrar,fixRange,refExpr);
}
registrar.register(new CreateClassFromUsageFix(ref, CreateClassKind.INTERFACE));
@@ -65,6 +70,57 @@ public class DefaultQuickFixProvider extends UnresolvedReferenceQuickFixProvider
}
}
private static void registerPriorityActions(@NotNull final QuickFixActionRegistrar registrar,
@NotNull final TextRange fixRange,
@NotNull final PsiReferenceExpression refExpr) {
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(refExpr.getProject());
final Map<VariableKind, IntentionAction> map = new HashMap<VariableKind, IntentionAction>() {
{
put(VariableKind.FIELD, new CreateFieldFromUsageFix(refExpr));
put(VariableKind.STATIC_FINAL_FIELD, new CreateConstantFieldFromUsageFix(refExpr));
if (!refExpr.isQualified()) {
put(VariableKind.LOCAL_VARIABLE, new CreateLocalFromUsageFix(refExpr));
put(VariableKind.PARAMETER, new CreateParameterFromUsageFix(refExpr));
}
}
};
final VariableKind kind = getKind(styleManager, refExpr);
if (map.containsKey(kind)){
map.put(kind, PriorityIntentionActionWrapper.highPriority(map.get(kind)));
}
for (IntentionAction action : map.values()){
registrar.register(fixRange, action, null);
}
}
@NotNull
private static VariableKind getKind(@NotNull JavaCodeStyleManager styleManager,
@NotNull PsiReferenceExpression refExpr) {
final String reference = refExpr.getText();
if (reference.toUpperCase().equals(reference)){
return VariableKind.STATIC_FINAL_FIELD;
}
for (VariableKind kind : VariableKind.values()) {
final String prefix = styleManager.getPrefixByVariableKind(kind);
final String suffix = styleManager.getSuffixByVariableKind(kind);
if (prefix.isEmpty() && suffix.isEmpty()) {
continue;
}
if (reference.startsWith(prefix) && reference.endsWith(suffix)) {
return kind;
}
}
return VariableKind.LOCAL_VARIABLE;
}
@Override
@NotNull
public Class<PsiJavaCodeReferenceElement> getReferenceClass() {
@@ -55,7 +55,7 @@ public class FileEqualsUsageInspection extends InternalInspection {
if (clazz == null) return;
String methodName = method.getName();
if ("java.io.File".equals(clazz.getQualifiedName())
if (CommonClassNames.JAVA_IO_FILE.equals(clazz.getQualifiedName())
&& ("equals".equals(methodName) || "compareTo".equals(methodName) || "hashCode".equals(methodName))) {
holder.registerProblem(methodExpression,
"Do not use File.equals/hashCode/compareTo as they don't honor case-sensitivity on MacOS. Use FileUtil.filesEquals/fileHashCode/compareFiles instead",
@@ -87,4 +87,5 @@ public interface CommonClassNames {
@NonNls String JAVA_LANG_INVOKE_MH_POLYMORPHIC = "java.lang.invoke.MethodHandle.PolymorphicSignature";
String TARGET_ANNOTATION_FQ_NAME = "java.lang.annotation.Target";
@NonNls String JAVA_LANG_RUNNABLE = "java.lang.Runnable";
@NonNls String JAVA_IO_FILE = "java.io.File";
}
@@ -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
}
@@ -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);
}
@@ -0,0 +1,96 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NotNull;
/**
* @author Danila Ponomarenko
*/
public abstract class PriorityIntentionActionWrapper implements IntentionAction {
private IntentionAction action;
private PriorityIntentionActionWrapper(@NotNull IntentionAction action) {
this.action = action;
}
@NotNull
@Override
public String getText() {
return action.getText();
}
@NotNull
@Override
public String getFamilyName() {
return action.getFamilyName();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return action.isAvailable(project, editor, file);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
action.invoke(project, editor, file);
}
@Override
public boolean startInWriteAction() {
return action.startInWriteAction();
}
private static class HighPriorityIntentionActionWrapper extends PriorityIntentionActionWrapper implements HighPriorityAction {
protected HighPriorityIntentionActionWrapper(@NotNull IntentionAction action) {
super(action);
}
}
private static class NormalPriorityIntentionActionWrapper extends PriorityIntentionActionWrapper {
protected NormalPriorityIntentionActionWrapper(@NotNull IntentionAction action) {
super(action);
}
}
private static class LowPriorityIntentionActionWrapper extends PriorityIntentionActionWrapper implements LowPriorityAction {
protected LowPriorityIntentionActionWrapper(@NotNull IntentionAction action) {
super(action);
}
}
@NotNull
public static IntentionAction highPriority(@NotNull IntentionAction action) {
return new HighPriorityIntentionActionWrapper(action);
}
@NotNull
public static IntentionAction normalPriority(@NotNull IntentionAction action) {
return new NormalPriorityIntentionActionWrapper(action);
}
@NotNull
public static IntentionAction lowPriority(@NotNull IntentionAction action) {
return new LowPriorityIntentionActionWrapper(action);
}
}
@@ -0,0 +1,85 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInsight.intention.impl;
import com.intellij.codeInsight.intention.HighPriorityAction;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
/**
* @author Danila Ponomarenko
*/
public abstract class PriorityLocalQuickFixWrapper implements LocalQuickFix {
private LocalQuickFix fix;
private PriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) {
this.fix = fix;
}
@NotNull
@Override
public String getName() {
return fix.getName();
}
@NotNull
@Override
public String getFamilyName() {
return fix.getFamilyName();
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
fix.applyFix(project, descriptor);
}
private static class HighPriorityLocalQuickFixWrapper extends PriorityLocalQuickFixWrapper implements HighPriorityAction {
protected HighPriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) {
super(fix);
}
}
private static class NormalPriorityLocalQuickFixWrapper extends PriorityLocalQuickFixWrapper {
protected NormalPriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) {
super(fix);
}
}
private static class LowPriorityLocalQuickFixWrapper extends PriorityLocalQuickFixWrapper implements LowPriorityAction {
protected LowPriorityLocalQuickFixWrapper(@NotNull LocalQuickFix fix) {
super(fix);
}
}
@NotNull
public static LocalQuickFix highPriority(@NotNull LocalQuickFix fix) {
return new HighPriorityLocalQuickFixWrapper(fix);
}
@NotNull
public static LocalQuickFix normalPriority(@NotNull LocalQuickFix fix) {
return new NormalPriorityLocalQuickFixWrapper(fix);
}
@NotNull
public static LocalQuickFix lowPriority(@NotNull LocalQuickFix fix) {
return new LowPriorityLocalQuickFixWrapper(fix);
}
}
@@ -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
}
@@ -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;
@@ -176,7 +176,6 @@ public class FilePathCompletionContributor extends CompletionContributor {
}
}
};
extend(CompletionType.CLASS_NAME, psiElement(), provider);
extend(CompletionType.BASIC, psiElement(), provider);
}
@@ -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";
}
@@ -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>
@@ -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
@@ -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()) {
+1
View File
@@ -126,6 +126,7 @@
<membersContributor implementation="org.jetbrains.plugins.groovy.gant.GantMemberContributor"/>
<typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.GrContainerTypeConverter"/>
<typeConverter implementation="org.jetbrains.plugins.groovy.lang.psi.impl.types.GrStringTypeConverter"/>
<typeConverter implementation="org.jetbrains.plugins.groovy.gpp.GppTypeConverter"/>
<expectedTypesContributor implementation="org.jetbrains.plugins.groovy.gpp.GppExpectedTypesContributor"/>
@@ -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);
}
});
}
}
}
@@ -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;
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.plugins.groovy.lang.psi.impl.types;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.InheritanceUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.groovy.config.GroovyConfigUtils;
import org.jetbrains.plugins.groovy.lang.psi.GrTypeConverter;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import static com.intellij.psi.CommonClassNames.JAVA_LANG_BOOLEAN;
import static com.intellij.psi.CommonClassNames.JAVA_LANG_CLASS;
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_GSTRING;
import static org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.JAVA_LANG_CHAR_SEQUENCE;
/**
* @author Max Medvedev
*/
public class GrStringTypeConverter extends GrTypeConverter {
@Override
public Boolean isConvertible(@NotNull PsiType lType, @NotNull PsiType rType, @NotNull GroovyPsiElement context) {
if (isMethodCallConversion(context)) return null;
if (!GroovyConfigUtils.getInstance().isVersionAtLeast(context, GroovyConfigUtils.GROOVY1_8)) return null;
if (!(InheritanceUtil.isInheritor(rType, JAVA_LANG_CHAR_SEQUENCE) || InheritanceUtil.isInheritor(rType, GROOVY_LANG_GSTRING))) {
return null;
}
if (lType == PsiType.BOOLEAN || resolvesTo(lType, JAVA_LANG_BOOLEAN)) return true;
if (resolvesTo(lType, JAVA_LANG_CLASS)) return true;
if (isEnum(lType)) return true;
return null;
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames;
import java.util.Map;
import java.util.Set;
import static com.intellij.psi.CommonClassNames.JAVA_IO_FILE;
import static org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil.skipParentheses;
/**
@@ -44,13 +45,13 @@ public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer {
simpleTypes.put("withDataOutputStream", "java.io.DataOutputStream");
simpleTypes.put("withDataInputStream", "java.io.DataInputStream");
simpleTypes.put("eachLine", "java.lang.String");
simpleTypes.put("eachFile", "java.io.File");
simpleTypes.put("eachDir", "java.io.File");
simpleTypes.put("eachFileRecurse", "java.io.File");
simpleTypes.put("traverse", "java.io.File");
simpleTypes.put("eachDirRecurse", "java.io.File");
simpleTypes.put("eachFileMatch", "java.io.File");
simpleTypes.put("eachDirMatch", "java.io.File");
simpleTypes.put("eachFile", JAVA_IO_FILE);
simpleTypes.put("eachDir", JAVA_IO_FILE);
simpleTypes.put("eachFileRecurse", JAVA_IO_FILE);
simpleTypes.put("traverse", JAVA_IO_FILE);
simpleTypes.put("eachDirRecurse", JAVA_IO_FILE);
simpleTypes.put("eachFileMatch", JAVA_IO_FILE);
simpleTypes.put("eachDirMatch", JAVA_IO_FILE);
simpleTypes.put("withReader", "java.io.Reader");
simpleTypes.put("withWriter", "java.io.Writer");
simpleTypes.put("withWriterAppend", "java.io.Writer");
@@ -259,7 +260,7 @@ public class ClosureParameterEnhancer extends AbstractClosureParameterEnhancer {
return res;
}
if (TypesUtil.isClassType(iterType, CommonClassNames.JAVA_LANG_STRING) || TypesUtil.isClassType(iterType, "java.io.File")) {
if (TypesUtil.isClassType(iterType, CommonClassNames.JAVA_LANG_STRING) || TypesUtil.isClassType(iterType, JAVA_IO_FILE)) {
return TypesUtil.createTypeByFQClassName(CommonClassNames.JAVA_LANG_STRING, context);
}
@@ -54,6 +54,7 @@ public final class GroovyCommonClassNames {
@NonNls public static final String GROOVY_TRANSFORM_COMPILE_STATIC = "groovy.transform.CompileStatic";
@NonNls public static final String GROOVY_TRANSFORM_TYPE_CHECKED = "groovy.transform.TypeChecked";
@NonNls public static final String GROOVY_TRANSFORM_TYPE_CHECKING_MODE = "groovy.transform.TypeCheckingMode";
@NonNls public static final String JAVA_LANG_CHAR_SEQUENCE = "java.lang.CharSequence";
private GroovyCommonClassNames() {
@@ -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);
@@ -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() {
@@ -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();
@@ -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>
@@ -177,6 +177,7 @@ public class DesignerActionPanel implements DataProvider {
myDynamicPopupGroup.removeAll();
}
WrapInAction.fill(myDesigner, myDynamicPopupGroup, area);
MorphingAction.fill(myDesigner, myDynamicPopupGroup, area);
return myPopupGroup;
@@ -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);
}
}
@@ -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;
}
}
@@ -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" />