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-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/impl/file/impl/PsiVFSListener.java b/platform/lang-impl/src/com/intellij/psi/impl/file/impl/PsiVFSListener.java index 68079c75381f..a6427f42e510 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); 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/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxCommonClassNames.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxCommonClassNames.java index 78f185b6a31a..051b427e3de9 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxCommonClassNames.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxCommonClassNames.java @@ -31,4 +31,5 @@ public class JavaFxCommonClassNames { @NonNls public static final String JAVAFX_EVENT_EVENT_HANDLER = "javafx.event.EventHandler"; @NonNls public static final String JAVAFX_SCENE_NODE = "javafx.scene.Node"; @NonNls public static final String JAVAFX_SCENE_PAINT = "javafx.scene.paint.Paint"; + @NonNls public static final String JAVAFX_FXML_BUILDER = "javafx.util.Builder"; } diff --git a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java index ec1e699473cc..9941ea92b390 100644 --- a/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java +++ b/plugins/javaFX/src/org/jetbrains/plugins/javaFX/fxml/JavaFxPsiUtil.java @@ -21,6 +21,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.*; import com.intellij.psi.impl.source.PostprocessReformattingAspect; +import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PropertyUtil; import com.intellij.psi.util.PsiTreeUtil; @@ -82,7 +83,11 @@ public class JavaFxPsiUtil { } public static PsiClass findPsiClass(String name, XmlTag tag) { - return findPsiClass(name, parseImports((XmlFile)tag.getContainingFile()), tag, tag.getProject()); + final Project project = tag.getProject(); + if (!StringUtil.getShortName(name).equals(name)) { + return JavaPsiFacade.getInstance(project).findClass(name, GlobalSearchScope.allScope(project)); + } + return findPsiClass(name, parseImports((XmlFile)tag.getContainingFile()), tag, project); } private static PsiClass findPsiClass(String name, List imports, XmlTag tag, Project project) { @@ -155,7 +160,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) { 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/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/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/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/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java b/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java index 701e1beb9fa6..236ca1a6a877 100644 --- a/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java +++ b/plugins/javaFX/testSrc/org/jetbrains/plugins/javaFX/fxml/JavaFXHighlightingTest.java @@ -151,6 +151,14 @@ public class JavaFXHighlightingTest extends DaemonAnalyzerTestCase { doTest(); } + public void testInstantiationAcceptance() throws Exception { + doTest(); + } + + public void testFQNtagNames() throws Exception { + doTest(); + } + @NotNull @Override protected String getTestDataPath() {