Editor for evaluate expression: implement highlighting and completion using ResolveElementCache
This commit is contained in:
@@ -19,13 +19,17 @@ package org.jetbrains.jet.lang.psi;
|
|||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.impl.PsiManagerEx;
|
import com.intellij.psi.impl.PsiManagerEx;
|
||||||
|
import com.intellij.psi.impl.file.impl.FileManager;
|
||||||
|
import com.intellij.psi.impl.source.tree.FileElement;
|
||||||
import com.intellij.psi.search.GlobalSearchScope;
|
import com.intellij.psi.search.GlobalSearchScope;
|
||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.testFramework.LightVirtualFile;
|
import com.intellij.testFramework.LightVirtualFile;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.plugin.JetFileType;
|
import org.jetbrains.jet.plugin.JetFileType;
|
||||||
|
|
||||||
public class JetCodeFragmentImpl extends JetFile implements PsiCodeFragment {
|
public abstract class JetCodeFragmentImpl extends JetFile implements PsiCodeFragment {
|
||||||
|
private final Project project;
|
||||||
|
|
||||||
protected PsiElement context;
|
protected PsiElement context;
|
||||||
private GlobalSearchScope resolveScope;
|
private GlobalSearchScope resolveScope;
|
||||||
|
|
||||||
@@ -34,6 +38,7 @@ public class JetCodeFragmentImpl extends JetFile implements PsiCodeFragment {
|
|||||||
new LightVirtualFile(name, JetFileType.INSTANCE, text), true), false);
|
new LightVirtualFile(name, JetFileType.INSTANCE, text), true), false);
|
||||||
((SingleRootFileViewProvider)getViewProvider()).forceCachedPsi(this);
|
((SingleRootFileViewProvider)getViewProvider()).forceCachedPsi(this);
|
||||||
init(TokenType.CODE_FRAGMENT, elementType);
|
init(TokenType.CODE_FRAGMENT, elementType);
|
||||||
|
this.project = project;
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,4 +73,27 @@ public class JetCodeFragmentImpl extends JetFile implements PsiCodeFragment {
|
|||||||
if (resolveScope != null) return resolveScope;
|
if (resolveScope != null) return resolveScope;
|
||||||
return super.getResolveScope();
|
return super.getResolveScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JetCodeFragmentImpl clone() {
|
||||||
|
JetCodeFragmentImpl clone = (JetCodeFragmentImpl)cloneImpl((FileElement)calcTreeElement().clone());
|
||||||
|
clone.myOriginalFile = this;
|
||||||
|
FileManager fileManager = ((PsiManagerEx) PsiManager.getInstance(project)).getFileManager();
|
||||||
|
SingleRootFileViewProvider cloneViewProvider = (SingleRootFileViewProvider)fileManager.createFileViewProvider(new LightVirtualFile(
|
||||||
|
getName(),
|
||||||
|
JetFileType.INSTANCE,
|
||||||
|
getText()), true);
|
||||||
|
cloneViewProvider.forceCachedPsi(clone);
|
||||||
|
clone.myViewProvider = cloneViewProvider;
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
private FileViewProvider myViewProvider = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public FileViewProvider getViewProvider() {
|
||||||
|
if (myViewProvider != null) return myViewProvider;
|
||||||
|
return super.getViewProvider();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,8 @@ import org.jetbrains.jet.completion.AbstractMultiFileJvmBasicCompletionTest
|
|||||||
import org.jetbrains.jet.plugin.refactoring.introduce.introduceVariable.AbstractJetExtractionTest
|
import org.jetbrains.jet.plugin.refactoring.introduce.introduceVariable.AbstractJetExtractionTest
|
||||||
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractKotlinEvaluateExpressionTest
|
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractKotlinEvaluateExpressionTest
|
||||||
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractSelectExpressionForDebuggerTest
|
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractSelectExpressionForDebuggerTest
|
||||||
|
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractCodeFragmentCompletionTest
|
||||||
|
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractCodeFragmentHighlightingTest
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
System.setProperty("java.awt.headless", "true")
|
System.setProperty("java.awt.headless", "true")
|
||||||
@@ -266,6 +268,10 @@ fun main(args: Array<String>) {
|
|||||||
model("checker/infos", testMethod = "doTestWithInfos")
|
model("checker/infos", testMethod = "doTestWithInfos")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass(javaClass<AbstractCodeFragmentHighlightingTest>()) {
|
||||||
|
model("checker/codeFragments", extension = "kt")
|
||||||
|
}
|
||||||
|
|
||||||
testClass(javaClass<AbstractJetJsCheckerTest>()) {
|
testClass(javaClass<AbstractJetJsCheckerTest>()) {
|
||||||
model("checker/js")
|
model("checker/js")
|
||||||
}
|
}
|
||||||
@@ -308,6 +314,10 @@ fun main(args: Array<String>) {
|
|||||||
model("completion/handlers/smart")
|
model("completion/handlers/smart")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testClass(javaClass<AbstractCodeFragmentCompletionTest>()) {
|
||||||
|
model("completion/basic/codeFragments", extension = "kt")
|
||||||
|
}
|
||||||
|
|
||||||
testClass(javaClass<AbstractGotoSuperTest>()) {
|
testClass(javaClass<AbstractGotoSuperTest>()) {
|
||||||
model("navigation/gotoSuper", extension = "test")
|
model("navigation/gotoSuper", extension = "test")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ import org.jetbrains.jet.plugin.project.ResolveSessionForBodies
|
|||||||
import org.jetbrains.jet.plugin.project.TargetPlatformDetector
|
import org.jetbrains.jet.plugin.project.TargetPlatformDetector
|
||||||
import java.util.HashSet
|
import java.util.HashSet
|
||||||
import org.jetbrains.jet.analyzer.AnalyzerFacade
|
import org.jetbrains.jet.analyzer.AnalyzerFacade
|
||||||
|
import org.jetbrains.jet.lang.psi.JetCodeFragmentImpl
|
||||||
|
|
||||||
private val LOG = Logger.getInstance(javaClass<KotlinResolveCache>())
|
private val LOG = Logger.getInstance(javaClass<KotlinResolveCache>())
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ class KotlinCacheService(val project: Project) {
|
|||||||
if (elements.isEmpty()) return AnalyzeExhaust.EMPTY
|
if (elements.isEmpty()) return AnalyzeExhaust.EMPTY
|
||||||
|
|
||||||
val firstFile = elements.first().getContainingJetFile()
|
val firstFile = elements.first().getContainingJetFile()
|
||||||
if (elements.size == 1 && !isFileInScope(firstFile)) {
|
if (elements.size == 1 && (!isFileInScope(firstFile) && firstFile !is JetCodeFragmentImpl)) {
|
||||||
return getCacheForSyntheticFile(firstFile).getAnalysisResultsForElements(elements)
|
return getCacheForSyntheticFile(firstFile).getAnalysisResultsForElements(elements)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,23 +21,19 @@ import com.intellij.debugger.engine.evaluation.TextWithImports
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.psi.JavaCodeFragment
|
import com.intellij.psi.JavaCodeFragment
|
||||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
|
||||||
import com.intellij.debugger.engine.evaluation.expression.EvaluatorBuilder
|
|
||||||
import org.jetbrains.jet.plugin.JetFileType
|
import org.jetbrains.jet.plugin.JetFileType
|
||||||
import org.jetbrains.jet.lang.psi.JetCodeFragmentImpl
|
|
||||||
import com.intellij.psi.tree.IElementType
|
|
||||||
import org.jetbrains.jet.lexer.JetToken
|
|
||||||
import org.jetbrains.jet.JetNodeType
|
|
||||||
import org.jetbrains.jet.lexer.JetTokens
|
|
||||||
import org.jetbrains.jet.lang.psi.JetExpressionCodeFragmentImpl
|
import org.jetbrains.jet.lang.psi.JetExpressionCodeFragmentImpl
|
||||||
import com.intellij.psi.PsiCodeBlock
|
import com.intellij.psi.PsiCodeBlock
|
||||||
import com.intellij.debugger.engine.evaluation.CodeFragmentKind
|
import com.intellij.debugger.engine.evaluation.CodeFragmentKind
|
||||||
import com.intellij.psi.JavaCodeFragmentFactory
|
import com.intellij.psi.JavaCodeFragmentFactory
|
||||||
|
import org.jetbrains.jet.plugin.debugger.KotlinEditorTextProvider
|
||||||
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression
|
||||||
|
|
||||||
class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
||||||
override fun createCodeFragment(item: TextWithImports, context: PsiElement?, project: Project): JavaCodeFragment {
|
override fun createCodeFragment(item: TextWithImports, context: PsiElement?, project: Project): JavaCodeFragment {
|
||||||
if (item.getKind() == CodeFragmentKind.EXPRESSION) {
|
if (item.getKind() == CodeFragmentKind.EXPRESSION) {
|
||||||
val codeFragment = JetExpressionCodeFragmentImpl(project, "fragment.kt", item.getText(), context)
|
val codeFragment = JetExpressionCodeFragmentImpl(project, "fragment.kt", item.getText(), getContextElement(context))
|
||||||
if (item.getImports().isNotEmpty()) {
|
if (item.getImports().isNotEmpty()) {
|
||||||
codeFragment.addImportsFromString(item.getImports())
|
codeFragment.addImportsFromString(item.getImports())
|
||||||
}
|
}
|
||||||
@@ -60,4 +56,16 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
|||||||
override fun getFileType() = JetFileType.INSTANCE
|
override fun getFileType() = JetFileType.INSTANCE
|
||||||
|
|
||||||
override fun getEvaluatorBuilder() = KotlinEvaluationBuilder
|
override fun getEvaluatorBuilder() = KotlinEvaluationBuilder
|
||||||
|
|
||||||
|
class object {
|
||||||
|
fun getContextElement(elementAt: PsiElement?): PsiElement? {
|
||||||
|
if (elementAt == null) return null
|
||||||
|
|
||||||
|
val expressionAtOffset = PsiTreeUtil.findElementOfClassAtOffset(elementAt.getContainingFile()!!, elementAt.getTextOffset(), javaClass<JetExpression>(), false)
|
||||||
|
if (expressionAtOffset != null) {
|
||||||
|
return expressionAtOffset
|
||||||
|
}
|
||||||
|
return KotlinEditorTextProvider.findExpressionInner(elementAt)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import com.intellij.openapi.progress.ProcessCanceledException;
|
|||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.checkers.DebugInfoUtil;
|
import org.jetbrains.jet.checkers.DebugInfoUtil;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetCodeFragmentImpl;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
@@ -46,7 +47,7 @@ public class DebugInfoAnnotator implements Annotator {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element instanceof JetFile) {
|
if (element instanceof JetFile && !(element instanceof JetCodeFragmentImpl)) {
|
||||||
JetFile file = (JetFile) element;
|
JetFile file = (JetFile) element;
|
||||||
try {
|
try {
|
||||||
BindingContext bindingContext = ResolvePackage.getAnalysisResults(file).getBindingContext();
|
BindingContext bindingContext = ResolvePackage.getAnalysisResults(file).getBindingContext();
|
||||||
|
|||||||
@@ -40,11 +40,14 @@ import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
|||||||
import org.jetbrains.jet.lang.diagnostics.Errors;
|
import org.jetbrains.jet.lang.diagnostics.Errors;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Severity;
|
import org.jetbrains.jet.lang.diagnostics.Severity;
|
||||||
import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages;
|
import org.jetbrains.jet.lang.diagnostics.rendering.DefaultErrorMessages;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetCodeFragmentImpl;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetElement;
|
||||||
import org.jetbrains.jet.lang.psi.JetFile;
|
import org.jetbrains.jet.lang.psi.JetFile;
|
||||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
import org.jetbrains.jet.plugin.JetPluginUtil;
|
import org.jetbrains.jet.plugin.JetPluginUtil;
|
||||||
import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
|
import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
|
||||||
|
import org.jetbrains.jet.plugin.project.ResolveSessionForBodies;
|
||||||
import org.jetbrains.jet.plugin.quickfix.JetIntentionActionsFactory;
|
import org.jetbrains.jet.plugin.quickfix.JetIntentionActionsFactory;
|
||||||
import org.jetbrains.jet.plugin.quickfix.QuickFixes;
|
import org.jetbrains.jet.plugin.quickfix.QuickFixes;
|
||||||
|
|
||||||
@@ -90,7 +93,8 @@ public class JetPsiChecker implements Annotator, HighlightRangeExtension {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) {
|
||||||
if (!JetPluginUtil.isInSource(element) || JetPluginUtil.isKtFileInGradleProjectInWrongFolder(element)) {
|
if (!(JetPluginUtil.isInSource(element) || element.getContainingFile() instanceof JetCodeFragmentImpl)
|
||||||
|
|| JetPluginUtil.isKtFileInGradleProjectInWrongFolder(element)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,19 +104,32 @@ public class JetPsiChecker implements Annotator, HighlightRangeExtension {
|
|||||||
|
|
||||||
JetFile file = (JetFile) element.getContainingFile();
|
JetFile file = (JetFile) element.getContainingFile();
|
||||||
|
|
||||||
AnalyzeExhaust analyzeExhaust = ResolvePackage.getAnalysisResults(file);
|
BindingContext bindingContext;
|
||||||
if (analyzeExhaust.isError()) {
|
if (file instanceof JetCodeFragmentImpl) {
|
||||||
HighlighterPackage.updateHighlightingResult(file, true);
|
if (element instanceof JetElement) {
|
||||||
|
ResolveSessionForBodies resolveSession = ResolvePackage.getLazyResolveSession((JetElement) element);
|
||||||
|
bindingContext = resolveSession.resolveToElement((JetElement) element);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
AnalyzeExhaust analyzeExhaust = ResolvePackage.getAnalysisResults(file);
|
||||||
|
if (analyzeExhaust.isError()) {
|
||||||
|
HighlighterPackage.updateHighlightingResult(file, true);
|
||||||
|
|
||||||
throw new ProcessCanceledException(analyzeExhaust.getError());
|
throw new ProcessCanceledException(analyzeExhaust.getError());
|
||||||
|
}
|
||||||
|
|
||||||
|
bindingContext = analyzeExhaust.getBindingContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
BindingContext bindingContext = analyzeExhaust.getBindingContext();
|
|
||||||
for (HighlightingVisitor visitor : getAfterAnalysisVisitor(holder, bindingContext)) {
|
for (HighlightingVisitor visitor : getAfterAnalysisVisitor(holder, bindingContext)) {
|
||||||
element.accept(visitor);
|
element.accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (JetPluginUtil.isInSource(element, /* includeLibrarySources = */ false)) {
|
if (JetPluginUtil.isInSource(element, /* includeLibrarySources = */ false) || file instanceof JetCodeFragmentImpl) {
|
||||||
ElementAnnotator elementAnnotator = new ElementAnnotator(element, holder);
|
ElementAnnotator elementAnnotator = new ElementAnnotator(element, holder);
|
||||||
for (Diagnostic diagnostic : bindingContext.getDiagnostics().forElement(element)) {
|
for (Diagnostic diagnostic : bindingContext.getDiagnostics().forElement(element)) {
|
||||||
elementAnnotator.registerDiagnosticAnnotations(diagnostic);
|
elementAnnotator.registerDiagnosticAnnotations(diagnostic);
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import kotlin.Function1;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.di.InjectorForBodyResolve;
|
import org.jetbrains.jet.di.InjectorForBodyResolve;
|
||||||
|
import org.jetbrains.jet.di.InjectorForMacros;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
import org.jetbrains.jet.lang.descriptors.annotations.Annotated;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
@@ -39,6 +40,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName;
|
|||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.types.TypeConstructor;
|
import org.jetbrains.jet.lang.types.TypeConstructor;
|
||||||
|
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||||
import org.jetbrains.jet.storage.ExceptionTracker;
|
import org.jetbrains.jet.storage.ExceptionTracker;
|
||||||
import org.jetbrains.jet.storage.LazyResolveStorageManager;
|
import org.jetbrains.jet.storage.LazyResolveStorageManager;
|
||||||
import org.jetbrains.jet.storage.MemoizedFunctionToNotNull;
|
import org.jetbrains.jet.storage.MemoizedFunctionToNotNull;
|
||||||
@@ -92,7 +94,8 @@ public class ResolveElementCache {
|
|||||||
JetAnnotationEntry.class,
|
JetAnnotationEntry.class,
|
||||||
JetTypeParameter.class,
|
JetTypeParameter.class,
|
||||||
JetTypeConstraint.class,
|
JetTypeConstraint.class,
|
||||||
JetPackageDirective.class);
|
JetPackageDirective.class,
|
||||||
|
JetExpressionCodeFragment.class);
|
||||||
|
|
||||||
if (elementOfAdditionalResolve != null && !(elementOfAdditionalResolve instanceof JetParameter)) {
|
if (elementOfAdditionalResolve != null && !(elementOfAdditionalResolve instanceof JetParameter)) {
|
||||||
if (elementOfAdditionalResolve instanceof JetPackageDirective) {
|
if (elementOfAdditionalResolve instanceof JetPackageDirective) {
|
||||||
@@ -159,6 +162,9 @@ public class ResolveElementCache {
|
|||||||
else if (resolveElement instanceof JetTypeConstraint) {
|
else if (resolveElement instanceof JetTypeConstraint) {
|
||||||
typeConstraintAdditionalResolve(resolveSession, (JetTypeConstraint) resolveElement);
|
typeConstraintAdditionalResolve(resolveSession, (JetTypeConstraint) resolveElement);
|
||||||
}
|
}
|
||||||
|
else if (resolveElement instanceof JetExpressionCodeFragment) {
|
||||||
|
codeFragmentAdditionalResolve(resolveSession, (JetExpressionCodeFragment) resolveElement, trace);
|
||||||
|
}
|
||||||
else if (PsiTreeUtil.getParentOfType(resolveElement, JetPackageDirective.class) != null) {
|
else if (PsiTreeUtil.getParentOfType(resolveElement, JetPackageDirective.class) != null) {
|
||||||
packageRefAdditionalResolve(resolveSession, trace, resolveElement);
|
packageRefAdditionalResolve(resolveSession, trace, resolveElement);
|
||||||
}
|
}
|
||||||
@@ -206,6 +212,34 @@ public class ResolveElementCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void codeFragmentAdditionalResolve(
|
||||||
|
ResolveSession resolveSession,
|
||||||
|
JetExpressionCodeFragment codeFragment,
|
||||||
|
BindingTrace trace
|
||||||
|
) {
|
||||||
|
JetExpression codeFragmentExpression = codeFragment.getExpression();
|
||||||
|
if (codeFragmentExpression == null) return;
|
||||||
|
|
||||||
|
PsiElement contextElement = codeFragment.getContext();
|
||||||
|
if (!(contextElement instanceof JetExpression)) return;
|
||||||
|
|
||||||
|
JetExpression contextExpression = (JetExpression) contextElement;
|
||||||
|
BindingContext contextForElement = resolveToElement(contextExpression);
|
||||||
|
|
||||||
|
JetScope scopeForContextElement = contextForElement.get(BindingContext.RESOLUTION_SCOPE, contextExpression);
|
||||||
|
if (scopeForContextElement != null) {
|
||||||
|
DataFlowInfo dataFlowInfoForContextElement = contextForElement.get(BindingContext.EXPRESSION_DATA_FLOW_INFO, contextExpression);
|
||||||
|
InjectorForMacros injectorForMacros = new InjectorForMacros(codeFragment.getProject(), resolveSession.getModuleDescriptor());
|
||||||
|
injectorForMacros.getExpressionTypingServices().getType(
|
||||||
|
scopeForContextElement,
|
||||||
|
codeFragmentExpression,
|
||||||
|
TypeUtils.NO_EXPECTED_TYPE,
|
||||||
|
dataFlowInfoForContextElement == null ? DataFlowInfo.EMPTY : dataFlowInfoForContextElement,
|
||||||
|
trace
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void annotationAdditionalResolve(ResolveSession resolveSession, JetAnnotationEntry jetAnnotationEntry) {
|
private static void annotationAdditionalResolve(ResolveSession resolveSession, JetAnnotationEntry jetAnnotationEntry) {
|
||||||
JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetDeclaration.class);
|
JetDeclaration declaration = PsiTreeUtil.getParentOfType(jetAnnotationEntry, JetDeclaration.class);
|
||||||
if (declaration != null) {
|
if (declaration != null) {
|
||||||
|
|||||||
@@ -96,6 +96,10 @@ public class ImportInsertHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void writeImportToFile(@NotNull ImportPath importPath, @NotNull JetFile file) {
|
public static void writeImportToFile(@NotNull ImportPath importPath, @NotNull JetFile file) {
|
||||||
|
if (file instanceof JetCodeFragmentImpl) {
|
||||||
|
// TODO Insert import doesn't work for codeFragments yet
|
||||||
|
return;
|
||||||
|
}
|
||||||
JetImportList importList = file.getImportList();
|
JetImportList importList = file.getImportList();
|
||||||
if (importList != null) {
|
if (importList != null) {
|
||||||
JetImportDirective newDirective = JetPsiFactory.createImportDirective(file.getProject(), importPath);
|
JetImportDirective newDirective = JetPsiFactory.createImportDirective(file.getProject(), importPath);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.intention.IntentionAction;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetCodeFragmentImpl;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -33,6 +34,11 @@ public abstract class JetSingleIntentionActionFactory implements JetIntentionAct
|
|||||||
@Override
|
@Override
|
||||||
public final List<IntentionAction> createActions(Diagnostic diagnostic) {
|
public final List<IntentionAction> createActions(Diagnostic diagnostic) {
|
||||||
List<IntentionAction> intentionActionList = new LinkedList<IntentionAction>();
|
List<IntentionAction> intentionActionList = new LinkedList<IntentionAction>();
|
||||||
|
|
||||||
|
if (diagnostic.getPsiElement().getContainingFile() instanceof JetCodeFragmentImpl) {
|
||||||
|
return intentionActionList;
|
||||||
|
}
|
||||||
|
|
||||||
IntentionAction intentionAction = createAction(diagnostic);
|
IntentionAction intentionAction = createAction(diagnostic);
|
||||||
if (intentionAction != null) {
|
if (intentionAction != null) {
|
||||||
intentionActionList.add(intentionAction);
|
intentionActionList.add(intentionAction);
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() {
|
||||||
|
val a = 1
|
||||||
|
<caret>a
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
a + <error>b</error>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo(i: Int, s: String) {
|
||||||
|
val a = 1
|
||||||
|
<caret>a
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
foo(a, <error>1</error>)
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() {
|
||||||
|
val a = 1
|
||||||
|
<caret>val b = 2
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
a + <error>c</error>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun foo() {
|
||||||
|
val a = 1
|
||||||
|
<caret>a
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<error>b</error>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
fun foo() {
|
||||||
|
val a: Int? = 1
|
||||||
|
if (a != null) {
|
||||||
|
<caret> a
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
a + 1
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
fun foo() {
|
||||||
|
val aaabbbccc = 1
|
||||||
|
aaa<caret>bbbccc
|
||||||
|
}
|
||||||
|
|
||||||
|
// INVOCATION_COUNT: 1
|
||||||
|
// EXIST: aaabbbccc
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
aaabb<caret>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
val aaabbbccc = 1
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
aaa<caret>bbbccc
|
||||||
|
}
|
||||||
|
|
||||||
|
// INVOCATION_COUNT: 1
|
||||||
|
// EXIST: aaabbbccc
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
aaabb<caret>
|
||||||
+1
-1
@@ -18,7 +18,7 @@ public abstract class AbstractKotlinSourceInJavaCompletionTest extends JetFixtur
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doTest(String testPath) {
|
public void doTest(String testPath) throws Exception {
|
||||||
File mockLibDir = new File(PluginTestCaseBase.getTestDataPathBase() + "/completion/injava/mockLib");
|
File mockLibDir = new File(PluginTestCaseBase.getTestDataPathBase() + "/completion/injava/mockLib");
|
||||||
File[] listFiles = mockLibDir.listFiles();
|
File[] listFiles = mockLibDir.listFiles();
|
||||||
assertNotNull(listFiles);
|
assertNotNull(listFiles);
|
||||||
|
|||||||
@@ -19,10 +19,12 @@ package org.jetbrains.jet.completion;
|
|||||||
import com.intellij.codeInsight.CodeInsightSettings;
|
import com.intellij.codeInsight.CodeInsightSettings;
|
||||||
import com.intellij.codeInsight.completion.CompletionType;
|
import com.intellij.codeInsight.completion.CompletionType;
|
||||||
import com.intellij.codeInsight.lookup.LookupElement;
|
import com.intellij.codeInsight.lookup.LookupElement;
|
||||||
|
import com.intellij.openapi.util.io.FileUtil;
|
||||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.plugin.project.TargetPlatform;
|
import org.jetbrains.jet.plugin.project.TargetPlatform;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -62,10 +64,10 @@ public abstract class JetFixtureCompletionBaseTestCase extends LightCodeInsightF
|
|||||||
@NotNull
|
@NotNull
|
||||||
protected abstract CompletionType completionType();
|
protected abstract CompletionType completionType();
|
||||||
|
|
||||||
public void doTest(String testPath) {
|
public void doTest(String testPath) throws Exception {
|
||||||
setUpFixture(testPath);
|
setUpFixture(testPath);
|
||||||
|
|
||||||
String fileText = myFixture.getFile().getText();
|
String fileText = FileUtil.loadFile(new File(testPath), true);
|
||||||
|
|
||||||
Integer invocationCount = ExpectedCompletionUtils.getInvocationCount(fileText);
|
Integer invocationCount = ExpectedCompletionUtils.getInvocationCount(fileText);
|
||||||
|
|
||||||
|
|||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.plugin.debugger.evaluate
|
||||||
|
|
||||||
|
import org.jetbrains.jet.checkers.AbstractJetPsiCheckerTest
|
||||||
|
import org.jetbrains.jet.completion.AbstractJvmBasicCompletionTest
|
||||||
|
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpressionCodeFragment
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import java.io.File
|
||||||
|
import org.jetbrains.jet.lang.psi.JetPsiFactory
|
||||||
|
import org.jetbrains.jet.plugin.debugger.KotlinEditorTextProvider
|
||||||
|
import com.intellij.openapi.util.text.StringUtil
|
||||||
|
|
||||||
|
abstract class AbstractCodeFragmentHighlightingTest: AbstractJetPsiCheckerTest() {
|
||||||
|
override fun doTest(filePath: String) {
|
||||||
|
myFixture.configureByCodeFragment(filePath)
|
||||||
|
myFixture.checkHighlighting(true, false, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractCodeFragmentCompletionTest : AbstractJvmBasicCompletionTest() {
|
||||||
|
override fun setUpFixture(testPath: String) {
|
||||||
|
myFixture.configureByCodeFragment(testPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun JavaCodeInsightTestFixture.configureByCodeFragment(filePath: String) {
|
||||||
|
configureByFile(filePath)
|
||||||
|
|
||||||
|
val elementAt = getFile()?.findElementAt(getCaretOffset())
|
||||||
|
val file = createExpressionCodeFragment(filePath, elementAt!!)
|
||||||
|
|
||||||
|
configureFromExistingVirtualFile(file.getVirtualFile())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createExpressionCodeFragment(filePath: String, contextElement: PsiElement): JetExpressionCodeFragment {
|
||||||
|
val codeFragmentText = FileUtil.loadFile(File(filePath + ".fragment"), true).trim()
|
||||||
|
return JetPsiFactory.createExpressionCodeFragment(
|
||||||
|
contextElement.getProject(),
|
||||||
|
codeFragmentText,
|
||||||
|
KotlinCodeFragmentFactory.getContextElement(contextElement)
|
||||||
|
)
|
||||||
|
}
|
||||||
+49
@@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.plugin.debugger.evaluate;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
|
import org.jetbrains.jet.test.InnerTestClasses;
|
||||||
|
import org.jetbrains.jet.test.TestMetadata;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractCodeFragmentCompletionTest;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("idea/testData/completion/basic/codeFragments")
|
||||||
|
public class CodeFragmentCompletionTestGenerated extends AbstractCodeFragmentCompletionTest {
|
||||||
|
public void testAllFilesPresentInCodeFragments() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/completion/basic/codeFragments"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("localVal.kt")
|
||||||
|
public void testLocalVal() throws Exception {
|
||||||
|
doTest("idea/testData/completion/basic/codeFragments/localVal.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevel.kt")
|
||||||
|
public void testTopLevel() throws Exception {
|
||||||
|
doTest("idea/testData/completion/basic/codeFragments/topLevel.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+64
@@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2014 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.jet.plugin.debugger.evaluate;
|
||||||
|
|
||||||
|
import junit.framework.Assert;
|
||||||
|
import junit.framework.Test;
|
||||||
|
import junit.framework.TestSuite;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import org.jetbrains.jet.JetTestUtils;
|
||||||
|
import org.jetbrains.jet.test.InnerTestClasses;
|
||||||
|
import org.jetbrains.jet.test.TestMetadata;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractCodeFragmentHighlightingTest;
|
||||||
|
|
||||||
|
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
@TestMetadata("idea/testData/checker/codeFragments")
|
||||||
|
public class CodeFragmentHighlightingTestGenerated extends AbstractCodeFragmentHighlightingTest {
|
||||||
|
public void testAllFilesPresentInCodeFragments() throws Exception {
|
||||||
|
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("idea/testData/checker/codeFragments"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("binaryExpression.kt")
|
||||||
|
public void testBinaryExpression() throws Exception {
|
||||||
|
doTest("idea/testData/checker/codeFragments/binaryExpression.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("callExpression.kt")
|
||||||
|
public void testCallExpression() throws Exception {
|
||||||
|
doTest("idea/testData/checker/codeFragments/callExpression.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("contextElementAsStatement.kt")
|
||||||
|
public void testContextElementAsStatement() throws Exception {
|
||||||
|
doTest("idea/testData/checker/codeFragments/contextElementAsStatement.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("simpleNameExpression.kt")
|
||||||
|
public void testSimpleNameExpression() throws Exception {
|
||||||
|
doTest("idea/testData/checker/codeFragments/simpleNameExpression.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("smartCasts.kt")
|
||||||
|
public void testSmartCasts() throws Exception {
|
||||||
|
doTest("idea/testData/checker/codeFragments/smartCasts.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user