private Domination dominates( PsiClass aClass, boolean accessible, String fqName, ClassCandidateInfo info) { final PsiClass otherClass = info.getElement(); assert otherClass != null; String otherQName = otherClass.getQualifiedName(); if (fqName.equals(otherQName)) { return Domination.DOMINATED_BY; } final PsiClass containingClass1 = aClass.getContainingClass(); final PsiClass containingClass2 = otherClass.getContainingClass(); if (containingClass1 != null && containingClass2 != null && containingClass2.isInheritor(containingClass1, true) && !isImported(myCurrentFileContext)) { // shadowing return Domination.DOMINATED_BY; } boolean infoAccessible = info.isAccessible(); if (infoAccessible && !accessible) { return Domination.DOMINATED_BY; } if (!infoAccessible && accessible) { return Domination.DOMINATES; } // everything wins over class from default package boolean isDefault = StringUtil.getPackageName(fqName).length() == 0; boolean otherDefault = otherQName != null && StringUtil.getPackageName(otherQName).length() == 0; if (isDefault && !otherDefault) { return Domination.DOMINATED_BY; } if (!isDefault && otherDefault) { return Domination.DOMINATES; } // single import wins over on-demand boolean myOnDemand = isOnDemand(myCurrentFileContext, aClass); boolean otherOnDemand = isOnDemand(info.getCurrentFileResolveScope(), otherClass); if (myOnDemand && !otherOnDemand) { return Domination.DOMINATED_BY; } if (!myOnDemand && otherOnDemand) { return Domination.DOMINATES; } return Domination.EQUAL; }
private static void generateImportCode( StringBuilder imports, String className, Collection<String> customRunners) { if (!StringUtil.isEmpty(StringUtil.getPackageName(className))) { generateImportCode(imports, className); } for (String customRunner : customRunners) { generateImportCode(imports, customRunner); } }
@Nullable public static JetClassOrObject getMainClass(@NotNull JetFile file) { List<JetDeclaration> classes = ContainerUtil.filter( file.getDeclarations(), new Condition<JetDeclaration>() { @Override public boolean value(JetDeclaration jetDeclaration) { return jetDeclaration instanceof JetClassOrObject; } }); if (classes.size() == 1) { if (StringUtil.getPackageName(file.getName()).equals(classes.get(0).getName())) { return (JetClassOrObject) classes.get(0); } } return null; }
private void appendClassName(PsiElement declaration) { if (declaration instanceof PsiClass) { final PsiClass psiClass = (PsiClass) declaration; final String ownerClassQN = getTopmostOwnerClassQualifiedName(psiClass); if (ownerClassQN != null) { appendClassName(ownerClassQN); final String ownerClassPackageName = StringUtil.getPackageName(ownerClassQN); if (!StringUtil.isEmpty(ownerClassPackageName)) { appendDemandedPackageName(ownerClassPackageName); } } else { final String classQN = psiClass.getQualifiedName(); if (classQN != null) { appendClassName(classQN); } } } }
public static boolean isSourceLevelAccessible( PsiElement context, PsiClass psiClass, final boolean pkgContext) { if (!JavaPsiFacade.getInstance(psiClass.getProject()) .getResolveHelper() .isAccessible(psiClass, context, null)) { return false; } if (pkgContext) { PsiClass topLevel = PsiUtil.getTopLevelClass(psiClass); if (topLevel != null) { String fqName = topLevel.getQualifiedName(); if (fqName != null && StringUtil.isEmpty(StringUtil.getPackageName(fqName))) { return false; } } } return true; }
@NotNull private PsiClass[] findClassesInDumbMode( @NotNull String qualifiedName, @NotNull GlobalSearchScope scope) { String packageName = StringUtil.getPackageName(qualifiedName); PsiJavaPackage pkg = findPackage(packageName, scope); String className = StringUtil.getShortName(qualifiedName); if (pkg == null && packageName.length() < qualifiedName.length()) { PsiClass[] containingClasses = findClassesInDumbMode(packageName, scope); if (containingClasses.length == 1) { return PsiElementFinder.filterByName(className, containingClasses[0].getInnerClasses()); } return PsiClass.EMPTY_ARRAY; } if (pkg == null || !pkg.containsClassNamed(className)) { return PsiClass.EMPTY_ARRAY; } return pkg.findClassByShortName(className, scope); }
private boolean isOnDemand(PsiElement fileContext, PsiClass psiClass) { if (isImported(fileContext)) { return ((PsiImportStatementBase) fileContext).isOnDemand(); } String fqn = psiClass.getQualifiedName(); if (fqn == null) return false; PsiFile file = myPlace == null ? null : FileContextUtil.getContextFile(myPlace); String[] defaultPackages = file instanceof PsiJavaFile ? ((PsiJavaFile) file).getImplicitlyImportedPackages() : DEFAULT_PACKAGES; String packageName = StringUtil.getPackageName(fqn); for (String defaultPackage : defaultPackages) { if (defaultPackage.equals(packageName)) return true; } // class from my package imported implicitly return file instanceof PsiJavaFile && ((PsiJavaFile) file).getPackageName().equals(packageName); }
private static void processAvailableTraces( RunConfigurationBase configuration, String[] fullTestNames) { final String tracesDirectory = getTracesDirectory(configuration); final TestDiscoveryIndex coverageIndex = TestDiscoveryIndex.getInstance(configuration.getProject()); synchronized (ourTracesLock) { for (String fullTestName : fullTestNames) { final String className = StringUtil.getPackageName(fullTestName); final String methodName = StringUtil.getShortName(fullTestName); if (!StringUtil.isEmptyOrSpaces(className) && !StringUtil.isEmptyOrSpaces(methodName)) { final File testMethodTrace = new File(tracesDirectory, className + "-" + methodName + ".tr"); if (testMethodTrace.exists()) { try { coverageIndex.updateFromTestTrace(testMethodTrace); FileUtil.delete(testMethodTrace); } catch (IOException e) { LOG.error("Can not load " + testMethodTrace, e); } } } } } }
@NotNull public String getDisplayName() { final String className = getClassName(); if (StringUtil.isEmpty(className)) return "<unnamed>"; MethodInfo singleInfo = null; for (MethodInfo info : myParameterMap.values()) { if (info.isEnabled()) { if (singleInfo == null) { singleInfo = info; } else { singleInfo = null; break; } } } final String name = singleInfo != null ? StringUtil.getShortName(className) + "." + singleInfo.methodName : StringUtil.getShortName(className); return /*"["+getInjectedLanguageId()+"] " +*/ name + " (" + StringUtil.getPackageName(className) + ")"; }
public static MultiMap<PsiElement, String> checkConflicts( final MemberInfoBase<? extends PsiMember>[] infos, @NotNull final PsiClass subclass, @Nullable PsiClass superClass, @NotNull final PsiPackage targetPackage, @NotNull PsiDirectory targetDirectory, final InterfaceContainmentVerifier interfaceContainmentVerifier, boolean movedMembers2Super) { final Set<PsiMember> movedMembers = new HashSet<PsiMember>(); final Set<PsiMethod> abstractMethods = new HashSet<PsiMethod>(); final boolean isInterfaceTarget; final PsiElement targetRepresentativeElement; if (superClass != null) { isInterfaceTarget = superClass.isInterface(); targetRepresentativeElement = superClass; } else { isInterfaceTarget = false; targetRepresentativeElement = targetDirectory; } for (MemberInfoBase<? extends PsiMember> info : infos) { PsiMember member = info.getMember(); if (member instanceof PsiMethod) { if (!info.isToAbstract() && !isInterfaceTarget) { movedMembers.add(member); } else { abstractMethods.add((PsiMethod) member); } } else { movedMembers.add(member); } } final MultiMap<PsiElement, String> conflicts = new MultiMap<PsiElement, String>(); final Set<PsiMethod> abstrMethods = new HashSet<PsiMethod>(abstractMethods); if (superClass != null) { for (PsiMethod method : subclass.getMethods()) { if (!movedMembers.contains(method) && !method.hasModifierProperty(PsiModifier.PRIVATE)) { if (method.findSuperMethods(superClass).length > 0) { abstrMethods.add(method); } } } } RefactoringConflictsUtil.analyzeAccessibilityConflicts( movedMembers, superClass, conflicts, VisibilityUtil.ESCALATE_VISIBILITY, targetRepresentativeElement, abstrMethods); if (superClass != null) { if (movedMembers2Super) { checkSuperclassMembers(superClass, infos, conflicts); if (isInterfaceTarget) { checkInterfaceTarget(infos, conflicts); } } else { final String qualifiedName = superClass.getQualifiedName(); assert qualifiedName != null; if (superClass.hasModifierProperty(PsiModifier.PACKAGE_LOCAL)) { if (!Comparing.strEqual( StringUtil.getPackageName(qualifiedName), targetPackage.getQualifiedName())) { conflicts.putValue( superClass, RefactoringUIUtil.getDescription(superClass, true) + " won't be accessible from " + RefactoringUIUtil.getDescription(targetPackage, true)); } } } } // check if moved methods use other members in the classes between Subclass and Superclass List<PsiElement> checkModuleConflictsList = new ArrayList<PsiElement>(); for (PsiMember member : movedMembers) { if (member instanceof PsiMethod || member instanceof PsiClass && !(member instanceof PsiCompiledElement)) { ClassMemberReferencesVisitor visitor = movedMembers2Super ? new ConflictingUsagesOfSubClassMembers( member, movedMembers, abstractMethods, subclass, superClass, superClass != null ? null : targetPackage, conflicts, interfaceContainmentVerifier) : new ConflictingUsagesOfSuperClassMembers( member, subclass, targetPackage, movedMembers, conflicts); member.accept(visitor); } ContainerUtil.addIfNotNull(checkModuleConflictsList, member); } for (final PsiMethod method : abstractMethods) { ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getParameterList()); ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getReturnTypeElement()); ContainerUtil.addIfNotNull(checkModuleConflictsList, method.getTypeParameterList()); } RefactoringConflictsUtil.analyzeModuleConflicts( subclass.getProject(), checkModuleConflictsList, new UsageInfo[0], targetRepresentativeElement, conflicts); final String fqName = subclass.getQualifiedName(); final String packageName; if (fqName != null) { packageName = StringUtil.getPackageName(fqName); } else { final PsiFile psiFile = PsiTreeUtil.getParentOfType(subclass, PsiFile.class); if (psiFile instanceof PsiClassOwner) { packageName = ((PsiClassOwner) psiFile).getPackageName(); } else { packageName = null; } } final boolean toDifferentPackage = !Comparing.strEqual(targetPackage.getQualifiedName(), packageName); for (final PsiMethod abstractMethod : abstractMethods) { abstractMethod.accept( new ClassMemberReferencesVisitor(subclass) { @Override protected void visitClassMemberReferenceElement( PsiMember classMember, PsiJavaCodeReferenceElement classMemberReference) { if (classMember != null && willBeMoved(classMember, movedMembers)) { boolean isAccessible = false; if (classMember.hasModifierProperty(PsiModifier.PRIVATE)) { isAccessible = true; } else if (classMember.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) && toDifferentPackage) { isAccessible = true; } if (isAccessible) { String message = RefactoringUIUtil.getDescription(abstractMethod, false) + " uses " + RefactoringUIUtil.getDescription(classMember, true) + " which won't be accessible from the subclass."; message = CommonRefactoringUtil.capitalize(message); conflicts.putValue(classMember, message); } } } }); if (abstractMethod.hasModifierProperty(PsiModifier.PACKAGE_LOCAL) && toDifferentPackage) { if (!isInterfaceTarget) { String message = "Can't make " + RefactoringUIUtil.getDescription(abstractMethod, false) + " abstract as it won't be accessible from the subclass."; message = CommonRefactoringUtil.capitalize(message); conflicts.putValue(abstractMethod, message); } } } return conflicts; }
private void buildText( @NotNull PsiClass aClass, @NotNull PsiSubstitutor substitutor, @NotNull StringBuilder buffer, @NotNull TextType textType, boolean annotated) { if (aClass instanceof PsiAnonymousClass) { ClassResolveResult baseResolveResult = ((PsiAnonymousClass) aClass).getBaseClassType().resolveGenerics(); PsiClass baseClass = baseResolveResult.getElement(); if (baseClass != null) { buildText(baseClass, baseResolveResult.getSubstitutor(), buffer, textType, false); } return; } boolean qualified = textType != TextType.PRESENTABLE; PsiClass enclosingClass = null; if (!aClass.hasModifierProperty(PsiModifier.STATIC)) { PsiElement parent = aClass.getParent(); if (parent instanceof PsiClass && !(parent instanceof PsiAnonymousClass)) { enclosingClass = (PsiClass) parent; } } if (enclosingClass != null) { buildText(enclosingClass, substitutor, buffer, textType, false); buffer.append('.'); } else if (qualified) { String fqn = aClass.getQualifiedName(); if (fqn != null) { String prefix = StringUtil.getPackageName(fqn); if (!StringUtil.isEmpty(prefix)) { buffer.append(prefix); buffer.append('.'); } } } if (annotated) { PsiNameHelper.appendAnnotations(buffer, getAnnotations(), qualified); } buffer.append(aClass.getName()); PsiTypeParameter[] typeParameters = aClass.getTypeParameters(); if (typeParameters.length > 0) { int pos = buffer.length(); buffer.append('<'); for (int i = 0; i < typeParameters.length; i++) { PsiTypeParameter typeParameter = typeParameters[i]; PsiUtilCore.ensureValid(typeParameter); if (i > 0) { buffer.append(','); if (textType == TextType.PRESENTABLE) buffer.append(' '); } PsiType substitutionResult = substitutor.substitute(typeParameter); if (substitutionResult == null) { buffer.setLength(pos); pos = -1; break; } PsiUtil.ensureValidType(substitutionResult); if (textType == TextType.PRESENTABLE) { buffer.append(substitutionResult.getPresentableText()); } else if (textType == TextType.CANONICAL) { buffer.append(substitutionResult.getCanonicalText(annotated)); } else { buffer.append(substitutionResult.getInternalCanonicalText()); } } if (pos >= 0) { buffer.append('>'); } } }
private Domination dominates( PsiClass aClass, boolean accessible, String fqName, ClassCandidateInfo info) { final PsiClass otherClass = info.getElement(); assert otherClass != null; String otherQName = otherClass.getQualifiedName(); if (fqName.equals(otherQName)) { return Domination.DOMINATED_BY; } final PsiClass containingClass1 = aClass.getContainingClass(); final PsiClass containingClass2 = otherClass.getContainingClass(); if (myAccessClass != null && !Comparing.equal(containingClass1, containingClass2)) { if (myAccessClass.equals(containingClass1)) return Domination.DOMINATES; if (myAccessClass.equals(containingClass2)) return Domination.DOMINATED_BY; } // JLS 8.5: // A class may inherit two or more type declarations with the same name, either from two // interfaces or from its superclass and an interface. // It is a compile-time error to attempt to refer to any ambiguously inherited class or // interface by its simple name. if (containingClass1 != null && containingClass2 != null && containingClass2.isInheritor(containingClass1, true) && !isImported(myCurrentFileContext)) { if (!isAmbiguousInherited(containingClass1)) { // shadowing return Domination.DOMINATED_BY; } } boolean infoAccessible = info.isAccessible() && isAccessible(otherClass); if (infoAccessible && !accessible) { return Domination.DOMINATED_BY; } if (!infoAccessible && accessible) { return Domination.DOMINATES; } // everything wins over class from default package boolean isDefault = StringUtil.getPackageName(fqName).length() == 0; boolean otherDefault = otherQName != null && StringUtil.getPackageName(otherQName).length() == 0; if (isDefault && !otherDefault) { return Domination.DOMINATED_BY; } if (!isDefault && otherDefault) { return Domination.DOMINATES; } // single import wins over on-demand boolean myOnDemand = isOnDemand(myCurrentFileContext, aClass); boolean otherOnDemand = isOnDemand(info.getCurrentFileResolveScope(), otherClass); if (myOnDemand && !otherOnDemand) { return Domination.DOMINATED_BY; } if (!myOnDemand && otherOnDemand) { return Domination.DOMINATES; } return Domination.EQUAL; }
@NotNull @Override public Runnable processFile(final PsiFile file) { VirtualFile vFile = file.getVirtualFile(); if (vFile instanceof VirtualFileWindow) vFile = ((VirtualFileWindow) vFile).getDelegate(); final Project project = file.getProject(); if (vFile == null || !ProjectRootManager.getInstance(project).getFileIndex().isInSourceContent(vFile)) { return EmptyRunnable.INSTANCE; } final List<Pair<String, Boolean>> names = new ArrayList<Pair<String, Boolean>>(); final Set<String> demandedForNested = new HashSet<>(); collectNamesToImport(names, demandedForNested, (XmlFile) file); Collections.sort(names, (o1, o2) -> StringUtil.compare(o1.first, o2.first, true)); final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(project); final List<Pair<String, Boolean>> sortedNames = ImportHelper.sortItemsAccordingToSettings(names, settings); final HashSet<String> onDemand = new HashSet<String>(); ImportHelper.collectOnDemandImports(sortedNames, onDemand, settings); onDemand.addAll(demandedForNested); final Set<String> imported = new HashSet<String>(); final List<String> imports = new ArrayList<String>(); for (Pair<String, Boolean> pair : sortedNames) { final String qName = pair.first; final String packageName = StringUtil.getPackageName(qName); if (imported.contains(packageName) || imported.contains(qName)) { continue; } if (onDemand.contains(packageName)) { imported.add(packageName); imports.add("<?import " + packageName + ".*?>"); } else { imported.add(qName); imports.add("<?import " + qName + "?>"); } } final PsiFileFactory factory = PsiFileFactory.getInstance(file.getProject()); final XmlFile dummyFile = (XmlFile) factory.createFileFromText( "_Dummy_.fxml", StdFileTypes.XML, StringUtil.join(imports, "\n")); final XmlDocument document = dummyFile.getDocument(); final XmlProlog newImportList = document != null ? document.getProlog() : null; if (newImportList == null) return EmptyRunnable.getInstance(); return () -> { final XmlDocument xmlDocument = ((XmlFile) file).getDocument(); final XmlProlog prolog = xmlDocument != null ? xmlDocument.getProlog() : null; if (prolog != null) { final Collection<XmlProcessingInstruction> instructions = PsiTreeUtil.findChildrenOfType(prolog, XmlProcessingInstruction.class); for (final XmlProcessingInstruction instruction : instructions) { final ASTNode node = instruction.getNode(); final ASTNode nameNode = node.findChildByType(XmlTokenType.XML_NAME); if (nameNode != null && nameNode.getText().equals("import")) { instruction.delete(); } } prolog.add(newImportList); } else { document.addBefore(newImportList, document.getRootTag()); } }; }