mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java dom stuff -> java-impl
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
<orderEntry type="module" module-name="execution-openapi" />
|
||||
<orderEntry type="module" module-name="boot" />
|
||||
<orderEntry type="library" name="asm" level="project" />
|
||||
<orderEntry type="module" module-name="dom-openapi" />
|
||||
</component>
|
||||
<component name="copyright">
|
||||
<Base>
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
package com.intellij.util.xml;
|
||||
|
||||
import com.intellij.codeInsight.completion.scope.JavaCompletionProcessor;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.UserDataCache;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReference;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceSet;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class CanonicalPsiTypeConverterImpl extends CanonicalPsiTypeConverter implements CustomReferenceConverter<PsiType> {
|
||||
|
||||
private static final UserDataCache<JavaClassReferenceProvider, Project, Object> REFERENCE_PROVIDER = new UserDataCache<JavaClassReferenceProvider, Project, Object>("CanonicalPsiTypeConverterImpl") {
|
||||
@Override
|
||||
protected JavaClassReferenceProvider compute(Project project, Object p) {
|
||||
return new JavaClassReferenceProvider(project);
|
||||
}
|
||||
};
|
||||
|
||||
@NonNls private static final String[] PRIMITIVES = new String[]{"boolean", "byte",
|
||||
"char", "double", "float", "int", "long", "short"};
|
||||
@NonNls private static final String ARRAY_PREFIX = "[L";
|
||||
|
||||
public PsiType fromString(final String s, final ConvertContext context) {
|
||||
if (s == null) return null;
|
||||
try {
|
||||
return JavaPsiFacade.getInstance(context.getFile().getProject()).getElementFactory().createTypeFromText(s.replace('$', '.'), null);
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public String toString(final PsiType t, final ConvertContext context) {
|
||||
return t == null? null:t.getCanonicalText();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiReference[] createReferences(final GenericDomValue<PsiType> genericDomValue, final PsiElement element, ConvertContext context) {
|
||||
final String str = genericDomValue.getStringValue();
|
||||
if (str != null) {
|
||||
final ElementManipulator<PsiElement> manipulator = ElementManipulators.getManipulator(element);
|
||||
assert manipulator != null;
|
||||
String trimmed = str.trim();
|
||||
int offset = manipulator.getRangeInElement(element).getStartOffset() + str.indexOf(trimmed);
|
||||
if (trimmed.startsWith(ARRAY_PREFIX)) {
|
||||
offset += ARRAY_PREFIX.length();
|
||||
if (trimmed.endsWith(";")) {
|
||||
trimmed = trimmed.substring(ARRAY_PREFIX.length(), trimmed.length() - 1);
|
||||
} else {
|
||||
trimmed = trimmed.substring(ARRAY_PREFIX.length());
|
||||
}
|
||||
}
|
||||
return new JavaClassReferenceSet(trimmed, element, offset, false, REFERENCE_PROVIDER.get(genericDomValue.getManager().getProject(), null)) {
|
||||
protected JavaClassReference createReference(final int referenceIndex, final String subreferenceText, final TextRange textRange,
|
||||
final boolean staticImport) {
|
||||
return new JavaClassReference(this, textRange, referenceIndex, subreferenceText, staticImport) {
|
||||
public boolean isSoft() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JavaResolveResult advancedResolve(final boolean incompleteCode) {
|
||||
PsiType type = genericDomValue.getValue();
|
||||
if (type != null) {
|
||||
type = type.getDeepComponentType();
|
||||
}
|
||||
if (type instanceof PsiPrimitiveType) {
|
||||
return new CandidateInfo(element, PsiSubstitutor.EMPTY, false, false, element);
|
||||
}
|
||||
|
||||
return super.advancedResolve(incompleteCode);
|
||||
}
|
||||
|
||||
public void processVariants(final PsiScopeProcessor processor) {
|
||||
if (processor instanceof JavaCompletionProcessor) {
|
||||
((JavaCompletionProcessor)processor).setCompletionElements(getVariants());
|
||||
} else {
|
||||
super.processVariants(processor);
|
||||
}
|
||||
}
|
||||
|
||||
public Object[] getVariants() {
|
||||
final Object[] variants = super.getVariants();
|
||||
if (myIndex == 0) {
|
||||
return ArrayUtil.mergeArrays(variants, PRIMITIVES, Object.class);
|
||||
}
|
||||
return variants;
|
||||
}
|
||||
};
|
||||
}
|
||||
}.getAllReferences();
|
||||
}
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
package com.intellij.util.xml;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
|
||||
import com.intellij.util.containers.BidirectionalMap;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.UserDataCache;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class JvmPsiTypeConverterImpl extends JvmPsiTypeConverter implements CustomReferenceConverter<PsiType> {
|
||||
|
||||
private static final BidirectionalMap<PsiType, Character> ourPrimitiveTypes = new BidirectionalMap<PsiType, Character>();
|
||||
private static final UserDataCache<JavaClassReferenceProvider, Project, Object> JVM_REFERENCE_PROVIDER = new UserDataCache<JavaClassReferenceProvider, Project, Object>("JvmPsiTypeConverterImplJVM") {
|
||||
@Override
|
||||
protected JavaClassReferenceProvider compute(Project project, Object p) {
|
||||
JavaClassReferenceProvider provider = new JavaClassReferenceProvider(project);
|
||||
provider.setOption(JavaClassReferenceProvider.JVM_FORMAT, Boolean.TRUE);
|
||||
provider.setSoft(true);
|
||||
return provider;
|
||||
}
|
||||
};
|
||||
private static final UserDataCache<JavaClassReferenceProvider, Project, Object> REFERENCE_PROVIDER = new UserDataCache<JavaClassReferenceProvider, Project, Object>("JvmPsiTypeConverterImplPlain") {
|
||||
@Override
|
||||
protected JavaClassReferenceProvider compute(Project project, Object p) {
|
||||
JavaClassReferenceProvider provider = new JavaClassReferenceProvider(project);
|
||||
provider.setSoft(true);
|
||||
return provider;
|
||||
}
|
||||
};
|
||||
|
||||
static {
|
||||
ourPrimitiveTypes.put(PsiType.BYTE, 'B');
|
||||
ourPrimitiveTypes.put(PsiType.CHAR, 'C');
|
||||
ourPrimitiveTypes.put(PsiType.DOUBLE, 'D');
|
||||
ourPrimitiveTypes.put(PsiType.FLOAT, 'F');
|
||||
ourPrimitiveTypes.put(PsiType.INT, 'I');
|
||||
ourPrimitiveTypes.put(PsiType.LONG, 'L');
|
||||
ourPrimitiveTypes.put(PsiType.SHORT, 'S');
|
||||
ourPrimitiveTypes.put(PsiType.BOOLEAN, 'Z');
|
||||
}
|
||||
|
||||
public PsiType fromString(final String s, final ConvertContext context) {
|
||||
return convertFromString(s, context);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiType convertFromString(final String s, final ConvertContext context) {
|
||||
if (s == null) return null;
|
||||
|
||||
if (s.startsWith("[")) {
|
||||
int arrayDimensions = getArrayDimensions(s);
|
||||
|
||||
if (arrayDimensions >= s.length()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final char c = s.charAt(arrayDimensions);
|
||||
if (c == 'L') {
|
||||
if (!s.endsWith(";")) return null;
|
||||
final PsiClass aClass =
|
||||
DomJavaUtil.findClass(s.substring(arrayDimensions + 1, s.length() - 1), context.getFile(), context.getModule(), null);
|
||||
return aClass == null ? null : makeArray(arrayDimensions, createType(aClass));
|
||||
}
|
||||
|
||||
if (s.length() == arrayDimensions + 1) {
|
||||
final List<PsiType> list = ourPrimitiveTypes.getKeysByValue(c);
|
||||
return list == null || list.isEmpty() ? null : makeArray(arrayDimensions, list.get(0));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
final PsiClass aClass1 = DomJavaUtil.findClass(s, context.getFile(), context.getModule(), null);
|
||||
return aClass1 == null ? null : createType(aClass1);
|
||||
}
|
||||
|
||||
private static int getArrayDimensions(final String s) {
|
||||
int arrayDimensions = 0;
|
||||
|
||||
while (arrayDimensions < s.length() && s.charAt(arrayDimensions) == '[') {
|
||||
arrayDimensions++;
|
||||
}
|
||||
return arrayDimensions;
|
||||
}
|
||||
|
||||
private static PsiClassType createType(final PsiClass aClass) {
|
||||
return JavaPsiFacade.getInstance(aClass.getProject()).getElementFactory().createType(aClass);
|
||||
}
|
||||
|
||||
private static PsiType makeArray(final int dimensions, final PsiType type) {
|
||||
return dimensions == 0 ? type : makeArray(dimensions - 1, new PsiArrayType(type));
|
||||
}
|
||||
|
||||
public String toString(final PsiType psiType, final ConvertContext context) {
|
||||
return convertToString(psiType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static String convertToString(final PsiType psiType) {
|
||||
if (psiType instanceof PsiArrayType) {
|
||||
return '[' + toStringArray(((PsiArrayType)psiType).getComponentType());
|
||||
}
|
||||
else if (psiType instanceof PsiClassType) {
|
||||
return psiType.getCanonicalText();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNls @Nullable
|
||||
private static String toStringArray(final PsiType psiType) {
|
||||
if (psiType instanceof PsiArrayType) {
|
||||
return '[' + toStringArray(((PsiArrayType)psiType).getComponentType());
|
||||
}
|
||||
else if (psiType instanceof PsiPrimitiveType) {
|
||||
return String.valueOf(ourPrimitiveTypes.get(psiType));
|
||||
}
|
||||
else if (psiType instanceof PsiClassType) {
|
||||
return "L" + psiType.getCanonicalText() + ";";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiReference[] createReferences(GenericDomValue<PsiType> value, PsiElement element, ConvertContext context) {
|
||||
final PsiType psiType = value.getValue();
|
||||
final String s = value.getStringValue();
|
||||
assert s != null;
|
||||
final int dimensions = getArrayDimensions(s);
|
||||
if (dimensions > 0) {
|
||||
if (s.charAt(dimensions) == 'L' && s.endsWith(";")) {
|
||||
return JVM_REFERENCE_PROVIDER.get(value.getManager().getProject(), null).getReferencesByString(s.substring(dimensions + 1), element,
|
||||
element.getText().indexOf(s) + dimensions + 1);
|
||||
}
|
||||
if (psiType != null) return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
return REFERENCE_PROVIDER.get(value.getManager().getProject(), null).getReferencesByElement(element);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2007 JetBrains s.r.o. All Rights Reserved.
|
||||
*/
|
||||
|
||||
package com.intellij.util.xml;
|
||||
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author Dmitry Avdeev
|
||||
*/
|
||||
public class PsiClassConverter extends Converter<PsiClass> implements CustomReferenceConverter<PsiClass> {
|
||||
|
||||
public PsiClass fromString(final String s, final ConvertContext context) {
|
||||
final DomElement element = context.getInvocationElement();
|
||||
final GlobalSearchScope scope = element instanceof GenericDomValue ? getScope((GenericDomValue)element) : null;
|
||||
return DomJavaUtil.findClass(s, context.getFile(), context.getModule(), scope);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getErrorMessage(@Nullable final String s, final ConvertContext context) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String toString(final PsiClass t, final ConvertContext context) {
|
||||
return t == null ? null:t.getQualifiedName();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiReference[] createReferences(GenericDomValue<PsiClass> genericDomValue, PsiElement element, ConvertContext context) {
|
||||
|
||||
ExtendClass extendClass = genericDomValue.getAnnotation(ExtendClass.class);
|
||||
final JavaClassReferenceProvider provider = createClassReferenceProvider(genericDomValue, context, extendClass);
|
||||
return provider.getReferencesByElement(element);
|
||||
}
|
||||
|
||||
protected JavaClassReferenceProvider createClassReferenceProvider(GenericDomValue<PsiClass> genericDomValue, ConvertContext context,
|
||||
ExtendClass extendClass) {
|
||||
final JavaClassReferenceProvider provider = new JavaClassReferenceProvider(getScope(genericDomValue), context.getPsiManager().getProject());
|
||||
if (extendClass != null) {
|
||||
if (StringUtil.isNotEmpty(extendClass.value())) {
|
||||
provider.setOption(JavaClassReferenceProvider.EXTEND_CLASS_NAMES, new String[] {extendClass.value()});
|
||||
}
|
||||
if (extendClass.instantiatable()) {
|
||||
provider.setOption(JavaClassReferenceProvider.INSTANTIATABLE, Boolean.TRUE);
|
||||
}
|
||||
if (!extendClass.allowAbstract()) {
|
||||
provider.setOption(JavaClassReferenceProvider.CONCRETE, Boolean.TRUE);
|
||||
}
|
||||
if (!extendClass.allowInterface()) {
|
||||
provider.setOption(JavaClassReferenceProvider.NOT_INTERFACE, Boolean.TRUE);
|
||||
}
|
||||
if (!extendClass.allowEnum()) {
|
||||
provider.setOption(JavaClassReferenceProvider.NOT_ENUM, Boolean.TRUE);
|
||||
}
|
||||
if (extendClass.jvmFormat()) {
|
||||
provider.setOption(JavaClassReferenceProvider.JVM_FORMAT, Boolean.TRUE);
|
||||
}
|
||||
provider.setAllowEmpty(extendClass.allowEmpty());
|
||||
|
||||
}
|
||||
|
||||
ClassTemplate template = genericDomValue.getAnnotation(ClassTemplate.class);
|
||||
if (template != null) {
|
||||
if (StringUtil.isNotEmpty(template.value())) {
|
||||
provider.setOption(JavaClassReferenceProvider.CLASS_TEMPLATE, template.value());
|
||||
}
|
||||
provider.setOption(JavaClassReferenceProvider.CLASS_KIND, template.kind());
|
||||
}
|
||||
|
||||
provider.setSoft(true);
|
||||
return provider;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected GlobalSearchScope getScope(final GenericDomValue domValue) {
|
||||
final Module module = domValue.getModule();
|
||||
return module == null ? null : GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.intellij.util.xml.converters;
|
||||
|
||||
import com.intellij.util.xml.converters.values.ClassArrayConverter;
|
||||
import com.intellij.util.xml.GenericDomValue;
|
||||
import com.intellij.util.xml.ConvertContext;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.ElementManipulators;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.UserDataCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: Sergey.Vasiliev
|
||||
*/
|
||||
public class ClassArrayConverterImpl extends ClassArrayConverter {
|
||||
private static final UserDataCache<JavaClassReferenceProvider, Project, Object> REFERENCE_PROVIDER = new UserDataCache<JavaClassReferenceProvider, Project, Object>("ClassArrayConverterImpl") {
|
||||
@Override
|
||||
protected JavaClassReferenceProvider compute(Project project, Object p) {
|
||||
JavaClassReferenceProvider provider = new JavaClassReferenceProvider(project);
|
||||
provider.setSoft(true);
|
||||
provider.setAllowEmpty(true);
|
||||
return provider;
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
public PsiReference[] createReferences(final GenericDomValue genericDomValue, final PsiElement element, final ConvertContext context) {
|
||||
final String s = genericDomValue.getStringValue();
|
||||
if (s != null) {
|
||||
final int offset = ElementManipulators.getOffsetInElement(element);
|
||||
final ArrayList<PsiReference> list = new ArrayList<PsiReference>();
|
||||
int pos = -1;
|
||||
while (true) {
|
||||
while (pos + 1 < s.length()) {
|
||||
if (!Character.isWhitespace(s.charAt(pos + 1))) {
|
||||
break;
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
int nextPos = s.indexOf(',', pos + 1);
|
||||
if (nextPos == -1) {
|
||||
createReference(element, s.substring(pos + 1), pos + 1 + offset, list);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
createReference(element, s.substring(pos + 1, nextPos), pos + 1 + offset, list);
|
||||
pos = nextPos;
|
||||
}
|
||||
}
|
||||
return list.toArray(new PsiReference[list.size()]);
|
||||
}
|
||||
return PsiReference.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
private static void createReference(final PsiElement element, final String s, final int offset, List<PsiReference> list) {
|
||||
final PsiReference[] references = REFERENCE_PROVIDER.get(element.getProject(), null).getReferencesByString(s, element, offset);
|
||||
//noinspection ManualArrayToCollectionCopy
|
||||
for (PsiReference ref: references) {
|
||||
list.add(ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.intellij.util.xml.converters;
|
||||
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
|
||||
import com.intellij.psi.PsiReference;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.util.xml.converters.values.ClassValueConverter;
|
||||
import com.intellij.util.xml.GenericDomValue;
|
||||
import com.intellij.util.xml.ConvertContext;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.UserDataCache;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* User: Sergey.Vasiliev
|
||||
*/
|
||||
public class ClassValueConverterImpl extends ClassValueConverter {
|
||||
private static final UserDataCache<JavaClassReferenceProvider, Project, Object> REFERENCE_PROVIDER = new UserDataCache<JavaClassReferenceProvider, Project, Object>("ClassValueConverterImpl") {
|
||||
@Override
|
||||
protected JavaClassReferenceProvider compute(Project project, Object p) {
|
||||
JavaClassReferenceProvider provider = new JavaClassReferenceProvider(project);
|
||||
provider.setSoft(true);
|
||||
provider.setAllowEmpty(true);
|
||||
return provider;
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
public PsiReference[] createReferences(final GenericDomValue genericDomValue, final PsiElement element, final ConvertContext context) {
|
||||
return REFERENCE_PROVIDER.get(element.getManager().getProject(), null).getReferencesByElement(element);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
package com.intellij.util.xml.impl;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReference;
|
||||
import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.util.ReflectionCache;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.ProcessingContext;
|
||||
import com.intellij.util.xml.*;
|
||||
import com.intellij.util.xml.highlighting.DomCustomAnnotationChecker;
|
||||
import com.intellij.util.xml.highlighting.DomElementAnnotationHolder;
|
||||
import com.intellij.util.xml.highlighting.DomElementProblemDescriptor;
|
||||
import com.intellij.util.xml.highlighting.DomHighlightingHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class ExtendsClassChecker extends DomCustomAnnotationChecker<ExtendClass>{
|
||||
private static final GenericValueReferenceProvider ourProvider = new GenericValueReferenceProvider();
|
||||
|
||||
@NotNull
|
||||
public Class<ExtendClass> getAnnotationClass() {
|
||||
return ExtendClass.class;
|
||||
}
|
||||
|
||||
public List<DomElementProblemDescriptor> checkForProblems(@NotNull final ExtendClass extend, @NotNull final DomElement _element, @NotNull final DomElementAnnotationHolder holder,
|
||||
@NotNull final DomHighlightingHelper helper) {
|
||||
if (!(_element instanceof GenericDomValue)) return Collections.emptyList();
|
||||
GenericDomValue element = (GenericDomValue)_element;
|
||||
|
||||
final Class genericValueParameter = DomUtil.getGenericValueParameter(element.getDomElementType());
|
||||
if (genericValueParameter == null || (!ReflectionCache.isAssignable(genericValueParameter, PsiClass.class) &&
|
||||
!ReflectionCache.isAssignable(genericValueParameter, PsiType.class))) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final Object valueObject = element.getValue();
|
||||
PsiClass psiClass = null;
|
||||
|
||||
if (valueObject instanceof PsiClass) {
|
||||
psiClass = (PsiClass)valueObject;
|
||||
} else if (valueObject instanceof PsiClassType) {
|
||||
psiClass = ((PsiClassType)valueObject).resolve();
|
||||
}
|
||||
|
||||
if (psiClass != null) {
|
||||
return checkExtendClass(element, psiClass, extend.value(),
|
||||
extend.instantiatable(), extend.canBeDecorator(), extend.allowInterface(),
|
||||
extend.allowNonPublic(), extend.allowAbstract(), extend.allowEnum(), holder);
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<DomElementProblemDescriptor> checkExtendClass(final GenericDomValue element, final PsiClass value, final String name,
|
||||
final boolean instantiatable, final boolean canBeDecorator, final boolean allowInterface,
|
||||
final boolean allowNonPublic,
|
||||
final boolean allowAbstract,
|
||||
final boolean allowEnum,
|
||||
final DomElementAnnotationHolder holder) {
|
||||
final Project project = element.getManager().getProject();
|
||||
PsiClass extendClass = JavaPsiFacade.getInstance(project).findClass(name, GlobalSearchScope.allScope(project));
|
||||
final SmartList<DomElementProblemDescriptor> list = new SmartList<DomElementProblemDescriptor>();
|
||||
if (extendClass != null) {
|
||||
if (!name.equals(value.getQualifiedName()) && !value.isInheritor(extendClass, true)) {
|
||||
String message = DomBundle.message("class.is.not.a.subclass", value.getQualifiedName(), extendClass.getQualifiedName());
|
||||
list.add(holder.createProblem(element, message));
|
||||
}
|
||||
}
|
||||
|
||||
if (instantiatable) {
|
||||
if (value.hasModifierProperty(PsiModifier.ABSTRACT)) {
|
||||
list.add(holder.createProblem(element, DomBundle.message("class.is.not.concrete", value.getQualifiedName())));
|
||||
}
|
||||
else if (!allowNonPublic && !value.hasModifierProperty(PsiModifier.PUBLIC)) {
|
||||
list.add(holder.createProblem(element, DomBundle.message("class.is.not.public", value.getQualifiedName())));
|
||||
}
|
||||
else if (!hasDefaultConstructor(value)) {
|
||||
if (canBeDecorator) {
|
||||
boolean hasConstructor = false;
|
||||
|
||||
for (PsiMethod method : value.getConstructors()) {
|
||||
final PsiParameterList psiParameterList = method.getParameterList();
|
||||
if (psiParameterList.getParametersCount() != 1) continue;
|
||||
final PsiType psiType = psiParameterList.getParameters()[0].getTypeElement().getType();
|
||||
if (psiType instanceof PsiClassType) {
|
||||
final PsiClass psiClass = ((PsiClassType)psiType).resolve();
|
||||
if (psiClass != null && InheritanceUtil.isInheritorOrSelf(psiClass, extendClass, true)) {
|
||||
hasConstructor = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!hasConstructor) {
|
||||
list.add(holder.createProblem(element, DomBundle.message("class.decorator.or.has.default.constructor", value.getQualifiedName())));
|
||||
}
|
||||
}
|
||||
else {
|
||||
list.add(holder.createProblem(element, DomBundle.message("class.has.no.default.constructor", value.getQualifiedName())));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!allowInterface && value.isInterface()) {
|
||||
list.add(holder.createProblem(element, DomBundle.message("interface.not.allowed", value.getQualifiedName())));
|
||||
}
|
||||
if (!allowEnum && value.isEnum()) {
|
||||
list.add(holder.createProblem(element, DomBundle.message("enum.not.allowed", value.getQualifiedName())));
|
||||
}
|
||||
if (!allowAbstract && value.hasModifierProperty(PsiModifier.ABSTRACT) && !value.isInterface()) {
|
||||
list.add(holder.createProblem(element, DomBundle.message("abstract.class.not.allowed", value.getQualifiedName())));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static boolean hasDefaultConstructor(PsiClass clazz) {
|
||||
final PsiMethod[] constructors = clazz.getConstructors();
|
||||
if (constructors.length > 0) {
|
||||
for (PsiMethod cls: constructors) {
|
||||
if ((cls.hasModifierProperty(PsiModifier.PUBLIC) || cls.hasModifierProperty(PsiModifier.PROTECTED)) && cls.getParameterList().getParametersCount() == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
final PsiClass superClass = clazz.getSuperClass();
|
||||
return superClass == null || hasDefaultConstructor(superClass);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static List<DomElementProblemDescriptor> checkExtendsClassInReferences(final GenericDomValue element, final DomElementAnnotationHolder holder) {
|
||||
final Object valueObject = element.getValue();
|
||||
if (!(valueObject instanceof PsiClass)) return Collections.emptyList();
|
||||
|
||||
final PsiReference[] references = ourProvider.getReferencesByElement(DomUtil.getValueElement(element), new ProcessingContext());
|
||||
for (PsiReference reference : references) {
|
||||
if (reference instanceof JavaClassReference) {
|
||||
final PsiReferenceProvider psiReferenceProvider = ((JavaClassReference)reference).getProvider();
|
||||
final String[] value = psiReferenceProvider instanceof JavaClassReferenceProvider ? JavaClassReferenceProvider.EXTEND_CLASS_NAMES
|
||||
.getValue(((JavaClassReferenceProvider)psiReferenceProvider).getOptions()) : null;
|
||||
if (value != null && value.length != 0) {
|
||||
for (String className : value) {
|
||||
final List<DomElementProblemDescriptor> problemDescriptors =
|
||||
checkExtendClass(element, ((PsiClass)valueObject), className, false, false, true, false, true, true, holder);
|
||||
if (!problemDescriptors.isEmpty()) {
|
||||
return problemDescriptors;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
package com.intellij.util.xml.impl;
|
||||
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.xml.*;
|
||||
import com.intellij.util.xml.converters.values.ClassValueConverter;
|
||||
import com.intellij.util.xml.converters.values.ClassArrayConverter;
|
||||
import com.intellij.util.xml.ui.*;
|
||||
|
||||
import javax.swing.table.TableCellEditor;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class JavaDomApplicationComponent {
|
||||
public JavaDomApplicationComponent(DomUIFactory factory, ConverterManager converterManager) {
|
||||
converterManager.addConverter(PsiClass.class, new PsiClassConverter());
|
||||
converterManager.addConverter(PsiType.class, new CanonicalPsiTypeConverterImpl());
|
||||
converterManager.registerConverterImplementation(JvmPsiTypeConverter.class, new JvmPsiTypeConverterImpl());
|
||||
converterManager.registerConverterImplementation(CanonicalPsiTypeConverter.class, new CanonicalPsiTypeConverterImpl());
|
||||
|
||||
final ClassValueConverter classValueConverter = ClassValueConverter.getClassValueConverter();
|
||||
converterManager.registerConverterImplementation(ClassValueConverter.class, classValueConverter);
|
||||
final ClassArrayConverter classArrayConverter = ClassArrayConverter.getClassArrayConverter();
|
||||
converterManager.registerConverterImplementation(ClassArrayConverter.class, classArrayConverter);
|
||||
|
||||
factory.registerCustomControl(PsiClass.class, new Function<DomWrapper<String>, BaseControl>() {
|
||||
public BaseControl fun(final DomWrapper<String> wrapper) {
|
||||
return new PsiClassControl(wrapper, false);
|
||||
}
|
||||
});
|
||||
factory.registerCustomControl(PsiType.class, new Function<DomWrapper<String>, BaseControl>() {
|
||||
public BaseControl fun(final DomWrapper<String> wrapper) {
|
||||
return new PsiTypeControl(wrapper, false);
|
||||
}
|
||||
});
|
||||
|
||||
factory.registerCustomCellEditor(PsiClass.class, new Function<DomElement, TableCellEditor>() {
|
||||
public TableCellEditor fun(final DomElement element) {
|
||||
return new PsiClassTableCellEditor(element.getManager().getProject(), element.getResolveScope());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 by JetBrains s.r.o. All Rights Reserved.
|
||||
* Use is subject to license terms.
|
||||
*/
|
||||
package com.intellij.util.xml.ui;
|
||||
|
||||
import com.intellij.ide.util.TreeClassChooser;
|
||||
import com.intellij.ide.util.TreeClassChooserFactory;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.module.ModuleUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.ReferenceEditorWithBrowseButton;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import com.intellij.ui.JavaReferenceEditorUtil;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
import com.intellij.util.xml.ExtendClass;
|
||||
import com.intellij.util.xml.GenericDomValue;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class PsiClassControl extends EditorTextFieldControl<PsiClassPanel> {
|
||||
|
||||
public PsiClassControl(final DomWrapper<String> domWrapper) {
|
||||
super(domWrapper);
|
||||
}
|
||||
|
||||
public PsiClassControl(final DomWrapper<String> domWrapper, final boolean commitOnEveryChange) {
|
||||
super(domWrapper, commitOnEveryChange);
|
||||
}
|
||||
|
||||
protected EditorTextField getEditorTextField(@NotNull final PsiClassPanel component) {
|
||||
return ((ReferenceEditorWithBrowseButton)component.getComponent(0)).getEditorTextField();
|
||||
}
|
||||
|
||||
protected PsiClassPanel createMainComponent(PsiClassPanel boundedComponent, final Project project) {
|
||||
if (boundedComponent == null) {
|
||||
boundedComponent = new PsiClassPanel();
|
||||
}
|
||||
ReferenceEditorWithBrowseButton editor = JavaReferenceEditorUtil
|
||||
.createReferenceEditorWithBrowseButton(null, "", PsiManager.getInstance(project), true);
|
||||
Document document = editor.getChildComponent().getDocument();
|
||||
JavaCodeFragment fragment = (JavaCodeFragment)PsiDocumentManager.getInstance(project).getPsiFile(document);
|
||||
assert fragment != null;
|
||||
fragment.setIntentionActionsFilter(IntentionFilterOwner.IntentionActionsFilter.EVERYTHING_AVAILABLE);
|
||||
fragment.putUserData(ModuleUtil.KEY_MODULE, getDomWrapper().getExistingDomElement().getModule());
|
||||
return initReferenceEditorWithBrowseButton(boundedComponent, editor, this);
|
||||
}
|
||||
|
||||
protected static <T extends JPanel> T initReferenceEditorWithBrowseButton(final T boundedComponent,
|
||||
final ReferenceEditorWithBrowseButton editor,
|
||||
final EditorTextFieldControl control) {
|
||||
boundedComponent.removeAll();
|
||||
boundedComponent.add(editor);
|
||||
final GlobalSearchScope resolveScope = control.getDomWrapper().getResolveScope();
|
||||
editor.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
|
||||
final DomElement domElement = control.getDomElement();
|
||||
ExtendClass extend = domElement.getAnnotation(ExtendClass.class);
|
||||
PsiClass baseClass = null;
|
||||
TreeClassChooser.ClassFilter filter = null;
|
||||
if (extend != null) {
|
||||
baseClass = JavaPsiFacade.getInstance(control.getProject()).findClass(extend.value(), resolveScope);
|
||||
if (extend.instantiatable()) {
|
||||
filter = TreeClassChooser.INSTANTIATABLE;
|
||||
}
|
||||
}
|
||||
|
||||
PsiClass initialClass = null;
|
||||
if (domElement instanceof GenericDomValue) {
|
||||
final Object value = ((GenericDomValue)domElement).getValue();
|
||||
if (value instanceof PsiClass)
|
||||
initialClass = (PsiClass)value;
|
||||
}
|
||||
|
||||
TreeClassChooser chooser = TreeClassChooserFactory.getInstance(control.getProject())
|
||||
.createInheritanceClassChooser(UIBundle.message("choose.class"), resolveScope, baseClass, initialClass, filter);
|
||||
chooser.showDialog();
|
||||
final PsiClass psiClass = chooser.getSelectedClass();
|
||||
if (psiClass != null) {
|
||||
control.setValue(psiClass.getQualifiedName());
|
||||
}
|
||||
}
|
||||
});
|
||||
return boundedComponent;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (c) 2005 Your Corporation. All Rights Reserved.
|
||||
*/
|
||||
package com.intellij.util.xml.ui;
|
||||
|
||||
import com.intellij.ide.util.TreeClassChooser;
|
||||
import com.intellij.ide.util.TreeClassChooserFactory;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileTypes.StdFileTypes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.FixedSizeButton;
|
||||
import com.intellij.openapi.util.Conditions;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.UIBundle;
|
||||
import com.intellij.ui.JavaReferenceEditorUtil;
|
||||
import com.intellij.util.ui.AbstractTableCellEditor;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
import java.util.EventObject;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class PsiClassTableCellEditor extends AbstractTableCellEditor {
|
||||
private final Project myProject;
|
||||
private final GlobalSearchScope mySearchScope;
|
||||
private EditorTextField myEditor;
|
||||
|
||||
public PsiClassTableCellEditor(final Project project, final GlobalSearchScope searchScope) {
|
||||
myProject = project;
|
||||
mySearchScope = searchScope;
|
||||
}
|
||||
|
||||
public final Object getCellEditorValue() {
|
||||
return myEditor.getText();
|
||||
}
|
||||
|
||||
public final boolean stopCellEditing() {
|
||||
final boolean b = super.stopCellEditing();
|
||||
myEditor = null;
|
||||
return b;
|
||||
}
|
||||
|
||||
public boolean isCellEditable(EventObject e) {
|
||||
return !(e instanceof MouseEvent) || ((MouseEvent)e).getClickCount() >= 2;
|
||||
}
|
||||
|
||||
public final Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
|
||||
final Document document = JavaReferenceEditorUtil.createDocument(value == null ? "" : (String)value, PsiManager.getInstance(myProject), true);
|
||||
myEditor = new EditorTextField(document, myProject, StdFileTypes.JAVA){
|
||||
protected boolean shouldHaveBorder() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addNotify() {
|
||||
super.addNotify();
|
||||
final JComponent editorComponent = getEditor().getContentComponent();
|
||||
editorComponent.getInputMap().put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "ENTER");
|
||||
editorComponent.getActionMap().put("ENTER", new AbstractAction() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
stopCellEditing();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
final JPanel panel = new JPanel();
|
||||
panel.setLayout(new BorderLayout());
|
||||
panel.add(myEditor);
|
||||
final FixedSizeButton button = new FixedSizeButton(myEditor);
|
||||
panel.add(button, BorderLayout.EAST);
|
||||
button.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
TreeClassChooser chooser = TreeClassChooserFactory.getInstance(myProject)
|
||||
.createInheritanceClassChooser(UIBundle.message("choose.class"), mySearchScope, null, true, true, Conditions.alwaysTrue());
|
||||
chooser.showDialog();
|
||||
final PsiClass psiClass = chooser.getSelectedClass();
|
||||
if (psiClass != null) {
|
||||
myEditor.setText(psiClass.getQualifiedName());
|
||||
}
|
||||
}
|
||||
});
|
||||
panel.addFocusListener(new FocusListener() {
|
||||
public void focusGained(FocusEvent e) {
|
||||
if (!e.isTemporary() && myEditor != null) {
|
||||
myEditor.requestFocus();
|
||||
}
|
||||
}
|
||||
|
||||
public void focusLost(FocusEvent e) {
|
||||
}
|
||||
});
|
||||
myEditor.addFocusListener(new FocusListener() {
|
||||
public void focusGained(FocusEvent e) {
|
||||
}
|
||||
|
||||
public void focusLost(FocusEvent e) {
|
||||
if (!e.isTemporary()) {
|
||||
stopCellEditing();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//ComponentWithBrowseButton.MyDoClickAction.addTo(button, myEditor);
|
||||
|
||||
return panel;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2006 JetBrains s.r.o. All Rights Reserved.
|
||||
*/
|
||||
package com.intellij.util.xml.ui;
|
||||
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.ui.EditorTextField;
|
||||
import com.intellij.ui.ReferenceEditorWithBrowseButton;
|
||||
import com.intellij.ui.JavaReferenceEditorUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.xml.AbstractConvertContext;
|
||||
import com.intellij.util.xml.DomElement;
|
||||
import com.intellij.util.xml.JvmPsiTypeConverterImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class PsiTypeControl extends EditorTextFieldControl<PsiTypePanel> {
|
||||
|
||||
public PsiTypeControl(final DomWrapper<String> domWrapper, final boolean commitOnEveryChange) {
|
||||
super(domWrapper, commitOnEveryChange);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected String getValue() {
|
||||
final String rawValue = super.getValue();
|
||||
try {
|
||||
final PsiType psiType = JavaPsiFacade.getInstance(getProject()).getElementFactory().createTypeFromText(rawValue, null);
|
||||
final String s = JvmPsiTypeConverterImpl.convertToString(psiType);
|
||||
if (s != null) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
catch (IncorrectOperationException e) {
|
||||
}
|
||||
return rawValue;
|
||||
}
|
||||
|
||||
private PsiManager getPsiManager() {
|
||||
return PsiManager.getInstance(getProject());
|
||||
}
|
||||
|
||||
protected void setValue(String value) {
|
||||
final PsiType type = JvmPsiTypeConverterImpl.convertFromString(value, new AbstractConvertContext() {
|
||||
@NotNull
|
||||
public DomElement getInvocationElement() {
|
||||
return getDomElement();
|
||||
}
|
||||
|
||||
public PsiManager getPsiManager() {
|
||||
return PsiTypeControl.this.getPsiManager();
|
||||
}
|
||||
});
|
||||
if (type != null) {
|
||||
value = type.getCanonicalText();
|
||||
}
|
||||
super.setValue(value);
|
||||
}
|
||||
|
||||
protected EditorTextField getEditorTextField(@NotNull final PsiTypePanel component) {
|
||||
return ((ReferenceEditorWithBrowseButton)component.getComponent(0)).getEditorTextField();
|
||||
}
|
||||
|
||||
protected PsiTypePanel createMainComponent(PsiTypePanel boundedComponent, final Project project) {
|
||||
if (boundedComponent == null) {
|
||||
boundedComponent = new PsiTypePanel();
|
||||
}
|
||||
return PsiClassControl.initReferenceEditorWithBrowseButton(boundedComponent,
|
||||
new ReferenceEditorWithBrowseButton(null, project, new Function<String, Document>() {
|
||||
public Document fun(final String s) {
|
||||
return JavaReferenceEditorUtil.createTypeDocument(s, PsiManager.getInstance(project));
|
||||
}
|
||||
}, ""), this);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user