lvcs-impl
[idea/community.git] / lang-api / src / com / intellij / lang / parameterInfo / ParameterInfoUtils.java
1 /*
2  * Copyright 2000-2007 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package com.intellij.lang.parameterInfo;
18
19 import com.intellij.lang.ASTNode;
20 import com.intellij.openapi.util.TextRange;
21 import com.intellij.psi.PsiElement;
22 import com.intellij.psi.PsiFile;
23 import com.intellij.psi.tree.IElementType;
24 import com.intellij.psi.util.PsiTreeUtil;
25 import com.intellij.util.text.CharArrayUtil;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.annotations.Nullable;
28
29 import java.util.Set;
30
31 /**
32  * @author Maxim.Mossienko
33  */
34 public class ParameterInfoUtils {
35   public static final String DEFAULT_PARAMETER_CLOSE_CHARS = ",){}";
36
37   public static <T extends PsiElement> T findParentOfType (PsiFile file, int offset, Class<T> parentClass) {
38     PsiElement element = file.findElementAt(offset);
39     if (element == null) return null;
40     return PsiTreeUtil.getParentOfType(element, parentClass);
41   }
42
43   public static int getCurrentParameterIndex(ASTNode argList, int offset, IElementType delimiterType) {
44     int curOffset = argList.getTextRange().getStartOffset();
45     if (offset < curOffset) return -1;
46     ASTNode[] children = argList.getChildren(null);
47     int index = 0;
48
49     for (ASTNode child : children) {
50       curOffset += child.getTextLength();
51       if (offset < curOffset) break;
52
53       IElementType type = child.getElementType();
54       if (type == delimiterType) index++;
55     }
56
57     return index;
58   }
59
60   @Nullable
61   public static <E extends PsiElement> E findArgumentList(PsiFile file, int offset, int lbraceOffset,
62                                                           @NotNull ParameterInfoHandlerWithTabActionSupport findArgumentListHelper){
63     if (file == null) return null;
64
65     CharSequence chars = file.getViewProvider().getContents();
66     if (offset >= chars.length()) offset = chars.length() - 1;
67     int offset1 = CharArrayUtil.shiftBackward(chars, offset, " \t\n\r");
68     if (offset1 < 0) return null;
69     boolean acceptRparenth = true;
70     boolean acceptLparenth = false;
71     if (offset1 != offset){
72       offset = offset1;
73       acceptRparenth = false;
74       acceptLparenth = true;
75     }
76
77     PsiElement element = file.findElementAt(offset);
78     if (element == null) return null;
79     PsiElement parent = element.getParent();
80
81     while(true){
82       if (findArgumentListHelper.getArgumentListClass().isInstance(parent)) {
83         TextRange range = parent.getTextRange();
84         if (!acceptRparenth){
85           if (offset == range.getEndOffset() - 1){
86             PsiElement[] children = parent.getChildren();
87             if (children.length == 0) return null;
88             PsiElement last = children[children.length - 1];
89             if (last.getNode().getElementType() == findArgumentListHelper.getActualParametersRBraceType()){
90               parent = parent.getParent();
91               continue;
92             }
93           }
94         }
95         if (!acceptLparenth){
96           if (offset == range.getStartOffset()){
97             parent = parent.getParent();
98             continue;
99           }
100         }
101         if (lbraceOffset >= 0 && range.getStartOffset() != lbraceOffset){
102           parent = parent.getParent();
103           continue;
104         }
105         break;
106       }
107       if (parent instanceof PsiFile || parent == null) return null;
108       parent = parent.getParent();
109     }
110
111     PsiElement listParent = parent.getParent();
112     for(Class c: (Set<Class>)findArgumentListHelper.getArgumentListAllowedParentClasses()) {
113       if (c.isInstance(listParent)) return (E)parent;
114     }
115
116     return null;
117   }
118 }