2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.jetbrains
.plugins
.groovy
.annotator
.intentions
;
18 import com
.intellij
.openapi
.editor
.Editor
;
19 import com
.intellij
.openapi
.fileEditor
.FileEditorManager
;
20 import com
.intellij
.openapi
.fileEditor
.OpenFileDescriptor
;
21 import com
.intellij
.openapi
.module
.Module
;
22 import com
.intellij
.openapi
.project
.Project
;
23 import com
.intellij
.openapi
.roots
.ProjectRootManager
;
24 import com
.intellij
.openapi
.util
.TextRange
;
25 import com
.intellij
.openapi
.vfs
.ReadonlyStatusHandler
;
26 import com
.intellij
.openapi
.vfs
.VirtualFile
;
27 import com
.intellij
.psi
.*;
28 import com
.intellij
.psi
.codeStyle
.JavaCodeStyleManager
;
29 import com
.intellij
.psi
.codeStyle
.SuggestedNameInfo
;
30 import com
.intellij
.psi
.codeStyle
.VariableKind
;
31 import com
.intellij
.psi
.util
.PsiTreeUtil
;
32 import com
.intellij
.psi
.util
.PsiTypesUtil
;
33 import com
.intellij
.util
.ArrayUtil
;
34 import gnu
.trove
.THashSet
;
35 import org
.jetbrains
.annotations
.NotNull
;
36 import org
.jetbrains
.annotations
.Nullable
;
37 import org
.jetbrains
.plugins
.groovy
.annotator
.intentions
.dynamic
.MyPair
;
38 import org
.jetbrains
.plugins
.groovy
.annotator
.intentions
.dynamic
.ui
.DynamicElementSettings
;
39 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.GroovyFileBase
;
40 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.GroovyPsiElement
;
41 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.arguments
.GrArgumentLabel
;
42 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.expressions
.GrCall
;
43 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.expressions
.GrExpression
;
44 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.expressions
.GrReferenceExpression
;
45 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.typedef
.GrTypeDefinition
;
46 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.impl
.statements
.expressions
.TypesUtil
;
47 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.util
.PsiUtil
;
48 import org
.jetbrains
.plugins
.groovy
.lang
.resolve
.ResolveUtil
;
53 * User: Dmitry.Krasilschikov
56 public class QuickfixUtil
{
58 public static PsiClass
findTargetClass(GrReferenceExpression refExpr
) {
59 final PsiClass psiClass
;
60 if (refExpr
.isQualified()) {
61 GrExpression qualifier
= refExpr
.getQualifierExpression();
62 PsiType type
= qualifier
.getType();
63 if (!(type
instanceof PsiClassType
)) return null;
65 psiClass
= ((PsiClassType
)type
).resolve();
67 GroovyPsiElement context
= PsiTreeUtil
.getParentOfType(refExpr
, GrTypeDefinition
.class, GroovyFileBase
.class);
68 if (context
instanceof GrTypeDefinition
) {
69 return (PsiClass
)context
;
70 } else if (context
instanceof GroovyFileBase
) return ((GroovyFileBase
)context
).getScriptClass();
76 public static boolean isStaticCall(GrReferenceExpression refExpr
) {
78 //todo: look more carefully
79 GrExpression qualifierExpression
= refExpr
.getQualifierExpression();
81 if (!(qualifierExpression
instanceof GrReferenceExpression
)) return false;
83 GrReferenceExpression referenceExpression
= (GrReferenceExpression
)qualifierExpression
;
84 GroovyPsiElement resolvedElement
= ResolveUtil
.resolveProperty(referenceExpression
, referenceExpression
.getName());
86 if (resolvedElement
== null) return false;
87 if (resolvedElement
instanceof PsiClass
) return true;
93 public static boolean ensureFileWritable(Project project
, PsiFile file
) {
94 final VirtualFile virtualFile
= file
.getVirtualFile();
95 final ReadonlyStatusHandler readonlyStatusHandler
= ReadonlyStatusHandler
.getInstance(project
);
96 final ReadonlyStatusHandler
.OperationStatus operationStatus
= readonlyStatusHandler
.ensureFilesWritable(virtualFile
);
97 return !operationStatus
.hasReadonlyFiles();
100 public static Editor
positionCursor(@NotNull Project project
, @NotNull PsiFile targetFile
, @NotNull PsiElement element
) {
101 TextRange range
= element
.getTextRange();
102 int textOffset
= range
.getStartOffset();
104 VirtualFile vFile
= targetFile
.getVirtualFile();
105 assert vFile
!= null;
106 OpenFileDescriptor descriptor
= new OpenFileDescriptor(project
, vFile
, textOffset
);
107 return FileEditorManager
.getInstance(project
).openTextEditor(descriptor
, true);
110 public static String
[] getMethodArgumentsNames(Project project
, PsiType
[] types
) {
111 Set
<String
> uniqNames
= new LinkedHashSet
<String
>();
112 Set
<String
> nonUniqNames
= new THashSet
<String
>();
113 for (PsiType type
: types
) {
114 final SuggestedNameInfo nameInfo
=
115 JavaCodeStyleManager
.getInstance(project
).suggestVariableName(VariableKind
.PARAMETER
, null, null, type
);
117 final String name
= nameInfo
.names
[0];
118 if (uniqNames
.contains(name
)) {
120 while (uniqNames
.contains(name
+ i
)) i
++;
121 uniqNames
.add(name
+ i
);
122 nonUniqNames
.add(name
);
128 final String
[] result
= new String
[uniqNames
.size()];
130 for (String name
: uniqNames
) {
131 result
[i
] = nonUniqNames
.contains(name
) ? name
+ 1 : name
;
137 public static List
<MyPair
> swapArgumentsAndTypes(String
[] names
, PsiType
[] types
) {
138 List
<MyPair
> result
= new ArrayList
<MyPair
>();
140 if (names
.length
!= types
.length
) return Collections
.emptyList();
142 for (int i
= 0; i
< names
.length
; i
++) {
143 String name
= names
[i
];
144 final PsiType type
= types
[i
];
146 result
.add(new MyPair(name
, type
.getCanonicalText()));
152 public static boolean isCall(GrReferenceExpression referenceExpression
) {
153 return referenceExpression
.getParent() instanceof GrCall
;
156 public static String
[] getArgumentsTypes(List
<MyPair
> listOfPairs
) {
157 final List
<String
> result
= new ArrayList
<String
>();
159 if (listOfPairs
== null) return new String
[0];
160 for (MyPair listOfPair
: listOfPairs
) {
161 String type
= PsiTypesUtil
.unboxIfPossible(listOfPair
.second
);
165 return ArrayUtil
.toStringArray(result
);
168 public static String
[] getArgumentsNames(List
<MyPair
> listOfPairs
) {
169 final ArrayList
<String
> result
= new ArrayList
<String
>();
170 for (MyPair listOfPair
: listOfPairs
) {
171 String name
= listOfPair
.first
;
175 return ArrayUtil
.toStringArray(result
);
178 public static String
shortenType(String typeText
) {
179 if (typeText
== null) return "";
180 final int i
= typeText
.lastIndexOf(".");
182 return typeText
.substring(i
+ 1);
187 public static Module
getModuleByPsiFile(PsiFile containingFile
) {
189 if (containingFile
!= null) {
190 file
= containingFile
.getVirtualFile();
191 if (file
== null) return null;
196 return ProjectRootManager
.getInstance(containingFile
.getProject()).getFileIndex().getModuleForFile(file
);
200 public static DynamicElementSettings
createSettings(GrReferenceExpression referenceExpression
) {
201 DynamicElementSettings settings
= new DynamicElementSettings();
202 final PsiClass containingClass
= findTargetClass(referenceExpression
);
204 assert containingClass
!= null;
205 String className
= containingClass
.getQualifiedName();
206 className
= className
== null ? containingClass
.getContainingFile().getName() : className
;
208 if (isStaticCall(referenceExpression
)) {
209 settings
.setStatic(true);
212 settings
.setContainingClassName(className
);
213 settings
.setName(referenceExpression
.getName());
215 if (isCall(referenceExpression
)) {
216 List
<PsiType
> unboxedTypes
= new ArrayList
<PsiType
>();
217 for (PsiType type
: PsiUtil
.getArgumentTypes(referenceExpression
, false, false)) {
218 unboxedTypes
.add(TypesUtil
.unboxPrimitiveTypeWraperAndEraseGenerics(type
));
220 final PsiType
[] types
= unboxedTypes
.toArray(new PsiType
[unboxedTypes
.size()]);
221 final String
[] names
= getMethodArgumentsNames(referenceExpression
.getProject(), types
);
222 final List
<MyPair
> pairs
= swapArgumentsAndTypes(names
, types
);
224 settings
.setMethod(true);
225 settings
.setPairs(pairs
);
227 settings
.setMethod(false);
232 public static DynamicElementSettings
createSettings(GrArgumentLabel label
, PsiClass targetClass
) {
233 DynamicElementSettings settings
= new DynamicElementSettings();
235 assert targetClass
!= null;
236 String className
= targetClass
.getQualifiedName();
237 className
= className
== null ? targetClass
.getContainingFile().getName() : className
;
239 settings
.setContainingClassName(className
);
240 settings
.setName(label
.getName());