Javafx: Fix highlighting and completion for css file names in FXML stylesheets property, both attribute and tag. Tests added (IDEA-154244)

This commit is contained in:
Pavel Dolgov
2016-04-08 13:00:39 +03:00
parent a724ae1d5c
commit 1cde5021be
11 changed files with 100 additions and 25 deletions
@@ -432,6 +432,18 @@ public class JavaFXHighlightingTest extends AbstractJavaFXTestCase {
doTest();
}
public void testMultipleStylesheetsAttribute() throws Exception {
myFixture.addFileToProject("mystyle.css", ".myStyle {}");
myFixture.addFileToProject("very/deeply/located/small.css", ".small {}");
doTest();
}
public void testMultipleStylesheetsTag() throws Exception {
myFixture.addFileToProject("mystyle.css", ".myStyle {}");
myFixture.addFileToProject("very/deeply/located/small.css", ".small {}");
doTest();
}
private void doTest() throws Exception {
myFixture.testHighlighting(false, false, false, getTestName(true) + ".fxml");
}
@@ -271,6 +271,18 @@ public class JavaFxCompletionTest extends LightFixtureCompletionTestCase {
assertSameElements(myFixture.getLookupElementStrings(), "MY_TEXT", "SUPER_TEXT");
}
public void testMultipleStylesheetsAttribute() throws Exception {
myFixture.addFileToProject("mystyle.css", ".myStyle {}");
myFixture.addFileToProject("very/deeply/located/small.css", ".small {}");
doTest();
}
public void testMultipleStylesheetsTag() throws Exception {
myFixture.addFileToProject("mystyle.css", ".myStyle {}");
myFixture.addFileToProject("very/deeply/located/small.css", ".small {}");
doTest();
}
private void configureAndComplete(final String... extraFiles) {
final String fxmlFileName = getTestName(true) + ".fxml";
if (extraFiles.length != 0) {
@@ -45,7 +45,8 @@ public class FxmlConstants {
@NonNls public static final String STYLE_CLASS = "styleClass";
@NonNls public static final String STYLESHEETS = "stylesheets";
@NonNls public static final String URL = "url";
@NonNls public static final String URL_ATTR = "url";
@NonNls public static final String URL_TAG = "URL";
@NonNls public static final String SOURCE = "source";
@@ -91,7 +91,7 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
new JavaFxEventHandlerReferenceProvider());
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withValue(string().startsWith("@")).and(attributeValueInFxml),
new JavaFxLocationReferenceProvider());
new JavaFxLocationReferenceProvider(), PsiReferenceRegistrar.LOWER_PRIORITY);
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withValue(string().startsWith("$"))
.withParent(XmlPatterns.xmlAttribute()
@@ -99,13 +99,21 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
.and(attributeValueInFxml),
new JavaFxComponentIdReferenceProvider());
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.URL))
.andNot(XmlPatterns.xmlAttributeValue().withValue(string().matches("^http(s)?://.*")))
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue()
.withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.URL_ATTR))
.andNot(XmlPatterns.xmlAttributeValue().withValue(string().matches("^https?://.*")))
.and(attributeValueInFxml),
new JavaFxLocationReferenceProvider(false, "png", "jpg", "gif", "bmp"));
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.STYLESHEETS)).and(attributeValueInFxml),
new JavaFxLocationReferenceProvider(true, "css"));
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withValue(string().startsWith("@"))
.withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.VALUE)
.withParent(XmlPatterns.xmlTag().withName(FxmlConstants.URL_TAG)
.withParent(XmlPatterns.xmlTag().withName(FxmlConstants.STYLESHEETS))))
.and(attributeValueInFxml),
new JavaFxLocationReferenceProvider(false, "css"));
registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlProcessingInstruction.class).inVirtualFile(virtualFile().withExtension(JavaFxFileTypeFactory.FXML_EXTENSION)),
new ImportReferenceProvider());
@@ -18,6 +18,7 @@ package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
@@ -55,31 +56,32 @@ class JavaFxLocationReferenceProvider extends PsiReferenceProvider {
public PsiReference[] getReferencesByElement(@NotNull final PsiElement element,
@NotNull ProcessingContext context) {
final String value = ((XmlAttributeValue)element).getValue();
if (value.startsWith("@")) {
return new FileReferenceSet(value.substring(1), element, 2, null, true).getAllReferences();
if (mySupportCommaInValue && value.contains(",")) {
int startIdx = 0;
List<PsiReference> refs = new ArrayList<PsiReference>();
while (true) {
int endIdx = value.indexOf(',', startIdx);
final String item = endIdx >= 0 ? value.substring(startIdx, endIdx) : value.substring(startIdx);
Collections.addAll(refs, collectRefs(element, item, startIdx + 1));
if (endIdx < 0) {
break;
}
startIdx = endIdx + 1;
}
return refs.toArray(PsiReference.EMPTY_ARRAY);
}
else {
if (mySupportCommaInValue && value.contains(",")) {
int startIdx = 0;
int endIdx = 0;
List<PsiReference> refs = new ArrayList<PsiReference>();
while (true) {
endIdx = value.indexOf(",", startIdx);
Collections.addAll(refs, collectRefs(element, endIdx >= 0 ? value.substring(startIdx, endIdx) : value.substring(startIdx), startIdx + 1, myAcceptedFileTypes));
startIdx = endIdx + 1;
if (endIdx < 0) {
break;
}
}
return refs.toArray(new PsiReference[refs.size()]);
} else {
return collectRefs(element, value, 1, myAcceptedFileTypes);
}
return collectRefs(element, value, 1);
}
}
private static PsiReference[] collectRefs(@NotNull PsiElement element, String value, final int startInElement, final FileType... acceptedFileTypes) {
final FileReferenceSet set = new FileReferenceSet(value, element, startInElement, null, true){
private PsiReference[] collectRefs(@NotNull PsiElement element, String value, int startInElement) {
final int atSignIndex = value.indexOf('@');
if (atSignIndex >= 0 && (atSignIndex == 0 || StringUtil.trimLeading(value).startsWith("@"))) {
value = value.substring(atSignIndex + 1);
startInElement += atSignIndex + 1;
}
final FileReferenceSet set = new FileReferenceSet(value, element, startInElement, null, true) {
@Override
protected Condition<PsiFileSystemItem> getReferenceCompletionFilter() {
return new Condition<PsiFileSystemItem>() {
@@ -89,7 +91,7 @@ class JavaFxLocationReferenceProvider extends PsiReferenceProvider {
final VirtualFile virtualFile = item.getVirtualFile();
if (virtualFile == null) return false;
final FileType fileType = virtualFile.getFileType();
return ArrayUtilRt.find(acceptedFileTypes, fileType) >= 0;
return ArrayUtilRt.find(myAcceptedFileTypes, fileType) >= 0;
}
};
}
@@ -0,0 +1,4 @@
<?import javafx.scene.layout.GridPane?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
fx:id="myGridPane" stylesheets="@mystyle.css, @very/deeply/located/<caret>">
</GridPane>
@@ -0,0 +1,4 @@
<?import javafx.scene.layout.GridPane?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
fx:id="myGridPane" stylesheets="@mystyle.css, @very/deeply/located/small.css">
</GridPane>
@@ -0,0 +1,9 @@
<?import javafx.scene.layout.GridPane?>
<?import java.net.URL?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
fx:id="myGridPane">
<stylesheets>
<URL value="@mystyle.css"/>
<URL value="@very/deeply/located/<caret>"/>
</stylesheets>
</GridPane>
@@ -0,0 +1,9 @@
<?import javafx.scene.layout.GridPane?>
<?import java.net.URL?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
fx:id="myGridPane">
<stylesheets>
<URL value="@mystyle.css"/>
<URL value="@very/deeply/located/small.css"/>
</stylesheets>
</GridPane>
@@ -0,0 +1,4 @@
<?import javafx.scene.layout.GridPane?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
fx:id="myGridPane" stylesheets="@mystyle.css, @<error descr="Cannot resolve file 'unknown.css'">unknown.css</error>, @very/deeply/located/small.css">
</GridPane>
@@ -0,0 +1,10 @@
<?import javafx.scene.layout.GridPane?>
<?import java.net.URL?>
<GridPane xmlns:fx="http://javafx.com/fxml" alignment="center" hgap="10" vgap="10"
fx:id="myGridPane">
<stylesheets>
<URL value="@mystyle.css"/>
<URL value="@<error descr="Cannot resolve file 'unknown.css'">unknown.css</error>"/>
<URL value="@very/deeply/located/small.css"/>
</stylesheets>
</GridPane>