javafx: filter completion lists by file types when appropriate (IDEA-103768)

This commit is contained in:
anna
2013-04-09 16:23:44 +02:00
parent 0bf15047ac
commit b6badc2cbd
6 changed files with 82 additions and 16 deletions
@@ -189,6 +189,24 @@ public class JavaFxCompletionTest extends LightFixtureCompletionTestCase {
doTest("ColumnConstraints");
}
public void testOnlyCssAsStylesheets() throws Exception {
myFixture.addFileToProject("my.fxml", "");
myFixture.addFileToProject("my.png", "");
myFixture.addFileToProject("sample.css", ".root{}");
configureByFile(getTestName(true) + ".fxml");
assertTrue(myItems.length == 1);
LookupElement selectionElement = null;
for (LookupElement item : myItems) {
if (item.getLookupString().equals("sample.css")) {
selectionElement = item;
break;
}
}
if (selectionElement == null) {
fail("sample.css was not found");
}
}
public void testReadOnly() throws Exception {
configureByFile(getTestName(true) + ".fxml");
assertTrue(myItems.length > 0);
@@ -1,9 +1,12 @@
package org.jetbrains.plugins.javaFX;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.openapi.vfs.newvfs.NewVirtualFileSystem;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
@@ -15,15 +18,21 @@ import java.util.Collections;
* Date: 4/3/13
*/
public class JavaFxFileReferenceProvider extends PsiReferenceProvider {
private final String myAcceptedExtension;
public JavaFxFileReferenceProvider(String acceptedExtension) {
myAcceptedExtension = acceptedExtension;
}
@NotNull
@Override
public PsiReference[] getReferencesByElement(@NotNull final PsiElement element, @NotNull ProcessingContext context) {
final Object value = ((PsiLiteralExpression)element).getValue();
return getReferences(element, value);
return getReferences(element, value, myAcceptedExtension);
}
public static PsiReference[] getReferences(final PsiElement element, final Object value) {
public static PsiReference[] getReferences(final PsiElement element, final Object value, final String acceptedExtension) {
final PsiDirectory directory = element.getContainingFile().getOriginalFile().getParent();
if (!(value instanceof String) || directory == null) return PsiReference.EMPTY_ARRAY;
final boolean startsWithSlash = ((String)value).startsWith("/");
@@ -37,6 +46,18 @@ public class JavaFxFileReferenceProvider extends PsiReferenceProvider {
}
return Collections.<PsiFileSystemItem>singletonList(directory);
}
@Override
protected Condition<PsiFileSystemItem> getReferenceCompletionFilter() {
return new Condition<PsiFileSystemItem>() {
@Override
public boolean value(PsiFileSystemItem item) {
if (item instanceof PsiDirectory) return true;
final VirtualFile virtualFile = PsiUtilCore.getVirtualFile(item);
return virtualFile != null && acceptedExtension.equals(virtualFile.getExtension());
}
};
}
};
if (startsWithSlash) {
fileReferenceSet.addCustomization(FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION, FileReferenceSet.ABSOLUTE_TOP_LEVEL);
@@ -93,9 +93,9 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
new JavaFxComponentIdReferenceProvider());
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName("url")).and(attributeValueInFxml),
new JavaFxLocationReferenceProvider());
new JavaFxLocationReferenceProvider(false, "png"));
registrar.registerReferenceProvider(XmlPatterns.xmlAttributeValue().withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.STYLESHEETS)).and(attributeValueInFxml),
new JavaFxLocationReferenceProvider(true));
new JavaFxLocationReferenceProvider(true, "css"));
registrar.registerReferenceProvider(PlatformPatterns.psiElement(XmlProcessingInstruction.class).inVirtualFile(virtualFile().withExtension(JavaFxFileTypeFactory.FXML_EXTENSION)),
new ImportReferenceProvider());
@@ -110,7 +110,7 @@ public class FxmlReferencesContributor extends PsiReferenceContributor {
.withParent(XmlPatterns.xmlAttribute().withName(FxmlConstants.FX_VALUE)
.withParent(XmlPatterns.xmlTag().withParent(XmlPatterns.xmlTag().withName(FxmlConstants.STYLESHEETS))))
.and(attributeValueInFxml),
new JavaFxLocationReferenceProvider(true));
new JavaFxLocationReferenceProvider(true, "css"));
}
private static class MyJavaClassReferenceProvider extends JavaClassReferenceProvider {
@@ -15,11 +15,14 @@
*/
package org.jetbrains.plugins.javaFX.fxml.refs;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiReferenceProvider;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.reference.impl.providers.FileReferenceSet;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
@@ -32,12 +35,19 @@ import java.util.List;
*/
class JavaFxLocationReferenceProvider extends PsiReferenceProvider {
private boolean mySupportCommaInValue = false;
private final FileType[] myAcceptedFileTypes;
JavaFxLocationReferenceProvider() {
this(false);
}
JavaFxLocationReferenceProvider(boolean supportCommaInValue) {
JavaFxLocationReferenceProvider(boolean supportCommaInValue, String... acceptedFileTypes) {
mySupportCommaInValue = supportCommaInValue;
myAcceptedFileTypes = new FileType[acceptedFileTypes.length];
final FileTypeManager fileTypeManager = FileTypeManager.getInstance();
for (int i = 0; i < acceptedFileTypes.length; i++) {
myAcceptedFileTypes[i] = fileTypeManager.getFileTypeByExtension(acceptedFileTypes[i]);
}
}
@NotNull
@@ -55,7 +65,7 @@ class JavaFxLocationReferenceProvider extends PsiReferenceProvider {
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));
Collections.addAll(refs, collectRefs(element, endIdx >= 0 ? value.substring(startIdx, endIdx) : value.substring(startIdx), startIdx + 1, myAcceptedFileTypes));
startIdx = endIdx + 1;
if (endIdx < 0) {
break;
@@ -63,13 +73,27 @@ class JavaFxLocationReferenceProvider extends PsiReferenceProvider {
}
return refs.toArray(new PsiReference[refs.size()]);
} else {
return collectRefs(element, value, 1);
return collectRefs(element, value, 1, myAcceptedFileTypes);
}
}
}
private static PsiReference[] collectRefs(PsiElement element, String value, final int startInElement) {
final FileReferenceSet set = new FileReferenceSet(value, element, startInElement, null, true);
private static PsiReference[] collectRefs(PsiElement element, String value, final int startInElement, final FileType... acceptedFileTypes) {
final FileReferenceSet set = new FileReferenceSet(value, element, startInElement, null, true){
@Override
protected Condition<PsiFileSystemItem> getReferenceCompletionFilter() {
return new Condition<PsiFileSystemItem>() {
@Override
public boolean value(PsiFileSystemItem item) {
if (item instanceof PsiDirectory) return true;
final VirtualFile virtualFile = item.getVirtualFile();
if (virtualFile == null) return false;
final FileType fileType = virtualFile.getFileType();
return ArrayUtilRt.find(acceptedFileTypes, fileType) >= 0;
}
};
}
};
if (value.startsWith("/")) {
set.addCustomization(FileReferenceSet.DEFAULT_PATH_EVALUATOR_OPTION, FileReferenceSet.ABSOLUTE_TOP_LEVEL);
}
@@ -23,6 +23,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import org.jetbrains.plugins.javaFX.JavaFxFileReferenceProvider;
import org.jetbrains.plugins.javaFX.fxml.JavaFxCommonClassNames;
import org.jetbrains.plugins.javaFX.fxml.JavaFxFileTypeFactory;
import static com.intellij.patterns.PsiJavaPatterns.literalExpression;
@@ -111,7 +112,7 @@ public class JavaFxReferencesContributor extends PsiReferenceContributor {
@Override
public void registerReferenceProviders(PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(FXML_PATTERN, new JavaFxFileReferenceProvider());
registrar.registerReferenceProvider(STYLESHEET_PATTERN, new JavaFxFileReferenceProvider());
registrar.registerReferenceProvider(FXML_PATTERN, new JavaFxFileReferenceProvider(JavaFxFileTypeFactory.FXML_EXTENSION));
registrar.registerReferenceProvider(STYLESHEET_PATTERN, new JavaFxFileReferenceProvider("css"));
}
}
@@ -0,0 +1,2 @@
<?import javafx.scene.layout.GridPane?>
<GridPane xmlns:fx="http://javafx.com/fxml" stylesheets="<caret>"/>