Resolve codeFragments with context of JetClass

This commit is contained in:
Natalia Ukhorskaya
2014-11-12 15:13:37 +03:00
parent a86e0336c9
commit 12b4fc7ad9
9 changed files with 82 additions and 25 deletions
@@ -203,31 +203,44 @@ public abstract class ElementResolver {
if (!(codeFragmentExpression instanceof JetExpression)) return;
PsiElement contextElement = codeFragment.getContext();
if (!(contextElement instanceof JetExpression)) return;
JetExpression contextExpression = (JetExpression) contextElement;
BindingContext contextForElement = resolveToElement(contextExpression);
JetScope scopeForContextElement;
DataFlowInfo dataFlowInfoForContextElement;
JetScope scopeForContextElement = contextForElement.get(BindingContext.RESOLUTION_SCOPE, contextExpression);
if (scopeForContextElement != null) {
JetScope codeFragmentScope = resolveSession.getScopeProvider().getFileScope(codeFragment);
ChainedScope chainedScope = new ChainedScope(
scopeForContextElement.getContainingDeclaration(),
"Scope for resolve code fragment",
scopeForContextElement,
codeFragmentScope
);
if (contextElement instanceof JetClassOrObject) {
LazyClassDescriptor descriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor((JetClassOrObject) contextElement);
DataFlowInfo dataFlowInfoForContextElement = getDataFlowInfo(contextForElement, contextExpression);
AnalyzerPackage.computeTypeInContext(
(JetExpression) codeFragmentExpression,
chainedScope,
trace,
dataFlowInfoForContextElement,
TypeUtils.NO_EXPECTED_TYPE,
resolveSession.getModuleDescriptor()
);
scopeForContextElement = descriptor.getScopeForMemberDeclarationResolution();
dataFlowInfoForContextElement = DataFlowInfo.EMPTY;
}
else {
if (!(contextElement instanceof JetExpression)) return;
JetExpression contextExpression = (JetExpression) contextElement;
BindingContext contextForElement = resolveToElement((JetElement) contextElement);
scopeForContextElement = contextForElement.get(BindingContext.RESOLUTION_SCOPE, contextExpression);
dataFlowInfoForContextElement = getDataFlowInfo(contextForElement, contextExpression);
}
if (scopeForContextElement == null) return;
JetScope codeFragmentScope = resolveSession.getScopeProvider().getFileScope(codeFragment);
ChainedScope chainedScope = new ChainedScope(
scopeForContextElement.getContainingDeclaration(),
"Scope for resolve code fragment",
scopeForContextElement,
codeFragmentScope
);
AnalyzerPackage.computeTypeInContext(
(JetExpression) codeFragmentExpression,
chainedScope,
trace,
dataFlowInfoForContextElement,
TypeUtils.NO_EXPECTED_TYPE,
resolveSession.getModuleDescriptor()
);
}
private static void annotationAdditionalResolve(ResolveSession resolveSession, JetAnnotationEntry jetAnnotationEntry) {
@@ -61,6 +61,9 @@ import org.jetbrains.jet.lang.resolve.BindingTraceContext
import org.jetbrains.jet.lang.types.TypeUtils
import org.jetbrains.jet.lang.resolve.scopes.ChainedScope
import org.jetbrains.jet.lang.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassDescriptor
import org.jetbrains.jet.lang.resolve.calls.smartcasts.DataFlowInfo
import org.jetbrains.jet.lang.resolve.scopes.JetScope
public trait CacheExtension<T> {
public val platform: TargetPlatform
@@ -272,11 +275,24 @@ private object KotlinResolveDataProvider {
if (codeFragmentExpression !is JetExpression) return BindingContext.EMPTY
val contextElement = codeFragment.getContext()
if (contextElement !is JetExpression) return BindingContext.EMPTY
val contextForElement = contextElement.getBindingContext()
val scopeForContextElement: JetScope?
val dataFlowInfo: DataFlowInfo
if (contextElement is JetClassOrObject) {
val descriptor = resolveSession.resolveToDescriptor(contextElement) as LazyClassDescriptor
scopeForContextElement = descriptor.getScopeForMemberDeclarationResolution()
dataFlowInfo = DataFlowInfo.EMPTY
}
else {
if (contextElement !is JetExpression) return BindingContext.EMPTY
val contextForElement = contextElement.getBindingContext()
scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, contextElement]
dataFlowInfo = contextForElement.getDataFlowInfo(contextElement)
}
val scopeForContextElement = contextForElement[BindingContext.RESOLUTION_SCOPE, contextElement]
if (scopeForContextElement == null) return BindingContext.EMPTY
val codeFragmentScope = resolveSession.getScopeProvider().getFileScope(codeFragment)
@@ -285,7 +301,6 @@ private object KotlinResolveDataProvider {
"Scope for resolve code fragment",
scopeForContextElement, codeFragmentScope)
val dataFlowInfo = contextForElement.getDataFlowInfo(contextElement)
return codeFragmentExpression.analyzeInContext(
chainedScope,
BindingTraceContext(),
@@ -31,6 +31,7 @@ import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.jet.lang.psi.JetExpression
import org.jetbrains.jet.lang.psi.JetBlockExpression
import org.jetbrains.jet.lang.psi.JetBlockCodeFragment
import org.jetbrains.jet.asJava.KotlinLightClass
class KotlinCodeFragmentFactory: CodeFragmentFactory() {
override fun createCodeFragment(item: TextWithImports, context: PsiElement?, project: Project): JavaCodeFragment {
@@ -68,6 +69,10 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
return getContextElement(elementAt.getContext()?.getContext())
}
if (elementAt is KotlinLightClass) {
return getContextElement(elementAt.origin)
}
val expressionAtOffset = PsiTreeUtil.findElementOfClassAtOffset(elementAt.getContainingFile()!!, elementAt.getTextOffset(), javaClass<JetExpression>(), false)
if (expressionAtOffset != null) {
return expressionAtOffset
@@ -0,0 +1,3 @@
class <caret>A(aaabbbccc: Int) {
val aabbcc = 1
}
@@ -0,0 +1 @@
"" + <error descr="[UNRESOLVED_REFERENCE] Unresolved reference: aaabbbccc">aaabbbccc</error> + aabbcc + this.toString()
@@ -0,0 +1,7 @@
class <caret>A(aaabbbccc: Int) {
val aabbcc = 1
}
// INVOCATION_COUNT: 1
// EXIST: aabbcc
// ABSENT: aaabbbccc
@@ -0,0 +1 @@
aa<caret>
@@ -42,6 +42,12 @@ public class CodeFragmentCompletionTestGenerated extends AbstractCodeFragmentCom
doTest(fileName);
}
@TestMetadata("classHeader.kt")
public void testClassHeader() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/codeFragments/classHeader.kt");
doTest(fileName);
}
@TestMetadata("localVal.kt")
public void testLocalVal() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/completion/basic/codeFragments/localVal.kt");
@@ -57,6 +57,12 @@ public class CodeFragmentHighlightingTestGenerated extends AbstractCodeFragmentH
doTest(fileName);
}
@TestMetadata("classHeader.kt")
public void testClassHeader() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/checker/codeFragments/classHeader.kt");
doTest(fileName);
}
@TestMetadata("contextElementAsStatement.kt")
public void testContextElementAsStatement() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/checker/codeFragments/contextElementAsStatement.kt");