use of com.intellij.util.Function in project intellij-community by JetBrains.
the class ResetConfigurationModuleAdapter method tryWithAnotherModule.
public static <T extends ModuleBasedConfiguration<JavaRunConfigurationModule> & CommonJavaRunConfigurationParameters> boolean tryWithAnotherModule(T configuration, boolean isDebug) {
final String packageName = configuration.getPackage();
if (packageName == null)
return false;
final Project project = configuration.getProject();
final PsiPackage aPackage = JavaPsiFacade.getInstance(project).findPackage(packageName);
if (aPackage == null)
return false;
final Module module = configuration.getConfigurationModule().getModule();
if (module == null)
return false;
final Set<Module> modulesWithPackage = new HashSet<>();
final PsiDirectory[] directories = aPackage.getDirectories();
for (PsiDirectory directory : directories) {
final Module currentModule = ModuleUtilCore.findModuleForFile(directory.getVirtualFile(), project);
if (module != currentModule && currentModule != null) {
modulesWithPackage.add(currentModule);
}
}
if (!modulesWithPackage.isEmpty()) {
final String testRunDebugId = isDebug ? ToolWindowId.DEBUG : ToolWindowId.RUN;
final ToolWindowManager toolWindowManager = ToolWindowManager.getInstance(project);
final Function<Module, String> moduleNameRef = module1 -> {
final String moduleName = module1.getName();
return "<a href=\"" + moduleName + "\">" + moduleName + "</a>";
};
String message = "Tests were not found in module \"" + module.getName() + "\".\n" + "Use ";
if (modulesWithPackage.size() == 1) {
message += "module \"" + moduleNameRef.fun(modulesWithPackage.iterator().next()) + "\" ";
} else {
message += "one of\n" + StringUtil.join(modulesWithPackage, moduleNameRef, "\n") + "\n";
}
message += "instead";
toolWindowManager.notifyByBalloon(testRunDebugId, MessageType.WARNING, message, null, new ResetConfigurationModuleAdapter(configuration, project, isDebug, toolWindowManager, testRunDebugId));
return true;
}
return false;
}
use of com.intellij.util.Function in project intellij-community by JetBrains.
the class ControlFlowUtil method hasObservableThrowExitPoints.
/**
* Detect throw instructions which might affect observable control flow via side effects with local variables.
*
* The side effect of exception thrown occurs when a local variable is written in the try block, and then accessed
* in the finally section or in/after a catch section.
*
* Example:
* <pre>
* { // --- start of theOuterBlock ---
* Status status = STARTED;
* try { // --- start of theTryBlock ---
* status = PREPARING;
* doPrepare(); // may throw exception
* status = WORKING;
* doWork(); // may throw exception
* status = FINISHED;
* } // --- end of theTryBlock ---
* catch (Exception e) {
* LOG.error("Failed when " + status, e); // can get PREPARING or WORKING here
* }
* if (status == FINISHED) LOG.info("Finished"); // can get PREPARING or WORKING here in the case of exception
* } // --- end of theOuterBlock ---
* </pre>
* In the example above {@code hasObservableThrowExitPoints(theTryBlock) == true},
* because the resulting value of the "status" variable depends on the exceptions being thrown.
* In the same example {@code hasObservableThrowExitPoints(theOuterBlock) == false},
* because no outgoing variables here depend on the exceptions being thrown.
*/
public static boolean hasObservableThrowExitPoints(@NotNull final ControlFlow flow, final int flowStart, final int flowEnd, @NotNull PsiElement[] elements, @NotNull PsiElement enclosingCodeFragment) {
final List<Instruction> instructions = flow.getInstructions();
class Worker {
@NotNull
private Map<PsiVariable, IntArrayList> getWritesOffsets() {
final Map<PsiVariable, IntArrayList> writeOffsets = new THashMap<>();
for (int i = flowStart; i < flowEnd; i++) {
Instruction instruction = instructions.get(i);
if (instruction instanceof WriteVariableInstruction) {
final PsiVariable variable = ((WriteVariableInstruction) instruction).variable;
if (variable instanceof PsiLocalVariable || variable instanceof PsiParameter) {
IntArrayList offsets = writeOffsets.get(variable);
if (offsets == null)
writeOffsets.put(variable, offsets = new IntArrayList());
offsets.add(i);
}
}
}
LOG.debug("writeOffsets:", writeOffsets);
return writeOffsets;
}
@NotNull
private Map<PsiVariable, IntArrayList> getVisibleReadsOffsets(Map<PsiVariable, IntArrayList> writeOffsets, PsiCodeBlock tryBlock) {
final Map<PsiVariable, IntArrayList> visibleReadOffsets = new THashMap<>();
for (PsiVariable variable : writeOffsets.keySet()) {
if (!PsiTreeUtil.isAncestor(tryBlock, variable, true)) {
visibleReadOffsets.put(variable, new IntArrayList());
}
}
if (visibleReadOffsets.isEmpty())
return visibleReadOffsets;
for (int i = 0; i < instructions.size(); i++) {
final Instruction instruction = instructions.get(i);
if (instruction instanceof ReadVariableInstruction) {
final PsiVariable variable = ((ReadVariableInstruction) instruction).variable;
final IntArrayList readOffsets = visibleReadOffsets.get(variable);
if (readOffsets != null) {
readOffsets.add(i);
}
}
}
LOG.debug("visibleReadOffsets:", visibleReadOffsets);
return visibleReadOffsets;
}
@NotNull
private Map<PsiVariable, Set<PsiElement>> getReachableAfterWrite(Map<PsiVariable, IntArrayList> writeOffsets, Map<PsiVariable, IntArrayList> visibleReadOffsets) {
final Map<PsiVariable, Set<PsiElement>> afterWrite = new THashMap<>();
for (PsiVariable variable : visibleReadOffsets.keySet()) {
final Function<Integer, BitSet> calculator = getReachableInstructionsCalculator();
final BitSet collectedOffsets = new BitSet(flowEnd);
for (final int writeOffset : writeOffsets.get(variable).toArray()) {
LOG.assertTrue(writeOffset >= flowStart, "writeOffset");
final BitSet reachableOffsets = calculator.fun(writeOffset);
collectedOffsets.or(reachableOffsets);
}
Set<PsiElement> throwSources = afterWrite.get(variable);
if (throwSources == null)
afterWrite.put(variable, throwSources = new THashSet<>());
for (int i = flowStart; i < flowEnd; i++) {
if (collectedOffsets.get(i)) {
throwSources.add(flow.getElement(i));
}
}
final List<PsiElement> subordinates = new ArrayList<>();
for (PsiElement element : throwSources) {
if (throwSources.contains(element.getParent())) {
subordinates.add(element);
}
}
throwSources.removeAll(subordinates);
}
LOG.debug("afterWrite:", afterWrite);
return afterWrite;
}
@NotNull
private IntArrayList getCatchOrFinallyOffsets(List<PsiTryStatement> tryStatements, List<PsiClassType> thrownExceptions) {
final IntArrayList catchOrFinallyOffsets = new IntArrayList();
for (PsiTryStatement tryStatement : tryStatements) {
final PsiCodeBlock finallyBlock = tryStatement.getFinallyBlock();
if (finallyBlock != null) {
int offset = flow.getStartOffset(finallyBlock);
if (offset >= 0) {
// -2 is an adjustment for rethrow-after-finally
catchOrFinallyOffsets.add(offset - 2);
}
}
for (PsiCatchSection catchSection : tryStatement.getCatchSections()) {
final PsiCodeBlock catchBlock = catchSection.getCatchBlock();
final PsiParameter parameter = catchSection.getParameter();
if (catchBlock != null && parameter != null) {
for (PsiClassType throwType : thrownExceptions) {
if (isCaughtExceptionType(throwType, parameter.getType())) {
int offset = flow.getStartOffset(catchBlock);
if (offset >= 0) {
// -1 is an adjustment for catch block initialization
catchOrFinallyOffsets.add(offset - 1);
}
}
}
}
}
}
return catchOrFinallyOffsets;
}
private boolean isAnyReadOffsetReachableFrom(IntArrayList readOffsets, IntArrayList fromOffsets) {
if (readOffsets != null && !readOffsets.isEmpty()) {
final int[] readOffsetsArray = readOffsets.toArray();
for (int j = 0; j < fromOffsets.size(); j++) {
int fromOffset = fromOffsets.get(j);
if (areInstructionsReachable(flow, readOffsetsArray, fromOffset)) {
LOG.debug("reachableFromOffset:", fromOffset);
return true;
}
}
}
return false;
}
private Function<Integer, BitSet> getReachableInstructionsCalculator() {
final ControlFlowGraph graph = new ControlFlowGraph(flow.getSize()) {
@Override
void addArc(int offset, int nextOffset) {
nextOffset = promoteThroughGotoChain(flow, nextOffset);
if (nextOffset >= flowStart && nextOffset < flowEnd) {
super.addArc(offset, nextOffset);
}
}
};
graph.buildFrom(flow);
return startOffset -> {
BitSet visitedOffsets = new BitSet(flowEnd);
graph.depthFirstSearch(startOffset, visitedOffsets);
return visitedOffsets;
};
}
}
final Worker worker = new Worker();
final Map<PsiVariable, IntArrayList> writeOffsets = worker.getWritesOffsets();
if (writeOffsets.isEmpty())
return false;
final PsiElement commonParent = elements.length != 1 ? PsiTreeUtil.findCommonParent(elements) : elements[0].getParent();
final List<PsiTryStatement> tryStatements = collectTryStatementStack(commonParent, enclosingCodeFragment);
if (tryStatements.isEmpty())
return false;
final PsiCodeBlock tryBlock = tryStatements.get(0).getTryBlock();
if (tryBlock == null)
return false;
final Map<PsiVariable, IntArrayList> visibleReadOffsets = worker.getVisibleReadsOffsets(writeOffsets, tryBlock);
if (visibleReadOffsets.isEmpty())
return false;
final Map<PsiVariable, Set<PsiElement>> afterWrite = worker.getReachableAfterWrite(writeOffsets, visibleReadOffsets);
if (afterWrite.isEmpty())
return false;
for (Map.Entry<PsiVariable, Set<PsiElement>> entry : afterWrite.entrySet()) {
final PsiVariable variable = entry.getKey();
final PsiElement[] psiElements = entry.getValue().toArray(PsiElement.EMPTY_ARRAY);
final List<PsiClassType> thrownExceptions = ExceptionUtil.getThrownExceptions(psiElements);
if (!thrownExceptions.isEmpty()) {
final IntArrayList catchOrFinallyOffsets = worker.getCatchOrFinallyOffsets(tryStatements, thrownExceptions);
if (worker.isAnyReadOffsetReachableFrom(visibleReadOffsets.get(variable), catchOrFinallyOffsets)) {
return true;
}
}
}
return false;
}
use of com.intellij.util.Function in project intellij-community by JetBrains.
the class PsiDiamondTypeImpl method generateStaticFactory.
@Nullable
private static PsiMethod generateStaticFactory(@Nullable PsiMethod constructor, PsiClass containingClass, PsiTypeParameter[] params, PsiJavaCodeReferenceElement reference) {
final StringBuilder buf = new StringBuilder();
final String modifier = VisibilityUtil.getVisibilityModifier(constructor != null ? constructor.getModifierList() : containingClass.getModifierList());
if (!PsiModifier.PACKAGE_LOCAL.equals(modifier)) {
buf.append(modifier);
buf.append(" ");
}
buf.append("static ");
buf.append("<");
//it's possible that constructor type parameters and class type parameters are same named:
//it's important that class type parameters names are preserved(they are first in the list),
//though constructor parameters would be renamed in case of conflicts
final UniqueNameGenerator generator = new UniqueNameGenerator();
buf.append(StringUtil.join(params, psiTypeParameter -> {
String extendsList = "";
if (psiTypeParameter.getLanguage().isKindOf(JavaLanguage.INSTANCE)) {
final PsiClassType[] extendsListTypes = psiTypeParameter.getExtendsListTypes();
if (extendsListTypes.length > 0) {
final Function<PsiClassType, String> canonicalTypePresentationFun = type -> type.getCanonicalText();
extendsList = " extends " + StringUtil.join(extendsListTypes, canonicalTypePresentationFun, "&");
}
}
return generator.generateUniqueName(psiTypeParameter.getName()) + extendsList;
}, ", "));
buf.append(">");
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(containingClass.getProject());
String qualifiedName = containingClass.getQualifiedName();
PsiElement qualifier = reference != null ? reference.getQualifier() : null;
if (qualifier instanceof PsiJavaCodeReferenceElement) {
final JavaResolveResult resolveResult = ((PsiJavaCodeReferenceElement) qualifier).advancedResolve(false);
final PsiElement element = resolveResult.getElement();
if (element instanceof PsiClass) {
final String outerClassSubstitutedQName = elementFactory.createType((PsiClass) element, resolveResult.getSubstitutor()).getInternalCanonicalText();
qualifiedName = outerClassSubstitutedQName + "." + containingClass.getName();
}
} else if (reference != null && qualifier == null && containingClass.getContainingClass() != null) {
qualifiedName = null;
}
buf.append(qualifiedName != null ? qualifiedName : containingClass.getName());
final PsiTypeParameter[] parameters = containingClass.getTypeParameters();
buf.append("<");
buf.append(StringUtil.join(parameters, psiTypeParameter -> psiTypeParameter.getName(), ", "));
buf.append("> ");
String staticFactoryName = "staticFactory";
final JavaCodeStyleManager styleManager = JavaCodeStyleManager.getInstance(containingClass.getProject());
staticFactoryName = styleManager.suggestUniqueVariableName(staticFactoryName, containingClass, false);
buf.append(staticFactoryName);
if (constructor == null) {
buf.append("()");
} else {
buf.append("(").append(StringUtil.join(constructor.getParameterList().getParameters(), new Function<PsiParameter, String>() {
int myIdx;
@Override
public String fun(PsiParameter psiParameter) {
return psiParameter.getType().getCanonicalText() + " p" + myIdx++;
}
}, ",")).append(")");
}
buf.append("{}");
try {
return elementFactory.createMethodFromText(buf.toString(), constructor != null ? constructor : containingClass);
} catch (IncorrectOperationException e) {
return null;
}
}
use of com.intellij.util.Function in project intellij-community by JetBrains.
the class PsiFileImpl method getStubTree.
/**
* @return a stub tree, if this file has it, and only if AST isn't loaded
*/
@Override
@Nullable
public StubTree getStubTree() {
ApplicationManager.getApplication().assertReadAccessAllowed();
if (myTrees.astLoaded && !mayReloadStub())
return null;
if (Boolean.TRUE.equals(getUserData(BUILDING_STUB)))
return null;
final StubTree derefd = derefStub();
if (derefd != null)
return derefd;
if (getElementTypeForStubBuilder() == null)
return null;
final VirtualFile vFile = getVirtualFile();
if (!(vFile instanceof VirtualFileWithId) || !vFile.isValid())
return null;
ObjectStubTree tree = StubTreeLoader.getInstance().readOrBuild(getProject(), vFile, this);
if (!(tree instanceof StubTree))
return null;
final FileViewProvider viewProvider = getViewProvider();
final List<Pair<IStubFileElementType, PsiFile>> roots = StubTreeBuilder.getStubbedRoots(viewProvider);
synchronized (PsiLock.LOCK) {
if (getTreeElement() != null || hasUnbindableCachedPsi())
return null;
final StubTree derefdOnLock = derefStub();
if (derefdOnLock != null)
return derefdOnLock;
PsiFileStub baseRoot = ((StubTree) tree).getRoot();
if (baseRoot instanceof PsiFileStubImpl && !((PsiFileStubImpl) baseRoot).rootsAreSet()) {
LOG.error("Stub roots must be set when stub tree was read or built with StubTreeLoader");
return null;
}
final PsiFileStub[] stubRoots = baseRoot.getStubRoots();
if (stubRoots.length != roots.size()) {
final Function<PsiFileStub, String> stubToString = stub -> stub.getClass().getSimpleName();
LOG.error("readOrBuilt roots = " + StringUtil.join(stubRoots, stubToString, ", ") + "; " + StubTreeLoader.getFileViewProviderMismatchDiagnostics(viewProvider));
rebuildStub();
return null;
}
// first, set all references from stubs to existing PSI (in AST or AstPathPsiMap)
Map<PsiFileImpl, StubTree> bindings = prepareAllStubTrees(roots, stubRoots);
StubTree result = bindings.get(this);
assert result != null : "Current file not in root list: " + roots + ", vp=" + viewProvider;
// now stubs can be safely published
for (PsiFileImpl eachPsiRoot : bindings.keySet()) {
eachPsiRoot.updateTrees(eachPsiRoot.myTrees.withExclusiveStub(bindings.get(eachPsiRoot), bindings.keySet()));
}
return result;
}
}
use of com.intellij.util.Function in project intellij-community by JetBrains.
the class PermanentCommitsInfoImpl method newInstance.
@NotNull
public static <CommitId> PermanentCommitsInfoImpl<CommitId> newInstance(@NotNull final List<? extends GraphCommit<CommitId>> graphCommits, @NotNull Map<Integer, CommitId> notLoadedCommits) {
TimestampGetter timestampGetter = createTimestampGetter(graphCommits);
boolean isIntegerCase = !graphCommits.isEmpty() && graphCommits.get(0).getId().getClass() == Integer.class;
List<CommitId> commitIdIndex;
if (isIntegerCase) {
commitIdIndex = (List<CommitId>) createCompressedIntList((List<? extends GraphCommit<Integer>>) graphCommits);
} else {
commitIdIndex = ContainerUtil.map(graphCommits, (Function<GraphCommit<CommitId>, CommitId>) GraphCommit::getId);
}
return new PermanentCommitsInfoImpl<>(timestampGetter, commitIdIndex, notLoadedCommits);
}
Aggregations