下面列出了com.intellij.psi.PsiRecursiveElementWalkingVisitor#com.jetbrains.php.lang.psi.PhpFile 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
@NotNull
@Override
public DataIndexer<String, TemplateAnnotationUsage, FileContent> getIndexer() {
return inputData -> {
final Map<String, TemplateAnnotationUsage> map = new HashMap<>();
PsiFile psiFile = inputData.getPsiFile();
if (!(psiFile instanceof PhpFile)) {
return map;
}
if (!AnnotationUtil.isValidForIndex(inputData)) {
return map;
}
psiFile.accept(new MyPsiRecursiveElementWalkingVisitor(map));
return map;
};
}
@NotNull
@Override
public DataIndexer<String, Set<String>, FileContent> getIndexer() {
return inputData -> {
final Map<String, Set<String>> map = new THashMap<>();
PsiFile psiFile = inputData.getPsiFile();
if (psiFile instanceof PhpFile) {
Map<String, ArrayList<TYPO3ServiceDefinition>> serviceMap = new THashMap<>();
psiFile.accept(new CoreServiceDefinitionParserVisitor(serviceMap));
serviceMap.forEach((serviceId, definitionList) -> {
Set<String> implementations = new HashSet<>();
definitionList.forEach(typo3ServiceDefinition -> implementations.add(typo3ServiceDefinition.getClassName()));
map.put(serviceId, implementations);
});
}
return map;
};
}
@Nullable
protected PhpClass getSwitchClass(final AnActionEvent e) {
Object psiFile = e.getData(PlatformDataKeys.PSI_FILE);
if (null == psiFile) {
return null;
}
if (!(psiFile instanceof PhpFile)) {
return null;
}
PhpFile phpFile = ((PhpFile) psiFile);
PhpClass testedClass = getSwitchClass(e.getProject(), phpFile);
if (null == testedClass) {
return null;
}
return testedClass;
}
@Nullable
protected PhpClass getSwitchClass(Project project, PhpFile phpFile) {
PhpClass currentClass = Utils.getFirstTestClassFromFile(phpFile);
if (currentClass != null) {
// The file contains a test class, switch to the tested class
return Utils.locateTestedClass(project, currentClass);
}
currentClass = Utils.getFirstClassFromFile(phpFile);
if (currentClass != null) {
// The file contains a class, switch to the test class if it exists
return Utils.locateTestClass(project, currentClass);
}
return null;
}
@Nullable
protected PhpClass getCurrentTestClass(AnActionEvent e) {
PhpFile phpFile = getPhpFile(e);
if (null == phpFile) {
return null;
}
PhpClass currentClass = Utils.getFirstTestClassFromFile(phpFile);
if (currentClass != null) {
// The file contains a test class, use it
return currentClass;
}
// There is no tests in this file, maybe this is a php class
currentClass = Utils.getFirstClassFromFile(phpFile);
if (null == currentClass) {
return null;
}
// This is a PHP class, find its test
return Utils.locateTestClass(e.getProject(), currentClass);
}
@Nullable
protected Method getCurrentTestMethod(AnActionEvent e) {
PhpFile file = getPhpFile(e);
Editor editor = getEditor(e);
if (file == null || editor == null) {
return null;
}
Method method = PsiTreeUtil.findElementOfClassAtOffset(file, editor.getCaretModel().getOffset(), Method.class, false);
if (method != null && method.getName().startsWith("test")) {
return method;
}
return null;
}
@NotNull
@Override
public DataIndexer<String, Void, FileContent> getIndexer() {
return fileContent -> {
final Map<String, Void> map = new THashMap<>();
PsiFile psiFile = fileContent.getPsiFile();
if(!(psiFile instanceof PhpFile)) {
return map;
}
String namespace = TranslationUtil.getNamespaceFromFilePath(fileContent.getFile().getPath());
if(namespace == null) {
return map;
}
psiFile.acceptChildren(new ArrayReturnPsiRecursiveVisitor(
namespace, (key, psiKey, isRootElement) -> map.put(key, null))
);
return map;
};
}
@NotNull
@Override
public DataIndexer<String, Void, FileContent> getIndexer() {
return fileContent -> {
final Map<String, Void> map = new THashMap<>();
PsiFile psiFile = fileContent.getPsiFile();
if(!(psiFile instanceof PhpFile)) {
return map;
}
psiFile.acceptChildren(new BladeCustomDirectivesVisitor(hit -> map.put(hit.second, null)));
return map;
};
}
@NotNull
@Override
public DataIndexer<String, Void, FileContent> getIndexer() {
return fileContent -> {
final Map<String, Void> map = new THashMap<>();
PsiFile psiFile = fileContent.getPsiFile();
if(!(psiFile instanceof PhpFile)) {
return map;
}
ConfigFileUtil.ConfigFileMatchResult result = ConfigFileUtil.matchConfigFile(fileContent.getProject(), fileContent.getFile());
// config/app.php
// config/testing/app.php
if(result.matches()) {
psiFile.acceptChildren(new ArrayReturnPsiRecursiveVisitor(result.getKeyPrefix(), (key, psiKey, isRootElement) -> {
if (!isRootElement) {
map.put(key, null);
}
}));
}
return map;
};
}
@NotNull
@Override
public DataIndexer<String, String, FileContent> getIndexer() {
return inputData -> {
final Map<String, String> map = new THashMap<>();
PsiFile psiFile = inputData.getPsiFile();
if(!(psiFile instanceof PhpFile)) {
return map;
}
if(!IndexUtil.isValidForIndex(inputData, psiFile)) {
return map;
}
psiFile.accept(new MyPsiRecursiveElementWalkingVisitor(map));
return map;
};
}
@Override
public void visitFile(PsiFile psiFile) {
ProblemRegistrar problemRegistrar = null;
if(psiFile instanceof YAMLFile) {
psiFile.acceptChildren(new YmlClassElementWalkingVisitor(holder, problemRegistrar = new ProblemRegistrar()));
} else if(psiFile instanceof XmlFile) {
psiFile.acceptChildren(new XmlClassElementWalkingVisitor(holder, problemRegistrar = new ProblemRegistrar()));
} else if(psiFile instanceof PhpFile) {
psiFile.acceptChildren(new PhpClassWalkingVisitor(holder, problemRegistrar = new ProblemRegistrar()));
}
if(problemRegistrar != null) {
problemRegistrar.reset();
}
super.visitFile(psiFile);
}
/**
* Index metadata file with its class and repository.
* As of often class stay in static only context
*/
@Nullable
public static Collection<Pair<String, String>> getClassRepositoryPair(@NotNull PsiFile psiFile) {
Collection<Pair<String, String>> pairs = null;
if(psiFile instanceof XmlFile) {
pairs = getClassRepositoryPair((XmlFile) psiFile);
} else if(psiFile instanceof YAMLFile) {
pairs = getClassRepositoryPair((YAMLFile) psiFile);
} else if(psiFile instanceof PhpFile) {
pairs = getClassRepositoryPair((PsiElement) psiFile);
}
return pairs;
}
@NotNull
@Override
public DataIndexer<String, ContainerBuilderCall, FileContent> getIndexer() {
return inputData -> {
Map<String, ContainerBuilderCall> map = new THashMap<>();
PsiFile psiFile = inputData.getPsiFile();
if(!(psiFile instanceof PhpFile) ||
!Symfony2ProjectComponent.isEnabledForIndex(psiFile.getProject()) ||
!isValidForIndex(inputData, psiFile)
){
return map;
}
StreamEx.of(PhpPsiUtil.findAllClasses((PhpFile) psiFile))
.flatMap(clazz -> StreamEx.of(clazz.getOwnMethods()))
.forEach(method -> processMethod(method, map));
return map;
};
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(final @NotNull ProblemsHolder holder, boolean isOnTheFly) {
if(!Symfony2ProjectComponent.isEnabled(holder.getProject())) {
return super.buildVisitor(holder, isOnTheFly);
}
return new PsiElementVisitor() {
@Override
public void visitFile(PsiFile psiFile) {
if(psiFile instanceof XmlFile) {
visitXmlFile(psiFile, holder, new ContainerCollectionResolver.LazyServiceCollector(holder.getProject()));
} else if(psiFile instanceof YAMLFile) {
visitYamlFile(psiFile, holder, new ContainerCollectionResolver.LazyServiceCollector(holder.getProject()));
} else if(psiFile instanceof PhpFile) {
visitPhpFile((PhpFile) psiFile, holder);
}
}
};
}
private boolean isValidForPhpClass(Editor editor, PsiFile file) {
if(!(file instanceof PhpFile)) {
return false;
}
int offset = editor.getCaretModel().getOffset();
if(offset <= 0) {
return false;
}
PsiElement psiElement = file.findElementAt(offset);
if(psiElement == null) {
return false;
}
return PlatformPatterns.psiElement().inside(PhpClass.class).accepts(psiElement);
}
public void update(AnActionEvent event) {
Project project = event.getData(PlatformDataKeys.PROJECT);
if (project == null || !Symfony2ProjectComponent.isEnabled(project)) {
this.setStatus(event, false);
return;
}
Pair<PsiFile, PhpClass> pair = findPhpClass(event);
if(pair == null) {
return;
}
PsiFile psiFile = pair.getFirst();
if(!(psiFile instanceof YAMLFile) && !(psiFile instanceof XmlFile) && !(psiFile instanceof PhpFile)) {
this.setStatus(event, false);
}
}
@Nullable
public static PhpClass getBundleClassInDirectory(@NotNull PsiDirectory bundleDirContext) {
for (PsiFile psiFile : bundleDirContext.getFiles()) {
if(!(psiFile instanceof PhpFile)) {
continue;
}
PhpClass aClass = PhpPsiUtil.findClass((PhpFile) psiFile, phpClass ->
PhpElementsUtil.isInstanceOf(phpClass, "\\Symfony\\Component\\HttpKernel\\Bundle\\BundleInterface")
);
if(aClass != null) {
return aClass;
}
}
return null;
}
@Override
protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
if(!(file instanceof PhpFile) || !DoctrineUtil.isDoctrineOrmInVendor(project)) {
return false;
}
int offset = editor.getCaretModel().getOffset();
if(offset <= 0) {
return false;
}
PsiElement psiElement = file.findElementAt(offset);
if(psiElement == null) {
return false;
}
if(!PlatformPatterns.psiElement().inside(PhpClass.class).accepts(psiElement)) {
return false;
}
return true;
}
@NotNull
@Override
public DataIndexer<String, Set<String>, FileContent> getIndexer() {
return inputData -> {
final Map<String, Set<String>> map = new THashMap<>();
PsiFile psiFile = inputData.getPsiFile();
if(!(psiFile instanceof PhpFile)) {
return map;
}
if(!AnnotationUtil.isValidForIndex(inputData)) {
return map;
}
psiFile.accept(new PhpDocTagAnnotationRecursiveElementWalkingVisitor(pair -> {
map.put(pair.getFirst(), new HashSet<>());
return true;
}));
return map;
};
}
@Override
public Result charTyped(char c, Project project, @NotNull Editor editor, @NotNull PsiFile file) {
if (!(file instanceof PhpFile)) {
return TypedHandlerDelegate.Result.CONTINUE;
}
if ((c != ' ')) {
return TypedHandlerDelegate.Result.CONTINUE;
}
PsiElement psiElement = file.findElementAt(editor.getCaretModel().getOffset() - 2);
if (psiElement == null || !(PlatformPatterns.psiElement(PhpTokenTypes.STRING_LITERAL).accepts(psiElement) || PlatformPatterns.psiElement(PhpTokenTypes.STRING_LITERAL_SINGLE_QUOTE).accepts(psiElement))) {
return TypedHandlerDelegate.Result.CONTINUE;
}
scheduleAutoPopup(project, editor, null);
return TypedHandlerDelegate.Result.CONTINUE;
}
@NotNull
@Override
public Collection<KeyUsagePsiElement> getUsages(PsiFile psiFile) {
if(psiFile instanceof PhpFile) {
PhpEnvironmentCallsVisitor visitor = new PhpEnvironmentCallsVisitor();
psiFile.acceptChildren(visitor);
return visitor.getCollectedItems();
}
return Collections.emptyList();
}
public void actionPerformed(final AnActionEvent e) {
PhpClass currentTestClass = getCurrentTestClass(e);
VirtualFile selectedDir = null;
if (currentTestClass == null) {
selectedDir = getCurrentTestDirectory(e);
if (null == selectedDir) {
return;
}
}
Project project = e.getProject();
RunnerConfiguration runConfiguration = new RunnerConfiguration();
if (null != currentTestClass) {
saveFiles(currentTestClass, project);
runConfiguration.setFile((PhpFile)currentTestClass.getContainingFile());
Method currentTestMethod = getCurrentTestMethod(e);
if (currentTestMethod != null) {
runConfiguration.setMethod(currentTestMethod);
}
}
if (null != selectedDir) {
runConfiguration.setDirectory(selectedDir);
}
Runner runner = new Runner(project);
runner.run(runConfiguration);
}
@Nullable
private PhpFile getPhpFile(AnActionEvent e)
{
PsiFile file = e.getData(CommonDataKeys.PSI_FILE);
if (file instanceof PhpFile) {
return (PhpFile) file;
}
return null;
}
public Icon getIcon(@NotNull PsiElement element, @IconFlags int flags) {
if (element instanceof PhpFile) {
if (Utils.getFirstTestClassFromFile((PhpFile) element) != null) {
return Icons.ATOUM_FILE;
}
}
return null;
}
@Nullable
public static PhpClass getFirstTestClassFromFile(PhpFile phpFile) {
Collection<PhpClass> phpClasses = PsiTreeUtil.collectElementsOfType(phpFile, PhpClass.class);
for (PhpClass phpClass:phpClasses) {
if (isClassAtoumTest(phpClass)) {
return phpClass;
}
}
return null;
}
public void testGetFirstClassFromFile() {
PhpClass phpClass = Utils.getFirstClassFromFile((PhpFile) myFixture.configureByFile(
"TestSimpleClass.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\TestSimpleClass", phpClass.getFQN());
phpClass = Utils.getFirstClassFromFile((PhpFile) myFixture.configureByFile(
"TestMultipleClassNotFirst.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\AnotherClassDefinedBeforeTheTest", phpClass.getFQN());
}
public void testGetFirstTestClassFromFile() {
// Include stubs
myFixture.copyFileToProject("atoum.php");
PhpClass phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestSimpleClass.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\TestSimpleClass", phpClass.getFQN());
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestMultipleClassNotFirst.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\TestMultipleClassNotFirst", phpClass.getFQN());
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestSimpleClassWithoutUse.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\TestSimpleClassWithoutUse", phpClass.getFQN());
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestWithParentClass.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\TestWithParentClass", phpClass.getFQN());
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestWrongExtends.php"
));
assertNull(phpClass);
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestWrongNamespace.php"
));
assertNull(phpClass);
}
public void testGetFirstTestClassFromFileWithoutStubs() {
PhpClass phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestSimpleClass.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\TestSimpleClass", phpClass.getFQN());
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestMultipleClassNotFirst.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\TestMultipleClassNotFirst", phpClass.getFQN());
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestSimpleClassWithoutUse.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\TestSimpleClassWithoutUse", phpClass.getFQN());
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestWithParentClass.php"
));
assertNotNull(phpClass);
assertEquals("\\PhpStormPlugin\\tests\\units\\TestWithParentClass", phpClass.getFQN());
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestWrongExtends.php"
));
assertNull(phpClass);
phpClass = Utils.getFirstTestClassFromFile((PhpFile) myFixture.configureByFile(
"TestWrongNamespace.php"
));
assertNull(phpClass);
}
@Override
protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
if(!(file instanceof PhpFile) || !Symfony2ProjectComponent.isEnabled(project)) {
return false;
}
PhpClass classAtCaret = PhpCodeEditUtil.findClassAtCaret(editor, file);
return
classAtCaret != null &&
PhpElementsUtil.isInstanceOf(classAtCaret, "Symfony\\Component\\Form\\FormTypeInterface")
;
}
/**
* return static function (ContainerConfigurator $container) { ... }
*/
@NotNull
private static Collection<Function> getPhpContainerConfiguratorFunctions(@NotNull PhpFile phpFile) {
Collection<Function> functions = new HashSet<>();
for (PhpNamespace phpNamespace : PhpNamespaceBraceConverter.getAllNamespaces(phpFile)) {
// its used for all service files:
// namespace \Symfony\Component\DependencyInjection\Loader\Configurator { ... }
String fqn = phpNamespace.getFQN();
if (!fqn.equals("\\Symfony\\Component\\DependencyInjection\\Loader\\Configurator")) {
continue;
}
for (PhpReturn phpReturn : PsiTreeUtil.collectElementsOfType(phpNamespace, PhpReturn.class)) {
for (Function function : PsiTreeUtil.collectElementsOfType(phpReturn, Function.class)) {
Parameter parameter = function.getParameter(0);
if (parameter == null) {
continue;
}
// \Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator
if(parameter.getLocalType().getTypes().stream().noneMatch(s -> s.contains("\\ContainerConfigurator"))) {
continue;
}
functions.add(function);
}
}
}
return functions;
}