下面列出了com.intellij.psi.PsiRecursiveElementVisitor#com.jetbrains.php.PhpIndex 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
static public List<ResolveResult> getClassInterfaceResolveResult(Project project, String FQNClassOrInterfaceName) {
PhpIndex phpIndex = PhpIndex.getInstance(project);
Collection<PhpClass> phpClasses = phpIndex.getClassesByFQN(FQNClassOrInterfaceName);
Collection<PhpClass> phpInterfaces = phpIndex.getInterfacesByFQN(FQNClassOrInterfaceName);
List<ResolveResult> results = new ArrayList<ResolveResult>();
for (PhpClass phpClass : phpClasses) {
results.add(new PsiElementResolveResult(phpClass));
}
for (PhpClass phpInterface : phpInterfaces) {
results.add(new PsiElementResolveResult(phpInterface));
}
return results;
}
public void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet resultSet) {
if(!Symfony2ProjectComponent.isEnabled(parameters.getPosition())) {
return;
}
PhpIndex phpIndex = PhpIndex.getInstance(parameters.getOriginalFile().getProject());
Map<String, String> entityNamespaces = ServiceXmlParserFactory.getInstance(parameters.getOriginalFile().getProject(), EntityNamesServiceParser.class).getEntityNameMap();
// copied from PhpCompletionUtil::addClassesInNamespace looks the official way to find classes in namespaces
// its a really performance nightmare
Collection<String> names = phpIndex.getAllClassNames(new CamelHumpMatcher(resultSet.getPrefixMatcher().getPrefix()));
for (String name : names) {
Collection<PhpClass> classes = phpIndex.getClassesByName(name);
for(Map.Entry<String, String> entry: entityNamespaces.entrySet()) {
String namespaceFqn = PhpLangUtil.toFQN(entry.getValue());
Collection<PhpClass> filtered = PhpCompletionUtil.filterByNamespace(classes, namespaceFqn);
for (PhpClass phpClass : filtered) {
resultSet.addElement(new PhpClassLookupElement(phpClass, true, PhpClassReferenceInsertHandler.getInstance()));
}
}
}
}
public static String getTypeDisplayName(Project project, Set<String> types) {
Collection<PhpClass> classFromPhpTypeSet = PhpElementsUtil.getClassFromPhpTypeSet(project, types);
if(classFromPhpTypeSet.size() > 0) {
return classFromPhpTypeSet.iterator().next().getPresentableFQN();
}
PhpType phpType = new PhpType();
for (String type : types) {
phpType.add(type);
}
PhpType phpTypeFormatted = PhpIndex.getInstance(project).completeType(project, phpType, new HashSet<>());
if(phpTypeFormatted.getTypes().size() > 0) {
return StringUtils.join(phpTypeFormatted.getTypes(), "|");
}
if(types.size() > 0) {
return types.iterator().next();
}
return "";
}
public static PhpClass getInstanseClass(Project project, MethodReference methodRef) {
Set<String> types = methodRef.getDeclaredType().getTypes();
if (types.size() == 0) return null;
String classType = null;
for (String type : types) {
if (type.contains("\\model\\")) {
classType = type;
break;
}
}
if (classType == null) return null;
String classFQN = classType.substring(classType.indexOf("\\"), classType.indexOf("."));
Collection<PhpClass> classesByFQN = PhpIndex.getInstance(project).getClassesByFQN(classFQN);
if (classesByFQN.size() == 0) return null;
else
return classesByFQN.iterator().next();
}
@NotNull
@Override
public Collection<PsiElement> getPsiTargets(@NotNull SourceContributorDeclarationHandlerParameter parameter) {
String contents = parameter.getHandlerParameter().getContents();
if(StringUtils.isBlank(contents)) {
return Collections.emptyList();
}
String sourceParameter = parameter.getSourceParameter();
if(sourceParameter == null) {
return Collections.emptyList();
}
final Collection<PsiElement> psiElements = new ArrayList<>();
for (PhpClass phpClass : PhpIndex.getInstance(parameter.getProject()).getAllSubclasses(sourceParameter)) {
if(StringUtils.stripStart(contents, "\\").equalsIgnoreCase(StringUtils.stripStart(phpClass.getPresentableFQN(), "\\"))) {
psiElements.add(phpClass);
}
}
return psiElements;
}
/**
* @see PhpTypeProviderUtil#getResolvedParameter
*/
public void testGetTypeSignature() {
Function<PhpNamedElement, String> func = phpNamedElement ->
phpNamedElement instanceof Method ? ((Method) phpNamedElement).getContainingClass().getFQN() : null;
ArrayList<? extends PhpNamedElement> typeSignature = new ArrayList<PhpNamedElement>(PhpTypeProviderUtil.getTypeSignature(
PhpIndex.getInstance(getProject()),
"#M#C\\Doctrine\\Common\\Persistence\\ObjectManager.getRepository|#M#C\\Doctrine\\Common\\Persistence\\ObjectFoo.getRepository"
));
assertContainsElements(ContainerUtil.map(typeSignature, func), "\\Doctrine\\Common\\Persistence\\ObjectManager", "\\Doctrine\\Common\\Persistence\\ObjectFoo");
typeSignature = new ArrayList<PhpNamedElement>(PhpTypeProviderUtil.getTypeSignature(
PhpIndex.getInstance(getProject()),
"#M#C\\Doctrine\\Common\\Persistence\\ObjectManager.getRepository"
));
assertContainsElements(ContainerUtil.map(typeSignature, func), "\\Doctrine\\Common\\Persistence\\ObjectManager");
}
public static void visitCustomTypes(@NotNull Project project, @NotNull ColumnTypeVisitor visitor) {
Set<String> found = new HashSet<>();
for (PhpClass phpClass : PhpIndex.getInstance(project).getAllSubclasses("\\Doctrine\\DBAL\\Types\\Type")) {
String name = PhpElementsUtil.getMethodReturnAsString(phpClass, "getName");
if(name != null) {
found.add(name);
visitor.visit(name, phpClass, phpClass.findMethodByName("getName"));
}
}
Stream.of("id", "string", "integer", "smallint", "bigint", "boolean", "decimal", "date", "time", "datetime", "text", "array", "float")
.filter(s -> !found.contains(s))
.forEach(s -> visitor.visit(s, null, null));
}
public static Set<String> getPluginsWithFilesystem(@NotNull Project project)
{
CachedValue<Set<String>> cachedPluginFilesystem = project.getUserData(PLUGIN_FILESYSTEM_KEY);
if (cachedPluginFilesystem != null && cachedPluginFilesystem.hasUpToDateValue()) {
return cachedPluginFilesystem.getValue();
}
CachedValue<Set<String>> cachedValue = CachedValuesManager.getManager(project).createCachedValue(() -> {
Set<String> plugins = new HashSet<>();
Collection<PhpClass> prefixFilesystem = PhpIndex.getInstance(project).getClassesByFQN(ShopwareFQDN.PREFIX_FILESYSTEM);
// If PrefixFilesystem does not exist, we have not running Shopware 5.5 where the new services are implemented
if (!prefixFilesystem.isEmpty()) {
for(PhpClass phpClass: PhpIndex.getInstance(project).getAllSubclasses(ShopwareFQDN.PLUGIN_BOOTSTRAP)) {
plugins.add(phpClass.getName());
}
}
return CachedValueProvider.Result.create(plugins, PsiModificationTracker.MODIFICATION_COUNT);
}, false);
project.putUserData(PLUGIN_FILESYSTEM_KEY, cachedValue);
return cachedValue.getValue();
}
@Override
public void invoke(@NotNull Project project, @NotNull PsiFile psiFile, @Nullable Editor editor, @NotNull PsiElement psiElement, @NotNull PsiElement psiElement1) {
if(editor == null) {
return;
}
Collection<PhpClass> anyByFQN = PhpIndex.getInstance(project).getAnyByFQN(this.expectedClass);
if(anyByFQN.size() == 0) {
return;
}
Collection<ContainerService> suggestions = ServiceUtil.getServiceSuggestionForPhpClass(anyByFQN.iterator().next(), ContainerCollectionResolver.getServices(project));
if(suggestions.size() == 0) {
HintManager.getInstance().showErrorHint(editor, "No suggestion found");
return;
}
ServiceSuggestDialog.create(
editor,
ContainerUtil.map(suggestions, ContainerService::getName),
new MyInsertCallback(editor, psiElement)
);
}
private void attachModels(Project project, String[] namespaces, List<PsiElement> targets) {
if(namespaces.length < 5) {
return;
}
// only show on controller context
if(!"model".equalsIgnoreCase(namespaces[3])) {
return;
}
Set<String> classMap = new HashSet<>(Arrays.asList(
String.format("Shopware\\Models\\%s\\%s", namespaces[2], ShopwareUtil.toCamelCase(namespaces[4], false)).toLowerCase(),
String.format("Shopware\\CustomModels\\%s\\%s", namespaces[2], ShopwareUtil.toCamelCase(namespaces[4], false)).toLowerCase()
));
addCustomModelNames(namespaces, classMap);
// @TODO: to be dropped no need as handled by symfony+annotations plugin
for(PhpClass phpClass: PhpIndex.getInstance(project).getAllSubclasses("\\Shopware\\Components\\Model\\ModelEntity")) {
String className = phpClass.getPresentableFQN();
if(classMap.contains(className.toLowerCase())) {
targets.add(phpClass);
}
}
}
@NotNull
@Override
public ResolveResult[] multiResolve(boolean incompleteCode) {
if (myElement instanceof FluidViewHelperReference) {
FluidViewHelperExpr viewHelperExpr = (FluidViewHelperExpr) PsiTreeUtil.findFirstParent(myElement, e -> e instanceof FluidViewHelperExpr);
String presentableName = viewHelperExpr.getPresentableName();
ViewHelper viewHelperByName = ViewHelperUtil.getViewHelperByName(myElement, presentableName);
if (viewHelperByName == null) {
return ResolveResult.EMPTY_ARRAY;
}
return PsiElementResolveResult.createResults(PhpIndex.getInstance(myElement.getProject()).getClassesByFQN(viewHelperByName.fqn));
}
return ResolveResult.EMPTY_ARRAY;
}
@Override
protected void addCompletions(@NotNull CompletionParameters params, ProcessingContext context, @NotNull CompletionResultSet result) {
PsiElement curr = params.getPosition().getOriginalElement();
if (PsiTreeUtil.getParentOfType(curr, LattePhpContent.class) == null) {
return;
}
PhpIndex phpIndex = PhpIndex.getInstance(curr.getProject());
String prefix = result.getPrefixMatcher().getPrefix();
String namespace = "";
if (prefix.contains("\\")) {
int index = prefix.lastIndexOf("\\");
namespace = prefix.substring(0, index) + "\\";
prefix = prefix.substring(index + 1);
}
PhpCompletionUtil.addSubNamespaces(namespace, result.withPrefixMatcher(prefix), phpIndex, PhpNamespaceInsertHandler.getInstance());
}
public static Collection<PhpClass> getClassFromPhpTypeSetArrayClean(Project project, Set<String> types) {
PhpType phpType = new PhpType();
for (String type : types) {
phpType.add(type);
}
ArrayList<PhpClass> phpClasses = new ArrayList<>();
for (String typeName : PhpIndex.getInstance(project).completeType(project, phpType, new HashSet<>()).getTypes()) {
if (typeName.startsWith("\\")) {
// we clean array types \Foo[]
if (typeName.endsWith("[]")) {
typeName = typeName.substring(0, typeName.length() - 2);
}
PhpClass phpClass = getClassInterface(project, typeName);
if (phpClass != null) {
phpClasses.add(phpClass);
}
}
}
return phpClasses;
}
public static Collection<DoctrineModel> getModelClasses(Project project, Map<String, String> shortcutNames) {
PhpClass repositoryInterface = PhpElementsUtil.getInterface(PhpIndex.getInstance(project), DoctrineTypes.REPOSITORY_INTERFACE);
if(repositoryInterface == null) {
repositoryInterface = PhpElementsUtil.getInterface(PhpIndex.getInstance(project), "\\Doctrine\\Persistence\\ObjectRepository");
}
Collection<DoctrineModel> models = new ArrayList<>();
for (Map.Entry<String, String> entry : shortcutNames.entrySet()) {
for(PhpClass phpClass: PhpIndexUtil.getPhpClassInsideNamespace(project, entry.getValue())) {
if(repositoryInterface != null && !isEntity(phpClass, repositoryInterface)) {
continue;
}
models.add(new DoctrineModel(phpClass, entry.getKey(), entry.getValue()));
}
}
return models;
}
public static String getTypeDisplayName(Project project, Set<String> types) {
Collection<PhpClass> classFromPhpTypeSet = getClassFromPhpTypeSet(project, types);
if (classFromPhpTypeSet.size() > 0) {
return classFromPhpTypeSet.iterator().next().getPresentableFQN();
}
PhpType phpType = new PhpType();
for (String type : types) {
phpType.add(type);
}
PhpType phpTypeFormatted = PhpIndex.getInstance(project).completeType(project, phpType, new HashSet<>());
if (phpTypeFormatted.getTypes().size() > 0) {
return StringUtils.join(phpTypeFormatted.getTypes(), "|");
}
if (types.size() > 0) {
return types.iterator().next();
}
return "";
}
protected void assertPhpReferenceSignatureEquals(LanguageFileType languageFileType, @NotNull Class aClass, String configureByText, String typeSignature) {
myFixture.configureByText(languageFileType, configureByText);
PsiElement psiElement = myFixture.getFile().findElementAt(myFixture.getCaretOffset());
psiElement = PsiTreeUtil.getParentOfType(psiElement, aClass);
if (!(psiElement instanceof PhpReference)) {
fail("Element is not PhpReference.");
}
PhpIndex phpIndex = PhpIndex.getInstance(myFixture.getProject());
Collection<? extends PhpNamedElement> collection = phpIndex.getBySignature(((PhpReference)psiElement).getSignature(), null, 0);
assertNotEmpty(collection);
for (String type : collection.iterator().next().getType().getTypes()) {
if (type.equals(typeSignature)) {
return;
}
}
fail("Can't find type: "+typeSignature+", found:"+collection.iterator().next().getType().toString());
}
@NotNull
private Method[] getExpectedMethods(@NotNull Project project, @NotNull String ClassInterfaceName, @NotNull String methodName) {
Set<Method> methods = new HashSet<>();
for (PhpClass phpClass : PhpIndex.getInstance(project).getAnyByFQN(ClassInterfaceName)) {
// handle constructor as string
if(methodName.equalsIgnoreCase("__construct")) {
Method constructor = phpClass.getConstructor();
if(constructor != null) {
methods.add(constructor);
}
continue;
}
Method method = phpClass.findMethodByName(methodName);
if(method != null) {
methods.add(method);
}
}
return methods.toArray(new Method[methods.size()]);
}
@Override
public Collection<? extends PhpNamedElement> getBySignature(String s, Project project) {
int endIndex = s.lastIndexOf("%");
if (endIndex == -1) {
return Collections.emptySet();
}
// Get FQN from parameter string.
// Example (PhpStorm 8): #K#C\Foo\Bar::get()%#K#C\Bar\Baz. -> \Bar\Baz.
// Example (PhpStorm 9): #K#C\Foo\Bar::get()%#K#C\Bar\Baz.class -> \Bar\Baz.class
String parameter = s.substring(endIndex + 5, s.length());
if (parameter.contains(".class")) { // for PhpStorm 9
parameter = parameter.replace(".class", "");
}
if (parameter.contains(".")) {
parameter = parameter.replace(".", "");
}
return PhpIndex.getInstance(project).getAnyByFQN(parameter);
}
@NotNull
private Method[] getExpectedMethods(@NotNull Project project, @NotNull String ClassInterfaceName, @NotNull String methodName) {
Set<Method> methods = new HashSet<>();
for (PhpClass phpClass : PhpIndex.getInstance(project).getAnyByFQN(ClassInterfaceName)) {
// handle constructor as string
if(methodName.equalsIgnoreCase("__construct")) {
Method constructor = phpClass.getConstructor();
if(constructor != null) {
methods.add(constructor);
}
continue;
}
Method method = phpClass.findMethodByName(methodName);
if(method != null) {
methods.add(method);
}
}
return methods.toArray(new Method[methods.size()]);
}
public static void visitControllerActions(@NotNull final Project project, @NotNull ControllerActionVisitor visitor) {
Collection<PhpClass> allSubclasses = new HashSet<PhpClass>() {{
addAll(PhpIndex.getInstance(project).getAllSubclasses("\\Illuminate\\Routing\\Controller"));
addAll(PhpIndex.getInstance(project).getAllSubclasses("\\App\\Http\\Controllers\\Controller"));
}};
for(PhpClass phpClass: allSubclasses) {
if(!phpClass.isAbstract()) {
for(Method method: phpClass.getMethods()) {
String className = phpClass.getPresentableFQN();
String methodName = method.getName();
if(!method.isStatic() && method.getAccess().isPublic() && !methodName.startsWith("__")) {
PhpClass phpTrait = method.getContainingClass();
if(phpTrait == null || !commonControllerTraits.contains(phpTrait.getName())) {
if(StringUtils.isNotBlank(className)) {
visitor.visit(phpClass, method, className + "@" + methodName);
}
}
}
}
}
}
}
@NotNull
@Override
public Collection<LookupElement> getLookupElements(@NotNull SourceContributorParameter parameter) {
String sourceParameter = parameter.getSourceParameter();
if(sourceParameter == null) {
return Collections.emptyList();
}
Collection<LookupElement> lookupElements = new ArrayList<>();
for (PhpClass phpClass : PhpIndex.getInstance(parameter.getProject()).getAllSubclasses(sourceParameter)) {
lookupElements.add(
LookupElementBuilder.create(phpClass.getPresentableFQN()).withIcon(phpClass.getIcon())
);
}
return lookupElements;
}
@NotNull
@Override
public Collection<PsiElement> getPsiTargets(@NotNull SourceContributorDeclarationHandlerParameter parameter) {
String contents = parameter.getHandlerParameter().getContents();
if(StringUtils.isBlank(contents)) {
return Collections.emptyList();
}
String sourceParameter = parameter.getSourceParameter();
if(sourceParameter == null) {
return Collections.emptyList();
}
final Collection<PsiElement> psiElements = new ArrayList<>();
for (PhpClass phpClass : PhpIndex.getInstance(parameter.getProject()).getAllSubclasses(sourceParameter)) {
if(StringUtils.stripStart(contents, "\\").equalsIgnoreCase(StringUtils.stripStart(phpClass.getPresentableFQN(), "\\"))) {
psiElements.add(phpClass);
}
}
return psiElements;
}
@NotNull
public Collection<LookupElement> getLookupElements(@NotNull PhpToolboxCompletionContributorParameter parameter) {
PhpIndex instance = PhpIndex.getInstance(parameter.getProject());
Collection<LookupElement> lookupElements = new ArrayList<>();
for (String className : getClasses(parameter)) {
// strip double backslash
className = className.replaceAll("\\\\+", "\\\\");
for (PhpClass phpClass : getPhpClassesForLookup(instance, className)) {
lookupElements.add(
LookupElementBuilder.create(phpClass.getPresentableFQN()).withIcon(phpClass.getIcon())
);
}
}
return lookupElements;
}
@NotNull
@Override
public Collection<LookupElement> getLookupElements(@NotNull SourceContributorParameter parameter) {
String sourceParameter = parameter.getSourceParameter();
if(sourceParameter == null) {
return Collections.emptyList();
}
Collection<LookupElement> lookupElements = new ArrayList<>();
for (PhpClass phpClass : PhpIndex.getInstance(parameter.getProject()).getAllSubclasses(sourceParameter)) {
lookupElements.add(
LookupElementBuilder.create(phpClass.getPresentableFQN()).withIcon(phpClass.getIcon())
);
}
return lookupElements;
}
@Override
public Collection<DoctrineModelProviderParameter.DoctrineModel> collectModels(DoctrineModelProviderParameter parameter) {
if(!ShopwareProjectComponent.isValidForProject(parameter.getProject())) {
return Collections.emptyList();
}
List<DoctrineModelProviderParameter.DoctrineModel> doctrineModels = new ArrayList<>();
for(PhpClass phpClass: PhpIndex.getInstance(parameter.getProject()).getAllSubclasses("\\Shopware\\Components\\Model\\ModelEntity")) {
doctrineModels.add(new DoctrineModelProviderParameter.DoctrineModel(phpClass));
}
return doctrineModels;
}
/**
* we can also pipe php references signatures and resolve them here
* overwrite parameter to get string value
*/
@Nullable
public static String getResolvedParameter(@NotNull PhpIndex phpIndex, @NotNull String parameter, @Nullable Set<String> visited, int depth) {
// PHP 5.5 class constant: "Class\Foo::class"
if(parameter.startsWith("#K#C")) {
// PhpStorm9: #K#C\Class\Foo.class
if(parameter.endsWith(".class")) {
return StringUtils.stripStart(parameter.substring(4, parameter.length() - 6), "\\");
}
}
// #K#C\Class\Foo.property
// #K#C\Class\Foo.CONST
if(parameter.startsWith("#")) {
// get psi element from signature
Collection<? extends PhpNamedElement> signTypes = phpIndex.getBySignature(parameter, visited, depth);
if(signTypes.size() == 0) {
return null;
}
// get string value
parameter = GenericsUtil.getStringValue(signTypes.iterator().next());
if(parameter == null) {
return null;
}
}
return parameter;
}
/**
* We can have multiple types inside a TypeProvider; split them on "|" so that we dont get empty types
*
* #M#x#M#C\FooBar.get?doctrine.odm.mongodb.document_manager.getRepository|
* #M#x#M#C\FooBar.get?doctrine.odm.mongodb.document_manager.getRepository
*/
@NotNull
public static Collection<? extends PhpNamedElement> getTypeSignature(@NotNull PhpIndex phpIndex, @NotNull String signature) {
if (!signature.contains("|")) {
return phpIndex.getBySignature(signature, null, 0);
}
Collection<PhpNamedElement> elements = new ArrayList<>();
for (String s : signature.split("\\|")) {
elements.addAll(phpIndex.getBySignature(s, null, 0));
}
return elements;
}
/**
* we can also pipe php references signatures and resolve them here
* overwrite parameter to get string value
*/
@Nullable
public static String getResolvedParameter(@NotNull PhpIndex phpIndex, @NotNull String parameter) {
// PHP 5.5 class constant: "Class\Foo::class"
if(parameter.startsWith("#K#C")) {
// PhpStorm9: #K#C\Class\Foo.class
if(parameter.endsWith(".class")) {
return parameter.substring(4, parameter.length() - 6);
}
// PhpStorm8: #K#C\Class\Foo.
// workaround since signature has empty type
if(parameter.endsWith(".")) {
return parameter.substring(4, parameter.length() - 1);
}
}
// #K#C\Class\Foo.property
// #K#C\Class\Foo.CONST
if(parameter.startsWith("#")) {
// get psi element from signature
Collection<? extends PhpNamedElement> signTypes = phpIndex.getBySignature(parameter, null, 0);
if(signTypes.size() == 0) {
return null;
}
// get string value
parameter = PhpElementsUtil.getStringValue(signTypes.iterator().next());
if(parameter == null) {
return null;
}
}
return parameter;
}
@Nullable
static public PhpClass getClassInterface(Project project, @NotNull String className) {
// api workaround for at least interfaces
if(!className.startsWith("\\")) {
className = "\\" + className;
}
Collection<PhpClass> phpClasses = PhpIndex.getInstance(project).getAnyByFQN(className);
return phpClasses.size() == 0 ? null : phpClasses.iterator().next();
}
@NotNull
@Override
public Collection<PsiElement> getPsiTargets(@NotNull PhpToolboxDeclarationHandlerParameter parameter) {
String contents = parameter.getContents();
if(!StringUtil.startsWithChar(contents, '\\')) {
contents = "\\" + contents;
}
return new ArrayList<>(
resolveParameter(PhpIndex.getInstance(parameter.getProject()), contents)
);
}