diff --git a/java/idea-ui/src/com/intellij/platform/templates/IC_templates.xml b/java/idea-ui/src/com/intellij/platform/templates/IC_templates.xml
index 8da6b26f055a..d8daaec7b869 100644
--- a/java/idea-ui/src/com/intellij/platform/templates/IC_templates.xml
+++ b/java/idea-ui/src/com/intellij/platform/templates/IC_templates.xml
@@ -1,8 +1,7 @@
Java Hello World
-
-
+
HelloWorld.zip
diff --git a/java/idea-ui/src/com/intellij/platform/templates/IU_template_groups.xml b/java/idea-ui/src/com/intellij/platform/templates/IU_template_groups.xml
new file mode 100644
index 000000000000..52446026f3b6
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/platform/templates/IU_template_groups.xml
@@ -0,0 +1,13 @@
+
+
+ Spring
+ Spring
+
+ Spring Core
+
+ SpringApp
+ IJ_BASE_PACKAGE
+ IJ_APPLICATION_SERVER
+
+
+
\ No newline at end of file
diff --git a/java/idea-ui/src/com/intellij/platform/templates/IU_template_groups.xsd b/java/idea-ui/src/com/intellij/platform/templates/IU_template_groups.xsd
new file mode 100644
index 000000000000..c7adb5afba89
--- /dev/null
+++ b/java/idea-ui/src/com/intellij/platform/templates/IU_template_groups.xsd
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java b/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java
index 33b6d84e594c..e6bd637eb0fd 100644
--- a/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java
+++ b/java/idea-ui/src/com/intellij/platform/templates/RemoteTemplatesFactory.java
@@ -22,21 +22,26 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.ModuleTypeManager;
+import com.intellij.openapi.util.ClearableLazyValue;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.platform.ProjectTemplate;
import com.intellij.platform.ProjectTemplatesFactory;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.NullableFunction;
import com.intellij.util.containers.ContainerUtil;
+import com.intellij.util.containers.MultiMap;
import com.intellij.util.net.HttpConfigurable;
import org.jdom.Element;
import org.jdom.JDOMException;
+import org.jdom.Namespace;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
+import java.util.Collection;
import java.util.List;
import java.util.zip.ZipInputStream;
@@ -47,32 +52,47 @@ import java.util.zip.ZipInputStream;
public class RemoteTemplatesFactory extends ProjectTemplatesFactory {
private static final String URL = "http://download.jetbrains.com/idea/project_templates/";
+ private static final String SAMPLES_GALLERY = "Samples Gallery";
+ private static final Namespace NAMESPACE = Namespace.getNamespace("http://www.jetbrains.com/projectTemplates");
+ private final ClearableLazyValue> myTemplates = new ClearableLazyValue>() {
+ @NotNull
+ @Override
+ protected MultiMap compute() {
+ return getTemplates();
+ }
+ };
@NotNull
@Override
public String[] getGroups() {
- return new String[] { "Samples Gallery"};
+ myTemplates.drop();
+ return ArrayUtil.toStringArray(myTemplates.getValue().keySet());
}
@NotNull
@Override
public ProjectTemplate[] createTemplates(String group, WizardContext context) {
+ Collection templates = myTemplates.getValue().get(group);
+ return templates.toArray(new ProjectTemplate[templates.size()]);
+ }
+
+ private static MultiMap getTemplates() {
InputStream stream = null;
HttpURLConnection connection = null;
String code = ApplicationInfo.getInstance().getBuild().getProductCode();
try {
connection = getConnection(code + "_templates.xml");
stream = connection.getInputStream();
- String text = StreamUtil.readText(stream);
+ String text = StreamUtil.readText(stream, TemplateModuleBuilder.UTF_8);
return createFromText(text);
}
catch (IOException ex) { // timeouts, lost connection etc
LOG.info(ex);
- return ProjectTemplate.EMPTY_ARRAY;
+ return MultiMap.emptyInstance();
}
catch (Exception e) {
LOG.error(e);
- return ProjectTemplate.EMPTY_ARRAY;
+ return MultiMap.emptyInstance();
}
finally {
StreamUtil.closeStream(stream);
@@ -83,15 +103,32 @@ public class RemoteTemplatesFactory extends ProjectTemplatesFactory {
}
@SuppressWarnings("unchecked")
- public static ProjectTemplate[] createFromText(String text) throws IOException, JDOMException {
+ public static MultiMap createFromText(String text) throws IOException, JDOMException {
- List elements = JDOMUtil.loadDocument(text).getRootElement().getChildren("template");
+ Element rootElement = JDOMUtil.loadDocument(text).getRootElement();
+ List groups = rootElement.getChildren("group", NAMESPACE);
+ MultiMap map = new MultiMap();
+ if (groups.isEmpty()) { // sample gallery by default
+ map.put(SAMPLES_GALLERY, createGroupTemplates(rootElement, Namespace.NO_NAMESPACE));
+ }
+ else {
+ for (Element group : groups) {
+ map.put(group.getChildText("name", NAMESPACE), createGroupTemplates(group, NAMESPACE));
+ }
+ }
- List templates = ContainerUtil.mapNotNull(elements, new NullableFunction() {
+ return map;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static List createGroupTemplates(Element groupElement, final Namespace ns) {
+ List elements = groupElement.getChildren("template", ns);
+
+ return ContainerUtil.mapNotNull(elements, new NullableFunction() {
@Override
public ProjectTemplate fun(final Element element) {
- List plugins = element.getChildren("requiredPlugin");
+ List plugins = element.getChildren("requiredPlugin", ns);
for (Element plugin : plugins) {
String id = plugin.getTextTrim();
if (!PluginManager.isPluginInstalled(PluginId.getId(id))) {
@@ -100,7 +137,7 @@ public class RemoteTemplatesFactory extends ProjectTemplatesFactory {
}
String type = element.getChildText("moduleType");
final ModuleType moduleType = ModuleTypeManager.getInstance().findByID(type);
- return new ArchivedProjectTemplate(element.getChildTextTrim("name")) {
+ return new ArchivedProjectTemplate(element.getChildTextTrim("name", ns)) {
@Override
protected ModuleType getModuleType() {
return moduleType;
@@ -108,7 +145,7 @@ public class RemoteTemplatesFactory extends ProjectTemplatesFactory {
@Override
public ZipInputStream getStream() throws IOException {
- String path = element.getChildText("path");
+ String path = element.getChildText("path", ns);
final HttpURLConnection connection = getConnection(path);
return new ZipInputStream(connection.getInputStream()) {
@Override
@@ -122,12 +159,11 @@ public class RemoteTemplatesFactory extends ProjectTemplatesFactory {
@Nullable
@Override
public String getDescription() {
- return element.getChildTextTrim("description");
+ return element.getChildTextTrim("description", ns);
}
};
}
});
- return templates.toArray(new ProjectTemplate[templates.size()]);
}
private static HttpURLConnection getConnection(String path) throws IOException {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
index 63d55511f488..236e2e6768f6 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionSorting.java
@@ -59,10 +59,7 @@ public class JavaCompletionSorting {
final boolean afterNew = JavaSmartCompletionContributor.AFTER_NEW.accepts(position);
List afterPriority = new ArrayList();
- if (!smart) {
- ContainerUtil.addIfNotNull(afterPriority, preferStatics(position, expectedTypes));
- }
- else {
+ if (smart) {
afterPriority.add(new PreferDefaultTypeWeigher(expectedTypes, parameters));
}
ContainerUtil.addIfNotNull(afterPriority, recursion(parameters, expectedTypes));
@@ -83,13 +80,13 @@ public class JavaCompletionSorting {
}
List afterPrefix = ContainerUtil.newArrayList();
- if (smart) {
- afterPriority.add(new PreferByKindWeigher(type, position, true));
+ if (!smart) {
+ ContainerUtil.addIfNotNull(afterPrefix, preferStatics(position, expectedTypes));
}
if (!smart && !afterNew) {
afterPrefix.add(new PreferExpected(false, expectedTypes));
}
- afterPrefix.add(new PreferByKindWeigher(type, position, false));
+ afterPrefix.add(new PreferByKindWeigher(type, position));
Collections.addAll(afterPrefix, new PreferNonGeneric(), new PreferAccessible(position), new PreferSimple(),
new PreferEnumConstants(parameters));
@@ -132,7 +129,9 @@ public class JavaCompletionSorting {
public Comparable weigh(@NotNull LookupElement element) {
final Object o = element.getObject();
if (o instanceof PsiKeyword) return -3;
- if (!(o instanceof PsiMember)) return 0;
+ if (!(o instanceof PsiMember) || element.getUserData(JavaOverrideCompletionContributor.OVERRIDE_ELEMENT) != null) {
+ return 0;
+ }
if (((PsiMember)o).hasModifierProperty(PsiModifier.STATIC) && !hasNonVoid(infos)) {
if (o instanceof PsiMethod) return -5;
@@ -405,7 +404,7 @@ public class JavaCompletionSorting {
public Comparable weigh(@NotNull LookupElement element) {
final PsiTypeLookupItem lookupItem = element.as(PsiTypeLookupItem.CLASS_CONDITION_KEY);
if (lookupItem != null) {
- return lookupItem.getBracketsCount();
+ return lookupItem.getBracketsCount() * 10 + (lookupItem.isAddArrayInitializer() ? 1 : 0);
}
if (element.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY) != null) {
return 239;
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java
index 52d493b551dd..9904c46f560a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaInheritorsGetter.java
@@ -50,6 +50,14 @@ public class JavaInheritorsGetter extends CompletionProvider extractClassTypes(ExpectedTypeInfo[] infos) {
final List expectedClassTypes = new SmartList();
for (PsiType type : ExpectedTypesGetter.extractTypes(infos, true)) {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java
new file mode 100644
index 000000000000..d71de30567c2
--- /dev/null
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaOverrideCompletionContributor.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2000-2013 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.generation.GenerateMembersUtil;
+import com.intellij.codeInsight.generation.OverrideImplementExploreUtil;
+import com.intellij.codeInsight.generation.OverrideImplementUtil;
+import com.intellij.codeInsight.generation.PsiGenerationInfo;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementBuilder;
+import com.intellij.icons.AllIcons;
+import com.intellij.openapi.util.Key;
+import com.intellij.psi.*;
+import com.intellij.psi.infos.CandidateInfo;
+import com.intellij.psi.util.PsiFormatUtil;
+import com.intellij.psi.util.PsiFormatUtilBase;
+import com.intellij.psi.util.TypeConversionUtil;
+import com.intellij.ui.RowIcon;
+import com.intellij.util.Consumer;
+
+import java.util.List;
+
+import static com.intellij.patterns.PlatformPatterns.psiElement;
+
+/**
+ * @author peter
+ */
+public class JavaOverrideCompletionContributor extends CompletionContributor {
+ static final Key OVERRIDE_ELEMENT = Key.create("OVERRIDE_ELEMENT");
+
+ @Override
+ public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet _result) {
+ if (parameters.getCompletionType() != CompletionType.BASIC && parameters.getCompletionType() != CompletionType.SMART) {
+ return;
+ }
+
+ PsiElement position = parameters.getPosition();
+ if (psiElement(PsiIdentifier.class).withParents(PsiJavaCodeReferenceElement.class, PsiTypeElement.class, PsiClass.class).
+ andNot(JavaCompletionData.AFTER_DOT).
+ andNot(psiElement().afterLeaf(psiElement().inside(PsiModifierList.class))).accepts(position)) {
+ final PsiClass parent = CompletionUtil.getOriginalElement((PsiClass)position.getParent().getParent().getParent());
+ if (parent != null) {
+ CompletionResultSet result = JavaCompletionSorting.addJavaSorting(parameters, _result);
+ addSuperSignatureElements(parent, true, result);
+ addSuperSignatureElements(parent, false, result);
+ }
+ }
+
+ }
+
+ private static void addSuperSignatureElements(final PsiClass parent, boolean implemented, CompletionResultSet result) {
+ for (CandidateInfo candidate : OverrideImplementExploreUtil.getMethodsToOverrideImplement(parent, implemented)) {
+ PsiMethod baseMethod = (PsiMethod)candidate.getElement();
+ if (!baseMethod.isConstructor()) {
+ PsiClass baseClass = baseMethod.getContainingClass();
+ List prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, candidate.getSubstitutor(), new Consumer() {
+ @Override
+ public void consume(PsiMethod method) {
+ OverrideImplementUtil.deleteDocComment(method);
+ }
+ });
+ if (!prototypes.isEmpty() && baseClass != null) {
+ result.addElement(createOverridingLookupElement(parent, implemented, baseMethod, baseClass, prototypes.get(0)));
+ }
+ }
+ }
+ }
+
+ private static LookupElementBuilder createOverridingLookupElement(final PsiClass parent,
+ boolean implemented,
+ final PsiMethod baseMethod,
+ PsiClass baseClass, final PsiMethod prototype) {
+ PsiIdentifier nameIdentifier = prototype.getNameIdentifier();
+ assert nameIdentifier != null;
+
+ String signature = prototype.getModifierList().getText();
+ if (!signature.isEmpty()) {
+ signature += " ";
+ }
+ PsiType returnType = prototype.getReturnType();
+ signature += TypeConversionUtil.erasure(returnType).getPresentableText() + " " + prototype.getName();
+
+ String parameters = PsiFormatUtil.formatMethod(prototype, PsiSubstitutor.EMPTY, PsiFormatUtilBase.SHOW_PARAMETERS, PsiFormatUtilBase.SHOW_NAME);
+
+ InsertHandler insertHandler = new InsertHandler() {
+ @Override
+ public void handleInsert(InsertionContext context, LookupElement item) {
+ context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset());
+ context.commitDocument();
+
+ List prototypes = OverrideImplementUtil.overrideOrImplementMethod(parent, baseMethod, false);
+ List> infos = OverrideImplementUtil.convert2GenerationInfos(prototypes);
+ List> newInfos = GenerateMembersUtil.insertMembersAtOffset(context.getFile(), context.getStartOffset(), infos);
+ if (!newInfos.isEmpty()) {
+ newInfos.get(0).positionCaret(context.getEditor(), true);
+ }
+ }
+ };
+
+ RowIcon icon = new RowIcon(2);
+ icon.setIcon(baseMethod.getIcon(0), 0);
+ icon.setIcon(implemented ? AllIcons.Gutter.ImplementingMethod : AllIcons.Gutter.OverridingMethod, 1);
+
+ LookupElementBuilder element = LookupElementBuilder.create(baseMethod, signature).withLookupString(prototype.getName()).
+ withLookupString(signature).withInsertHandler(insertHandler).
+ appendTailText(parameters, false).appendTailText(" {...}", true).withTypeText(baseClass.getName()).withIcon(icon);
+ element.putUserData(OVERRIDE_ELEMENT, true);
+ return element;
+ }
+}
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java
index 824a8907f435..349cb7b47890 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaPsiClassReferenceElement.java
@@ -155,9 +155,12 @@ public class JavaPsiClassReferenceElement extends LookupItem {
String tailText = StringUtil.notNullize((String) item.getAttribute(LookupItem.TAIL_TEXT_ATTR));
PsiSubstitutor substitutor = (PsiSubstitutor)item.getAttribute(LookupItem.SUBSTITUTOR);
- if (item instanceof PsiTypeLookupItem && ((PsiTypeLookupItem)item).isIndicateAnonymous() &&
- (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT))) {
- tailText = "{...}" + tailText;
+ if (item instanceof PsiTypeLookupItem) {
+ if (((PsiTypeLookupItem)item).isIndicateAnonymous() &&
+ (psiClass.isInterface() || psiClass.hasModifierProperty(PsiModifier.ABSTRACT)) ||
+ ((PsiTypeLookupItem)item).isAddArrayInitializer()) {
+ tailText = "{...}" + tailText;
+ }
}
if (substitutor == null && !diamond && psiClass.getTypeParameters().length > 0) {
tailText = "<" + StringUtil.join(psiClass.getTypeParameters(), new Function() {
diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
index 8ed82061134f..a3a44ad6d4aa 100644
--- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
+++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java
@@ -46,7 +46,8 @@ public class PreferByKindWeigher extends LookupElementWeigher {
psiElement(PsiVariable.class).withParent(PsiCatchSection.class)))));
static final ElementPattern IN_MULTI_CATCH_TYPE =
or(psiElement().afterLeaf(psiElement().withText("|").withParent(PsiTypeElement.class).withSuperParent(2, PsiCatchSection.class)),
- psiElement().afterLeaf(psiElement().withText("|").withParent(PsiTypeElement.class).withSuperParent(2, PsiParameter.class).withSuperParent(3, PsiCatchSection.class)));
+ psiElement().afterLeaf(psiElement().withText("|").withParent(PsiTypeElement.class).withSuperParent(2, PsiParameter.class)
+ .withSuperParent(3, PsiCatchSection.class)));
static final ElementPattern INSIDE_METHOD_THROWS_CLAUSE =
psiElement().afterLeaf(PsiKeyword.THROWS, ",").inside(psiElement(JavaElementType.THROWS_LIST));
static final ElementPattern IN_RESOURCE_TYPE =
@@ -55,15 +56,13 @@ public class PreferByKindWeigher extends LookupElementWeigher {
withParent(or(psiElement(PsiResourceVariable.class), psiElement(PsiResourceList.class)))));
private final CompletionType myCompletionType;
private final PsiElement myPosition;
- private final boolean myLocal;
private final Set myNonInitializedFields;
@NotNull private final Condition myRequiredSuper;
- public PreferByKindWeigher(CompletionType completionType, final PsiElement position, boolean local) {
- super("kind" + (local ? "Local" : "Global"));
+ public PreferByKindWeigher(CompletionType completionType, final PsiElement position) {
+ super("kind");
myCompletionType = completionType;
myPosition = position;
- myLocal = local;
myNonInitializedFields = JavaCompletionProcessor.getNonInitializedFields(position);
myRequiredSuper = createSuitabilityCondition(position);
}
@@ -155,10 +154,6 @@ public class PreferByKindWeigher extends LookupElementWeigher {
}
}
- if (myLocal) {
- return MyResult.normal;
- }
-
if (object instanceof String && item.getUserData(JavaCompletionUtil.SUPER_METHOD_PARAMETERS) == Boolean.TRUE) {
return MyResult.superMethodParameters;
}
diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
index 3ca3e538c054..e0eaca96611e 100644
--- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/analysis/HighlightClassUtil.java
@@ -282,10 +282,14 @@ public class HighlightClassUtil {
PsiElement file = aClass.getParent();
if (file instanceof PsiJavaFile && !((PsiJavaFile)file).getPackageName().isEmpty()) {
PsiElement directory = file.getParent();
- if (directory instanceof PsiDirectory && ((PsiDirectory)directory).findSubdirectory(aClass.getName()) != null) {
- String message = JavaErrorMessages.message("class.clashes.with.package", name);
- TextRange range = HighlightNamesUtil.getClassDeclarationTextRange(aClass);
- return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, range, message);
+ if (directory instanceof PsiDirectory) {
+ String simpleName = aClass.getName();
+ PsiDirectory subDirectory = ((PsiDirectory)directory).findSubdirectory(simpleName);
+ if (subDirectory != null && simpleName.equals(subDirectory.getName())) {
+ String message = JavaErrorMessages.message("class.clashes.with.package", name);
+ TextRange range = HighlightNamesUtil.getClassDeclarationTextRange(aClass);
+ return HighlightInfo.createHighlightInfo(HighlightInfoType.ERROR, range, message);
+ }
}
}
@@ -691,7 +695,7 @@ public class HighlightClassUtil {
IntentionAction fix = QUICK_FIX_FACTORY.createModifierListFix(aClass, PsiModifier.STATIC, false, false);
QuickFixAction.registerQuickFixAction(info, fix);
}
-
+
} else if (aClass instanceof PsiAnonymousClass) {
final PsiClass baseClass = PsiUtil.resolveClassInType(((PsiAnonymousClass)aClass).getBaseClassType());
if (baseClass != null && baseClass.isInterface()) {
@@ -982,7 +986,7 @@ public class HighlightClassUtil {
PsiNewExpression newExpression =
(PsiNewExpression)JavaPsiFacade.getElementFactory(project).createExpressionFromText(startElement.getText() + "{}", startElement);
newExpression = (PsiNewExpression)startElement.replace(newExpression);
- final PsiClass psiClass = newExpression.getAnonymousClass();
+ final PsiClass psiClass = newExpression.getAnonymousClass();
if (psiClass == null) return;
PsiClassType baseClassType = ((PsiAnonymousClass)psiClass).getBaseClassType();
PsiClass resolve = baseClassType.resolve();
diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
index 115545a38828..8a2fa775a35a 100644
--- a/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
+++ b/java/java-impl/src/com/intellij/codeInsight/generation/OverrideImplementUtil.java
@@ -61,6 +61,7 @@ import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.util.*;
import com.intellij.util.ArrayUtil;
+import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
@@ -95,7 +96,7 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil {
* @return list of method prototypes
*/
@NotNull
- public static Collection overrideOrImplementMethod(PsiClass aClass, PsiMethod method, boolean toCopyJavaDoc) throws IncorrectOperationException {
+ public static List overrideOrImplementMethod(PsiClass aClass, PsiMethod method, boolean toCopyJavaDoc) throws IncorrectOperationException {
final PsiClass containingClass = method.getContainingClass();
LOG.assertTrue(containingClass != null);
PsiSubstitutor substitutor = aClass.isInheritor(containingClass, true)
@@ -126,11 +127,18 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil {
}
@NotNull
- private static Collection overrideOrImplementMethod(PsiClass aClass,
+ private static List overrideOrImplementMethod(PsiClass aClass,
PsiMethod method,
PsiSubstitutor substitutor,
boolean toCopyJavaDoc,
boolean insertOverrideIfPossible) throws IncorrectOperationException {
+ return overrideOrImplementMethod(aClass, method, substitutor, createDefaultDecorator(aClass, method, toCopyJavaDoc, insertOverrideIfPossible));
+ }
+
+ public static List overrideOrImplementMethod(PsiClass aClass,
+ PsiMethod method,
+ PsiSubstitutor substitutor,
+ Consumer decorator) throws IncorrectOperationException {
if (!method.isValid() || !substitutor.isValid()) return Collections.emptyList();
List results = new ArrayList();
@@ -141,13 +149,14 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil {
}
else {
for (PsiMethod prototype : prototypes) {
- results.add(decorateMethod(aClass, method, toCopyJavaDoc, insertOverrideIfPossible, prototype));
+ decorator.consume(prototype);
+ results.add(prototype);
}
}
}
if (results.isEmpty()) {
PsiMethod method1 = GenerateMembersUtil.substituteGenericMethod(method, substitutor, aClass);
-
+
PsiElementFactory factory = JavaPsiFacade.getInstance(method.getProject()).getElementFactory();
PsiMethod result = (PsiMethod)factory.createClass("Dummy").add(method1);
if (PsiUtil.isAnnotationMethod(result)) {
@@ -161,7 +170,8 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil {
defaultValue.getParent().deleteChildRange(defaultKeyword, defaultValue);
}
}
- results.add(decorateMethod(aClass, method, toCopyJavaDoc, insertOverrideIfPossible, result));
+ decorator.consume(result);
+ results.add(result);
}
for (Iterator iterator = results.iterator(); iterator.hasNext();) {
@@ -173,6 +183,18 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil {
return results;
}
+ public static Consumer createDefaultDecorator(final PsiClass aClass,
+ final PsiMethod method,
+ final boolean toCopyJavaDoc,
+ final boolean insertOverrideIfPossible) {
+ return new Consumer() {
+ @Override
+ public void consume(PsiMethod result) {
+ decorateMethod(aClass, method, toCopyJavaDoc, insertOverrideIfPossible, result);
+ }
+ };
+ }
+
private static PsiMethod decorateMethod(PsiClass aClass,
PsiMethod method,
boolean toCopyJavaDoc,
@@ -182,10 +204,7 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil {
PsiUtil.setModifierProperty(result, PsiModifier.NATIVE, false);
if (!toCopyJavaDoc){
- PsiDocComment comment = result.getDocComment();
- if (comment != null){
- comment.delete();
- }
+ deleteDocComment(result);
}
//method type params are not allowed when overriding from raw type
@@ -231,6 +250,13 @@ public class OverrideImplementUtil extends OverrideImplementExploreUtil {
return result;
}
+ public static void deleteDocComment(PsiMethod result) {
+ PsiDocComment comment = result.getDocComment();
+ if (comment != null){
+ comment.delete();
+ }
+ }
+
public static void annotateOnOverrideImplement(PsiMethod method, PsiClass targetClass, PsiMethod overridden) {
annotateOnOverrideImplement(method, targetClass, overridden,
CodeStyleSettingsManager.getSettings(method.getProject()).INSERT_OVERRIDE_ANNOTATION);
diff --git a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java
index 11cfe66ef6c0..cba613755b46 100644
--- a/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java
+++ b/java/java-impl/src/com/intellij/codeInsight/lookup/PsiTypeLookupItem.java
@@ -27,7 +27,6 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.DebugUtil;
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
import com.intellij.psi.impl.source.PsiClassReferenceType;
-import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -55,6 +54,7 @@ public class PsiTypeLookupItem extends LookupItem {
private final int myBracketsCount;
private boolean myIndicateAnonymous;
private final InsertHandler myImportFixer;
+ private boolean myAddArrayInitializer;
private PsiTypeLookupItem(Object o, @NotNull @NonNls String lookupString, boolean diamond, int bracketsCount, InsertHandler fixer) {
super(o, lookupString);
@@ -84,7 +84,17 @@ public class PsiTypeLookupItem extends LookupItem {
@Override
public boolean equals(final Object o) {
- return super.equals(o) && o instanceof PsiTypeLookupItem && getBracketsCount() == ((PsiTypeLookupItem) o).getBracketsCount();
+ return super.equals(o) && o instanceof PsiTypeLookupItem &&
+ getBracketsCount() == ((PsiTypeLookupItem) o).getBracketsCount() &&
+ myAddArrayInitializer == ((PsiTypeLookupItem) o).myAddArrayInitializer;
+ }
+
+ public boolean isAddArrayInitializer() {
+ return myAddArrayInitializer;
+ }
+
+ public void setAddArrayInitializer() {
+ myAddArrayInitializer = true;
}
@Override
@@ -93,7 +103,6 @@ public class PsiTypeLookupItem extends LookupItem {
PsiElement position = context.getFile().findElementAt(context.getStartOffset());
assert position != null;
- boolean addBraces = shouldAddBraces(position);
int genericsStart = context.getTailOffset();
context.getDocument().insertString(genericsStart, JavaCompletionUtil.escapeXmlIfNeeded(context, calcGenerics(position, context)));
JavaCompletionUtil.shortenReference(context.getFile(), genericsStart - 1);
@@ -102,7 +111,7 @@ public class PsiTypeLookupItem extends LookupItem {
String braces = StringUtil.repeat("[]", getBracketsCount());
Editor editor = context.getEditor();
if (!braces.isEmpty()) {
- if (LookupEvent.isSpecialCompletionChar(context.getCompletionChar()) && addBraces) {
+ if (myAddArrayInitializer) {
context.getDocument().insertString(tail, braces + "{}");
editor.getCaretModel().moveToOffset(tail + braces.length() + 1);
} else {
@@ -125,14 +134,6 @@ public class PsiTypeLookupItem extends LookupItem {
}
}
- private static boolean shouldAddBraces(PsiElement position) {
- if (!JavaCompletionContributor.isInJavaContext(position) || !JavaSmartCompletionContributor.AFTER_NEW.accepts(position)) {
- return false;
- }
- PsiNewExpression newExpression = PsiTreeUtil.getParentOfType(position, PsiNewExpression.class);
- return newExpression != null && newExpression.getParent() instanceof PsiExpressionList;
- }
-
public String calcGenerics(@NotNull PsiElement context, InsertionContext insertionContext) {
if (insertionContext.getCompletionChar() == '<') {
return "";
diff --git a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
index 0b2397f4e1df..dca78ce60d56 100644
--- a/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
+++ b/java/java-psi-impl/src/com/intellij/codeInsight/javadoc/JavaDocInfoGenerator.java
@@ -467,7 +467,7 @@ public class JavaDocInfoGenerator {
}
// not a javadoc in fact..
- private void generateVariableJavaDoc(@NonNls StringBuilder buffer, PsiVariable variable, boolean generatePrologueAndEpilogue) {
+ private static void generateVariableJavaDoc(@NonNls StringBuilder buffer, PsiVariable variable, boolean generatePrologueAndEpilogue) {
if (generatePrologueAndEpilogue)
generatePrologue(buffer);
@@ -604,7 +604,7 @@ public class JavaDocInfoGenerator {
}
}
- private void generateAnnotations (@NonNls StringBuilder buffer, PsiModifierListOwner owner) {
+ private static void generateAnnotations(@NonNls StringBuilder buffer, PsiModifierListOwner owner) {
final PsiModifierList ownerModifierList = owner.getModifierList();
if (ownerModifierList == null) return;
PsiAnnotation[] annotations = ownerModifierList.getAnnotations();
@@ -1861,5 +1861,10 @@ public class JavaDocInfoGenerator {
public void visitLiteralExpression(PsiLiteralExpression expression) {
myBuffer.append(expression.getText());
}
+
+ @Override
+ public void visitReferenceExpression(PsiReferenceExpression expression) {
+ myBuffer.append(expression.getText());
+ }
}
}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/ImplementViaCompletion.java b/java/java-tests/testData/codeInsight/completion/normal/ImplementViaCompletion.java
new file mode 100644
index 000000000000..85d7845803d8
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/ImplementViaCompletion.java
@@ -0,0 +1,7 @@
+interface Foo {
+ void run(T t, int myInt);
+}
+
+public class A implements Foo {
+ p
+}
diff --git a/java/java-tests/testData/codeInsight/completion/normal/ImplementViaCompletion_after.java b/java/java-tests/testData/codeInsight/completion/normal/ImplementViaCompletion_after.java
new file mode 100644
index 000000000000..a13b20e89807
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/completion/normal/ImplementViaCompletion_after.java
@@ -0,0 +1,10 @@
+interface Foo {
+ void run(T t, int myInt);
+}
+
+public class A implements Foo {
+ @Override
+ public void run(String s, int myInt) {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ArrayInitializerBeforeVarargs-out.java b/java/java-tests/testData/codeInsight/completion/smartType/ArrayInitializerBeforeVarargs-out.java
index bec60ac2de6b..49ce3eb54d4b 100644
--- a/java/java-tests/testData/codeInsight/completion/smartType/ArrayInitializerBeforeVarargs-out.java
+++ b/java/java-tests/testData/codeInsight/completion/smartType/ArrayInitializerBeforeVarargs-out.java
@@ -1,5 +1,5 @@
class Super {
void foo(String[] params, int... indices) {
- foo(new String[]{}, 0);
+ foo(new String[], 0);
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/completion/smartType/ThrowExceptionConstructor-out.java b/java/java-tests/testData/codeInsight/completion/smartType/ThrowExceptionConstructor-out.java
index 7d740e51351c..d105afd9a5d7 100644
--- a/java/java-tests/testData/codeInsight/completion/smartType/ThrowExceptionConstructor-out.java
+++ b/java/java-tests/testData/codeInsight/completion/smartType/ThrowExceptionConstructor-out.java
@@ -4,6 +4,6 @@ class MyException extends RuntimeException {
class XXX {
{
- throw new MyException(new String[]{});
+ throw new MyException(new String[]);
}
}
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash/java/lang.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/lang.java
similarity index 100%
rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash/java/lang.java
rename to java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/lang.java
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash/pkg/sub.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash1/pkg/sub.java
similarity index 100%
rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash/pkg/sub.java
rename to java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash1/pkg/sub.java
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash/pkg/sub/Test.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash1/pkg/sub/Test.java
similarity index 100%
rename from java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash/pkg/sub/Test.java
rename to java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash1/pkg/sub/Test.java
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash2/pkg/Sub.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash2/pkg/Sub.java
new file mode 100644
index 000000000000..bea47a75e0e3
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash2/pkg/Sub.java
@@ -0,0 +1,3 @@
+package pkg;
+
+public class Sub { }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash2/pkg/sub/Test.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash2/pkg/sub/Test.java
new file mode 100644
index 000000000000..bf2f203764d6
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/advHighlighting/packageClassClash2/pkg/sub/Test.java
@@ -0,0 +1,3 @@
+package pkg.sub;
+
+public class Test { }
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/javadocIG/initializerWithReference.html b/java/java-tests/testData/codeInsight/javadocIG/initializerWithReference.html
new file mode 100644
index 000000000000..f4ba3cbff9d1
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/javadocIG/initializerWithReference.html
@@ -0,0 +1 @@
+ Testpublic int field = anotherField
\ No newline at end of file
diff --git a/java/java-tests/testData/codeInsight/javadocIG/initializerWithReference.java b/java/java-tests/testData/codeInsight/javadocIG/initializerWithReference.java
new file mode 100644
index 000000000000..39a7384fdbb1
--- /dev/null
+++ b/java/java-tests/testData/codeInsight/javadocIG/initializerWithReference.java
@@ -0,0 +1,4 @@
+class Test {
+ public int field = anotherField;
+ public static int anotherField = 1;
+}
\ No newline at end of file
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
index ba50bdbe788c..0c7e3f1ce4bf 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/NormalCompletionTest.groovy
@@ -1316,5 +1316,20 @@ class XInternalError {}
assert lookup.items.size() == 1
}
+ public void testImplementViaCompletion() {
+ configure()
+ myFixture.assertPreferredCompletionItems 0, 'private', 'protected', 'public', 'public void run'
+ def item = lookup.items[3]
+
+ def p = LookupElementPresentation.renderElement(item)
+ assert p.itemText == 'public void run'
+ assert p.tailText == '(s, myInt) {...}'
+ assert p.typeText == 'Foo'
+
+ lookup.currentItem = item
+ myFixture.type('\n')
+ checkResult()
+ }
+
}
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
index 7741a09efe0a..6b971c14f233 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/completion/SmartTypeCompletionTest.java
@@ -348,6 +348,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
String path = "/generics";
configureByFile(path + "/before9.java");
+ selectItem(myItems[1]);
checkResultByFile(path + "/after9.java");
}
@@ -421,7 +422,7 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testArrayAccessIndex() throws Throwable { doTest(); }
- public void testThrowExceptionConstructor() throws Throwable { doTest(); }
+ public void testThrowExceptionConstructor() throws Throwable { doTest('\n'); }
public void testJavadocThrows() throws Throwable { doTest(); }
@@ -594,16 +595,18 @@ public class SmartTypeCompletionTest extends LightFixtureCompletionTestCase {
public void testNewVararg() throws Throwable {
configureByTestName();
- assertStringItems("Foo", "Foo");
+ assertStringItems("Foo", "Foo", "Foo");
assertEquals("{...} (default package)", LookupElementPresentation.renderElement(myItems[0]).getTailText());
assertEquals("[] (default package)", LookupElementPresentation.renderElement(myItems[1]).getTailText());
+ assertEquals("[]{...} (default package)", LookupElementPresentation.renderElement(myItems[2]).getTailText());
}
public void testNewVararg2() throws Throwable {
configureByTestName();
- assertStringItems("String", "String");
+ assertStringItems("String", "String", "String");
assertEquals(" (java.lang)", LookupElementPresentation.renderElement(myItems[0]).getTailText());
assertEquals("[] (java.lang)", LookupElementPresentation.renderElement(myItems[1]).getTailText());
+ assertEquals("[]{...} (java.lang)", LookupElementPresentation.renderElement(myItems[2]).getTailText());
}
public void testNewByteArray() {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java
index b513b4732b3c..076773a62e34 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/daemon/AdvHighlightingTest.java
@@ -286,16 +286,24 @@ public class AdvHighlightingTest extends DaemonAnalyzerTestCase {
doTest(BASE_PATH + "/notAKeywords/Test.java", BASE_PATH + "/notAKeywords", false, false);
}
- public void testPackageAndClassConflict1() throws Exception {
- doTest(BASE_PATH + "/packageClassClash/pkg/sub/Test.java", BASE_PATH + "/packageClassClash", false, false);
+ public void testPackageAndClassConflict11() throws Exception {
+ doTest(BASE_PATH + "/packageClassClash1/pkg/sub/Test.java", BASE_PATH + "/packageClassClash1", false, false);
}
- public void testPackageAndClassConflict2() throws Exception {
- doTest(BASE_PATH + "/packageClassClash/pkg/sub.java", BASE_PATH + "/packageClassClash", false, false);
+ public void testPackageAndClassConflict12() throws Exception {
+ doTest(BASE_PATH + "/packageClassClash1/pkg/sub.java", BASE_PATH + "/packageClassClash1", false, false);
}
- public void testPackageAndClassConflict3() throws Exception {
- doTest(BASE_PATH + "/packageClassClash/java/lang.java", false, false);
+ public void testPackageAndClassConflict21() throws Exception {
+ doTest(BASE_PATH + "/packageClassClash2/pkg/sub/Test.java", BASE_PATH + "/packageClassClash2", false, false);
+ }
+
+ public void testPackageAndClassConflict22() throws Exception {
+ doTest(BASE_PATH + "/packageClassClash2/pkg/Sub.java", BASE_PATH + "/packageClassClash2", false, false);
+ }
+
+ public void testDefaultPackageAndClassConflict() throws Exception {
+ doTest(BASE_PATH + "/lang.java", false, false);
}
public void testPackageObscuring() throws Exception {
diff --git a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java
index 666709af1083..e6595b98b11a 100644
--- a/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java
+++ b/java/java-tests/testSrc/com/intellij/codeInsight/javadoc/JavaDocInfoGeneratorTest.java
@@ -58,6 +58,10 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase {
public void testInitializerWithNew() throws Exception {
doTestField();
}
+
+ public void testInitializerWithReference() throws Exception {
+ doTestField();
+ }
private void doTestField() throws Exception {
PsiClass psiClass = getTestClass();
@@ -80,6 +84,7 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase {
final File htmlPath = new File(JavaTestUtil.getJavaTestDataPath() + "/codeInsight/javadocIG/" + getTestName(true) + ".html");
String htmlText = FileUtil.loadFile(htmlPath);
String docInfo = new JavaDocInfoGenerator(getProject(), field).generateDocInfo(null);
+ assertNotNull(docInfo);
assertEquals(StringUtil.convertLineSeparators(htmlText.trim()), StringUtil.convertLineSeparators(docInfo.trim()));
}
@@ -90,6 +95,7 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase {
final String info =
new JavaDocInfoGenerator(getProject(), JavaPsiFacade.getInstance(getProject()).findPackage(getTestName(true))).generateDocInfo(null);
String htmlText = FileUtil.loadFile(new File(packageInfo + File.separator + "packageInfo.html"));
+ assertNotNull(info);
assertEquals(StringUtil.convertLineSeparators(htmlText.trim()), StringUtil.convertLineSeparators(info.trim()));
}
diff --git a/platform/core-api/src/com/intellij/psi/tree/IFileElementType.java b/platform/core-api/src/com/intellij/psi/tree/IFileElementType.java
index a9a3a83bc5a1..39149eab2e6e 100644
--- a/platform/core-api/src/com/intellij/psi/tree/IFileElementType.java
+++ b/platform/core-api/src/com/intellij/psi/tree/IFileElementType.java
@@ -31,6 +31,10 @@ public class IFileElementType extends ILazyParseableElementType {
super(debugName, language);
}
+ public IFileElementType(@NonNls @NotNull final String debugName, @Nullable final Language language, boolean register) {
+ super(debugName, language, register);
+ }
+
@Nullable
@Override
public ASTNode parseContents(final ASTNode chameleon) {
diff --git a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java
index 9efc76f78cf2..d6e62c9bac38 100644
--- a/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java
+++ b/platform/lang-api/src/com/intellij/codeInsight/intention/PsiElementBaseIntentionAction.java
@@ -56,6 +56,7 @@ public abstract class PsiElementBaseIntentionAction extends BaseIntentionAction
@Override
public final boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
+ if (file == null) return false;
final PsiManager manager = file.getManager();
if (manager == null) return false;
if (!manager.isInProject(file)) return false;
diff --git a/platform/lang-impl/src/com/intellij/application/options/CodeCompletion.form b/platform/lang-impl/src/com/intellij/application/options/CodeCompletion.form
index 891220a929bd..b7c932770a7b 100644
--- a/platform/lang-impl/src/com/intellij/application/options/CodeCompletion.form
+++ b/platform/lang-impl/src/com/intellij/application/options/CodeCompletion.form
@@ -109,9 +109,7 @@
-
-
-
+
@@ -137,7 +135,9 @@
-
+
+
+
diff --git a/platform/lang-impl/src/com/intellij/application/options/CodeCompletionPanel.java b/platform/lang-impl/src/com/intellij/application/options/CodeCompletionPanel.java
index 99b1a6fdb314..2067a9cc6a4a 100644
--- a/platform/lang-impl/src/com/intellij/application/options/CodeCompletionPanel.java
+++ b/platform/lang-impl/src/com/intellij/application/options/CodeCompletionPanel.java
@@ -65,7 +65,10 @@ public class CodeCompletionPanel {
new ActionListener() {
@Override
public void actionPerformed(ActionEvent event) {
- myAutocompletionDelayField.setEnabled(myCbAutocompletion.isSelected());
+ boolean selected = myCbAutocompletion.isSelected();
+ myAutocompletionDelayField.setEnabled(selected);
+ myFocusLookup.setEnabled(selected);
+ myCbSelectByChars.setEnabled(selected);
}
}
);
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/CompletionPreview.java b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/CompletionPreview.java
index 206f098120ec..1f6437a71d1b 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/CompletionPreview.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/lookup/impl/CompletionPreview.java
@@ -15,7 +15,10 @@
*/
package com.intellij.codeInsight.lookup.impl;
-import com.intellij.codeInsight.lookup.*;
+import com.intellij.codeInsight.lookup.LookupElement;
+import com.intellij.codeInsight.lookup.LookupElementPresentation;
+import com.intellij.codeInsight.lookup.LookupEvent;
+import com.intellij.codeInsight.lookup.LookupListener;
import com.intellij.ide.ui.UISettings;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
@@ -87,6 +90,11 @@ public class CompletionPreview implements Disposable {
return;
}
+ final EditorImpl editor = getEditorImpl();
+ if (editor.getSelectionModel().hasSelection() || editor.getSelectionModel().hasBlockSelection()) {
+ return;
+ }
+
String text = getPreviewText(item);
int prefixLength = myLookup.getPrefixLength(item);
@@ -103,7 +111,7 @@ public class CompletionPreview implements Disposable {
prefixLength = arrayList.get(arrayList.size() - 1).getEndOffset();
}
- final EditorImpl editor = getEditorImpl();
+
editor.setCustomImage(null);
BufferedImage previewImage = createPreviewImage(text.substring(prefixLength));
editor.setCustomImage(Pair.create(getCaretPoint(), previewImage));
diff --git a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
index 2002d01dfac0..c321696b5729 100644
--- a/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
+++ b/platform/lang-impl/src/com/intellij/execution/console/LanguageConsoleImpl.java
@@ -389,31 +389,24 @@ public class LanguageConsoleImpl implements Disposable, TypeSafeDataProvider {
final boolean scrollToEnd = shouldScrollHistoryToEnd();
final int[] offsets = new int[attributedText.size() + 1];
int i = 0;
- offsets[i] = 0;
- final StringBuilder sb = new StringBuilder();
+ final Document history = myHistoryViewer.getDocument();
+ offsets[i] = history.getTextLength();
for (final Pair pair : attributedText) {
final String str = StringUtil.convertLineSeparators(pair.getFirst());
- final int lastOffset = offsets[i];
- offsets[++i] = lastOffset + str.length();
- sb.append(str);
+ appendToHistoryDocument(history, str);
+ offsets[++i] = history.getTextLength();
}
LOG.debug("printToHistory(): text processed");
- final Document history = myHistoryViewer.getDocument();
final MarkupModel markupModel = DocumentMarkupModel.forDocument(history, myProject, true);
- final int oldHistoryLength = history.getTextLength();
- appendToHistoryDocument(history, sb.toString());
- if ((oldHistoryLength + offsets[i]) != history.getTextLength()) {
- assert false : "Last offset - " + offsets[i] + " history length: old " + oldHistoryLength + ", new - " + history.getTextLength()
- + ", history - " + history;
- }
- LOG.debug("printToHistory(): text added");
i = 0;
for (final Pair pair : attributedText) {
- markupModel.addRangeHighlighter(oldHistoryLength + offsets[i],
- oldHistoryLength + offsets[i+1],
- HighlighterLayer.SYNTAX,
- pair.getSecond(),
- HighlighterTargetArea.EXACT_RANGE);
+ markupModel.addRangeHighlighter(
+ offsets[i],
+ offsets[i+1],
+ HighlighterLayer.SYNTAX,
+ pair.getSecond(),
+ HighlighterTargetArea.EXACT_RANGE
+ );
++i;
}
LOG.debug("printToHistory(): markup added");
diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/CompositeWhiteSpaceFormattingStrategy.java b/platform/lang-impl/src/com/intellij/psi/formatter/CompositeWhiteSpaceFormattingStrategy.java
index 2844adb44c57..ad19870515df 100644
--- a/platform/lang-impl/src/com/intellij/psi/formatter/CompositeWhiteSpaceFormattingStrategy.java
+++ b/platform/lang-impl/src/com/intellij/psi/formatter/CompositeWhiteSpaceFormattingStrategy.java
@@ -109,6 +109,11 @@ public class CompositeWhiteSpaceFormattingStrategy implements WhiteSpaceFormatti
@Override
public boolean containsWhitespacesOnly(@NotNull ASTNode node) {
+ for (WhiteSpaceFormattingStrategy strategy : myStrategies) {
+ if (strategy.containsWhitespacesOnly(node)) {
+ return true;
+ }
+ }
return false;
}
diff --git a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java
index 858da1d904ee..b208bd2ea1f7 100644
--- a/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java
+++ b/platform/lang-impl/src/com/intellij/psi/formatter/FormatterUtil.java
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.actions.ReformatAndOptimizeImportsProcessor;
import com.intellij.codeInsight.actions.ReformatCodeProcessor;
import com.intellij.lang.ASTFactory;
import com.intellij.lang.ASTNode;
+import com.intellij.lang.Language;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
@@ -254,12 +255,12 @@ public class FormatterUtil {
if (node == null) return false;
if (isWhitespaceOrEmpty(node)) return true;
- for (WhiteSpaceFormattingStrategy strategy : WhiteSpaceFormattingStrategyFactory.getAllStrategies()) {
- if (strategy.containsWhitespacesOnly(node)) {
- return true;
- }
+ PsiElement psi = node.getPsi();
+ if (psi == null) {
+ return false;
}
- return false;
+ Language language = psi.getLanguage();
+ return WhiteSpaceFormattingStrategyFactory.getStrategy(language).containsWhitespacesOnly(node);
}
/**
diff --git a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java
index 68079c75381f..62b05c081bd0 100644
--- a/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java
+++ b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java
@@ -318,7 +318,8 @@ public class PsiVFSListener extends VirtualFileAdapter {
VirtualFile parent = vFile.getParent();
final PsiDirectory parentDir = getCachedDirectory(parent);
- if (parentDir == null) {
+ // do not suppress reparse request for light files
+ if (parentDir == null && !FileContentUtil.FORCE_RELOAD_REQUESTOR.equals(event.getRequestor())) {
boolean fire = VirtualFile.PROP_NAME.equals(propertyName) && vFile.isDirectory();
if (fire) {
PsiDirectory psiDir = myFileManager.getCachedDirectory(vFile);
@@ -395,8 +396,10 @@ public class PsiVFSListener extends VirtualFileAdapter {
}
else if (newPsiFile != null) {
myFileManager.cacheViewProvider(vFile, fileViewProvider);
- treeEvent.setChild(newPsiFile);
- myManager.childAdded(treeEvent);
+ if (parentDir != null) {
+ treeEvent.setChild(newPsiFile);
+ myManager.childAdded(treeEvent);
+ }
}
}
}
diff --git a/platform/lang-impl/src/com/intellij/testIntegration/TestFinderHelper.java b/platform/lang-impl/src/com/intellij/testIntegration/TestFinderHelper.java
index 58fc1de4cbd1..8b419e4a58bb 100644
--- a/platform/lang-impl/src/com/intellij/testIntegration/TestFinderHelper.java
+++ b/platform/lang-impl/src/com/intellij/testIntegration/TestFinderHelper.java
@@ -23,6 +23,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiNamedElement;
import com.intellij.psi.codeStyle.NameUtil;
+import org.jetbrains.annotations.Nullable;
import java.util.*;
@@ -72,12 +73,18 @@ public class TestFinderHelper {
public static List getSortedElements(final List> elementsWithWeights,
final boolean weightsAscending) {
+ return getSortedElements(elementsWithWeights, weightsAscending, null);
+ }
+
+ public static List getSortedElements(final List> elementsWithWeights,
+ final boolean weightsAscending,
+ @Nullable final Comparator sameNameComparator) {
Collections.sort(elementsWithWeights, new Comparator>() {
public int compare(Pair extends PsiNamedElement, Integer> o1, Pair extends PsiNamedElement, Integer> o2) {
int result = weightsAscending ? o1.second.compareTo(o2.second) : o2.second.compareTo(o1.second);
- if (result == 0) {
- result = Comparing.compare(o1.first.getName(), o2.first.getName());
- }
+ if (result == 0) result = Comparing.compare(o1.first.getName(), o2.first.getName());
+ if (result == 0 && sameNameComparator != null) result = sameNameComparator.compare(o1.first, o2.first);
+
return result;
}
});
diff --git a/platform/platform-api/src/com/intellij/util/proxy/CommonProxy.java b/platform/platform-api/src/com/intellij/util/proxy/CommonProxy.java
index 864b8b4a2c52..059332638865 100644
--- a/platform/platform-api/src/com/intellij/util/proxy/CommonProxy.java
+++ b/platform/platform-api/src/com/intellij/util/proxy/CommonProxy.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.ui.popup.util.PopupUtil;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.util.net.HTTPProxySettingsPanel;
import org.jetbrains.annotations.NotNull;
@@ -283,15 +284,7 @@ public class CommonProxy extends ProxySelector {
}
private static URI createUri(final URL url) {
- final URI uri;
- try {
- uri = new URI(url.toString());
- }
- catch (URISyntaxException e) {
- LOG.info(e);
- throw new RuntimeException(e);
- }
- return uri;
+ return VfsUtil.toUri(url.toString());
}
public static class HostInfo {
diff --git a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
index 3825696a03be..900495084ca8 100644
--- a/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
+++ b/platform/platform-impl/src/com/intellij/ide/XmlRpcServerImpl.java
@@ -34,7 +34,7 @@ import org.jetbrains.io.Responses;
import java.util.Arrays;
@ChannelHandler.Sharable
-public class XmlRpcServerImpl extends SimpleChannelUpstreamHandler implements XmlRpcServer, Consumer {
+public class XmlRpcServerImpl extends SimpleChannelUpstreamHandler implements XmlRpcServer {
private static final Logger LOG = Logger.getInstance(XmlRpcServerImpl.class);
private final XmlRpcHandlerMappingImpl handlerMapping;
@@ -76,9 +76,12 @@ public class XmlRpcServerImpl extends SimpleChannelUpstreamHandler implements Xm
LOG.debug("XmlRpcServerImpl instantiated, handlers " + handlerMapping);
}
- @Override
- public void consume(ChannelPipeline pipeline) {
- pipeline.addLast("pluggable_xmlRpc", this);
+ static final class XmlRpcPipelineConsumer implements Consumer {
+ @Override
+ public void consume(ChannelPipeline pipeline) {
+ XmlRpcServer xmlRpcServer = SERVICE.getInstance();
+ pipeline.addLast("pluggable_xmlRpc", (XmlRpcServerImpl)xmlRpcServer);
+ }
}
@Override
diff --git a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
index 2b313d131512..f775685995ef 100644
--- a/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/fileChooser/ex/FileChooserDialogImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -124,7 +124,8 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD
show();
if (myChosenFiles.length > 0) {
callback.consume(Arrays.asList(myChosenFiles));
- } else if (callback instanceof FileChooser.FileChooserConsumer){
+ }
+ else if (callback instanceof FileChooser.FileChooserConsumer) {
((FileChooser.FileChooserConsumer)callback).cancelled();
}
}
@@ -357,13 +358,21 @@ public class FileChooserDialogImpl extends DialogWrapper implements FileChooserD
myFileSystemTree.registerMouseListener(group);
}
+ @Nullable
private VirtualFile[] getSelectedFilesInt() {
if (myTreeIsUpdating || !myUiUpdater.isEmpty()) {
- if (!isTextFieldActive() || StringUtil.isEmpty(myPathTextField.getTextFieldText()))
- return VirtualFile.EMPTY_ARRAY;
- final LocalFsFinder.VfsFile toFind = (LocalFsFinder.VfsFile)myPathTextField.getFile();
- return toFind == null || !toFind.exists() ? VirtualFile.EMPTY_ARRAY : new VirtualFile[]{toFind.getFile()};
+ if (isTextFieldActive() && !StringUtil.isEmpty(myPathTextField.getTextFieldText())) {
+ LookupFile toFind = myPathTextField.getFile();
+ if (toFind instanceof LocalFsFinder.VfsFile && toFind.exists()) {
+ VirtualFile file = ((LocalFsFinder.VfsFile)toFind).getFile();
+ if (file != null) {
+ return new VirtualFile[]{file};
+ }
+ }
+ }
+ return VirtualFile.EMPTY_ARRAY;
}
+
final List selectedFiles = Arrays.asList(myFileSystemTree.getSelectedFiles());
return VfsUtilCore.toVirtualFileArray(FileChooserUtil.getChosenFiles(myChooserDescriptor, selectedFiles));
}
diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java
index 33498fbf29c4..81dacf7d3de8 100644
--- a/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java
+++ b/platform/platform-impl/src/com/intellij/openapi/vfs/impl/local/FileWatcher.java
@@ -44,6 +44,7 @@ import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import static com.intellij.util.containers.ContainerUtil.*;
@@ -83,6 +84,7 @@ public class FileWatcher {
private final ManagingFS myManagingFS;
private final File myExecutable;
+ private final AtomicBoolean myInitialized = new AtomicBoolean(false);
private volatile MyProcessHandler myProcessHandler;
private volatile int myStartAttemptCount = 0;
private volatile boolean myIsShuttingDown = false;
@@ -101,12 +103,21 @@ public class FileWatcher {
myExecutable = getExecutable();
if (disabled) {
+ myInitialized.set(true);
LOG.info("Native file watcher is disabled");
}
else if (myExecutable == null) {
+ myInitialized.set(true);
LOG.info("Native file watcher is not supported on this platform");
}
- else if (!myExecutable.exists()) {
+ }
+
+ private void init() {
+ if (!myInitialized.compareAndSet(false, true)) {
+ return;
+ }
+
+ if (!myExecutable.exists()) {
notifyOnFailure(ApplicationBundle.message("watcher.exe.not.found"), null);
}
else if (!myExecutable.canExecute()) {
@@ -244,7 +255,7 @@ public class FileWatcher {
}
public boolean isOperational() {
- return myProcessHandler != null;
+ return !myInitialized.get() || myProcessHandler != null;
}
public boolean isSettingRoots() {
@@ -280,6 +291,7 @@ public class FileWatcher {
}
public void setWatchRoots(final List recursive, final List flat) {
+ init();
setWatchRoots(recursive, flat, false);
}
@@ -309,8 +321,7 @@ public class FileWatcher {
writeLine("#");
}
catch (IOException e) {
- LOG.error(e);
- shutdownProcess();
+ LOG.warn(e);
}
myRecursiveWatchRoots = recursive;
diff --git a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
index 72c8b275c1e2..de2b85cc1e88 100644
--- a/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
+++ b/platform/platform-impl/src/com/intellij/openapi/wm/impl/ToolWindowManagerImpl.java
@@ -989,6 +989,14 @@ public final class ToolWindowManagerImpl extends ToolWindowManagerEx implements
}
}
}
+ //todo[kb] it's just a temporary solution due a number of focus issues in JDK 7
+ if (SystemInfo.isJavaVersionAtLeast("1.7")) {
+ if (hasOpenEditorFiles()) {
+ activateEditorComponentImpl(getSplittersFromFocus(), commandList, false);
+ } else {
+ focusToolWinowByDefault(id);
+ }
+ }
execute(commandList);
}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java
index eb5f0a0bc4d0..a8a14a49900a 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkData.java
@@ -53,4 +53,8 @@ public interface RemoteSdkData extends RemoteCredentials {
boolean isHelpersVersionChecked();
void setHelpersVersionChecked(boolean helpersVersionChecked);
+
+ boolean isInitialized();
+
+ void setInitialized(boolean initialized);
}
diff --git a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java
index e167fe781139..2c9b731d380a 100644
--- a/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java
+++ b/platform/platform-impl/src/com/intellij/remotesdk/RemoteSdkDataHolder.java
@@ -30,6 +30,7 @@ public class RemoteSdkDataHolder implements RemoteSdkData {
private static final String HELPERS_PATH = "HELPERS_PATH";
private static final String REMOTE_ROOTS = "REMOTE_ROOTS";
private static final String REMOTE_PATH = "REMOTE_PATH";
+ private static final String INITIALIZED = "INITIALIZED";
private String myHost;
private int myPort;
@@ -52,6 +53,8 @@ public class RemoteSdkDataHolder implements RemoteSdkData {
private List myRemoteRoots = new ArrayList();
+ private boolean myInitialized;
+
public RemoteSdkDataHolder(@NotNull final String defaultDirName) {
myHelpersDefaultDirName = defaultDirName;
}
@@ -285,6 +288,16 @@ public class RemoteSdkDataHolder implements RemoteSdkData {
myHelpersVersionChecked = helpersVersionChecked;
}
+ @Override
+ public boolean isInitialized() {
+ return myInitialized;
+ }
+
+ @Override
+ public void setInitialized(boolean initialized) {
+ myInitialized = initialized;
+ }
+
public static boolean isRemoteSdk(@Nullable String path) {
if (path != null) {
return path.startsWith(SSH_PREFIX);
@@ -309,6 +322,8 @@ public class RemoteSdkDataHolder implements RemoteSdkData {
setHelpersPath(StringUtil.nullize(element.getAttributeValue(HELPERS_PATH)));
setRemoteRoots(loadStringsList(element, REMOTE_ROOTS, REMOTE_PATH));
+
+ setInitialized(StringUtil.parseBoolean(element.getAttributeValue(INITIALIZED), true));
}
protected static List loadStringsList(Element element, String rootName, String attrName) {
@@ -336,6 +351,8 @@ public class RemoteSdkDataHolder implements RemoteSdkData {
rootElement.setAttribute(INTERPRETER_PATH, StringUtil.notNullize(getInterpreterPath()));
rootElement.setAttribute(HELPERS_PATH, StringUtil.notNullize(getHelpersPath()));
+ rootElement.setAttribute(INITIALIZED, Boolean.toString(isInitialized()));
+
for (String remoteRoot : getRemoteRoots()) {
final Element child = new Element(REMOTE_ROOTS);
child.setAttribute(REMOTE_PATH, remoteRoot);
diff --git a/platform/platform-impl/src/org/jetbrains/ide/XmlRpcPipelineConsumer.java b/platform/platform-impl/src/org/jetbrains/ide/XmlRpcPipelineConsumer.java
deleted file mode 100644
index b441f6ff3b2d..000000000000
--- a/platform/platform-impl/src/org/jetbrains/ide/XmlRpcPipelineConsumer.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package org.jetbrains.ide;
-
-import com.intellij.ide.XmlRpcServer;
-import com.intellij.ide.XmlRpcServerImpl;
-import com.intellij.util.Consumer;
-import org.jboss.netty.channel.ChannelPipeline;
-
-class XmlRpcPipelineConsumer implements Consumer {
- @Override
- public void consume(ChannelPipeline pipeline) {
- XmlRpcServer xmlRpcServer = XmlRpcServer.SERVICE.getInstance();
- ((XmlRpcServerImpl)xmlRpcServer).consume(pipeline);
- }
-}
\ No newline at end of file
diff --git a/platform/platform-resources-en/src/messages/XmlBundle.properties b/platform/platform-resources-en/src/messages/XmlBundle.properties
index ae8f03f7bfbb..e581c3658a20 100644
--- a/platform/platform-resources-en/src/messages/XmlBundle.properties
+++ b/platform/platform-resources-en/src/messages/XmlBundle.properties
@@ -248,3 +248,4 @@ zen.coding.incorrect.abbreviation.error=Incorrect abbreviation
title.cannot.create.html.file=Cannot create HTML file
new.html.file.action=HTML File
new.html.file.action.description=Creates new HTML file
+html5.outline.mode=HTML5 Outline
\ No newline at end of file
diff --git a/platform/platform-resources/src/META-INF/PlatformExtensions.xml b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
index c1d815c11599..6a055bc54557 100644
--- a/platform/platform-resources/src/META-INF/PlatformExtensions.xml
+++ b/platform/platform-resources/src/META-INF/PlatformExtensions.xml
@@ -289,7 +289,7 @@
-
+
diff --git a/platform/platform-resources/src/META-INF/XmlPlugin.xml b/platform/platform-resources/src/META-INF/XmlPlugin.xml
index aebe669a4bbb..ec3789d0fcbb 100644
--- a/platform/platform-resources/src/META-INF/XmlPlugin.xml
+++ b/platform/platform-resources/src/META-INF/XmlPlugin.xml
@@ -438,8 +438,7 @@
-
-
+
diff --git a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java
index 5de553b97230..071dd4b3a22b 100644
--- a/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java
+++ b/platform/testFramework/src/com/intellij/testFramework/ParsingTestCase.java
@@ -271,15 +271,15 @@ public abstract class ParsingTestCase extends PlatformLiteFixture {
doCheckResult(myFullDataPath, targetDataName, text);
}
- private static void doCheckResult(String myFullDataPath, String targetDataName, String text) throws IOException {
+ public static void doCheckResult(String fullPath, String targetDataName, String text) throws IOException {
text = text.trim();
- String expectedFileName = myFullDataPath + File.separatorChar + targetDataName;
+ String expectedFileName = fullPath + File.separatorChar + targetDataName;
if (OVERWRITE_TESTDATA) {
VfsTestUtil.overwriteTestData(expectedFileName, text);
System.out.println("File " + expectedFileName + " created.");
}
try {
- String expectedText = doLoadFile(myFullDataPath, targetDataName);
+ String expectedText = doLoadFile(fullPath, targetDataName);
if (!Comparing.equal(expectedText, text)) {
throw new FileComparisonFailure(targetDataName, expectedText, text, expectedFileName);
}
@@ -304,7 +304,7 @@ public abstract class ParsingTestCase extends PlatformLiteFixture {
return text;
}
- private static void ensureParsed(PsiFile file) {
+ public static void ensureParsed(PsiFile file) {
file.accept(new PsiElementVisitor() {
@Override
public void visitElement(PsiElement element) {
diff --git a/platform/util/src/com/intellij/execution/process/BaseOSProcessHandler.java b/platform/util/src/com/intellij/execution/process/BaseOSProcessHandler.java
index f9ca8c45599e..322e9cc8d973 100644
--- a/platform/util/src/com/intellij/execution/process/BaseOSProcessHandler.java
+++ b/platform/util/src/com/intellij/execution/process/BaseOSProcessHandler.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -159,7 +159,7 @@ public class BaseOSProcessHandler extends ProcessHandler {
myProcess.getOutputStream().close();
}
catch (IOException e) {
- LOG.error(e);
+ LOG.warn(e);
}
}
diff --git a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
index 51b23ef559f0..2a319eb07638 100644
--- a/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
+++ b/platform/util/src/com/intellij/util/xmlb/XmlSerializerImpl.java
@@ -45,7 +45,7 @@ class XmlSerializerImpl {
throw e;
}
catch (Exception e) {
- throw new XmlSerializationException(e);
+ throw new XmlSerializationException("Can't serialize instance of " + object.getClass(), e);
}
}
diff --git a/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierIntention.java b/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierIntention.java
index 767d3481bb93..cdde20ef83e6 100644
--- a/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierIntention.java
+++ b/plugins/IntentionPowerPak/src/com/siyeh/ipp/modifiers/ModifierIntention.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2000-2012 JetBrains s.r.o.
+ * Copyright 2000-2013 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.
@@ -94,7 +94,7 @@ abstract class ModifierIntention extends Intention implements LowPriorityAction
final String name = FileUtil.getNameWithoutExtension(javaFile.getName());
final String className = aClass.getName();
if (name.equals(className)) {
- MultiMap.emptyInstance();
+ return MultiMap.emptyInstance();
}
final MultiMap conflicts = new MultiMap();
conflicts.putValue(aClass, IntentionPowerPackBundle.message(
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.java
index e149c4e64c99..e1d7b4bdb5c6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonCreateProjectDialog.java
@@ -15,13 +15,12 @@
*/
package org.jetbrains.plugins.groovy.griffon;
+import com.intellij.execution.configurations.ParametersList;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.groovy.mvc.MvcCommand;
import javax.swing.*;
@@ -50,20 +49,29 @@ public class GriffonCreateProjectDialog extends DialogWrapper {
return myComponent;
}
- String getCommand() {
- if (myCreateAddon.isSelected()) return "create-addon";
- if (myCreateApp.isSelected()) return "create-app";
- if (myCreateArchetype.isSelected()) return "create-archetype";
- if (myCreatePlugin.isSelected()) return "create-plugin";
- throw new AssertionError("No selection");
- }
+ MvcCommand getCommand() {
+ String cmd;
- String[] getArguments() {
- String text = myOptionField.getText();
- if (StringUtil.isEmptyOrSpaces(text)) {
- return ArrayUtil.EMPTY_STRING_ARRAY;
+ if (myCreateAddon.isSelected()) {
+ cmd = "create-addon";
}
- return text.split(" ");
+ else if (myCreateApp.isSelected()) {
+ cmd = "create-app";
+ }
+ else if (myCreateArchetype.isSelected()) {
+ cmd = "create-archetype";
+ }
+ else if (myCreatePlugin.isSelected()) {
+ cmd = "create-plugin";
+ }
+ else {
+ throw new AssertionError("No selection");
+ }
+
+ String text = myOptionField.getText();
+ if (text == null) text = "";
+
+ return new MvcCommand(cmd, ParametersList.parse(text));
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java
index ed8c1fedd42c..5e9ccae44555 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/griffon/GriffonFramework.java
@@ -19,6 +19,7 @@ package org.jetbrains.plugins.groovy.griffon;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.configurations.JavaParameters;
+import com.intellij.execution.configurations.ParametersList;
import com.intellij.lang.properties.IProperty;
import com.intellij.lang.properties.psi.PropertiesFile;
import com.intellij.openapi.application.AccessToken;
@@ -41,17 +42,13 @@ import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
-import com.intellij.util.ArrayUtil;
import gnu.trove.TIntArrayList;
import icons.JetgroovyIcons;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.GroovyFileType;
-import org.jetbrains.plugins.groovy.mvc.MvcFramework;
-import org.jetbrains.plugins.groovy.mvc.MvcModuleStructureUtil;
-import org.jetbrains.plugins.groovy.mvc.MvcPathMacros;
-import org.jetbrains.plugins.groovy.mvc.MvcProjectStructure;
+import org.jetbrains.plugins.groovy.mvc.*;
import javax.swing.*;
import java.io.File;
@@ -105,7 +102,7 @@ public class GriffonFramework extends MvcFramework {
return null;
}
- return createCommandAndShowErrors(null, module, true, dialog.getCommand(), dialog.getArguments());
+ return createCommandAndShowErrors(null, module, true, dialog.getCommand());
}
@Override
@@ -231,8 +228,7 @@ public class GriffonFramework extends MvcFramework {
public JavaParameters createJavaParameters(@NotNull Module module, boolean forCreation, boolean forTests,
boolean classpathFromDependencies,
@Nullable String jvmParams,
- @NotNull String command,
- @NotNull String... args) throws ExecutionException {
+ @NotNull MvcCommand command) throws ExecutionException {
JavaParameters params = new JavaParameters();
Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
@@ -284,7 +280,8 @@ public class GriffonFramework extends MvcFramework {
throw new ExecutionException("Failed to initialize griffon module: module " + module.getName() + " contains more than one root");
}
- args = ArrayUtil.mergeArrays(new String[]{roots[0].getName()}, args);
+ command.getArgs().add(0, roots[0].getName());
+
rootFile = roots[0].getParent();
}
else {
@@ -331,8 +328,9 @@ public class GriffonFramework extends MvcFramework {
params.setWorkingDirectory(workDir);
- String argsString = args.length == 0 ? command : command + ' ' + StringUtil.join(args, " ");
- params.getProgramParametersList().add(argsString);
+ ParametersList paramList = new ParametersList();
+ command.addToParametersList(paramList);
+ params.getProgramParametersList().add(paramList.getParametersString());
params.setDefaultCharset(module.getProject());
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java
index a2e133dea603..142cc63ad193 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyCompletionUtil.java
@@ -50,17 +50,17 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.formatter.GeeseUtil;
import org.jetbrains.plugins.groovy.lang.GrReferenceAdjuster;
+import org.jetbrains.plugins.groovy.lang.psi.GrControlFlowOwner;
import org.jetbrains.plugins.groovy.lang.psi.GrReferenceElement;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFile;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement;
import org.jetbrains.plugins.groovy.lang.psi.api.GroovyResolveResult;
import org.jetbrains.plugins.groovy.lang.psi.api.auxiliary.modifiers.annotation.GrAnnotation;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrLabeledStatement;
+import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariable;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrCodeBlock;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.clauses.GrCaseSection;
-import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrApplicationStatement;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrNewExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
@@ -214,11 +214,10 @@ public class GroovyCompletionUtil {
public static boolean asVariableInBlock(PsiElement context) {
if (context.getParent() instanceof GrReferenceExpression) {
PsiElement parent = context.getParent().getParent();
- if (parent instanceof GrApplicationStatement) {
+ while (parent instanceof GrStatement) {
parent = parent.getParent();
}
- if ((parent instanceof GrCodeBlock || parent instanceof GrCaseSection || parent instanceof GrLabeledStatement) &&
- isNewStatement(context, true)) {
+ if ((parent instanceof GrControlFlowOwner || parent instanceof GrCaseSection) && isNewStatement(context, true)) {
return true;
}
}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcCommand.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcCommand.java
new file mode 100644
index 000000000000..5ddb553ab38b
--- /dev/null
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcCommand.java
@@ -0,0 +1,118 @@
+package org.jetbrains.plugins.groovy.mvc;
+
+import com.intellij.execution.configurations.ParametersList;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author Sergey Evdokimov
+ */
+public class MvcCommand {
+
+ public static final Collection ourEnvironments = Arrays.asList("prod", "test", "dev");
+
+ private String myEnv;
+ private String myCommand;
+
+ private final ArrayList myArgs = new ArrayList();
+ private final ArrayList myProperties = new ArrayList();
+
+ public MvcCommand() {
+ }
+
+ public MvcCommand(String command, String ... args) {
+ myCommand = command;
+ Collections.addAll(myArgs, args);
+ }
+
+ @Nullable
+ public String getEnv() {
+ return myEnv;
+ }
+
+ public void setEnv(@Nullable String env) {
+ myEnv = env;
+ }
+
+ @Nullable
+ public String getCommand() {
+ return myCommand;
+ }
+
+ public void setCommand(@Nullable String command) {
+ myCommand = command;
+ }
+
+ /**
+ * Returns MODIFIABLE list of arguments
+ */
+ public ArrayList getArgs() {
+ return myArgs;
+ }
+
+ public void setArgs(List args) {
+ if (args == myArgs) return;
+
+ myArgs.clear();
+ myArgs.addAll(args);
+ }
+
+ /**
+ * Returns MODIFIABLE list of system properties definition written before command (e.g. -Dgrails.port=9090 run-app)
+ */
+ public ArrayList getProperties() {
+ return myProperties;
+ }
+
+ public void setProperties(List properties) {
+ if (myProperties == properties) return;
+
+ myProperties.clear();
+ myProperties.addAll(properties);
+ }
+
+ public void addToParametersList(@NotNull ParametersList list) {
+ if (myEnv != null) {
+ list.add(myEnv);
+ }
+
+ list.addAll(myProperties);
+
+ if (myCommand != null) {
+ list.add(myCommand);
+ }
+
+ list.addAll(myArgs);
+ }
+
+ @NotNull
+ public static MvcCommand parse(@NotNull String cmd) {
+ String[] args = ParametersList.parse(cmd);
+
+ MvcCommand res = new MvcCommand();
+
+ int i = 0;
+
+ while (res.myCommand == null && i < args.length) {
+ String s = args[i];
+
+ if (s.startsWith("-D")) {
+ res.myProperties.add(s);
+ }
+ else if (res.myEnv == null && ourEnvironments.contains(s)) {
+ res.myEnv = s;
+ }
+ else {
+ res.myCommand = s;
+ }
+
+ i++;
+ }
+
+ res.myArgs.addAll(Arrays.asList(args).subList(i, args.length));
+
+ return res;
+ }
+}
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
index c3afadde2332..44190d8d0411 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcFramework.java
@@ -166,7 +166,7 @@ public abstract class MvcFramework {
return null;
}
- return createCommandAndShowErrors(null, module, true, result == 0 ? "create-app" : "create-plugin");
+ return createCommandAndShowErrors(null, module, true, new MvcCommand(result == 0 ? "create-app" : "create-plugin"));
}
public abstract void updateProjectStructure(@NotNull final Module module);
@@ -316,32 +316,12 @@ public abstract class MvcFramework {
from.remove(extension.getCompilerOutputPathForTests());
}
-
- public static Pair parsedCmd(String cmdLine) {
- return parsedCmd(ParametersList.parse(cmdLine));
- }
-
- public static Pair parsedCmd(String[] args) {
- if (args.length == 0) {
- return new Pair("", ArrayUtil.EMPTY_STRING_ARRAY);
- }
- if (args.length == 1) {
- return new Pair(args[0], ArrayUtil.EMPTY_STRING_ARRAY);
- }
-
- String[] array = new String[args.length - 1];
- System.arraycopy(args, 1, array, 0, array.length);
-
- return new Pair(args[0], array);
- }
-
public abstract JavaParameters createJavaParameters(@NotNull Module module,
boolean forCreation,
boolean forTests,
boolean classpathFromDependencies,
@Nullable String jvmParams,
- @NotNull String command,
- @NotNull String... args) throws ExecutionException;
+ @NotNull MvcCommand command) throws ExecutionException;
protected static void ensureRunConfigurationExists(Module module, ConfigurationType configurationType, String name) {
final RunManagerEx runManager = RunManagerEx.getInstanceEx(module.getProject());
@@ -373,19 +353,24 @@ public abstract class MvcFramework {
public abstract String getSdkHomePropertyName();
@Nullable
- public GeneralCommandLine createCommandAndShowErrors(@NotNull Module module, @NotNull String command, @NotNull String... args) {
- return createCommandAndShowErrors(null, module, command, args);
+ public GeneralCommandLine createCommandAndShowErrors(@NotNull Module module, @NotNull String command, String... args) {
+ return createCommandAndShowErrors(null, module, new MvcCommand(command, args));
}
@Nullable
- public GeneralCommandLine createCommandAndShowErrors(@Nullable String vmOptions, @NotNull Module module, @NotNull String command, @NotNull String... args) {
- return createCommandAndShowErrors(vmOptions, module, false, command, args);
+ public GeneralCommandLine createCommandAndShowErrors(@NotNull Module module, @NotNull MvcCommand command) {
+ return createCommandAndShowErrors(null, module, command);
}
@Nullable
- public GeneralCommandLine createCommandAndShowErrors(@Nullable String vmOptions, @NotNull Module module, final boolean forCreation, @NotNull String command, @NotNull String... args) {
+ public GeneralCommandLine createCommandAndShowErrors(@Nullable String vmOptions, @NotNull Module module, @NotNull MvcCommand command) {
+ return createCommandAndShowErrors(vmOptions, module, false, command);
+ }
+
+ @Nullable
+ public GeneralCommandLine createCommandAndShowErrors(@Nullable String vmOptions, @NotNull Module module, final boolean forCreation, @NotNull MvcCommand command) {
try {
- return createCommand(module, vmOptions, forCreation, command, args);
+ return createCommand(module, vmOptions, forCreation, command);
}
catch (ExecutionException e) {
Messages.showErrorDialog(e.getMessage(), "Failed to run grails command: " + command);
@@ -397,9 +382,8 @@ public abstract class MvcFramework {
public GeneralCommandLine createCommand(@NotNull Module module,
@Nullable String jvmParams,
final boolean forCreation,
- @NotNull String command,
- @NotNull String... args) throws ExecutionException {
- final JavaParameters params = createJavaParameters(module, forCreation, false, true, jvmParams, command, args);
+ @NotNull MvcCommand command) throws ExecutionException {
+ final JavaParameters params = createJavaParameters(module, forCreation, false, true, jvmParams, command);
addJavaHome(params, module);
final GeneralCommandLine commandLine = createCommandLine(params);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfiguration.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfiguration.java
index d6c2a74a2815..6e0cec286e8f 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfiguration.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunConfiguration.java
@@ -288,10 +288,9 @@ public abstract class MvcRunConfiguration extends ModuleBasedConfiguration parsedCmd = MvcFramework.parsedCmd(myCmdLine);
+ MvcCommand cmd = MvcCommand.parse(myCmdLine);
- final JavaParameters params = myFramework.createJavaParameters(myModule, false, myForTests, depsClasspath, vmParams, parsedCmd.first,
- parsedCmd.second);
+ final JavaParameters params = myFramework.createJavaParameters(myModule, false, myForTests, depsClasspath, vmParams, cmd);
addEnvVars(params);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTarget.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTarget.java
index a88782104954..6efc6665504e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTarget.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTarget.java
@@ -18,7 +18,6 @@ package org.jetbrains.plugins.groovy.mvc;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
/**
@@ -36,11 +35,9 @@ public class MvcRunTarget extends MvcActionBase {
Module selectedModule = dialog.getSelectedModule();
- String[] targetArgs = dialog.getTargetArguments();
+ MvcCommand cmd = MvcCommand.parse(dialog.getTargetArguments());
- Pair parsedCmd = MvcFramework.parsedCmd(targetArgs);
-
- final GeneralCommandLine commandLine = framework.createCommandAndShowErrors(dialog.getVmOptions(), selectedModule, parsedCmd.first, parsedCmd.second);
+ final GeneralCommandLine commandLine = framework.createCommandAndShowErrors(dialog.getVmOptions(), selectedModule, cmd);
if (commandLine == null) return;
MvcConsole.executeProcess(selectedModule, commandLine, null, false);
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java
index d1da3439d662..668554bdcb6e 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/MvcRunTargetDialog.java
@@ -147,7 +147,8 @@ public class MvcRunTargetDialog extends DialogWrapper {
return (String)myTargetField.getEditor().getItem();
}
- public String[] getTargetArguments() {
+ @NotNull
+ public String getTargetArguments() {
String text = getSelectedText();
text = text.trim();
@@ -155,12 +156,7 @@ public class MvcRunTargetDialog extends DialogWrapper {
text = text.substring(GRAILS_PREFIX.length());
}
- Iterable iterable = StringUtil.tokenize(text, " ");
- ArrayList args = new ArrayList();
- for (String s : iterable) {
- args.add(s);
- }
- return ArrayUtil.toStringArray(args);
+ return text;
}
protected JComponent createCenterPanel() {
diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/util/MvcTargetDialogCompletionUtils.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/util/MvcTargetDialogCompletionUtils.java
index 17c11008a90e..626cbd7acdb6 100644
--- a/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/util/MvcTargetDialogCompletionUtils.java
+++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/mvc/util/MvcTargetDialogCompletionUtils.java
@@ -77,7 +77,7 @@ public class MvcTargetDialogCompletionUtils {
List res = new ArrayList();
- if (text.substring(0, offset).matches("\\s*(grails\\s*)?(?:(:?-\\S+|dev|prod|test)\\s+)*\\S*")) {
+ if (text.substring(0, offset).matches("\\s*(grails\\s*)?(?:(:?-D\\S+|dev|prod|test)\\s+)*\\S*")) {
// Complete command name because command name is not typed.
for (String completionVariant : getAllTargetNames(module)) {
res.add(TailTypeDecorator.withTail(LookupElementBuilder.create(completionVariant), TailType.SPACE));
diff --git a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy
index 4551f407fc1f..20a8e57a3bcd 100644
--- a/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy
+++ b/plugins/groovy/test/org/jetbrains/plugins/groovy/completion/GroovyCompletionTest.groovy
@@ -1663,4 +1663,11 @@ package bar
print new foo.Myclass()
''')
}
+
+ public void "test def before assignment"() {
+ assert doContainsTest("def", """
+void foo() {
+ = baz
+}""")
+ }
}
\ No newline at end of file
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPlatformFacade.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgPlatformFacade.java
index 9697de70d25f..3eebfbd53098 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPlatformFacade.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgPlatformFacade.java
@@ -29,12 +29,4 @@ public interface HgPlatformFacade extends DvcsPlatformFacade {
@NotNull
HgVcs getVcs(@NotNull Project project);
- @NotNull
- HgRepositoryManager getRepositoryManager(@NotNull Project project);
-
- //@NotNull
- //HgProjectSettings getSettings(Project project);
- //
- //@NotNull
- //HgCommandResultNotifier getNotificator(@NotNull Project project);
}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPlatformFacadeImpl.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgPlatformFacadeImpl.java
index 0a3ac43e0c81..4a13cb4b4d45 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgPlatformFacadeImpl.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgPlatformFacadeImpl.java
@@ -25,12 +25,6 @@ import org.jetbrains.annotations.NotNull;
*/
public class HgPlatformFacadeImpl extends DvcsPlatformFacadeImpl implements HgPlatformFacade {
- @NotNull
- @Override
- public HgRepositoryManager getRepositoryManager(@NotNull Project project) {
- throw new UnsupportedOperationException();
- }
-
@NotNull
@Override
public HgVcs getVcs(@NotNull Project project) {
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRepositoryManager.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgRepositoryManager.java
deleted file mode 100644
index 6b2cff148afe..000000000000
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgRepositoryManager.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2000-2013 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.zmlx.hg4idea;
-
-import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
-
-import java.util.List;
-
-/**
- * @author Nadya Zabrodina
- */
-public interface HgRepositoryManager {
- /**
- * @return all repositories tracked by the manager.
- */
- @NotNull
- List getRepositories();
-}
diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java
index 1cc26ab5040c..0d1a12e9a49a 100644
--- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java
+++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommitedChangesProvider.java
@@ -202,7 +202,7 @@ public class HgCachingCommitedChangesProvider implements CachingCommittedChanges
if (changeBrowserSettings != null) {
args = new ArrayList();
if (changeBrowserSettings.USE_CHANGE_AFTER_FILTER) {
- args.add("-r " + changeBrowserSettings.getChangeAfterFilter());
+ args.add("-r " + changeBrowserSettings.getChangeAfterFilter() + ":");
}
}
List localRevisions = hgLogCommand.execute(hgFile, maxCount == 0 ? -1 : maxCount, true, args);
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
index b6785bcdb295..99a90cbd8d78 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgExecutor.java
@@ -17,7 +17,6 @@ package hg4idea.test;
import com.intellij.dvcs.test.Executor;
import com.intellij.openapi.util.text.StringUtil;
-import org.zmlx.hg4idea.provider.HgRepositoryLocation;
import java.util.Arrays;
import java.util.List;
@@ -25,7 +24,7 @@ import java.util.List;
/**
* @author Nadya Zabrodina
*/
-class HgExecutor extends Executor {
+public class HgExecutor extends Executor {
private static final String HG_EXECUTABLE_ENV = "IDEA_TEST_HG_EXECUTABLE";
//private static final String TEAMCITY_HG_EXECUTABLE_ENV = "TEAMCITY_HG_PATH"; //todo var for server testing
@@ -37,31 +36,18 @@ class HgExecutor extends Executor {
return findExecutable("hg", "hg", "hg.exe", Arrays.asList(HG_EXECUTABLE_ENV));
}
- public String hg(String command) {
+ public static String hg(String command) {
printVersionTheFirstTime();
List split = StringUtil.split(command, " ");
split.add(0, HG_EXECUTABLE);
log("hg " + command);
- for (int attempt = 0; attempt < 3; attempt++) {
- String stdout = run(split);
- return stdout;
+ for(int attempt = 0; attempt < 3; attempt++) {
+ return run(split);
}
throw new RuntimeException("fatal error during execution of Hg command: " + command);
}
-
- public String hg(HgRepositoryLocation repository, String command) {
- if (repository != null) {
- cd(repository);
- }
- return hg(command);
- }
-
- public void cd(HgRepositoryLocation repository) {
- cd(repository.getRoot().getPath());
- }
-
- private void printVersionTheFirstTime() {
+ private static void printVersionTheFirstTime() {
if (!myVersionPrinted) {
myVersionPrinted = true;
hg("version");
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgLightTest.java b/plugins/hg4idea/testSrc/hg4idea/test/HgLightTest.java
index f8cd598b6bec..cf214a774e5c 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgLightTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgLightTest.java
@@ -15,6 +15,7 @@
*/
package hg4idea.test;
+import com.intellij.dvcs.test.Executor;
import com.intellij.dvcs.test.MockProject;
import com.intellij.dvcs.test.MockVirtualFile;
import com.intellij.openapi.application.PluginPathManager;
@@ -33,7 +34,7 @@ import static org.junit.Assume.assumeTrue;
/**
* @author Nadya Zabrodina
*/
-public class HgLightTest extends HgExecutor {
+public class HgLightTest {
//private static final String USER_NAME = "John Doe";
//private static final String USER_EMAIL = "John.Doe@example.com";
@@ -62,13 +63,14 @@ public class HgLightTest extends HgExecutor {
catch (IOException e) {
fail("Can not start test case!\n"); //todo change
}
- cd(myTestRoot);
- myProjectRoot = mkdir("project");
+ Executor.cd(myTestRoot);
+ myProjectRoot = Executor.mkdir("project");
myProject = new MockProject(myProjectRoot);
myPlatformFacade = new HgTestPlatformFacade();
- cd(".hg");
+ Executor.cd(".hg");
File pluginRoot = new File(PluginPathManager.getPluginHomePath("hg4idea"));
- File hgrcFile = new File(new File(pluginRoot, "testData\\repo\\dot_hg"), "hgrc");
+ String pathToHgrc = "testData\\repo\\dot_hg";
+ File hgrcFile = new File(new File(pluginRoot, FileUtil.toSystemIndependentName(pathToHgrc)), "hgrc");
File hgrc = new File(new File(myProjectRoot, ".hg"), "hgrc");
try {
FileUtil.copy(hgrcFile, hgrc);
@@ -96,11 +98,11 @@ public class HgLightTest extends HgExecutor {
return new MockVirtualFile(rootDir);
}
- private void initRepo(String repoRoot) {
- cd(repoRoot);
- hg("init");
- touch("file.txt");
- hg("add file.txt");
- hg("commit -m initial");
+ private static void initRepo(String repoRoot) {
+ Executor.cd(repoRoot);
+ HgExecutor.hg("init");
+ Executor.touch("file.txt");
+ HgExecutor.hg("add file.txt");
+ HgExecutor.hg("commit -m initial");
}
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgMockVcsManager.java b/plugins/hg4idea/testSrc/hg4idea/test/HgMockVcsManager.java
index 5ca7089902c3..c1a80b9b86af 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgMockVcsManager.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgMockVcsManager.java
@@ -251,12 +251,7 @@ public class HgMockVcsManager extends ProjectLevelVcsManager {
@NotNull
@Override
public VcsRoot[] getAllVcsRoots() {
- List vcsRoots = new ArrayList();
- List repositories = myPlatformFacade.getRepositoryManager(myProject).getRepositories();
- for (VirtualFile repository : repositories) {
- vcsRoots.add(new VcsRoot(getVcsFor(repository), repository));
- }
- return vcsRoots.toArray(new VcsRoot[0]);
+ throw new UnsupportedOperationException();
}
@Override
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgTestPlatformFacade.java b/plugins/hg4idea/testSrc/hg4idea/test/HgTestPlatformFacade.java
index 76fa2fe065fc..7c21b0f638cc 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgTestPlatformFacade.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/HgTestPlatformFacade.java
@@ -20,19 +20,17 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import org.jetbrains.annotations.NotNull;
-import org.zmlx.hg4idea.*;
+import org.zmlx.hg4idea.HgGlobalSettings;
+import org.zmlx.hg4idea.HgPlatformFacade;
+import org.zmlx.hg4idea.HgProjectSettings;
+import org.zmlx.hg4idea.HgVcs;
/**
* @author Nadya Zabrodina
*/
-class HgTestPlatformFacade extends DvcsTestPlatformFacade implements HgPlatformFacade {
+public class HgTestPlatformFacade extends DvcsTestPlatformFacade implements HgPlatformFacade {
private HgMockVcs myVcs;
private HgMockVcsManager myVcsManager;
- private HgTestRepositoryManager myRepositoryManager;
-
- HgTestPlatformFacade() {
- myRepositoryManager = new HgTestRepositoryManager();
- }
@NotNull
@Override
@@ -44,6 +42,7 @@ class HgTestPlatformFacade extends DvcsTestPlatformFacade implements HgPlatformF
return myVcs;
}
+
@NotNull
@Override
public ProjectLevelVcsManager getVcsManager(@NotNull Project project) {
@@ -58,11 +57,5 @@ class HgTestPlatformFacade extends DvcsTestPlatformFacade implements HgPlatformF
public void showDialog(@NotNull DialogWrapper dialog) {
throw new UnsupportedOperationException();
}
-
- @NotNull
- @Override
- public HgRepositoryManager getRepositoryManager(@NotNull Project project) {
- return myRepositoryManager;
- }
}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/HgTestRepositoryManager.java b/plugins/hg4idea/testSrc/hg4idea/test/HgTestRepositoryManager.java
deleted file mode 100644
index bff58e4facc1..000000000000
--- a/plugins/hg4idea/testSrc/hg4idea/test/HgTestRepositoryManager.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2000-2013 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 hg4idea.test;
-
-import com.intellij.openapi.vfs.VirtualFile;
-import org.jetbrains.annotations.NotNull;
-import org.zmlx.hg4idea.HgRepositoryManager;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author Nadya Zabrodina
- */
-public class HgTestRepositoryManager implements HgRepositoryManager {
-
- private final List myRepositories = new ArrayList();
-
- public void add(VirtualFile repository) {
- myRepositories.add(repository);
- }
-
- @NotNull
- @Override
- public List getRepositories() {
- return myRepositories;
- }
-}
diff --git a/plugins/hg4idea/testSrc/hg4idea/test/diff/HgGetDiffForDirTest.java b/plugins/hg4idea/testSrc/hg4idea/test/diff/HgGetDiffForDirTest.java
index bfae5ed4f242..d8bd6b561a63 100644
--- a/plugins/hg4idea/testSrc/hg4idea/test/diff/HgGetDiffForDirTest.java
+++ b/plugins/hg4idea/testSrc/hg4idea/test/diff/HgGetDiffForDirTest.java
@@ -15,9 +15,11 @@
*/
package hg4idea.test.diff;
+import com.intellij.dvcs.test.Executor;
import com.intellij.dvcs.test.MockVirtualFile;
import com.intellij.openapi.vcs.FilePath;
import com.intellij.openapi.vcs.changes.Change;
+import hg4idea.test.HgExecutor;
import hg4idea.test.HgLightTest;
import org.junit.After;
import org.junit.Test;
@@ -53,28 +55,28 @@ public class HgGetDiffForDirTest extends HgLightTest {
@Test
public void testDiffForDir() {
- cd(myProjectRoot);
- touch("A.txt", "dsfdfdsf");
- hg("add A.txt");
- touch("B.txt");
- hg("add B.txt");
- hg("commit -m 2files_added");
- mkdir("dir");
- cd("dir");
- touch("C.txt");
- touch("D.txt");
- hg("add C.txt");
- hg("add D.txt");
- hg("commit -m createDir");
+ Executor.cd(myProjectRoot);
+ Executor.touch("A.txt", "dsfdfdsf");
+ HgExecutor.hg("add A.txt");
+ Executor.touch("B.txt");
+ HgExecutor.hg("add B.txt");
+ HgExecutor.hg("commit -m 2files_added");
+ Executor.mkdir("dir");
+ Executor.cd("dir");
+ Executor.touch("C.txt");
+ Executor.touch("D.txt");
+ HgExecutor.hg("add C.txt");
+ HgExecutor.hg("add D.txt");
+ HgExecutor.hg("commit -m createDir");
File dirFile = new File(myProjectRoot, "dir");
- String[] hash1 = hg("log -l 1 --template=" + SHORT_TEMPLATE_REVISION).split(":");
+ String[] hash1 = HgExecutor.hg("log -l 1 --template=" + SHORT_TEMPLATE_REVISION).split(":");
HgRevisionNumber r1number = HgRevisionNumber.getInstance(hash1[0], hash1[1]);
HgFileRevision rev1 =
new HgFileRevision(myProject, new HgFile(myRepository, dirFile), r1number, "", null, "", "", null, null, null, null);
- echo("C.txt", "aaaa");
- echo("D.txt", "dddd");
- hg("commit -m modifyDir");
- String[] hash2 = hg("log -l 1 --template=" + SHORT_TEMPLATE_REVISION).split(":");
+ Executor.echo("C.txt", "aaaa");
+ Executor.echo("D.txt", "dddd");
+ HgExecutor.hg("commit -m modifyDir");
+ String[] hash2 = HgExecutor.hg("log -l 1 --template=" + SHORT_TEMPLATE_REVISION).split(":");
HgRevisionNumber r2number = HgRevisionNumber.getInstance(hash2[0], hash2[1]);
HgFileRevision rev2 =
new HgFileRevision(myProject, new HgFile(myRepository, dirFile), r2number, "", null, "", "", null, null, null, null);
diff --git a/plugins/javaFX/src/META-INF/plugin.xml b/plugins/javaFX/src/META-INF/plugin.xml
index 93d77ab56757..a4b9b29515f7 100644
--- a/plugins/javaFX/src/META-INF/plugin.xml
+++ b/plugins/javaFX/src/META-INF/plugin.xml
@@ -18,5 +18,6 @@
+
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/FxmlConstants.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/FxmlConstants.java
index 0e9f05bfb3a0..6a7364b6b79e 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/FxmlConstants.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/FxmlConstants.java
@@ -39,6 +39,8 @@ public class FxmlConstants {
@NonNls public static final String FX_DEFINE = "fx:define";
@NonNls public static final String FX_SCRIPT = "fx:script";
@NonNls public static final String FX_INCLUDE = "fx:include";
+ @NonNls public static final String FX_ROOT = "fx:root";
+ @NonNls public static final String TYPE = "type";
public static final List FX_DEFAULT_PROPERTIES = Arrays.asList(FX_ID, FX_CONTROLLER, VALUE, FX_VALUE, FX_FACTORY, FX_CONSTANT);
public static final List FX_DEFAULT_ELEMENTS = Arrays.asList(FX_INCLUDE, FX_REFERENCE, FX_COPY, FX_DEFINE, FX_SCRIPT);
@@ -49,12 +51,15 @@ public class FxmlConstants {
static {
FX_ELEMENT_ATTRIBUTES.put(FX_INCLUDE, Arrays.asList(FX_ELEMENT_SOURCE, FX_ID));
FX_ELEMENT_ATTRIBUTES.put(FX_REFERENCE, Arrays.asList(FX_ELEMENT_SOURCE));
+ FX_ELEMENT_ATTRIBUTES.put(FX_ROOT, Arrays.asList(TYPE));
}
public static final Map> FX_REQUIRED_ELEMENT_ATTRIBUTES = new HashMap>();
+
static {
FX_REQUIRED_ELEMENT_ATTRIBUTES.put(FX_INCLUDE, Arrays.asList(FX_ELEMENT_SOURCE));
FX_REQUIRED_ELEMENT_ATTRIBUTES.put(FX_REFERENCE, Arrays.asList(FX_ELEMENT_SOURCE));
+ FX_REQUIRED_ELEMENT_ATTRIBUTES.put(FX_ROOT, Arrays.asList(TYPE));
}
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
index 231a3c96a7a9..ccc02fd95a11 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFXNSDescriptor.java
@@ -9,6 +9,7 @@ import com.intellij.xml.XmlNSDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxClassBackedElementDescriptor;
+import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxDefaultPropertyElementDescriptor;
/**
* User: anna
@@ -22,7 +23,9 @@ public class JavaFXNSDescriptor implements XmlNSDescriptor, Validator imports, XmlTag tag, Project project) {
@@ -155,7 +161,11 @@ public class JavaFxPsiUtil {
public static boolean isClassTag(String name) {
final String shortName = StringUtil.getShortName(name);
- return StringUtil.isCapitalized(name) && name.equals(shortName);
+ final boolean capitalized = StringUtil.isCapitalized(name);
+ if (name.equals(shortName)) {
+ return capitalized;
+ }
+ return !capitalized;
}
public static PsiMethod findPropertySetter(String attributeName, XmlTag context) {
@@ -220,4 +230,26 @@ public class JavaFxPsiUtil {
}
return true;
}
+
+ @Nullable
+ public static PsiClass getTagClass(XmlAttributeValue xmlAttributeValue) {
+ if (xmlAttributeValue == null) return null;
+ final PsiElement xmlAttribute = xmlAttributeValue.getParent();
+ final XmlTag xmlTag = ((XmlAttribute)xmlAttribute).getParent();
+ if (xmlTag != null) {
+ final XmlElementDescriptor descriptor = xmlTag.getDescriptor();
+ if (descriptor != null) {
+ final PsiElement declaration = descriptor.getDeclaration();
+ if (declaration instanceof PsiClass) {
+ return (PsiClass)declaration;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static boolean isVisibleInFxml(PsiMember psiMember) {
+ return psiMember.hasModifierProperty(PsiModifier.PUBLIC) ||
+ AnnotationUtil.isAnnotated(psiMember, JavaFxCommonClassNames.JAVAFX_FXML_ANNOTATION, false);
+ }
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java
new file mode 100644
index 000000000000..361a31651445
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/codeInsight/JavaFxRelatedItemLineMarkerProvider.java
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2000-2013 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.javaFX.fxml.codeInsight;
+
+import com.intellij.codeHighlighting.Pass;
+import com.intellij.codeInsight.daemon.GutterIconNavigationHandler;
+import com.intellij.codeInsight.daemon.RelatedItemLineMarkerInfo;
+import com.intellij.codeInsight.daemon.RelatedItemLineMarkerProvider;
+import com.intellij.codeInsight.navigation.NavigationUtil;
+import com.intellij.icons.AllIcons;
+import com.intellij.navigation.GotoRelatedItem;
+import com.intellij.openapi.editor.markup.GutterIconRenderer;
+import com.intellij.openapi.ui.popup.JBPopup;
+import com.intellij.psi.*;
+import com.intellij.psi.search.searches.ReferencesSearch;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.ui.awt.RelativePoint;
+import com.intellij.util.CommonProcessors;
+import com.intellij.util.ConstantFunction;
+import com.intellij.util.Function;
+import com.intellij.util.Processor;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
+
+import java.awt.event.MouseEvent;
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * User: anna
+ */
+public class JavaFxRelatedItemLineMarkerProvider extends RelatedItemLineMarkerProvider {
+ @Override
+ protected void collectNavigationMarkers(@NotNull PsiElement element, final Collection super RelatedItemLineMarkerInfo> result) {
+ if (element instanceof PsiField) {
+ final PsiField field = (PsiField)element;
+ if (JavaFxPsiUtil.isVisibleInFxml(field) && !field.hasModifierProperty(PsiModifier.STATIC)) {
+ final PsiClass containingClass = field.getContainingClass();
+ if (containingClass != null && containingClass.hasModifierProperty(PsiModifier.PUBLIC)) {
+ final ArrayList targets = new ArrayList();
+ collectTargets(element, targets, new Function() {
+ @Override
+ public GotoRelatedItem fun(PsiElement element) {
+ return new GotoRelatedItem(element);
+ }
+ }, true);
+ if (targets.isEmpty()) return;
+
+ result.add(new RelatedItemLineMarkerInfo(field, field.getNameIdentifier().getTextRange(),
+ AllIcons.FileTypes.Xml, Pass.UPDATE_OVERRIDEN_MARKERS, null,
+ new JavaFXIdIconNavigationHandler(), GutterIconRenderer.Alignment.LEFT,
+ targets));
+ }
+ }
+ }
+ }
+
+ private static void collectTargets(PsiElement element, final ArrayList targets, final Function fun, final boolean stopAtFirst) {
+ ReferencesSearch.search(element).forEach(new Processor() {
+ @Override
+ public boolean process(PsiReference reference) {
+ final PsiElement referenceElement = reference.getElement();
+ if (referenceElement == null) return true;
+ if (!(referenceElement instanceof XmlAttributeValue)) return true;
+ final XmlAttributeValue attributeValue = (XmlAttributeValue)referenceElement;
+ final PsiElement parent = attributeValue.getParent();
+ if (!(parent instanceof XmlAttribute)) return true;
+ final PsiFile containingFile = referenceElement.getContainingFile();
+ if (containingFile == null) return true;
+ if (JavaFxFileTypeFactory.isFxml(containingFile)) {
+ targets.add(fun.fun(parent));
+ if (stopAtFirst) return false;
+ }
+ return true;
+ }
+ });
+ }
+
+ private static class JavaFXIdIconNavigationHandler implements GutterIconNavigationHandler {
+ @Override
+ public void navigate(MouseEvent e, PsiField field) {
+ final ArrayList relatedItems = new ArrayList();
+ collectTargets(field, relatedItems, Function.ID, false);
+ if (relatedItems.size() == 1) {
+ NavigationUtil.activateFileWithPsiElement(relatedItems.get(0));
+ return;
+ }
+ final JBPopup popup = NavigationUtil
+ .getPsiElementPopup(relatedItems.toArray(new PsiElement[relatedItems.size()]), "Choose component with fx:id " + field.getName() + "");
+ popup.show(new RelativePoint(e));
+ }
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxClassBackedElementDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxClassBackedElementDescriptor.java
index 093a9bedf7d0..2cf007f383b6 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxClassBackedElementDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxClassBackedElementDescriptor.java
@@ -4,17 +4,22 @@ import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.codeInsight.daemon.Validator;
import com.intellij.codeInsight.daemon.impl.analysis.GenericsHighlightUtil;
import com.intellij.codeInsight.daemon.impl.analysis.HighlightUtil;
+import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.xml.XmlAttributeImpl;
+import com.intellij.psi.search.GlobalSearchScope;
+import com.intellij.psi.search.searches.ClassInheritorsSearch;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PropertyUtil;
import com.intellij.psi.util.PsiUtil;
+import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Function;
+import com.intellij.util.Processor;
import com.intellij.xml.XmlAttributeDescriptor;
import com.intellij.xml.XmlElementDescriptor;
import com.intellij.xml.XmlElementsGroup;
@@ -279,6 +284,31 @@ public class JavaFxClassBackedElementDescriptor implements XmlElementDescriptor,
}
}
validateTagAccordingToFieldType(context, parentTag, host);
+ if (myPsiClass != null && myPsiClass.isValid()) {
+ if(myPsiClass.getConstructors().length > 0) {
+ final Project project = myPsiClass.getProject();
+ final PsiMethod noArgConstructor = myPsiClass
+ .findMethodBySignature(JavaPsiFacade.getElementFactory(project).createConstructor(myPsiClass.getName()), false);
+ if (noArgConstructor == null) {
+ final PsiClass builderClass = JavaPsiFacade.getInstance(project).findClass(JavaFxCommonClassNames.JAVAFX_FXML_BUILDER,
+ GlobalSearchScope.allScope(project));
+ if (builderClass != null) {
+ //todo cache this info
+ final PsiTypeParameter typeParameter = builderClass.getTypeParameters()[0];
+ if (ClassInheritorsSearch.search(builderClass).forEach(new Processor() {
+ @Override
+ public boolean process(PsiClass aClass) {
+ final PsiType initType =
+ TypeConversionUtil.getSuperClassSubstitutor(builderClass, aClass, PsiSubstitutor.EMPTY).substitute(typeParameter);
+ return !Comparing.equal(myPsiClass, PsiUtil.resolveClassInClassTypeOnly(initType));
+ }
+ })) {
+ host.addMessage(context, "Unable to instantiate", ValidationHost.ErrorType.ERROR);
+ }
+ }
+ }
+ }
+ }
}
private void validateTagAccordingToFieldType(XmlTag context, XmlTag parentTag, ValidationHost host) {
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultAttributeDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultAttributeDescriptor.java
index 80b05a8d6397..b5894330eaea 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultAttributeDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultAttributeDescriptor.java
@@ -16,10 +16,16 @@
package org.jetbrains.plugins.javaFX.fxml.descriptors;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.psi.PsiClass;
-import com.intellij.psi.PsiField;
-import com.intellij.psi.PsiModifier;
+import com.intellij.psi.*;
+import com.intellij.psi.xml.XmlAttribute;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.psi.xml.XmlElement;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlAttributeDescriptor;
+import com.intellij.xml.XmlElementDescriptor;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
import java.util.List;
@@ -29,6 +35,7 @@ import java.util.List;
*/
public class JavaFxDefaultAttributeDescriptor extends JavaFxPropertyAttributeDescriptor {
private static final Logger LOG = Logger.getInstance("#" + JavaFxDefaultAttributeDescriptor.class.getName());
+ public static final String VALUE_OF = "valueOf";
private String myDefaultPropertyName = null;
public JavaFxDefaultAttributeDescriptor(String name, PsiClass psiClass) {
@@ -67,4 +74,41 @@ public class JavaFxDefaultAttributeDescriptor extends JavaFxPropertyAttributeDes
protected boolean isConstant(PsiField field) {
return field.hasModifierProperty(PsiModifier.STATIC) && field.hasModifierProperty(PsiModifier.FINAL) && field.hasModifierProperty(PsiModifier.PUBLIC);
}
+
+ @Nullable
+ @Override
+ public String validateValue(XmlElement context, String value) {
+ if (context instanceof XmlAttributeValue) {
+ final PsiElement parent = context.getParent();
+ if (parent instanceof XmlAttribute) {
+ final XmlAttribute attribute = (XmlAttribute)parent;
+ if (FxmlConstants.FX_VALUE.equals(attribute.getName())) {
+ final PsiClass tagClass = JavaFxPsiUtil.getTagClass((XmlAttributeValue)context);
+ if (tagClass != null) {
+ final PsiMethod method = getValueOfMethod(tagClass);
+ if (method == null) {
+ return "Unable to coerce '" + value + "' to " + tagClass.getQualifiedName() + ".";
+ }
+ }
+ }
+ }
+ }
+ return super.validateValue(context, value);
+ }
+
+ private static PsiMethod getValueOfMethod(PsiClass tagClass) {
+ final PsiMethod[] methods = tagClass.findMethodsByName(VALUE_OF, false);
+ for (PsiMethod method : methods) {
+ if (method.hasModifierProperty(PsiModifier.STATIC)) {
+ final PsiParameter[] parameters = method.getParameterList().getParameters();
+ if (parameters.length == 1) {
+ final PsiType type = parameters[0].getType();
+ if (type.equalsToText(CommonClassNames.JAVA_LANG_STRING) || type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
+ return method;
+ }
+ }
+ }
+ }
+ return null;
+ }
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultPropertyElementDescriptor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultPropertyElementDescriptor.java
index f63e9f8abcee..7614ddb645ba 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultPropertyElementDescriptor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/descriptors/JavaFxDefaultPropertyElementDescriptor.java
@@ -66,7 +66,7 @@ public class JavaFxDefaultPropertyElementDescriptor implements XmlElementDescrip
@Nullable
@Override
public XmlElementDescriptor getElementDescriptor(XmlTag childTag, XmlTag contextTag) {
- if (myName.equals(FxmlConstants.FX_DEFINE)) {
+ if (myName.equals(FxmlConstants.FX_DEFINE) || myName.equals(FxmlConstants.FX_ROOT)) {
final String name = childTag.getName();
if (JavaFxPsiUtil.isClassTag(name)) {
return new JavaFxClassBackedElementDescriptor(name, childTag);
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/EnumeratedAttributeReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/EnumeratedAttributeReferenceProvider.java
index 8f8746082845..ef72a7fbb20e 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/EnumeratedAttributeReferenceProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/EnumeratedAttributeReferenceProvider.java
@@ -15,15 +15,14 @@
*/
package org.jetbrains.plugins.javaFX.fxml.refs;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiReference;
-import com.intellij.psi.PsiReferenceBase;
-import com.intellij.psi.PsiReferenceProvider;
+import com.intellij.psi.*;
import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import com.intellij.xml.XmlAttributeDescriptor;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.javaFX.fxml.descriptors.JavaFxPropertyAttributeDescriptor;
/**
@@ -39,7 +38,20 @@ class EnumeratedAttributeReferenceProvider extends PsiReferenceProvider {
if (parent instanceof XmlAttribute) {
final XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
if (descriptor instanceof JavaFxPropertyAttributeDescriptor && descriptor.isEnumerated()) {
- return new PsiReference[] {new PsiReferenceBase.Immediate(xmlAttributeValue, ((JavaFxPropertyAttributeDescriptor)descriptor).getEnumConstant(xmlAttributeValue.getValue()))};
+ final PsiField enumConstant = ((JavaFxPropertyAttributeDescriptor)descriptor).getEnumConstant(xmlAttributeValue.getValue());
+ return new PsiReference[] {new PsiReferenceBase(xmlAttributeValue){
+ @Nullable
+ @Override
+ public PsiElement resolve() {
+ return enumConstant;
+ }
+
+ @NotNull
+ @Override
+ public Object[] getVariants() {
+ return ArrayUtil.EMPTY_OBJECT_ARRAY;
+ }
+ }};
}
}
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java
index f4d44b4446d3..885441678602 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/FxmlReferencesContributor.java
@@ -41,6 +41,12 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
.and(attributeValueInFxml),
CLASS_REFERENCE_PROVIDER);
+ registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue()
+ .withParent(XmlPatterns.xmlAttribute().withName("type")
+ .withParent(XmlPatterns.xmlTag().withName(FxmlConstants.FX_ROOT)))
+ .and(attributeValueInFxml),
+ CLASS_REFERENCE_PROVIDER);
+
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_ID))
.and(attributeValueInFxml),
new JavaFxFieldIdReferenceProvider());
@@ -57,6 +63,10 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
.and(attributeValueInFxml),
new JavaFxComponentIdReferenceProvider());
+ registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_FACTORY))
+ .and(attributeValueInFxml),
+ new JavaFxFactoryReferenceProvider());
+
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withValue(string().startsWith("#"))
.and(attributeValueInFxml),
new JavaFxEventHandlerReferenceProvider());
@@ -64,6 +74,9 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withValue(string().startsWith("@")).and(attributeValueInFxml),
new JavaFxLocationReferenceProvider());
+ registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName("url")).and(attributeValueInFxml),
+ new JavaFxLocationReferenceProvider());
+
registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlTokenType.XML_TAG_CHARACTERS).inFile(inFxmlElementPattern()), new ImportReferenceProvider());
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().and(attributeValueInFxml),
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
index 979b48889cc0..bc8e89e721e4 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxAnnotator.java
@@ -59,8 +59,7 @@ public class JavaFxAnnotator implements Annotator {
for (PsiReference reference : references) {
final PsiElement resolve = reference.resolve();
if (resolve instanceof PsiMember) {
- if (!((PsiMember)resolve).hasModifierProperty(PsiModifier.PUBLIC) &&
- !AnnotationUtil.isAnnotated((PsiMember)resolve, Collections.singleton(JavaFxCommonClassNames.JAVAFX_FXML_ANNOTATION))) {
+ if (!JavaFxPsiUtil.isVisibleInFxml((PsiMember)resolve)) {
final String symbolPresentation = "'" + SymbolPresentationUtil.getSymbolPresentableText(resolve) + "'";
final Annotation annotation = holder.createErrorAnnotation(element,
symbolPresentation + (resolve instanceof PsiClass ? " should be public" : " should be public or annotated with @FXML"));
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerBasedReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerBasedReferenceProvider.java
index dc83e4c8fec5..a200fad4aaba 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerBasedReferenceProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxControllerBasedReferenceProvider.java
@@ -15,16 +15,12 @@
*/
package org.jetbrains.plugins.javaFX.fxml.refs;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
-import com.intellij.psi.xml.XmlAttribute;
import com.intellij.psi.xml.XmlAttributeValue;
-import com.intellij.psi.xml.XmlFile;
-import com.intellij.psi.xml.XmlTag;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.plugins.javaFX.fxml.FxmlConstants;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
/**
* User: anna
@@ -38,21 +34,8 @@ public abstract class JavaFxControllerBasedReferenceProvider extends PsiReferenc
final PsiFile containingFile = xmlAttrVal.getContainingFile();
if (!JavaFxFileTypeFactory.isFxml(containingFile)) return PsiReference.EMPTY_ARRAY;
- final XmlTag rootTag = ((XmlFile)containingFile).getRootTag();
- if (rootTag != null) {
- final XmlAttribute attribute = rootTag.getAttribute(FxmlConstants.FX_CONTROLLER);
- if (attribute != null) {
- final String attributeValue = attribute.getValue();
- if (!StringUtil.isEmptyOrSpaces(attributeValue)) {
- final PsiClass controllerClass =
- JavaPsiFacade.getInstance(xmlAttrVal.getProject()).findClass(attributeValue, xmlAttrVal.getResolveScope());
- if (controllerClass != null) {
- return getReferencesByElement(controllerClass, xmlAttrVal, context);
- }
- }
- }
- }
- return PsiReference.EMPTY_ARRAY;
+ final PsiClass controllerClass = JavaFxPsiUtil.getControllerClass(containingFile);
+ return controllerClass != null ? getReferencesByElement(controllerClass, xmlAttrVal, context) : PsiReference.EMPTY_ARRAY;
}
protected abstract PsiReference[] getReferencesByElement(@NotNull PsiClass controllerClass, XmlAttributeValue element, ProcessingContext context);
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFactoryReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFactoryReferenceProvider.java
new file mode 100644
index 000000000000..f2da17c1454e
--- /dev/null
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFactoryReferenceProvider.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2013 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.javaFX.fxml.refs;
+
+import com.intellij.psi.*;
+import com.intellij.psi.xml.XmlAttributeValue;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.ProcessingContext;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* User: anna
+*/
+class JavaFxFactoryReferenceProvider extends PsiReferenceProvider {
+ @NotNull
+ @Override
+ public PsiReference[] getReferencesByElement(@NotNull PsiElement element,
+ @NotNull ProcessingContext context) {
+ final XmlAttributeValue attributeValue = (XmlAttributeValue)element;
+ return new PsiReference[] {new JavaFXFactoryReference(attributeValue)};
+ }
+
+ private static class JavaFXFactoryReference extends PsiReferenceBase {
+ public JavaFXFactoryReference(XmlAttributeValue attributeValue) {
+ super(attributeValue);
+ }
+
+ @Nullable
+ @Override
+ public PsiElement resolve() {
+ final PsiClass psiClass = JavaFxPsiUtil.getTagClass(getElement());
+ if (psiClass != null) {
+ final PsiMethod[] psiMethods = psiClass.findMethodsByName(getElement().getValue(), false);
+ for (PsiMethod method : psiMethods) {
+ if (isFactoryMethod(method)) {
+ return method;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static boolean isFactoryMethod(PsiMethod method) {
+ return method.hasModifierProperty(PsiModifier.STATIC) && method.getParameterList().getParametersCount() == 0;
+ }
+
+ @NotNull
+ @Override
+ public Object[] getVariants() {
+ final PsiClass psiClass = JavaFxPsiUtil.getTagClass(getElement());
+ if (psiClass != null) {
+ final List methods = new ArrayList();
+ for (PsiMethod method : psiClass.getMethods()) {
+ if (isFactoryMethod(method)) {
+ methods.add(method);
+ }
+ }
+ return ArrayUtil.toObjectArray(methods);
+ }
+ return ArrayUtil.EMPTY_OBJECT_ARRAY;
+ }
+ }
+}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java
index 403e1be2df95..9185b75fc511 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxFieldIdReferenceProvider.java
@@ -15,14 +15,13 @@
*/
package org.jetbrains.plugins.javaFX.fxml.refs;
-import com.intellij.codeInsight.AnnotationUtil;
import com.intellij.psi.*;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.util.ArrayUtil;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
+import org.jetbrains.plugins.javaFX.fxml.JavaFxPsiUtil;
import java.util.ArrayList;
import java.util.List;
@@ -51,7 +50,7 @@ class JavaFxFieldIdReferenceProvider extends JavaFxControllerBasedReferenceProvi
final PsiField[] fields = aClass.getFields();
for (PsiField psiField : fields) {
if (!psiField.hasModifierProperty(PsiModifier.STATIC)) {
- if (psiField.hasModifierProperty(PsiModifier.PUBLIC) || AnnotationUtil.isAnnotated(psiField, JavaFxCommonClassNames.JAVAFX_FXML_ANNOTATION, false)) {
+ if (JavaFxPsiUtil.isVisibleInFxml(psiField)) {
fieldsToSuggest.add(psiField);
}
}
diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxLocationReferenceProvider.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxLocationReferenceProvider.java
index 9e2f2eb771c4..c901ad7c9697 100644
--- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxLocationReferenceProvider.java
+++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/refs/JavaFxLocationReferenceProvider.java
@@ -32,8 +32,16 @@ class JavaFxLocationReferenceProvider extends PsiReferenceProvider {
public PsiReference[] getReferencesByElement(@NotNull final PsiElement element,
@NotNull ProcessingContext context) {
final String value = ((XmlAttributeValue)element).getValue();
- final String relativePathToResource = value.substring(1);
- final FileReferenceSet set = new FileReferenceSet(relativePathToResource, element, 2, null, true);
+ final FileReferenceSet set;
+ if (value.startsWith("@")) {
+ set = new FileReferenceSet(value.substring(1), element, 2, null, true);
+ }
+ else {
+ set = new FileReferenceSet(value, element, 1, null, true);
+ if (value.startsWith("/")) {
+ set.addCustomization(FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION, FileReferenceSet.ABSOLUTE_TOP_LEVEL);
+ }
+ }
return set.getAllReferences();
}
}
diff --git a/plugins/javaFX/testData/completion/factoryMethods.fxml b/plugins/javaFX/testData/completion/factoryMethods.fxml
new file mode 100644
index 000000000000..b10f088fbc38
--- /dev/null
+++ b/plugins/javaFX/testData/completion/factoryMethods.fxml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/javaFX/testData/completion/factoryMethods_after.fxml b/plugins/javaFX/testData/completion/factoryMethods_after.fxml
new file mode 100644
index 000000000000..6be1200c2452
--- /dev/null
+++ b/plugins/javaFX/testData/completion/factoryMethods_after.fxml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/plugins/javaFX/testData/highlighting/fQNtagNames.fxml b/plugins/javaFX/testData/highlighting/fQNtagNames.fxml
new file mode 100644
index 000000000000..6137837891f2
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/fQNtagNames.fxml
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/plugins/javaFX/testData/highlighting/imageIcon.fxml b/plugins/javaFX/testData/highlighting/imageIcon.fxml
index 060671ad1c65..76d655bdbed7 100644
--- a/plugins/javaFX/testData/highlighting/imageIcon.fxml
+++ b/plugins/javaFX/testData/highlighting/imageIcon.fxml
@@ -10,6 +10,11 @@
+
+
+
+
+
unknownIcon.png"/>
diff --git a/plugins/javaFX/testData/highlighting/instantiationAcceptance.fxml b/plugins/javaFX/testData/highlighting/instantiationAcceptance.fxml
new file mode 100644
index 000000000000..4a538b7bd0da
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/instantiationAcceptance.fxml
@@ -0,0 +1,9 @@
+
+
+
+
+
+ <File />
+
+
+
diff --git a/plugins/javaFX/testData/highlighting/rootTag.fxml b/plugins/javaFX/testData/highlighting/rootTag.fxml
new file mode 100644
index 000000000000..6fa1c4ac7c85
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/rootTag.fxml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/rootTagWithoutType.fxml b/plugins/javaFX/testData/highlighting/rootTagWithoutType.fxml
new file mode 100644
index 000000000000..c7fd34ee6fe6
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/rootTagWithoutType.fxml
@@ -0,0 +1,7 @@
+
+
+
+<fx:root xmlns:fx="http://javafx.com/fxml">
+
+
+fx:root >
\ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/unresolvedRootTag.fxml b/plugins/javaFX/testData/highlighting/unresolvedRootTag.fxml
new file mode 100644
index 000000000000..650af2aafe84
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/unresolvedRootTag.fxml
@@ -0,0 +1,9 @@
+
+
+
+
+
+unknownPackage.unknownClass " xmlns:fx="http://javafx.com/fxml">
+
+
+
\ No newline at end of file
diff --git a/plugins/javaFX/testData/highlighting/valueOfAcceptance.fxml b/plugins/javaFX/testData/highlighting/valueOfAcceptance.fxml
new file mode 100644
index 000000000000..a4b16c30662e
--- /dev/null
+++ b/plugins/javaFX/testData/highlighting/valueOfAcceptance.fxml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+ "A"/>
+
+
+
+
+
+
+
+
diff --git a/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java b/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java
index 4a30d877f449..69de76553876 100644
--- a/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java
+++ b/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java
@@ -147,6 +147,30 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase {
doDoTest(false, false);
}
+ public void testValueOfAcceptance() throws Exception {
+ doTest();
+ }
+
+ public void testInstantiationAcceptance() throws Exception {
+ doTest();
+ }
+
+ public void testFQNtagNames() throws Exception {
+ doTest();
+ }
+
+ public void testRootTag() throws Exception {
+ doTest();
+ }
+
+ public void testUnresolvedRootTag() throws Exception {
+ doTest();
+ }
+
+ public void testRootTagWithoutType() throws Exception {
+ doTest();
+ }
+
@NotNull
@Override
protected String getTestDataPath() {
diff --git a/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCompletionTest.java b/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCompletionTest.java
index 42cb5084adcf..d21c73adbe59 100644
--- a/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCompletionTest.java
+++ b/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFxCompletionTest.java
@@ -85,6 +85,10 @@ public class JavaFxCompletionTest extends CompletionTestCase {
doTest("text");
}
+ public void testFactoryMethods() throws Exception {
+ doTest("observableArrayList");
+ }
+
private void doTest() throws Exception {
doTest(null);
}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenModelInspection.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenModelInspection.java
deleted file mode 100644
index 4ce00f70b3bd..000000000000
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenModelInspection.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright 2000-2009 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.idea.maven.dom;
-
-import com.intellij.codeInspection.InspectionToolProvider;
-import com.intellij.util.xml.highlighting.BasicDomElementsInspection;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
-
-public class MavenModelInspection extends BasicDomElementsInspection implements InspectionToolProvider {
- public MavenModelInspection() {
- super(MavenDomProjectModel.class);
- }
-
- @NotNull
- public String getGroupDisplayName() {
- return MavenDomBundle.message("inspection.group");
- }
-
- @NotNull
- public String getDisplayName() {
- return MavenDomBundle.message("inspection.name");
- }
-
- @NotNull
- public String getShortName() {
- return "MavenModelInspection";
- }
-
- public Class[] getInspectionClasses() {
- return new Class[]{MavenModelInspection.class};
- }
-}
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
index 275772baa18c..7fe54ca40d43 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/MavenPropertyResolver.java
@@ -153,7 +153,7 @@ public class MavenPropertyResolver {
VirtualFile file = MavenDomUtil.getVirtualFile(element);
if (file == null) return text;
- MavenProjectsManager manager = MavenProjectsManager.getInstance(element.getProject());
+ MavenProjectsManager manager = MavenProjectsManager.getInstance(projectDom.getManager().getProject());
MavenProject mavenProject = manager.findProject(file);
if (mavenProject == null) return text;
diff --git a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenModelInspection.java b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenModelInspection.java
index 359305790bc0..e9cf234c5d30 100644
--- a/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenModelInspection.java
+++ b/plugins/maven/src/main/java/org/jetbrains/idea/maven/dom/inspections/MavenModelInspection.java
@@ -15,13 +15,16 @@
*/
package org.jetbrains.idea.maven.dom.inspections;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.xml.Converter;
+import com.intellij.util.xml.DomUtil;
import com.intellij.util.xml.GenericDomValue;
import com.intellij.util.xml.highlighting.BasicDomElementsInspection;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.dom.MavenDomBundle;
import org.jetbrains.idea.maven.dom.converters.MavenDomSoftAwareConverter;
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
+import org.jetbrains.idea.maven.project.MavenProjectsManager;
public class MavenModelInspection extends BasicDomElementsInspection {
public MavenModelInspection() {
@@ -43,8 +46,23 @@ public class MavenModelInspection extends BasicDomElementsInspection
-
+
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenCombineChildAttributeTest.groovy b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenCombineChildAttributeTest.groovy
index f01b25787125..78554863c5ae 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenCombineChildAttributeTest.groovy
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenCombineChildAttributeTest.groovy
@@ -50,59 +50,4 @@ class MavenCombineChildAttributeTest extends MavenDomTestCase {
assertCompletionVariants(myProjectPom, "override", "append")
}
- public void testHighlighting() {
- createProjectPom("""
- test
- project
- 1
-
-
-
-
- maven-compiler-plugin
-
-
-
-
-
- compile
-
-
-
-
-
-
-
-
-
-
-
-
- testProfile
-
-
-
- maven-compiler-plugin
-
-
-
-
-
- compile
-
-
-
-
-
-
-
-
-
-
-
-""")
-
- checkHighlighting()
- }
-
}
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java
index 905dcba3869b..48e8b72fcf83 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDependencyCompletionAndResolutionTest.java
@@ -893,21 +893,60 @@ public class MavenDependencyCompletionAndResolutionTest extends MavenDomWithIndi
checkHighlighting();
}
- public void testDoNotHighlightProblemsInNotLoadedProject() throws Throwable {
- VirtualFile m = createModulePom("not-a-module",
- "test " +
- "project " +
- "1 " +
+ public void testDontHighlightProblemsInNonManagedPom1() throws Throwable {
+ createProjectPom("test " +
+ "project " +
+ "1 " +
+ "" +
+ " 4.0 " +
+ " ");
+
+ VirtualFile m = createModulePom("m1",
+ "m1 " +
+
+ "" +
+ " test " +
+ " project " +
+ " 1 " +
+ " " +
"" +
- " " +
- " xxx " +
- " xxx " +
- " xxx " +
- " " +
+ " " +
+ " junit " +
+ " junit " +
+ " ${junitVersion} " +
+ " " +
" ");
- checkHighlighting(m);
+ importProject();
+
+ checkHighlighting(m, true, false, true);
+ }
+
+ public void testDontHighlightProblemsInNonManagedPom2() throws Throwable {
+ createProjectPom("test " +
+ "project " +
+ "1 " +
+
+ "" +
+ " 4.0 " +
+ " ");
+
+ VirtualFile m = createModulePom("m1",
+ "m1 " +
+
+ "" +
+ " test " +
+ " project " +
+ " 1 " +
+ " " +
+ "" +
+ " ${junitVersion} " +
+ " ");
+
+ importProject();
+
+ checkHighlighting(m, true, false, true);
}
public void testUpdateIndicesIntention() throws Throwable {
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java
index 36b037431930..1211ce5c60e6 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenDomTestCase.java
@@ -58,6 +58,7 @@ import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.MavenImportingTestCase;
+import org.jetbrains.idea.maven.dom.inspections.MavenModelInspection;
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
import org.jetbrains.idea.maven.dom.references.MavenPsiElementWrapper;
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenNotManagedProjectInspectionsTest.java b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenNotManagedProjectInspectionsTest.java
index 5160573eb00c..5727ff47960c 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenNotManagedProjectInspectionsTest.java
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/dom/MavenNotManagedProjectInspectionsTest.java
@@ -37,15 +37,15 @@ public class MavenNotManagedProjectInspectionsTest extends MavenDomTestCase {
"1 " +
"" +
- " m1 " +
- " m2 " +
+ " m1 " +
+ " m2 " +
" " +
"" +
" " +
- " xxx " +
- " yyy " +
- " zzz " +
+ " xxx " +
+ " yyy " +
+ " zzz " +
" " +
" ");
diff --git a/plugins/maven/src/test/java/org/jetbrains/idea/maven/inspections/MavenRedundantGroupIdTest.groovy b/plugins/maven/src/test/java/org/jetbrains/idea/maven/inspections/MavenRedundantGroupIdTest.groovy
index e7fdda78e31b..1218cb13a0d9 100644
--- a/plugins/maven/src/test/java/org/jetbrains/idea/maven/inspections/MavenRedundantGroupIdTest.groovy
+++ b/plugins/maven/src/test/java/org/jetbrains/idea/maven/inspections/MavenRedundantGroupIdTest.groovy
@@ -19,7 +19,7 @@ class MavenRedundantGroupIdTest extends MavenDomTestCase {
public void testHighlighting1() {
createProjectPom("""
- mavenParent
+ my.group
childA
1.0
""")
@@ -34,9 +34,25 @@ class MavenRedundantGroupIdTest extends MavenDomTestCase {
1.0
- mavenParent
- childA
- 1.0
+ my.group
+ parent
+ 1.0
+
+""")
+
+ checkHighlighting()
+ }
+
+ public void testHighlighting3() {
+ createProjectPom("""
+ my.group
+ childA
+ 1.0
+
+
+ my.group
+ parent
+ 1.0
""")
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
index 083228821fd2..6cd0df2744d1 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/RootsToWorkingCopies.java
@@ -129,6 +129,7 @@ public class RootsToWorkingCopies implements VcsListener {
try {
workingCopyRoot = SVNWCUtil.getWorkingCopyRoot(ioFile, true);
if (workingCopyRoot != null) {
+ // ok to use low-level 1.6 API, 1.7 is checked below
SVNWCAccess wcAccess = SVNWCAccess.newInstance(null);
try {
wcAccess.probeOpen(workingCopyRoot, false, 0);
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java
index b0e0d3251a18..30cb2a92a6af 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnFileSystemListener.java
@@ -246,15 +246,15 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
final boolean is17 = SvnUtil.is17CopyPart(src);
if (is17) {
- SVNStatus srcStatus = getFileStatus(src);
+ SVNStatus srcStatus = getFileStatus(vcs, src);
final File toDir = dst.getParentFile();
- SVNStatus dstStatus = getFileStatus(toDir);
+ SVNStatus dstStatus = getFileStatus(vcs, toDir);
final boolean srcUnversioned = srcStatus == null || SvnVcs.svnStatusIsUnversioned(srcStatus);
if (srcUnversioned && (dstStatus == null || SvnVcs.svnStatusIsUnversioned(dstStatus))) {
return false;
}
if (srcUnversioned) {
- SVNStatus dstWasStatus = getFileStatus(dst);
+ SVNStatus dstWasStatus = getFileStatus(vcs, dst);
if (dstWasStatus == null || SvnVcs.svnStatusIsUnversioned(dstWasStatus)) {
return false;
}
@@ -309,7 +309,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
} else {
if (doUsualMove(vcs, src)) return true;
// check destination directory
- final SVNStatus dstParentStatus = getFileStatus(dst.getParentFile());
+ final SVNStatus dstParentStatus = getFileStatus(vcs, dst.getParentFile());
if (dstParentStatus == null || SvnVcs.svnStatusIsUnversioned(dstParentStatus)) {
try {
copyFileOrDir(src, dst);
@@ -482,7 +482,7 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
//
}
- SVNStatus status = getFileStatus(ioFile);
+ SVNStatus status = getFileStatus(vcs, ioFile);
if (status == null ||
SvnVcs.svnStatusIsUnversioned(status) ||
@@ -1031,18 +1031,6 @@ public class SvnFileSystemListener extends CommandAdapter implements LocalFileOp
return new File(vf.getPath()).getAbsoluteFile();
}
- @Nullable
- private static SVNStatus getFileStatus(File file) {
- final SVNClientManager clientManager = SVNClientManager.newInstance();
- try {
- SVNStatusClient stClient = clientManager.getStatusClient();
- return getFileStatus(file, stClient);
- }
- finally {
- clientManager.dispose();
- }
- }
-
@Nullable
private static SVNStatus getFileStatus(SvnVcs vcs, File file) {
SVNStatusClient stClient = vcs.createStatusClient();
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
index c5f88f7d6760..f407b175e79a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnUtil.java
@@ -16,6 +16,7 @@
package org.jetbrains.idea.svn;
import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
@@ -45,8 +46,6 @@ import org.jetbrains.idea.svn.dialogs.LockDialog;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.internal.util.SVNPathUtil;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
-import org.tmatesoft.svn.core.internal.wc.admin.SVNEntry;
-import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess;
import org.tmatesoft.svn.core.internal.wc2.SvnWcGeneration;
import org.tmatesoft.svn.core.io.SVNCapability;
import org.tmatesoft.svn.core.io.SVNRepository;
@@ -62,6 +61,7 @@ public class SvnUtil {
@NonNls public static final String WC_DB_FILE_NAME = "wc.db";
@NonNls public static final String DIR_PROPS_FILE_NAME = "dir-props";
@NonNls public static final String PATH_TO_LOCK_FILE = SVN_ADMIN_DIR_NAME + "/lock";
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.idea.svn.SvnUtil");
private SvnUtil() { }
@@ -583,23 +583,15 @@ public class SvnUtil {
}
@Nullable
- public static SVNURL getUrl(final File file) {
- SVNWCAccess wcAccess = SVNWCAccess.newInstance(null);
+ public static SVNURL getUrl(final SvnVcs vcs, final File file) {
try {
- wcAccess.probeOpen(file, false, 0);
- SVNEntry entry = wcAccess.getVersionedEntry(file, false);
- return entry.getSVNURL();
- } catch (SVNException e) {
- //
- } finally {
- try {
- wcAccess.close();
- }
- catch (SVNException e) {
- //
- }
+ final SVNInfo info = vcs.createWCClient().doInfo(file, SVNRevision.UNDEFINED);
+ return info == null ? null : info.getURL(); // todo for moved items?
+ }
+ catch (SVNException e) {
+ LOG.debug(e);
+ return null;
}
- return null;
}
public static boolean doesRepositorySupportMergeInfo(final SvnVcs vcs, final SVNURL url) {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
index 45e71c9f9c68..ce0874fec74b 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnVcs.java
@@ -91,7 +91,6 @@ import org.tmatesoft.svn.core.internal.util.jna.SVNJNAUtil;
import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea14;
import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminAreaFactory;
-import org.tmatesoft.svn.core.internal.wc.admin.SVNWCAccess;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.*;
@@ -734,12 +733,6 @@ public class SvnVcs extends AbstractVcs {
return client;
}
- public SVNWCAccess createWCAccess() {
- final SVNWCAccess access = SVNWCAccess.newInstance(null);
- access.setOptions(myConfiguration.getOptions(myProject));
- return access;
- }
-
public ISVNOptions getSvnOptions() {
return myConfiguration.getOptions(myProject);
}
@@ -1128,7 +1121,7 @@ public class SvnVcs extends AbstractVcs {
final File ioFile = new File(vf.getPath());
SVNURL url = mapping.getUrlForFile(ioFile);
if (url == null) {
- url = SvnUtil.getUrl(ioFile);
+ url = SvnUtil.getUrl(this, ioFile);
if (url == null) {
notMatched.add(s);
continue;
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java
index 58b48f2f93e9..1bfe1733c06a 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/actions/CompareWithBranchAction.java
@@ -223,7 +223,9 @@ public class CompareWithBranchAction extends AnAction implements DumbAware {
}
private void report16DirDiff(SvnVcs vcs, SVNURL url) throws SVNException {
- SVNWCAccess wcAccess = vcs.createWCAccess();
+ // here there's 1.6 copy so ok to use SVNWCAccess
+ final SVNWCAccess wcAccess = SVNWCAccess.newInstance(null);
+ wcAccess.setOptions(vcs.getSvnOptions());
SVNRepository repository = null;
SVNRepository repository2 = null;
try {
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
index 836f6b4c83b1..459e9ab3a30e 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryContentRevision.java
@@ -40,6 +40,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.SvnBundle;
import org.jetbrains.idea.svn.SvnRevisionNumber;
+import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.io.SVNRepository;
@@ -65,7 +66,16 @@ public class SvnRepositoryContentRevision implements ContentRevision, MarkerVcsC
myFilePath = localPath;
}
else {
- myFilePath = VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(myPath, false);
+ FilePath local;
+ try {
+ final String fullPath = SvnUtil.appendMultiParts(repositoryRoot, myPath);
+ local = VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(fullPath, false);
+ }
+ catch (SVNException e) {
+ // todo what to do safely?
+ local = VcsContextFactory.SERVICE.getInstance().createFilePathOnNonLocal(repositoryRoot, false);
+ }
+ myFilePath = local;
}
myRevision = revision;
}
diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java
index 3d5bcaf0d92b..0366c21ea202 100644
--- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java
+++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnRepositoryLocation.java
@@ -16,12 +16,18 @@
package org.jetbrains.idea.svn.history;
import com.intellij.openapi.vcs.FilePath;
+import com.intellij.openapi.vcs.ProjectLevelVcsManager;
import com.intellij.openapi.vcs.RepositoryLocation;
import com.intellij.openapi.vcs.VcsException;
+import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.NotNullFunction;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.svn.RootUrlInfo;
+import org.jetbrains.idea.svn.SvnUtil;
import org.jetbrains.idea.svn.SvnVcs;
+import org.tmatesoft.svn.core.SVNException;
+import org.tmatesoft.svn.core.SVNURL;
+import org.tmatesoft.svn.core.internal.util.SVNURLUtil;
import java.io.File;
@@ -62,9 +68,26 @@ public class SvnRepositoryLocation implements RepositoryLocation {
@Nullable
public static FilePath getLocalPath(final String fullPath, final NotNullFunction detector, final SvnVcs vcs) {
if (vcs.getProject().isDefault()) return null;
+ final SVNURL fullPathURL;
+ try {
+ fullPathURL = SVNURL.parseURIEncoded(fullPath);
+ }
+ catch (SVNException e) {
+ return null;
+ }
final RootUrlInfo rootForUrl = vcs.getSvnFileUrlMapping().getWcRootForUrl(fullPath);
if (rootForUrl != null) {
return LocationDetector.filePathByUrlAndPath(fullPath, rootForUrl.getUrl().toString(), rootForUrl.getIoFile().getAbsolutePath(), detector);
+ } else {
+ final VirtualFile[] underVcs = ProjectLevelVcsManager.getInstance(vcs.getProject()).getRootsUnderVcs(vcs);
+ if (underVcs.length == 0) return null;
+ for (VirtualFile vf : underVcs) {
+ final File ioFile = new File(vf.getPath());
+ final SVNURL url = SvnUtil.getUrl(vcs, ioFile);
+ if (url != null && SVNURLUtil.isAncestor(url, fullPathURL)) {
+ return LocationDetector.filePathByUrlAndPath(fullPath, url.toString(), ioFile.getPath(), detector);
+ }
+ }
}
return null;
diff --git a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeListsTest.java b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeListsTest.java
index 3739d15fe4fd..9ec9da35ef40 100644
--- a/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeListsTest.java
+++ b/plugins/svn4idea/testSource/org/jetbrains/idea/svn/SvnNativeListsTest.java
@@ -72,7 +72,7 @@ public class SvnNativeListsTest extends Svn17TestCase {
ensureAddedToNativeList();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "A a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "A a.txt");
}
private void ensureAddedToNativeList() {
@@ -104,7 +104,7 @@ public class SvnNativeListsTest extends Svn17TestCase {
sleepABit();
ensureAddedToNativeList();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "D a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "D a.txt");
}
@Test
@@ -128,7 +128,7 @@ public class SvnNativeListsTest extends Svn17TestCase {
sleepABit();
ensureAddedToNativeList();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "M a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "M a.txt");
}
@Test
@@ -153,17 +153,17 @@ public class SvnNativeListsTest extends Svn17TestCase {
sleepABit();
ensureAddedToNativeList();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "M a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "M a.txt");
renameFileInCommand(file, "b.txt");
myDirtyScopeManager.markEverythingDirty();
myChangeListManager.ensureUpToDate(false);
sleepABit();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
ensureAddedToNativeList();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
}
@Test
@@ -189,7 +189,7 @@ public class SvnNativeListsTest extends Svn17TestCase {
sleepABit();
ensureAddedToNativeList();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
}
@Test
@@ -215,17 +215,17 @@ public class SvnNativeListsTest extends Svn17TestCase {
sleepABit();
ensureAddedToNativeList();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "A + b.txt", "D a.txt");
renameFileInCommand(file, "c.txt");
myDirtyScopeManager.markEverythingDirty();
myChangeListManager.ensureUpToDate(false);
sleepABit();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + c.txt", "D a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "A + c.txt", "D a.txt");
ensureAddedToNativeList();
- verify(runSvn("status"), "", "--- Changelist 'newOne':", "A + c.txt", "D a.txt");
+ verifySorted(runSvn("status"), "", "--- Changelist 'newOne':", "A + c.txt", "D a.txt");
}
private void sleepABit() {
diff --git a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java
index 78f9764fc879..02e3d431ce25 100644
--- a/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java
+++ b/plugins/tasks/jira-connector/src/main/java/com/intellij/tasks/jira/JiraRepository.java
@@ -18,6 +18,7 @@ import com.intellij.util.xmlb.annotations.Tag;
import org.apache.axis.AxisProperties;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.cookie.CookiePolicy;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
@@ -117,6 +118,7 @@ public class JiraRepository extends BaseRepositoryImpl {
private HttpClient login() throws Exception {
HttpClient client = getHttpClient();
+ client.getParams().setCookiePolicy(CookiePolicy.BROWSER_COMPATIBILITY);
if (myJira4) {
PostMethod postMethod = getLoginMethodFor4x();
client.executeMethod(postMethod);
diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java
index 330c90a74c89..ad6d77e4d9c3 100644
--- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java
+++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/DesignerEditorPanel.java
@@ -173,12 +173,7 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
@Override
public RadComponent findTarget(int x, int y, @Nullable ComponentTargetFilter filter) {
- if (myRootComponent != null) {
- FindComponentVisitor visitor = new FindComponentVisitor(myLayeredPane, filter, x, y);
- myRootComponent.accept(visitor, false);
- return visitor.getResult();
- }
- return null;
+ return DesignerEditorPanel.this.findTarget(x, y, filter);
}
@Override
@@ -727,10 +722,21 @@ public abstract class DesignerEditorPanel extends JPanel implements DataProvider
public abstract String getPlatformTarget();
+ protected RadComponent findTarget(int x, int y, @Nullable ComponentTargetFilter filter) {
+ if (myRootComponent != null) {
+ FindComponentVisitor visitor = new FindComponentVisitor(myLayeredPane, filter, x, y);
+ myRootComponent.accept(visitor, false);
+ return visitor.getResult();
+ }
+ return null;
+ }
+
protected abstract ComponentDecorator getRootSelectionDecorator();
@Nullable
- protected abstract EditOperation processRootOperation(OperationContext context);
+ protected EditOperation processRootOperation(OperationContext context) {
+ return null;
+ }
protected abstract boolean execute(ThrowableRunnable operation, boolean updateProperties);
diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/FlowBaseOperation.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/FlowBaseOperation.java
index e0a75b8fa64f..93956a554ed7 100644
--- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/FlowBaseOperation.java
+++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/FlowBaseOperation.java
@@ -47,7 +47,7 @@ public abstract class FlowBaseOperation extends AbstractEditOperation {
createFirstInsertFeedback();
createInsertFeedback();
- if (myContainer.getChildren().isEmpty()) {
+ if (getChildren().isEmpty()) {
layer.add(myFirstInsertFeedback);
}
else {
@@ -57,6 +57,10 @@ public abstract class FlowBaseOperation extends AbstractEditOperation {
}
}
+ protected List getChildren() {
+ return myContainer.getChildren();
+ }
+
protected void createInsertFeedback() {
myInsertFeedback = new LineInsertFeedback(Color.green, !myHorizontal);
myInsertFeedback.size(myBounds.width, myBounds.height);
@@ -71,28 +75,17 @@ public abstract class FlowBaseOperation extends AbstractEditOperation {
public void showFeedback() {
createFeedback();
- if (!myContainer.getChildren().isEmpty()) {
+ List children = getChildren();
+ if (!children.isEmpty()) {
FeedbackLayer layer = myContext.getArea().getFeedbackLayer();
Point location = myContext.getLocation();
myChildTarget = null;
if (myHorizontal) {
- for (RadComponent child : myContainer.getChildren()) {
- Rectangle childBounds = getBounds(child, layer);
- if (childBounds.x <= location.x && location.x <= childBounds.getMaxX()) {
- myChildTarget = child;
- break;
- }
- }
+ handleHorizontal(children, layer, location);
}
else {
- for (RadComponent child : myContainer.getChildren()) {
- Rectangle childBounds = getBounds(child, layer);
- if (childBounds.y <= location.y && location.y <= childBounds.getMaxY()) {
- myChildTarget = child;
- break;
- }
- }
+ handleVertical(children, layer, location);
}
if (myChildTarget == null) {
myChildTarget = getSideChildTarget();
@@ -106,6 +99,26 @@ public abstract class FlowBaseOperation extends AbstractEditOperation {
}
}
+ protected void handleHorizontal(List children, FeedbackLayer layer, Point location) {
+ for (RadComponent child : children) {
+ Rectangle childBounds = getBounds(child, layer);
+ if (childBounds.x <= location.x && location.x <= childBounds.getMaxX()) {
+ myChildTarget = child;
+ break;
+ }
+ }
+ }
+
+ protected void handleVertical(List children, FeedbackLayer layer, Point location) {
+ for (RadComponent child : children) {
+ Rectangle childBounds = getBounds(child, layer);
+ if (childBounds.y <= location.y && location.y <= childBounds.getMaxY()) {
+ myChildTarget = child;
+ break;
+ }
+ }
+ }
+
protected void setInsertFeedbackBounds(Rectangle targetBounds) {
if (myHorizontal) {
if (myInsertBefore) {
@@ -131,7 +144,7 @@ public abstract class FlowBaseOperation extends AbstractEditOperation {
private RadComponent getSideChildTarget() {
Point location = myContext.getLocation();
- List children = myContainer.getChildren();
+ List children = getChildren();
RadComponent lastChild = children.get(children.size() - 1);
Rectangle childBounds = lastChild.getBounds(myContext.getArea().getFeedbackLayer());
diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/tools/SelectionTool.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/tools/SelectionTool.java
index eed759966137..e6e6b05f92f1 100644
--- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/tools/SelectionTool.java
+++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/designSurface/tools/SelectionTool.java
@@ -22,6 +22,7 @@ import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.ActionPopupMenu;
import org.jetbrains.annotations.Nullable;
+import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
@@ -75,7 +76,8 @@ public class SelectionTool extends InputTool {
}
}
else {
- setTracker(component.getDragTracker());
+ Point location = component.convertPoint(myArea.getNativeComponent(), myCurrentScreenX, myCurrentScreenY);
+ setTracker(component.getDragTracker(location, myArea.isTree()));
}
}
}
diff --git a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java
index 632e389b7c70..38115576a7f7 100644
--- a/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java
+++ b/plugins/ui-designer/ui-designer-new/src/com/intellij/designer/model/RadComponent.java
@@ -138,7 +138,7 @@ public abstract class RadComponent extends PropertiesContainer {
return null;
}
- public InputTool getDragTracker() {
+ public InputTool getDragTracker(Point location, boolean isTree) {
return new DragTracker(this);
}
diff --git a/resources/src/META-INF/IdeaPlugin.xml b/resources/src/META-INF/IdeaPlugin.xml
index 99fc80a5159c..debd34b9ffad 100644
--- a/resources/src/META-INF/IdeaPlugin.xml
+++ b/resources/src/META-INF/IdeaPlugin.xml
@@ -254,6 +254,8 @@
+
diff --git a/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlTagTreeElement.java b/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlTagTreeElement.java
index e46a5b286192..a2ecfd7cecac 100644
--- a/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlTagTreeElement.java
+++ b/xml/impl/src/com/intellij/ide/structureView/impl/xml/XmlTagTreeElement.java
@@ -89,7 +89,7 @@ public class XmlTagTreeElement extends AbstractXmlTagTreeElement{
}
@Nullable
- protected static String toCanonicalForm(@Nullable String id) {
+ public static String toCanonicalForm(@Nullable String id) {
if (id != null) {
id = id.trim();
if (id.length() == 0) id = null;
diff --git a/xml/impl/src/com/intellij/lang/html/HtmlStructureViewBuilderProvider.java b/xml/impl/src/com/intellij/lang/html/HtmlStructureViewBuilderProvider.java
deleted file mode 100644
index 19a063d59ce7..000000000000
--- a/xml/impl/src/com/intellij/lang/html/HtmlStructureViewBuilderProvider.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package com.intellij.lang.html;
-
-import com.intellij.ide.highlighter.HtmlFileType;
-import com.intellij.ide.structureView.StructureViewBuilder;
-import com.intellij.ide.structureView.StructureViewModel;
-import com.intellij.ide.structureView.StructureViewTreeElement;
-import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
-import com.intellij.ide.structureView.impl.xml.XmlStructureViewTreeModel;
-import com.intellij.ide.structureView.xml.XmlStructureViewBuilderProvider;
-import com.intellij.ide.util.treeView.smartTree.Sorter;
-import com.intellij.psi.xml.XmlDocument;
-import com.intellij.psi.xml.XmlFile;
-import com.intellij.psi.xml.XmlTag;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-public class HtmlStructureViewBuilderProvider implements XmlStructureViewBuilderProvider {
- @Nullable
- public StructureViewBuilder createStructureViewBuilder(@NotNull final XmlFile file) {
- if (file.getViewProvider().getVirtualFile().getFileType() != HtmlFileType.INSTANCE) return null;
-
- return new TreeBasedStructureViewBuilder() {
- public boolean isRootNodeShown() {
- return false;
- }
-
- @NotNull
- public StructureViewModel createStructureViewModel() {
- return new XmlStructureViewTreeModel(file) {
- @NotNull
- public Sorter[] getSorters() {
- return Sorter.EMPTY_ARRAY;
- }
-
- @NotNull
- public StructureViewTreeElement getRoot() {
- final XmlDocument document = ((XmlFile)getPsiFile()).getDocument();
- final XmlTag rootTag = document == null ? null : document.getRootTag();
-
- if (rootTag != null && "html".equalsIgnoreCase(rootTag.getLocalName())) {
- final XmlTag[] subTags = rootTag.getSubTags();
- if (subTags.length == 1 &&
- ("head".equalsIgnoreCase(subTags[0].getLocalName()) || "body".equalsIgnoreCase(subTags[0].getLocalName()))) {
- return new HtmlStructureViewElementProvider.HtmlTagTreeElement(subTags[0]);
- }
-
- return new HtmlStructureViewElementProvider.HtmlTagTreeElement(rootTag);
- }
-
- return super.getRoot();
- }
- };
- }
- };
- }
-}
diff --git a/xml/impl/src/com/intellij/lang/html/HtmlStructureViewElementProvider.java b/xml/impl/src/com/intellij/lang/html/HtmlStructureViewElementProvider.java
deleted file mode 100644
index c6adcfd9e71f..000000000000
--- a/xml/impl/src/com/intellij/lang/html/HtmlStructureViewElementProvider.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.intellij.lang.html;
-
-import com.intellij.ide.IdeBundle;
-import com.intellij.ide.highlighter.HtmlFileType;
-import com.intellij.ide.structureView.StructureViewTreeElement;
-import com.intellij.ide.structureView.impl.xml.XmlTagTreeElement;
-import com.intellij.ide.structureView.xml.XmlStructureViewElementProvider;
-import com.intellij.navigation.LocationPresentation;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.psi.xml.XmlTag;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-
-import java.util.Collections;
-import java.util.List;
-
-public class HtmlStructureViewElementProvider implements XmlStructureViewElementProvider {
-
- private static int MAX_TEXT_LENGTH = 50;
-
- @Nullable
- public StructureViewTreeElement createCustomXmlTagTreeElement(@NotNull final XmlTag tag) {
- if (tag.getContainingFile().getViewProvider().getVirtualFile().getFileType() != HtmlFileType.INSTANCE) return null;
-
- return new HtmlTagTreeElement(tag);
- }
-
- static class HtmlTagTreeElement extends XmlTagTreeElement implements LocationPresentation {
- public HtmlTagTreeElement(final XmlTag tag) {
- super(tag);
- }
-
- public String getPresentableText() {
- final XmlTag tag = getElement();
- if (tag == null) return IdeBundle.message("node.structureview.invalid");
-
- final String id = toCanonicalForm(tag.getAttributeValue("id"));
-
- final String classValue = tag.getAttributeValue("class");
- final List classValues = classValue != null ? StringUtil.split(classValue, " ") : Collections.emptyList();
-
- final StringBuilder text = new StringBuilder(tag.getLocalName());
-
- if (id != null) {
- text.append("#").append(id);
- }
-
- if (!classValues.isEmpty()) {
- text.append('.').append(StringUtil.join(classValues, "."));
- }
-
- return text.toString();
- }
-
- public String getLocationString() {
- final XmlTag tag = getElement();
- if (tag == null) return null;
-
- final String text = normalizeSpaces(tag.getValue().getTrimmedText());
- return text.isEmpty() ? null : shortenTextIfLong(text);
- }
-
- public boolean isSearchInLocationString() {
- return true;
- }
-
- private static String normalizeSpaces(final String text) {
- final StringBuilder buf = new StringBuilder();
-
- for (char ch : text.toCharArray()) {
- if (ch <= ' ' || Character.isSpaceChar(ch)) {
- if (buf.length() == 0 || buf.charAt(buf.length() - 1) != ' ') {
- buf.append(' ');
- }
- }
- else {
- buf.append(ch);
- }
- }
-
- return buf.toString();
- }
-
- private static String shortenTextIfLong(final String text) {
- if (text.length() <= MAX_TEXT_LENGTH) return text;
-
- int index;
- for (index = MAX_TEXT_LENGTH; index > MAX_TEXT_LENGTH - 20; index--) {
- if (!Character.isLetter(text.charAt(index))) {
- break;
- }
- }
-
- final int endIndex = Character.isLetter(index) ? MAX_TEXT_LENGTH : index;
- return text.substring(0, endIndex) + "...";
- }
-
- public String getLocationPrefix() {
- return " ";
- }
-
- public String getLocationSuffix() {
- return "";
- }
- }
-}
diff --git a/xml/impl/src/com/intellij/lang/html/structureView/Html5SectionTreeElement.java b/xml/impl/src/com/intellij/lang/html/structureView/Html5SectionTreeElement.java
new file mode 100644
index 000000000000..76b240e4f9c7
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/structureView/Html5SectionTreeElement.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2000-2013 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.lang.html.structureView;
+
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.impl.common.PsiTreeElementBase;
+import com.intellij.openapi.util.Computable;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Collection;
+
+class Html5SectionTreeElement extends PsiTreeElementBase {
+
+ private final Computable> myChildrenComputable;
+ private final String myHeader;
+
+ public Html5SectionTreeElement(final XmlTag tag, final Computable> childrenComputable, final @Nullable String header) {
+ super(tag);
+ myChildrenComputable = childrenComputable;
+ myHeader = header;
+ }
+
+ @NotNull
+ public Collection getChildrenBase() {
+ return myChildrenComputable.compute();
+ }
+
+ public String getPresentableText() {
+ if (myHeader != null) {
+ return HtmlTagTreeElement.normalizeSpacesAndShortenIfLong(myHeader);
+ }
+
+ final XmlTag tag = getElement();
+ return tag == null ? null : HtmlTagTreeElement.normalizeSpacesAndShortenIfLong(tag.getValue().getTrimmedText());
+ }
+
+ public String getLocationString() {
+ final XmlTag tag = getElement();
+ if (tag == null) return null;
+
+ return HtmlTagTreeElement.getTagPresentation(tag);
+ }
+
+ public boolean isSearchInLocationString() {
+ return true;
+ }
+}
diff --git a/xml/impl/src/com/intellij/lang/html/structureView/Html5SectionsNodeProvider.java b/xml/impl/src/com/intellij/lang/html/structureView/Html5SectionsNodeProvider.java
new file mode 100644
index 000000000000..184ceee58859
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/structureView/Html5SectionsNodeProvider.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright 2000-2013 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.lang.html.structureView;
+
+import com.intellij.ide.util.FileStructureNodeProvider;
+import com.intellij.ide.util.treeView.smartTree.ActionPresentation;
+import com.intellij.ide.util.treeView.smartTree.ActionPresentationData;
+import com.intellij.ide.util.treeView.smartTree.TreeElement;
+import com.intellij.openapi.actionSystem.Shortcut;
+import com.intellij.openapi.keymap.KeymapManager;
+import com.intellij.openapi.util.PropertyOwner;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.xml.XmlBundle;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+
+public class Html5SectionsNodeProvider implements FileStructureNodeProvider, PropertyOwner {
+
+ public static final String ACTION_ID = "HTML5_OUTLINE_MODE";
+ public static final String HTML5_OUTLINE_PROVIDER_PROPERTY = "html5.sections.node.provider";
+
+ @NotNull
+ public String getName() {
+ return ACTION_ID;
+ }
+
+ @NotNull
+ public ActionPresentation getPresentation() {
+ return new ActionPresentationData(XmlBundle.message("html5.outline.mode"), null, null);
+ }
+
+ public String getCheckBoxText() {
+ return XmlBundle.message("html5.outline.mode");
+ }
+
+ public Shortcut[] getShortcut() {
+ return KeymapManager.getInstance().getActiveKeymap().getShortcuts("FileStructurePopup");
+ }
+
+ @NotNull
+ public String getPropertyName() {
+ return HTML5_OUTLINE_PROVIDER_PROPERTY;
+ }
+
+ public Collection provideNodes(final TreeElement node) {
+ if (!(node instanceof HtmlFileTreeElement)) return Collections.emptyList();
+
+ final XmlFile xmlFile = ((HtmlFileTreeElement)node).getElement();
+ final XmlTag rootTag = xmlFile == null ? null : xmlFile.getRootTag();
+ if (rootTag == null) return Collections.emptyList();
+
+ return Html5SectionsProcessor.processAndGetRootSections(rootTag);
+ }
+}
diff --git a/xml/impl/src/com/intellij/lang/html/structureView/Html5SectionsProcessor.java b/xml/impl/src/com/intellij/lang/html/structureView/Html5SectionsProcessor.java
new file mode 100644
index 000000000000..0b9f5cb35003
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/structureView/Html5SectionsProcessor.java
@@ -0,0 +1,289 @@
+/*
+ * Copyright 2000-2013 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.lang.html.structureView;
+
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.openapi.util.Computable;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.containers.SortedList;
+import com.intellij.util.containers.Stack;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.LinkedList;
+
+
+// Algorithm described at http://www.w3.org/html/wg/drafts/html/master/sections.html#outlines
+// One of implementations: http://hoyois.github.com/html5outliner/ (https://github.com/hoyois/html5outliner)
+class Html5SectionsProcessor {
+
+ private static class SectionHolder {
+ private final XmlTag myTag;
+ private LinkedList myChildren = new LinkedList();
+
+ private SectionHolder(final XmlTag tag) {
+ myTag = tag;
+ }
+
+ public void addChildSection(final Section section) {
+ myChildren.add(section);
+ }
+
+ public LinkedList getChildren() {
+ return myChildren;
+ }
+
+ public XmlTag getTag() {
+ return myTag;
+ }
+ }
+
+ private static class Section extends SectionHolder {
+ private Section myParent = null;
+ private XmlTag myHeader = null;
+
+ public Section(final XmlTag tag) {
+ super(tag);
+ }
+
+ public void addChildSection(final Section section) {
+ section.myParent = this;
+ super.addChildSection(section);
+ }
+
+ public XmlTag getHeader() {
+ return myHeader;
+ }
+
+ public void setHeader(final XmlTag header) {
+ myHeader = header;
+ }
+
+ public Section getParent() {
+ return myParent;
+ }
+ }
+
+ private static final String[] SECTIONING_ROOT_ELEMENTS = {"blockquote", "body", "details", "dialog", "fieldset", "figure", "td"};
+ private static final String[] SECTIONING_CONTENT_ELEMENTS = {"article", "aside", "nav", "section"};
+ private static final String[] HEADER_ELEMENTS = {"h1", "h2", "h3", "h4", "h5", "h6"};
+ private static final String HGROUP_ELEMENT = "hgroup";
+
+ private final Collection myRootSectionHolders = new SortedList(new Comparator() {
+ public int compare(final SectionHolder first, final SectionHolder second) {
+ return first.getTag().getTextRange().getStartOffset() - second.getTag().getTextRange().getStartOffset();
+ }
+ });
+
+ private SectionHolder myCurrentOutlinee = null;
+ private Section myCurrentSection = null;
+ private final Stack myStack = new Stack();
+
+ public static Collection processAndGetRootSections(final XmlTag rootTag) {
+ final Html5SectionsProcessor processor = new Html5SectionsProcessor();
+ processRecursively(rootTag, processor);
+ return processor.getRootSections();
+ }
+
+ private static void processRecursively(final XmlTag tag, final Html5SectionsProcessor processor) {
+ if (tag.getAttribute("hidden") != null) return;
+
+ processor.tagEntered(tag);
+
+ if (!isHeader(tag)) {
+ for (final XmlTag subTag : tag.getSubTags()) {
+ processRecursively(subTag, processor);
+ }
+ }
+
+ processor.tagExited(tag);
+ }
+
+ private void tagEntered(final XmlTag tag) {
+ if (isSectioningContentElement(tag) || isSectioningRootElement(tag)) {
+ if (myCurrentOutlinee != null) {
+ myStack.push(myCurrentOutlinee);
+ }
+
+ myCurrentOutlinee = new SectionHolder(tag);
+ myCurrentSection = new Section(tag);
+ myCurrentOutlinee.addChildSection(myCurrentSection);
+ }
+ else if (myCurrentOutlinee == null) {
+ // do nothing
+ }
+ else if (isHeader(tag)) {
+ if (myCurrentSection.getHeader() == null) {
+ myCurrentSection.setHeader(tag);
+ }
+ else if (myCurrentOutlinee.getChildren().getLast().getHeader() == null ||
+ compareHeaderRanks(tag, myCurrentOutlinee.getChildren().getLast().getHeader()) >= 0) {
+ myCurrentSection = new Section(tag);
+ myCurrentSection.setHeader(tag);
+ myCurrentOutlinee.addChildSection(myCurrentSection);
+ }
+ else {
+ Section candidateSection = myCurrentSection;
+ do {
+ if (compareHeaderRanks(tag, candidateSection.getHeader()) < 0) {
+ myCurrentSection = new Section(tag);
+ myCurrentSection.setHeader(tag);
+ candidateSection.addChildSection(myCurrentSection);
+ break;
+ }
+ candidateSection = candidateSection.getParent();
+ }
+ while (true);
+ }
+ //myStack.push(); not needed, because our iterator doesn't enter hidden elements
+ }
+ }
+
+ private void tagExited(final XmlTag tag) {
+ if (!myStack.isEmpty() && myStack.peek().getTag() == tag) {
+ assert false;
+ }
+ else if (!myStack.isEmpty() && isHeader(tag)) {
+ // do nothing
+ }
+ else if (!myStack.isEmpty() && isSectioningContentElement(tag)) {
+ final SectionHolder exitedSectioningContent = myCurrentOutlinee;
+ assert exitedSectioningContent.getTag() == tag;
+
+ myCurrentOutlinee = myStack.pop();
+ myCurrentSection = myCurrentOutlinee.getChildren().getLast();
+
+ for (Section section : exitedSectioningContent.getChildren()) {
+ myCurrentSection.addChildSection(section);
+ }
+ }
+ else if (!myStack.isEmpty() && isSectioningRootElement(tag)) {
+ final SectionHolder exitedSectioningRoot = myCurrentOutlinee;
+ assert exitedSectioningRoot.getTag() == tag;
+ myRootSectionHolders.add(exitedSectioningRoot);
+
+ myCurrentOutlinee = myStack.pop();
+
+ myCurrentSection = myCurrentOutlinee.getChildren().getLast();
+ while (!myCurrentSection.getChildren().isEmpty()) {
+ myCurrentSection = myCurrentSection.getChildren().getLast();
+ }
+ }
+ else if (isSectioningContentElement(tag) || isSectioningRootElement(tag)) {
+ assert myStack.isEmpty();
+
+ assert myCurrentOutlinee.getTag() == tag;
+ myRootSectionHolders.add(myCurrentOutlinee);
+
+ // reset algorithm
+ myCurrentOutlinee = null;
+ myCurrentSection = null;
+ }
+ }
+
+ private Collection getRootSections() {
+ final Collection result = new ArrayList();
+ for (SectionHolder sectionHolder : myRootSectionHolders) {
+ for (Section section : sectionHolder.getChildren()) {
+ result.add(createHtml5SectionTreeElement(section));
+ }
+ }
+ return result;
+ }
+
+ private static Html5SectionTreeElement createHtml5SectionTreeElement(final Section section) {
+ return new Html5SectionTreeElement(section.getTag(),
+ createChildrenComputable(section.getChildren()),
+ getHeaderText(section.getHeader()));
+ }
+
+ private static Computable> createChildrenComputable(final Collection children) {
+ return new Computable>() {
+ public Collection compute() {
+ final Collection result = new ArrayList();
+ for (Section section : children) {
+ result.add(createHtml5SectionTreeElement(section));
+ }
+ return result;
+ }
+ };
+ }
+
+ private static String getHeaderText(final @Nullable XmlTag header) {
+ if (header == null) return null;
+
+ if (HGROUP_ELEMENT.equalsIgnoreCase(header.getLocalName())) {
+ final StringBuilder buf = new StringBuilder();
+ for (XmlTag subTag : header.getSubTags()) {
+ if (ArrayUtil.contains(subTag.getLocalName().toLowerCase(), HEADER_ELEMENTS)) {
+ if (buf.length() > 0) {
+ buf.append(" ");
+ }
+ buf.append(subTag.getValue().getTrimmedText());
+ }
+ }
+
+ return buf.toString();
+ }
+
+ return header.getValue().getTrimmedText();
+ }
+
+ private static boolean isSectioningRootElement(final XmlTag tag) {
+ return ArrayUtil.contains(tag.getLocalName().toLowerCase(), SECTIONING_ROOT_ELEMENTS);
+ }
+
+ private static boolean isSectioningContentElement(final XmlTag tag) {
+ return ArrayUtil.contains(tag.getLocalName().toLowerCase(), SECTIONING_CONTENT_ELEMENTS);
+ }
+
+ private static boolean isHeader(final XmlTag tag) {
+ return ArrayUtil.contains(tag.getLocalName().toLowerCase(), HEADER_ELEMENTS) || HGROUP_ELEMENT.equalsIgnoreCase(tag.getLocalName());
+ }
+
+ private static int compareHeaderRanks(final @NotNull XmlTag header1, final @NotNull XmlTag header2) {
+ return getHeaderRank(header2) - getHeaderRank(header1);
+ }
+
+ private static int getHeaderRank(final XmlTag header) {
+ if (HGROUP_ELEMENT.equalsIgnoreCase(header.getLocalName())) {
+ int minIndex = HEADER_ELEMENTS.length;
+
+ for (XmlTag subTag : header.getSubTags()) {
+ final int index = ArrayUtil.indexOf(HEADER_ELEMENTS, subTag.getLocalName().toLowerCase());
+ if (index < minIndex) {
+ minIndex = index;
+ if (minIndex == 0) break;
+ }
+ }
+
+ if (minIndex == HEADER_ELEMENTS.length) {
+ // no headers is equivalent to
+ minIndex = 0;
+ }
+
+ return minIndex + 1;
+ }
+
+ final int index = ArrayUtil.indexOf(HEADER_ELEMENTS, header.getLocalName().toLowerCase());
+ if (index < 0) throw new IllegalArgumentException(header.getName());
+ return index + 1;
+ }
+}
diff --git a/xml/impl/src/com/intellij/lang/html/structureView/HtmlFileTreeElement.java b/xml/impl/src/com/intellij/lang/html/structureView/HtmlFileTreeElement.java
new file mode 100644
index 000000000000..07a40704917c
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/structureView/HtmlFileTreeElement.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2000-2013 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.lang.html.structureView;
+
+import com.intellij.ide.structureView.StructureViewFactoryEx;
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.impl.common.PsiTreeElementBase;
+import com.intellij.ide.util.FileStructurePopup;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.psi.xml.XmlDocument;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.psi.xml.XmlTag;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+class HtmlFileTreeElement extends PsiTreeElementBase {
+
+ private final boolean myInStructureViewPopup;
+
+ public HtmlFileTreeElement(final boolean inStructureViewPopup, final XmlFile xmlFile) {
+ super(xmlFile);
+ myInStructureViewPopup = inStructureViewPopup;
+ }
+
+ @NotNull
+ public Collection getChildrenBase() {
+ if (isHtml5SectionsMode()) {
+ return Collections.emptyList(); // Html5SectionsNodeProvider will return its structure
+ }
+
+ final XmlFile xmlFile = getElement();
+ if (xmlFile == null) return Collections.emptyList();
+
+ final XmlDocument document = xmlFile.getDocument();
+ final XmlTag rootTag = document == null ? null : document.getRootTag();
+
+ if (rootTag == null) return Collections.emptyList();
+
+ if ("html".equalsIgnoreCase(rootTag.getLocalName())) {
+ final XmlTag[] subTags = rootTag.getSubTags();
+ if (subTags.length == 1 &&
+ ("head".equalsIgnoreCase(subTags[0].getLocalName()) || "body".equalsIgnoreCase(subTags[0].getLocalName()))) {
+ return new HtmlTagTreeElement(subTags[0]).getChildrenBase();
+ }
+
+ return new HtmlTagTreeElement(rootTag).getChildrenBase();
+ }
+
+ return Arrays.asList(new HtmlTagTreeElement(rootTag));
+ }
+
+ private boolean isHtml5SectionsMode() {
+ final XmlFile xmlFile = getElement();
+ if (xmlFile == null) return false;
+
+ if (myInStructureViewPopup) {
+ final String propertyName = FileStructurePopup.getPropertyName(Html5SectionsNodeProvider.HTML5_OUTLINE_PROVIDER_PROPERTY);
+ if (PropertiesComponent.getInstance().getBoolean(propertyName, false)) {
+ return true;
+ }
+ }
+ else if (StructureViewFactoryEx.getInstanceEx(xmlFile.getProject()).isActionActive(Html5SectionsNodeProvider.ACTION_ID)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ @Nullable
+ public String getPresentableText() {
+ return toString(); // root element is not visible
+ }
+}
diff --git a/xml/impl/src/com/intellij/lang/html/structureView/HtmlStructureViewBuilderProvider.java b/xml/impl/src/com/intellij/lang/html/structureView/HtmlStructureViewBuilderProvider.java
new file mode 100644
index 000000000000..3243fe7db7de
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/structureView/HtmlStructureViewBuilderProvider.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2000-2013 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.lang.html.structureView;
+
+import com.intellij.ide.highlighter.HtmlFileType;
+import com.intellij.ide.structureView.StructureViewBuilder;
+import com.intellij.ide.structureView.StructureViewModel;
+import com.intellij.ide.structureView.TreeBasedStructureViewBuilder;
+import com.intellij.ide.structureView.xml.XmlStructureViewBuilderProvider;
+import com.intellij.psi.xml.XmlFile;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class HtmlStructureViewBuilderProvider implements XmlStructureViewBuilderProvider {
+ @Nullable
+ public StructureViewBuilder createStructureViewBuilder(@NotNull final XmlFile file) {
+ if (file.getViewProvider().getVirtualFile().getFileType() != HtmlFileType.INSTANCE) return null;
+
+ return new TreeBasedStructureViewBuilder() {
+ public boolean isRootNodeShown() {
+ return false;
+ }
+
+ @NotNull
+ public StructureViewModel createStructureViewModel() {
+ return new HtmlStructureViewTreeModel(file);
+ }
+ };
+ }
+}
diff --git a/xml/impl/src/com/intellij/lang/html/structureView/HtmlStructureViewTreeModel.java b/xml/impl/src/com/intellij/lang/html/structureView/HtmlStructureViewTreeModel.java
new file mode 100644
index 000000000000..230a89ae4c26
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/structureView/HtmlStructureViewTreeModel.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2000-2013 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.lang.html.structureView;
+
+import com.intellij.ide.actions.ViewStructureAction;
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.impl.xml.XmlStructureViewTreeModel;
+import com.intellij.ide.util.treeView.smartTree.NodeProvider;
+import com.intellij.ide.util.treeView.smartTree.Sorter;
+import com.intellij.psi.xml.XmlFile;
+import com.intellij.ui.PlaceHolder;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+class HtmlStructureViewTreeModel extends XmlStructureViewTreeModel implements PlaceHolder {
+
+ private final Collection myNodeProviders;
+
+ private String myStructureViewPlace;
+
+ public HtmlStructureViewTreeModel(final XmlFile file) {
+ super(file);
+ myNodeProviders = Arrays.asList(new Html5SectionsNodeProvider());
+ }
+
+ public void setPlace(final String place) {
+ myStructureViewPlace = place;
+ }
+
+ public String getPlace() {
+ return myStructureViewPlace;
+ }
+
+ @NotNull
+ public Sorter[] getSorters() {
+ return Sorter.EMPTY_ARRAY;
+ }
+
+ @NotNull
+ public Collection getNodeProviders() {
+ return myNodeProviders;
+ }
+
+ @NotNull
+ public StructureViewTreeElement getRoot() {
+ return new HtmlFileTreeElement(ViewStructureAction.isInStructureViewPopup(this), (XmlFile)getPsiFile());
+ }
+}
diff --git a/xml/impl/src/com/intellij/lang/html/structureView/HtmlTagTreeElement.java b/xml/impl/src/com/intellij/lang/html/structureView/HtmlTagTreeElement.java
new file mode 100644
index 000000000000..d53bcbcd1daa
--- /dev/null
+++ b/xml/impl/src/com/intellij/lang/html/structureView/HtmlTagTreeElement.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2000-2013 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.lang.html.structureView;
+
+import com.intellij.ide.IdeBundle;
+import com.intellij.ide.structureView.StructureViewTreeElement;
+import com.intellij.ide.structureView.impl.common.PsiTreeElementBase;
+import com.intellij.ide.structureView.impl.xml.XmlTagTreeElement;
+import com.intellij.navigation.LocationPresentation;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.psi.xml.XmlTag;
+import com.intellij.util.Function;
+import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+class HtmlTagTreeElement extends PsiTreeElementBase implements LocationPresentation {
+ private static final int MAX_TEXT_LENGTH = 50;
+
+ public HtmlTagTreeElement(final XmlTag tag) {
+ super(tag);
+ }
+
+ @NotNull
+ public Collection getChildrenBase() {
+ final XmlTag tag = getElement();
+ if (tag == null || !tag.isValid()) return Collections.emptyList();
+
+ return ContainerUtil.map2List(tag.getSubTags(), new Function() {
+ public StructureViewTreeElement fun(final XmlTag subTag) {
+ return new HtmlTagTreeElement(subTag);
+ }
+ });
+ }
+
+ public String getPresentableText() {
+ final XmlTag tag = getElement();
+ if (tag == null) return IdeBundle.message("node.structureview.invalid");
+
+ return getTagPresentation(tag);
+ }
+
+ public String getLocationString() {
+ final XmlTag tag = getElement();
+ if (tag == null) return null;
+
+ final String text = normalizeSpacesAndShortenIfLong(tag.getValue().getTrimmedText());
+ return text.isEmpty() ? null : text;
+ }
+
+ public boolean isSearchInLocationString() {
+ return true;
+ }
+
+ public static String getTagPresentation(final @NotNull XmlTag tag) {
+ final String id = XmlTagTreeElement.toCanonicalForm(tag.getAttributeValue("id"));
+
+ final String classValue = tag.getAttributeValue("class");
+ final List classValues = classValue != null ? StringUtil.split(classValue, " ") : Collections.emptyList();
+
+ final StringBuilder text = new StringBuilder(tag.getLocalName());
+
+ if (id != null) {
+ text.append("#").append(id);
+ }
+
+ if (!classValues.isEmpty()) {
+ text.append('.').append(StringUtil.join(classValues, "."));
+ }
+
+ return text.toString();
+ }
+
+ @NotNull
+ public static String normalizeSpacesAndShortenIfLong(final @NotNull String text) {
+ return shortenTextIfLong(normalizeSpaces(text));
+ }
+
+ private static String normalizeSpaces(final String text) {
+ final StringBuilder buf = new StringBuilder();
+
+ for (char ch : text.toCharArray()) {
+ if (ch <= ' ' || Character.isSpaceChar(ch)) {
+ if (buf.length() == 0 || buf.charAt(buf.length() - 1) != ' ') {
+ buf.append(' ');
+ }
+ }
+ else {
+ buf.append(ch);
+ }
+ }
+
+ return buf.toString();
+ }
+
+ private static String shortenTextIfLong(final String text) {
+ if (text.length() <= MAX_TEXT_LENGTH) return text;
+
+ int index;
+ for (index = MAX_TEXT_LENGTH; index > MAX_TEXT_LENGTH - 20; index--) {
+ if (!Character.isLetter(text.charAt(index))) {
+ break;
+ }
+ }
+
+ final int endIndex = Character.isLetter(index) ? MAX_TEXT_LENGTH : index;
+ return text.substring(0, endIndex) + "...";
+ }
+
+ public String getLocationPrefix() {
+ return " ";
+ }
+
+ public String getLocationSuffix() {
+ return "";
+ }
+}
diff --git a/xml/tests/src/com/intellij/xml/structureView/HtmlFileStructureTest.java b/xml/tests/src/com/intellij/xml/structureView/HtmlFileStructureTest.java
new file mode 100644
index 000000000000..d3d79b2b34e1
--- /dev/null
+++ b/xml/tests/src/com/intellij/xml/structureView/HtmlFileStructureTest.java
@@ -0,0 +1,48 @@
+package com.intellij.xml.structureView;
+
+import com.intellij.ide.util.FileStructurePopup;
+import com.intellij.ide.util.PropertiesComponent;
+import com.intellij.lang.html.structureView.Html5SectionsNodeProvider;
+import com.intellij.testFramework.FileStructureTestBase;
+
+public class HtmlFileStructureTest extends FileStructureTestBase {
+
+ private boolean myHtml5OutlineModeDefault;
+
+ public void setUp() throws Exception {
+ super.setUp();
+ myHtml5OutlineModeDefault = PropertiesComponent.getInstance().getBoolean(getHtml5OutlineModePropertyName(), false);
+ setHtml5OutlineMode(true);
+ }
+
+ public void tearDown() throws Exception {
+ PropertiesComponent.getInstance().setValue(getHtml5OutlineModePropertyName(), String.valueOf(myHtml5OutlineModeDefault));
+ super.tearDown();
+ }
+
+ private static String getHtml5OutlineModePropertyName() {
+ return FileStructurePopup.getPropertyName(Html5SectionsNodeProvider.HTML5_OUTLINE_PROVIDER_PROPERTY);
+ }
+
+ protected String getFileExtension() {
+ return "html";
+ }
+
+ protected String getBasePath() {
+ return "/xml/tests/testData/structureView/";
+ }
+
+ protected boolean isCommunity() {
+ return true;
+ }
+
+ public void setHtml5OutlineMode(boolean enabled) throws Exception {
+ myPopup.setTreeActionState(Html5SectionsNodeProvider.class, enabled);
+ update();
+ }
+
+ public void testEmpty() throws Exception {checkTree();}
+ public void testSimple() throws Exception {checkTree();}
+ public void testNoSectioningRoot() throws Exception {checkTree();}
+ public void testImplicitSections() throws Exception {checkTree();}
+}
diff --git a/xml/tests/testData/structureView/Empty.html b/xml/tests/testData/structureView/Empty.html
new file mode 100644
index 000000000000..e69de29bb2d1
diff --git a/xml/tests/testData/structureView/Empty.tree b/xml/tests/testData/structureView/Empty.tree
new file mode 100644
index 000000000000..becaf0af7fde
--- /dev/null
+++ b/xml/tests/testData/structureView/Empty.tree
@@ -0,0 +1 @@
++HtmlFile:Empty.html
\ No newline at end of file
diff --git a/xml/tests/testData/structureView/ImplicitSections.html b/xml/tests/testData/structureView/ImplicitSections.html
new file mode 100644
index 000000000000..32314bf6729f
--- /dev/null
+++ b/xml/tests/testData/structureView/ImplicitSections.html
@@ -0,0 +1,47 @@
+
+
+
+
section
+ h5
+ h4
+ h3
+
+
hh4
+ hh5
+
+
+
+ h4
+
+ h3
+
+
hh4
+
hh3
+
+
+
+
+
+
hhh2
+ hhh1
+
+
+
+
+
+ hh6
+ hhh6
+
+ hhh5
+ g4
+ g6
+ g3
+ g2
+
+
+
body
+
+body2
+body3
+
+
\ No newline at end of file
diff --git a/xml/tests/testData/structureView/ImplicitSections.tree b/xml/tests/testData/structureView/ImplicitSections.tree
new file mode 100644
index 000000000000..9903463aa790
--- /dev/null
+++ b/xml/tests/testData/structureView/ImplicitSections.tree
@@ -0,0 +1,24 @@
+-HtmlFile:ImplicitSections.html
+ -body
+ -[section]
+ h5
+ h4
+ -h3
+ -hh4
+ hh5
+ -h4 h3
+ hh4
+ hh3
+ hh6
+ hhh6
+ hhh5
+ -g4
+ g6
+ g3
+ g2
+ -body2
+ body3
+ -
+ -
+ hhh2
+ hhh1
\ No newline at end of file
diff --git a/xml/tests/testData/structureView/NoSectioningRoot.html b/xml/tests/testData/structureView/NoSectioningRoot.html
new file mode 100644
index 000000000000..d0b4849a0d9b
--- /dev/null
+++ b/xml/tests/testData/structureView/NoSectioningRoot.html
@@ -0,0 +1,17 @@
+
+ blockquote
+ body
+ details
+ dialog
+ fieldset
+ figure
+ td
+
+
+ 1
+ 2
+
+ 3
+ 4
+
+
\ No newline at end of file
diff --git a/xml/tests/testData/structureView/NoSectioningRoot.tree b/xml/tests/testData/structureView/NoSectioningRoot.tree
new file mode 100644
index 000000000000..e63bb3297a2e
--- /dev/null
+++ b/xml/tests/testData/structureView/NoSectioningRoot.tree
@@ -0,0 +1,9 @@
+-HtmlFile:NoSectioningRoot.html
+ [1 2 3 4]
+ blockquote
+ body
+ details
+ dialog
+ fieldset
+ figure
+ td
\ No newline at end of file
diff --git a/xml/tests/testData/structureView/Simple.html b/xml/tests/testData/structureView/Simple.html
new file mode 100644
index 000000000000..cb128240b9a9
--- /dev/null
+++ b/xml/tests/testData/structureView/Simple.html
@@ -0,0 +1,6 @@
+
+title
+
+
+
+
\ No newline at end of file
diff --git a/xml/tests/testData/structureView/Simple.tree b/xml/tests/testData/structureView/Simple.tree
new file mode 100644
index 000000000000..4f8e03e31bd5
--- /dev/null
+++ b/xml/tests/testData/structureView/Simple.tree
@@ -0,0 +1,2 @@
+-HtmlFile:Simple.html
+ []
\ No newline at end of file