PsiVariable (@NotNull PsiElement endPositionElement) { final PsiElement parent = endPositionElement.getParent(); if (parent == null) return null; // reuse of cache is possible IF requests are done up-to-down. otherwise - not first declaration can be returned final PsiVariable cachedCandidate = cache.get(parent); if (cachedCandidate != null) { return cachedCandidate; } if (parent != myMethod) { // go up final PsiVariable parentResult = getLocalDeclaration(parent); if (parentResult != null) { return parentResult; } } // look self for (PsiElement element = parent.getFirstChild(); element != null; element = element.getNextSibling()) { if (element == endPositionElement) { break; } if (element instanceof PsiDeclarationStatement) { final PsiElement[] declared = ((PsiDeclarationStatement) element).getDeclaredElements(); for (final PsiElement declaredElement : declared) { if (declaredElement instanceof PsiLocalVariable && myTargetType.equals(((PsiLocalVariable)declaredElement).getType())) { return goThroughCache(parent, (PsiVariable) declaredElement); } } } else if (element instanceof PsiParameter) { // foreach if (myTargetType.equals(((PsiParameter) element).getType())) { return goThroughCache(parent, (PsiVariable) element); } } } return null; }