in flex/src/com/intellij/javascript/flex/MxmlReferenceContributor.java [71:435]
public void registerReferenceProviders(final @NotNull PsiReferenceRegistrar registrar) {
registrar.registerReferenceProvider(
XmlPatterns.xmlAttributeValue().withLocalName(or(string().endsWith(STYLE_NAME_ATTR_SUFFIX),
string().equalTo(STYLE_NAME_ATTR)))
.and(new FilterPattern(new ElementFilter() {
@Override
public boolean isAcceptable(final Object element, final PsiElement context) {
return !((PsiElement)element).textContains('{');
}
@Override
public boolean isClassAcceptable(final Class hintClass) {
return true;
}
})),
CssReferenceProviderUtil.CSS_CLASS_OR_ID_KEY_PROVIDER.getProvider());
XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, null, new ElementFilter() {
@Override
public boolean isAcceptable(Object element, PsiElement context) {
PsiElement parent = ((PsiElement)element).getParent();
if (parent instanceof XmlAttribute) {
XmlAttributeDescriptor descriptor = ((XmlAttribute)parent).getDescriptor();
if (descriptor instanceof AnnotationBackedDescriptorImpl) {
String format = ((AnnotationBackedDescriptor)descriptor).getFormat();
return FlexCssPropertyDescriptor.COLOR_FORMAT.equals(format);
}
}
return false;
}
@Override
public boolean isClassAcceptable(Class hintClass) {
return true;
}
}, true, new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(final @NotNull PsiElement element, @NotNull ProcessingContext context) {
XmlAttributeValue value = (XmlAttributeValue)element;
XmlAttribute parent = (XmlAttribute)value.getParent();
int length = value.getTextLength();
if (length >= 2) {
AnnotationBackedDescriptor descriptor = (AnnotationBackedDescriptor)parent.getDescriptor();
assert descriptor != null;
if (JSCommonTypeNames.ARRAY_CLASS_NAME.equals(descriptor.getType())) {
// drop quotes
String text = element.getText().substring(1, length - 1);
final List<PsiReference> references = new ArrayList<>();
new ArrayAttributeValueProcessor() {
@Override
protected void processElement(int start, int end) {
references.add(new FlexColorReference(element, new TextRange(start + 1, end + 1)));
}
}.process(text);
return references.toArray(PsiReference.EMPTY_ARRAY);
}
else {
// inside quotes
return new PsiReference[]{new FlexColorReference(element, new TextRange(1, length - 1))};
}
}
return PsiReference.EMPTY_ARRAY;
}
});
XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, null, new ElementFilter() {
@Override
public boolean isAcceptable(final Object element, final PsiElement context) {
PsiElement parent = ((PsiElement)element).getParent();
if (!(parent instanceof XmlAttribute) || !((XmlAttribute)parent).isNamespaceDeclaration()) {
return false;
}
final PsiElement parentParent = parent.getParent();
if (parentParent instanceof XmlTag && MxmlJSClass.isInsideTagThatAllowsAnyXmlContent((XmlTag)parentParent)) {
return false;
}
return true;
}
@Override
public boolean isClassAcceptable(final Class hintClass) {
return true;
}
}, true, new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(@NotNull PsiElement element, @NotNull ProcessingContext context) {
final String trimmedText = StringUtil.unquoteString(element.getText());
if (CodeContext.isPackageBackedNamespace(trimmedText)) {
return new ActionScriptReferenceSet(element, trimmedText, 1, false, false).getReferences();
}
return PsiReference.EMPTY_ARRAY;
}
});
// source attribute of Binding tag is handled in JSLanguageInjector
XmlUtil.registerXmlAttributeValueReferenceProvider(
registrar,
new String[]{FlexReferenceContributor.DESTINATION_ATTR_NAME},
new ScopeFilter(new ParentElementFilter(new AndFilter(XmlTagFilter.INSTANCE, new TagNameFilter(BINDING_TAG_NAME),
new NamespaceFilter(FlexSupportLoader.LANGUAGE_NAMESPACES)), 2)),
new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(final @NotNull PsiElement element,
final @NotNull ProcessingContext context) {
final String trimmedText = StringUtil.unquoteString(element.getText());
final JSReferenceSet referenceSet =
new ActionScriptReferenceSet(element, trimmedText, 1, false);
return referenceSet.getReferences();
}
});
XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, new String[]{FlexReferenceContributor.SOURCE_ATTR_NAME}, new ScopeFilter(
new ParentElementFilter(new AndFilter(XmlTagFilter.INSTANCE, new ElementFilterBase<>(PsiElement.class) {
@Override
protected boolean isElementAcceptable(final PsiElement element, final PsiElement context) {
return true;
}
}), 2)), new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(final @NotNull PsiElement element, final @NotNull ProcessingContext context) {
final XmlAttribute attribute = (XmlAttribute)element.getParent();
final XmlTag tag = attribute.getParent();
final String tagName = tag.getLocalName();
final String trimmedText = StringUtil.unquoteString(element.getText());
if (FlexSupportLoader.isLanguageNamespace(tag.getNamespace())) {
if (FlexPredefinedTagNames.SCRIPT.equals(tagName)) {
return ReferenceSupport.getFileRefs(element, element, 1, ReferenceSupport.LookupOptions.SCRIPT_SOURCE);
}
final String[] tagsWithSourceAttr = {
MxmlJSClass.XML_TAG_NAME, FlexPredefinedTagNames.MODEL,
JSCommonTypeNames.STRING_CLASS_NAME, JSCommonTypeNames.BOOLEAN_CLASS_NAME,
JSCommonTypeNames.INT_TYPE_NAME, JSCommonTypeNames.UINT_TYPE_NAME, JSCommonTypeNames.NUMBER_CLASS_NAME
};
if (ArrayUtil.contains(tagName, tagsWithSourceAttr)) {
return ReferenceSupport.getFileRefs(element, element, 1, ReferenceSupport.LookupOptions.XML_AND_MODEL_SOURCE);
}
if (FlexPredefinedTagNames.STYLE.equals(tagName)) {
if (trimmedText.startsWith("http:")) {
return PsiReference.EMPTY_ARRAY;
}
else {
return ReferenceSupport.getFileRefs(element, element, 1, ReferenceSupport.LookupOptions.STYLE_SOURCE);
}
}
}
if (element.textContains('{') || element.textContains('@')) {
return PsiReference.EMPTY_ARRAY;
}
final XmlAttributeDescriptor descriptor = attribute.getDescriptor();
final PsiElement psiElement = descriptor == null ? null : descriptor.getDeclaration();
if (psiElement instanceof JSFunction) {
final JSAttribute inspectableAttr = AnnotationBackedDescriptorImpl.findInspectableAttr(psiElement);
if (inspectableAttr != null) {
final JSAttributeNameValuePair attributeNameValuePair = inspectableAttr.getValueByName(FORMAT_ATTR_NAME);
if (attributeNameValuePair != null && FILE_ATTR_VALUE.equals(attributeNameValuePair.getSimpleValue())) {
return ReferenceSupport.getFileRefs(element, element, 1, ReferenceSupport.LookupOptions.NON_EMBEDDED_ASSET);
}
}
}
return PsiReference.EMPTY_ARRAY;
}
});
final Function<PsiReference, LocalQuickFix[]> quickFixProvider = reference -> {
final PsiElement element = reference.getElement();
final String classFqn = getTrimmedValueAndRange((XmlElement)element).first;
final String tagOrAttrName = element instanceof XmlAttributeValue
? ((XmlAttribute)element.getParent()).getName()
: ((XmlTag)element).getLocalName();
final CreateClassIntentionWithCallback[] intentions;
if (SKIN_CLASS_ATTR_NAME.equals(tagOrAttrName)) {
intentions = new CreateClassIntentionWithCallback[]{new CreateFlexSkinIntention(classFqn, element)};
}
else if ("firstView".equals(tagOrAttrName)) {
intentions = new CreateClassIntentionWithCallback[]{new CreateFlexMobileViewIntentionAndFix(classFqn, element, false)};
}
else {
intentions = new CreateClassIntentionWithCallback[]{
new ActionScriptCreateClassOrInterfaceFix(classFqn, null, element),
new CreateFlexComponentFix(classFqn, element)
};
}
for (CreateClassIntentionWithCallback intention : intentions) {
intention.setCreatedClassFqnConsumer(fqn -> {
if (!element.isValid()) return;
if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return;
if (element instanceof XmlAttributeValue) {
((XmlAttribute)element.getParent()).setValue(fqn);
}
else {
((XmlTag)element).getValue().setText(fqn);
}
});
}
return intentions;
};
XmlUtil.registerXmlTagReferenceProvider(registrar, null, TrueFilter.INSTANCE, true,
createReferenceProviderForTagOrAttributeExpectingJSClass(quickFixProvider));
XmlUtil.registerXmlAttributeValueReferenceProvider(registrar, null, TrueFilter.INSTANCE,
createReferenceProviderForTagOrAttributeExpectingJSClass(quickFixProvider));
registrar.registerReferenceProvider(xmlAttribute().withParent(XmlTag.class).with(new PatternCondition<>("") {
@Override
public boolean accepts(@NotNull XmlAttribute xmlAttribute, ProcessingContext context) {
String attrName = xmlAttribute.getLocalName();
int dotPos = attrName.indexOf('.');
if (dotPos == -1) return false;
return FlexSupportLoader.isFlexMxmFile(xmlAttribute.getContainingFile());
}
}), new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(final @NotNull PsiElement element, final @NotNull ProcessingContext context) {
String attrName = ((XmlAttribute)element).getLocalName();
int dotPos = attrName.indexOf('.');
if (dotPos == -1) return PsiReference.EMPTY_ARRAY;
return new PsiReference[]{new FlexReferenceContributor.StateReference(element, new TextRange(dotPos + 1, attrName.length()))};
}
});
XmlUtil.registerXmlTagReferenceProvider(
registrar, null, new ElementFilterBase<>(XmlTag.class) {
@Override
protected boolean isElementAcceptable(final XmlTag element, final PsiElement context) {
return element.getName().indexOf('.') != -1;
}
}, false, new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(final @NotNull PsiElement element, final @NotNull ProcessingContext context) {
final String name = ((XmlTag)element).getName();
int dotIndex = name.indexOf('.');
if (dotIndex == -1) return PsiReference.EMPTY_ARRAY;
final int tagOffset = element.getTextRange().getStartOffset();
final XmlToken startTagElement = XmlTagUtil.getStartTagNameElement((XmlTag)element);
final XmlToken endTagElement = XmlTagUtil.getEndTagNameElement((XmlTag)element);
if (startTagElement != null) {
if (endTagElement != null && endTagElement.getText().equals(startTagElement.getText())) {
final int start1 = startTagElement.getTextRange().getStartOffset() - tagOffset;
final int start2 = endTagElement.getTextRange().getStartOffset() - tagOffset;
return new PsiReference[]{
new FlexReferenceContributor.StateReference(element,
new TextRange(start1 + dotIndex + 1,
startTagElement.getTextRange().getEndOffset() - tagOffset)),
new FlexReferenceContributor.StateReference(element,
new TextRange(start2 + dotIndex + 1,
endTagElement.getTextRange().getEndOffset() - tagOffset)),
};
}
else {
final int start = startTagElement.getTextRange().getStartOffset() - tagOffset;
return new PsiReference[]{
new FlexReferenceContributor.StateReference(element,
new TextRange(start + dotIndex + 1,
startTagElement.getTextRange().getEndOffset() - tagOffset))};
}
}
return PsiReference.EMPTY_ARRAY;
}
}
);
XmlUtil.registerXmlAttributeValueReferenceProvider(
registrar,
new String[]{"basedOn", "fromState", "toState", FlexStateElementNames.NAME, FlexStateElementNames.STATE_GROUPS},
new ScopeFilter(new ParentElementFilter(new AndFilter(XmlTagFilter.INSTANCE, new NamespaceFilter(MxmlJSClass.MXML_URIS)), 2)),
new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(final @NotNull PsiElement element, final @NotNull ProcessingContext context) {
final PsiElement parent = element.getParent();
final PsiElement tag = parent.getParent();
PsiReference ref = null;
String tagName = ((XmlTag)tag).getLocalName();
String attrName = ((XmlAttribute)parent).getName();
String attrValue = ((XmlAttribute)parent).getValue();
if (attrValue != null && attrValue.contains("{")) return PsiReference.EMPTY_ARRAY;
if (FlexStateElementNames.NAME.equals(attrName)) {
if ("State".equals(tagName)) {
ref = new AttributeValueSelfReference(element);
}
else {
return PsiReference.EMPTY_ARRAY;
}
}
else if ("basedOn".equals(attrName) && element.getTextLength() == 2) {
return PsiReference.EMPTY_ARRAY;
}
else if (FlexStateElementNames.STATE_GROUPS.equals(attrName)) {
if ("State".equals(tagName)) {
return buildStateRefs(element, true);
}
else {
return PsiReference.EMPTY_ARRAY;
}
}
if (FlexReferenceContributor.TRANSITION_TAG_NAME.equals(tagName)) {
if ((element.textContains('*') &&
"*".equals(StringUtil.unquoteString(element.getText()))) ||
element.getTextLength() == 2 // empty value for attr, current state
) {
return PsiReference.EMPTY_ARRAY;
}
}
if (ref == null) {
ref = new FlexReferenceContributor.StateReference(element);
}
return new PsiReference[]{ref};
}
});
XmlUtil.registerXmlAttributeValueReferenceProvider(
registrar,
new String[]{FlexStateElementNames.EXCLUDE_FROM, FlexStateElementNames.INCLUDE_IN},
new ScopeFilter(new ParentElementFilter(XmlTagFilter.INSTANCE, 2)),
new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(final @NotNull PsiElement element,
final @NotNull ProcessingContext context) {
return buildStateRefs(element, false);
}
});
XmlUtil.registerXmlAttributeValueReferenceProvider(
registrar, new String[]{CodeContext.TARGET_ATTR_NAME},
new ScopeFilter(
new ParentElementFilter(
new AndFilter(XmlTagFilter.INSTANCE,
new TagNameFilter(CodeContext.REPARENT_TAG_NAME),
new NamespaceFilter(FlexSupportLoader.MXML_URI3)
), 2
)
),
new PsiReferenceProvider() {
@Override
public PsiReference @NotNull [] getReferencesByElement(final @NotNull PsiElement element,
final @NotNull ProcessingContext context) {
return new PsiReference[]{new XmlIdValueReference(element)};
}
});
}