IDEA-136017 (obscure lookup inside decompiled files avoided)
[idea/community.git] / platform / core-impl / src / com / intellij / codeInsight / completion / CompletionUtilCoreImpl.java
1 /*
2  * Copyright 2000-2015 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 package com.intellij.codeInsight.completion;
17
18 import com.intellij.injected.editor.DocumentWindow;
19 import com.intellij.openapi.editor.Document;
20 import com.intellij.openapi.util.TextRange;
21 import com.intellij.psi.PsiCompiledFile;
22 import com.intellij.psi.PsiElement;
23 import com.intellij.psi.PsiFile;
24 import com.intellij.psi.util.PsiTreeUtil;
25 import org.jetbrains.annotations.NotNull;
26 import org.jetbrains.annotations.Nullable;
27
28 /**
29  * @author yole
30  */
31 public class CompletionUtilCoreImpl {
32   @Nullable
33   public static <T extends PsiElement> T getOriginalElement(@NotNull T psi) {
34     return getOriginalElement(psi, psi.getContainingFile());
35   }
36
37   @Nullable
38   public static <T extends PsiElement> T getOriginalElement(@NotNull T psi, PsiFile containingFile) {
39     if (containingFile == null) return psi;
40
41     PsiFile originalFile = containingFile.getOriginalFile();
42     if (originalFile != containingFile && !(originalFile instanceof PsiCompiledFile) && psi.getTextRange() != null) {
43       TextRange range = psi.getTextRange();
44       Integer start = range.getStartOffset();
45       Integer end = range.getEndOffset();
46
47       Document document = containingFile.getViewProvider().getDocument();
48       if (document != null) {
49         Document hostDocument = document instanceof DocumentWindow ? ((DocumentWindow)document).getDelegate() : document;
50         OffsetTranslator translator = hostDocument.getUserData(OffsetTranslator.RANGE_TRANSLATION);
51         if (translator != null) {
52           if (document instanceof DocumentWindow) {
53             TextRange translated = ((DocumentWindow)document).injectedToHost(new TextRange(start, end));
54             start = translated.getStartOffset();
55             end = translated.getEndOffset();
56           }
57
58           start = translator.translateOffset(start);
59           end = translator.translateOffset(end);
60           if (start == null || end == null) {
61             return null;
62           }
63
64           if (document instanceof DocumentWindow) {
65             start = ((DocumentWindow)document).hostToInjected(start);
66             end = ((DocumentWindow)document).hostToInjected(end);
67           }
68         }
69       }
70
71       //noinspection unchecked
72       return (T)PsiTreeUtil.findElementOfClassAtRange(originalFile, start, end, psi.getClass());
73     }
74
75     return psi;
76   }
77 }