diff --git a/.idea/libraries/coverage_plugin.xml b/.idea/libraries/coverage_plugin.xml
new file mode 100644
index 00000000000..91df8c11739
--- /dev/null
+++ b/.idea/libraries/coverage_plugin.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt
index 84a6fe9d568..6ce34f21539 100644
--- a/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt
+++ b/generators/src/org/jetbrains/jet/generators/tests/GenerateTests.kt
@@ -133,6 +133,7 @@ import org.jetbrains.jet.checkers.AbstractJetDiagnosticsTestWithJsStdLib
import org.jetbrains.jet.renderer.AbstractDescriptorRendererTest
import org.jetbrains.jet.types.AbstractJetTypeBindingTest
import org.jetbrains.jet.plugin.debugger.evaluate.AbstractCodeFragmentCompletionHandlerTest
+import org.jetbrains.jet.plugin.coverage.AbstractKotlinCoverageOutputFilesTest
fun main(args: Array) {
System.setProperty("java.awt.headless", "true")
@@ -638,6 +639,10 @@ fun main(args: Array) {
testClass(javaClass()) {
model("debugger/selectExpression")
}
+
+ testClass(javaClass()) {
+ model("coverage/outputFiles")
+ }
}
testGroup("idea/tests", "compiler/testData") {
diff --git a/idea/idea.iml b/idea/idea.iml
index 21412d50803..ea77e4c848e 100644
--- a/idea/idea.iml
+++ b/idea/idea.iml
@@ -44,5 +44,6 @@
+
\ No newline at end of file
diff --git a/idea/src/META-INF/coverage.xml b/idea/src/META-INF/coverage.xml
new file mode 100644
index 00000000000..ce1756d8453
--- /dev/null
+++ b/idea/src/META-INF/coverage.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 69d3cdcc2fc..e2ec1a1f633 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -15,6 +15,7 @@
com.intellij.copyright
JavaScriptDebugger
org.jetbrains.android
+ Coverage
diff --git a/idea/src/org/jetbrains/jet/plugin/coverage/KotlinCoverageExtension.kt b/idea/src/org/jetbrains/jet/plugin/coverage/KotlinCoverageExtension.kt
new file mode 100644
index 00000000000..1bdb6aea475
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/coverage/KotlinCoverageExtension.kt
@@ -0,0 +1,98 @@
+/*
+ * 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.coverage
+
+import com.intellij.coverage.JavaCoverageEngineExtension
+import com.intellij.execution.configurations.RunConfigurationBase
+import org.jetbrains.jet.plugin.run.JetRunConfiguration
+import com.intellij.psi.PsiFile
+import com.intellij.openapi.vfs.VirtualFile
+import com.intellij.coverage.CoverageSuitesBundle
+import java.io.File
+import org.jetbrains.jet.lang.psi.JetFile
+import org.jetbrains.jet.plugin.debugger.JetPositionManager
+import org.jetbrains.jet.plugin.caches.resolve.getModuleInfo
+import java.util.HashSet
+import org.jetbrains.jet.lang.psi.JetTreeVisitor
+import org.jetbrains.jet.lang.psi.JetDeclaration
+import com.intellij.openapi.roots.ProjectRootManager
+import org.jetbrains.jet.lang.psi.JetTreeVisitorVoid
+import org.jetbrains.annotations.TestOnly
+import com.intellij.openapi.application.ApplicationManager
+import org.jetbrains.jet.lang.psi.JetFunctionLiteralExpression
+import com.intellij.psi.PsiElement
+import java.util.LinkedHashSet
+
+public class KotlinCoverageExtension(): JavaCoverageEngineExtension() {
+ override fun isApplicableTo(conf: RunConfigurationBase?): Boolean = conf is JetRunConfiguration
+
+ override fun collectOutputFiles(srcFile: PsiFile,
+ output: VirtualFile?,
+ testoutput: VirtualFile?,
+ suite: CoverageSuitesBundle,
+ classFiles: MutableSet): Boolean {
+ if (srcFile is JetFile) {
+ val fileIndex = ProjectRootManager.getInstance(srcFile.getProject()).getFileIndex()
+ if (fileIndex.isInLibraryClasses(srcFile.getVirtualFile()) ||
+ fileIndex.isInLibrarySource(srcFile.getVirtualFile())) {
+ return false
+ }
+
+ val classNames = ApplicationManager.getApplication().runReadAction> { collectOutputClassNames(srcFile) }
+
+ fun findUnder(name: String, root: VirtualFile?): File? {
+ if (root != null) {
+ val outputFile = File(root.getPath(), name + ".class")
+ if (outputFile.exists()) {
+ return outputFile
+ }
+ }
+ return null
+ }
+
+ classNames.map { findUnder(it, output) ?: findUnder(it, testoutput) }.filterNotNullTo(classFiles)
+ return true
+ }
+ return false
+ }
+
+ class object {
+ public fun collectOutputClassNames(srcFile: JetFile): Set {
+ val typeMapper = JetPositionManager.createTypeMapper(srcFile, srcFile.getModuleInfo())
+ val classNames = LinkedHashSet()
+ srcFile.acceptChildren(object: JetTreeVisitorVoid() {
+ override fun visitDeclaration(dcl: JetDeclaration) {
+ super.visitDeclaration(dcl)
+ collectClassName(dcl.getFirstChild())
+ }
+
+ override fun visitFunctionLiteralExpression(expression: JetFunctionLiteralExpression) {
+ super.visitFunctionLiteralExpression(expression)
+ collectClassName(expression.getFunctionLiteral().getFirstChild())
+ }
+
+ private fun collectClassName(element: PsiElement) {
+ val className = JetPositionManager.getClassNameForElement(element, typeMapper, srcFile, false)
+ if (className != null) {
+ classNames.add(className)
+ }
+ }
+ })
+ return classNames
+ }
+ }
+}
\ No newline at end of file
diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java
deleted file mode 100644
index c72fb74f455..00000000000
--- a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.java
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * Copyright 2010-2013 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;
-
-import com.intellij.debugger.NoDataException;
-import com.intellij.debugger.PositionManager;
-import com.intellij.debugger.SourcePosition;
-import com.intellij.debugger.engine.DebugProcess;
-import com.intellij.debugger.requests.ClassPrepareRequestor;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.openapi.project.DumbService;
-import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.libraries.LibraryUtil;
-import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.Ref;
-import com.intellij.psi.PsiElement;
-import com.intellij.psi.PsiFile;
-import com.intellij.psi.search.GlobalSearchScope;
-import com.intellij.psi.util.*;
-import com.sun.jdi.AbsentInformationException;
-import com.sun.jdi.Location;
-import com.sun.jdi.ReferenceType;
-import com.sun.jdi.request.ClassPrepareRequest;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.annotations.TestOnly;
-import org.jetbrains.jet.analyzer.AnalysisResult;
-import org.jetbrains.jet.codegen.AsmUtil;
-import org.jetbrains.jet.codegen.ClassBuilderFactories;
-import org.jetbrains.jet.codegen.state.GenerationState;
-import org.jetbrains.jet.codegen.state.JetTypeMapper;
-import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
-import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
-import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
-import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
-import org.jetbrains.jet.lang.psi.*;
-import org.jetbrains.jet.lang.resolve.BindingContext;
-import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
-import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
-import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
-import org.jetbrains.jet.lang.resolve.extension.InlineAnalyzerExtension;
-import org.jetbrains.jet.lang.resolve.java.JvmClassName;
-import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils;
-import org.jetbrains.jet.lang.resolve.name.FqName;
-import org.jetbrains.jet.lang.types.lang.InlineStrategy;
-import org.jetbrains.jet.lang.types.lang.InlineUtil;
-import org.jetbrains.jet.plugin.caches.resolve.IdeaModuleInfo;
-import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheService;
-import org.jetbrains.jet.plugin.caches.resolve.ResolvePackage;
-import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils;
-import org.jetbrains.jet.plugin.util.DebuggerUtils;
-import org.jetbrains.org.objectweb.asm.Type;
-
-import java.util.*;
-
-import static org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForAnonymousClass;
-import static org.jetbrains.jet.plugin.stubindex.PackageIndexUtil.findFilesWithExactPackage;
-
-public class JetPositionManager implements PositionManager {
- private final DebugProcess myDebugProcess;
- private final WeakHashMap, CachedValue> myTypeMappers = new WeakHashMap, CachedValue>();
-
- public JetPositionManager(DebugProcess debugProcess) {
- myDebugProcess = debugProcess;
- }
-
- @Override
- @Nullable
- public SourcePosition getSourcePosition(@Nullable Location location) throws NoDataException {
- if (location == null) {
- throw new NoDataException();
- }
- PsiFile psiFile = getPsiFileByLocation(location);
- if (psiFile == null) {
- throw new NoDataException();
- }
-
- int lineNumber;
- try {
- lineNumber = location.lineNumber() - 1;
- }
- catch (InternalError e) {
- lineNumber = -1;
- }
-
- if (lineNumber >= 0) {
- JetFunctionLiteral lambdaIfInside = getLambdaIfInside(location, (JetFile) psiFile, lineNumber);
- if (lambdaIfInside != null) {
- return SourcePosition.createFromElement(lambdaIfInside.getBodyExpression().getStatements().get(0));
- }
- return SourcePosition.createFromLine(psiFile, lineNumber);
- }
-
- throw new NoDataException();
- }
-
- private JetFunctionLiteral getLambdaIfInside(@NotNull Location location, @NotNull JetFile file, int lineNumber) {
- String currentLocationFqName = location.declaringType().name();
- if (currentLocationFqName == null) return null;
-
- Integer start = CodeInsightUtils.getStartLineOffset(file, lineNumber);
- Integer end = CodeInsightUtils.getEndLineOffset(file, lineNumber);
- if (start == null || end == null) return null;
-
- PsiElement[] literals = CodeInsightUtils.findElementsOfClassInRange(file, start, end, JetFunctionLiteral.class);
- if (literals == null || literals.length == 0) return null;
-
- boolean isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null;
- JetTypeMapper typeMapper = !isInLibrary
- ? prepareTypeMapper(file)
- : createTypeMapperForLibraryFile(file.findElementAt(start), file);
-
- String currentLocationClassName = JvmClassName.byFqNameWithoutInnerClasses(new FqName(currentLocationFqName)).getInternalName();
- for (PsiElement literal : literals) {
- JetFunctionLiteral functionLiteral = (JetFunctionLiteral) literal;
- if (isInlinedLambda(functionLiteral, typeMapper.getBindingContext())) {
- continue;
- }
-
- String internalClassName = getClassNameForElement(literal.getFirstChild(), typeMapper, file, isInLibrary);
- if (internalClassName.equals(currentLocationClassName)) {
- return functionLiteral;
- }
- }
-
- return null;
- }
-
- @Nullable
- private PsiFile getPsiFileByLocation(@NotNull Location location) {
- String sourceName;
- try {
- sourceName = location.sourceName();
- }
- catch (AbsentInformationException e) {
- return null;
- }
-
- // JDI names are of form "package.Class$InnerClass"
- String referenceFqName = location.declaringType().name();
- String referenceInternalName = referenceFqName.replace('.', '/');
- JvmClassName className = JvmClassName.byInternalName(referenceInternalName);
-
- Project project = myDebugProcess.getProject();
-
- if (DumbService.getInstance(project).isDumb()) return null;
-
- return DebuggerUtils.findSourceFileForClass(project, GlobalSearchScope.allScope(project), className, sourceName, location.lineNumber() - 1);
- }
-
- @NotNull
- @Override
- public List getAllClasses(SourcePosition sourcePosition) throws NoDataException {
- if (!(sourcePosition.getFile() instanceof JetFile)) {
- throw new NoDataException();
- }
- String name = classNameForPosition(sourcePosition);
- List result = new ArrayList();
- if (name != null) {
- result.addAll(myDebugProcess.getVirtualMachineProxy().classesByName(name));
- }
- return result;
- }
-
- @Nullable
- private String classNameForPosition(final SourcePosition sourcePosition) {
- final Ref result = Ref.create();
-
- ApplicationManager.getApplication().runReadAction(new Runnable() {
- @Override
- @SuppressWarnings("unchecked")
- public void run() {
- JetFile file = (JetFile) sourcePosition.getFile();
- boolean isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null;
- JetTypeMapper typeMapper = !isInLibrary ? prepareTypeMapper(file) : createTypeMapperForLibraryFile(sourcePosition.getElementAt(), file);
- result.set(getClassNameForElement(sourcePosition.getElementAt(), typeMapper, file, isInLibrary));
- }
-
- });
-
- return result.get();
- }
-
- @SuppressWarnings("unchecked")
- public static String getClassNameForElement(
- @Nullable PsiElement notPositionedElement,
- @NotNull JetTypeMapper typeMapper,
- @NotNull JetFile file,
- boolean isInLibrary
- ) {
- PsiElement element = getElementToCalculateClassName(notPositionedElement);
-
- if (element instanceof JetClassOrObject) {
- return getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) element);
- }
- else if (element instanceof JetFunctionLiteral) {
- if (isInlinedLambda((JetFunctionLiteral) element, typeMapper.getBindingContext())) {
- return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary);
- } else {
- Type asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), ((JetFunctionLiteral) element));
- return asmType.getInternalName();
- }
- }
- else if (element instanceof JetClassInitializer) {
- PsiElement parent = getElementToCalculateClassName(element.getParent());
- // Class-object initializer
- if (parent instanceof JetObjectDeclaration && ((JetObjectDeclaration) parent).isClassObject()) {
- return getClassNameForElement(parent.getParent(), typeMapper, file, isInLibrary);
- }
- return getClassNameForElement(element, typeMapper, file, isInLibrary);
- }
- else if (element instanceof JetProperty && (!((JetProperty) element).isTopLevel() || !isInLibrary)) {
- if (isInPropertyAccessor(notPositionedElement)) {
- JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(element, JetClassOrObject.class);
- if (classOrObject != null) {
- return getJvmInternalNameForImpl(typeMapper, classOrObject);
- }
- }
-
- VariableDescriptor descriptor = (VariableDescriptor) typeMapper.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element);
- if (!(descriptor instanceof PropertyDescriptor)) {
- return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary);
- }
-
- return getJvmInternalNameForPropertyOwner(typeMapper, (PropertyDescriptor) descriptor);
- }
- else if (element instanceof JetNamedFunction) {
- PsiElement parent = getElementToCalculateClassName(element);
- if (parent instanceof JetClassOrObject) {
- return getJvmInternalNameForImpl(typeMapper, (JetClassOrObject) parent);
- }
- else if (parent != null) {
- Type asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), (JetElement) element);
- return asmType.getInternalName();
- }
- }
-
- if (isInLibrary) {
- JetElement elementAtForLibraryFile = getElementToCreateTypeMapperForLibraryFile(notPositionedElement);
- assert elementAtForLibraryFile != null : "Couldn't find element at breakpoint for library file " + file.getName()
- + (notPositionedElement == null ? "" : ", notPositionedElement = " + JetPsiUtil.getElementTextWithContext( (JetElement) notPositionedElement));
- return DebuggerPackage.findPackagePartInternalNameForLibraryFile(elementAtForLibraryFile);
- }
-
- return PackagePartClassUtils.getPackagePartInternalName(file);
- }
-
- @Nullable
- private static JetDeclaration getElementToCalculateClassName(@Nullable PsiElement notPositionedElement) {
- //noinspection unchecked
- return PsiTreeUtil.getParentOfType(notPositionedElement,
- JetClassOrObject.class,
- JetFunctionLiteral.class, JetNamedFunction.class,
- JetProperty.class,
- JetClassInitializer.class);
- }
-
- @NotNull
- public static String getJvmInternalNameForPropertyOwner(@NotNull JetTypeMapper typeMapper, @NotNull PropertyDescriptor descriptor) {
- return typeMapper.mapOwner(
- AsmUtil.isPropertyWithBackingFieldInOuterClass(descriptor) ? descriptor.getContainingDeclaration() : descriptor,
- true)
- .getInternalName();
- }
-
- private static boolean isInPropertyAccessor(@Nullable PsiElement element) {
- //noinspection unchecked
- return element instanceof JetPropertyAccessor || ((JetElement) PsiTreeUtil.getParentOfType(element, JetProperty.class, JetPropertyAccessor.class)) instanceof JetPropertyAccessor;
- }
-
- @Nullable
- private static JetElement getElementToCreateTypeMapperForLibraryFile(@Nullable PsiElement element) {
- return element instanceof JetElement ? (JetElement) element : PsiTreeUtil.getParentOfType(element, JetElement.class);
- }
-
- @Nullable
- private static String getJvmInternalNameForImpl(JetTypeMapper typeMapper, JetClassOrObject jetClass) {
- ClassDescriptor classDescriptor = typeMapper.getBindingContext().get(BindingContext.CLASS, jetClass);
- if (classDescriptor == null) {
- return null;
- }
-
- if (jetClass instanceof JetClass && ((JetClass) jetClass).isTrait()) {
- return typeMapper.mapTraitImpl(classDescriptor).getInternalName();
- }
-
- return typeMapper.mapClass(classDescriptor).getInternalName();
- }
-
- private static JetTypeMapper createTypeMapperForLibraryFile(@Nullable PsiElement notPositionedElement, @NotNull JetFile file) {
- JetElement element = getElementToCreateTypeMapperForLibraryFile(notPositionedElement);
- AnalysisResult analysisResult = ResolvePackage.analyzeAndGetResult(element);
-
- GenerationState state = new GenerationState(file.getProject(), ClassBuilderFactories.THROW_EXCEPTION,
- analysisResult.getModuleDescriptor(),
- analysisResult.getBindingContext(),
- Collections.singletonList(file)
- );
- state.beforeCompile();
- return state.getTypeMapper();
- }
-
- private JetTypeMapper prepareTypeMapper(final JetFile file) {
- final Pair key = createKeyForTypeMapper(file);
-
- CachedValue value = myTypeMappers.get(key);
- if(value == null) {
- value = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider() {
- @Override
- public Result compute() {
- Project project = file.getProject();
- GlobalSearchScope packageFacadeScope = key.second.contentScope();
- Collection packageFiles = findFilesWithExactPackage(key.first, packageFacadeScope, project);
-
- AnalysisResult analysisResult = KotlinCacheService.OBJECT$.getInstance(project).getAnalysisResults(packageFiles);
- analysisResult.throwIfError();
-
- GenerationState state = new GenerationState(project, ClassBuilderFactories.THROW_EXCEPTION,
- analysisResult.getModuleDescriptor(), analysisResult.getBindingContext(),
- new ArrayList(packageFiles)
- );
- state.beforeCompile();
- return new Result(state.getTypeMapper(), PsiModificationTracker.MODIFICATION_COUNT);
- }
- }, false);
-
- myTypeMappers.put(key, value);
- }
-
- return value.getValue();
- }
-
- @NotNull
- @Override
- public List locationsOfLine(ReferenceType type, SourcePosition position) throws NoDataException {
- if (!(position.getFile() instanceof JetFile)) {
- throw new NoDataException();
- }
- try {
- int line = position.getLine() + 1;
- List locations = myDebugProcess.getVirtualMachineProxy().versionHigher("1.4")
- ? type.locationsOfLine(DebugProcess.JAVA_STRATUM, null, line)
- : type.locationsOfLine(line);
- if (locations == null || locations.isEmpty()) throw new NoDataException();
- return locations;
- }
- catch (AbsentInformationException e) {
- throw new NoDataException();
- }
- }
-
- @Override
- public ClassPrepareRequest createPrepareRequest(ClassPrepareRequestor classPrepareRequestor,
- SourcePosition sourcePosition) throws NoDataException {
- if (!(sourcePosition.getFile() instanceof JetFile)) {
- throw new NoDataException();
- }
- String className = classNameForPosition(sourcePosition);
- if (className == null) {
- return null;
- }
- return myDebugProcess.getRequestsManager().createClassPrepareRequest(classPrepareRequestor, className.replace('/', '.'));
- }
-
- @TestOnly
- public void addTypeMapper(JetFile file, final JetTypeMapper typeMapper) {
- CachedValue value = CachedValuesManager.getManager(file.getProject()).createCachedValue(new CachedValueProvider() {
- @Override
- public Result compute() {
- return new Result(typeMapper, PsiModificationTracker.MODIFICATION_COUNT);
- }
- }, false);
-
- Pair key = createKeyForTypeMapper(file);
- myTypeMappers.put(key, value);
- }
-
-
- public static boolean isInlinedLambda(@NotNull JetFunctionLiteral functionLiteral, @NotNull BindingContext context) {
- PsiElement functionLiteralExpression = functionLiteral.getParent();
- if (functionLiteralExpression == null) return false;
-
- PsiElement parent = functionLiteralExpression.getParent();
-
- PsiElement valueArgument = functionLiteralExpression;
- while (parent instanceof JetParenthesizedExpression ||
- parent instanceof JetBinaryExpressionWithTypeRHS ||
- parent instanceof JetLabeledExpression) {
- valueArgument = parent;
- parent = parent.getParent();
- }
-
- while (parent instanceof ValueArgument ||
- parent instanceof JetValueArgumentList) {
- parent = parent.getParent();
- }
-
- if (!(parent instanceof JetElement)) return false;
-
- ResolvedCall> call = CallUtilPackage.getResolvedCall((JetElement) parent, context);
- if (call == null) return false;
-
- InlineStrategy inlineType = InlineUtil.getInlineType(call.getResultingDescriptor());
- if (!inlineType.isInline()) return false;
-
- for (Map.Entry entry : call.getValueArguments().entrySet()) {
- ValueParameterDescriptor valueParameterDescriptor = entry.getKey();
- ResolvedValueArgument resolvedValueArgument = entry.getValue();
-
- for (ValueArgument next : resolvedValueArgument.getArguments()) {
- JetExpression expression = next.getArgumentExpression();
- if (valueArgument == expression) {
- return InlineAnalyzerExtension.checkInlinableParameter(
- valueParameterDescriptor, expression,
- call.getResultingDescriptor(), null
- );
- }
- }
- }
- return false;
- }
-
- private static Pair createKeyForTypeMapper(@NotNull JetFile file) {
- return new Pair(file.getPackageFqName(), ResolvePackage.getModuleInfo(file));
- }
-
-}
diff --git a/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.kt b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.kt
new file mode 100644
index 00000000000..2f784819d8d
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/debugger/JetPositionManager.kt
@@ -0,0 +1,391 @@
+/*
+ * 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
+
+import com.intellij.debugger.NoDataException
+import com.intellij.debugger.PositionManager
+import com.intellij.debugger.SourcePosition
+import com.intellij.debugger.engine.DebugProcess
+import com.intellij.debugger.requests.ClassPrepareRequestor
+import com.intellij.openapi.application.ApplicationManager
+import com.intellij.openapi.project.DumbService
+import com.intellij.openapi.project.Project
+import com.intellij.openapi.roots.libraries.LibraryUtil
+import com.intellij.openapi.util.Pair
+import com.intellij.openapi.util.Ref
+import com.intellij.psi.PsiElement
+import com.intellij.psi.PsiFile
+import com.intellij.psi.search.GlobalSearchScope
+import com.intellij.psi.util.*
+import com.sun.jdi.AbsentInformationException
+import com.sun.jdi.Location
+import com.sun.jdi.ReferenceType
+import com.sun.jdi.request.ClassPrepareRequest
+import org.jetbrains.annotations.TestOnly
+import org.jetbrains.jet.analyzer.AnalysisResult
+import org.jetbrains.jet.codegen.AsmUtil
+import org.jetbrains.jet.codegen.ClassBuilderFactories
+import org.jetbrains.jet.codegen.state.GenerationState
+import org.jetbrains.jet.codegen.state.JetTypeMapper
+import org.jetbrains.jet.lang.descriptors.ClassDescriptor
+import org.jetbrains.jet.lang.descriptors.PropertyDescriptor
+import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor
+import org.jetbrains.jet.lang.descriptors.VariableDescriptor
+import org.jetbrains.jet.lang.psi.*
+import org.jetbrains.jet.lang.resolve.BindingContext
+import org.jetbrains.jet.lang.resolve.calls.callUtil.*
+import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall
+import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument
+import org.jetbrains.jet.lang.resolve.extension.InlineAnalyzerExtension
+import org.jetbrains.jet.lang.resolve.java.JvmClassName
+import org.jetbrains.jet.lang.resolve.kotlin.PackagePartClassUtils
+import org.jetbrains.jet.lang.resolve.name.FqName
+import org.jetbrains.jet.lang.types.lang.InlineStrategy
+import org.jetbrains.jet.lang.types.lang.InlineUtil
+import org.jetbrains.jet.plugin.caches.resolve.IdeaModuleInfo
+import org.jetbrains.jet.plugin.caches.resolve.KotlinCacheService
+import org.jetbrains.jet.plugin.caches.resolve.*
+import org.jetbrains.jet.plugin.codeInsight.CodeInsightUtils
+import org.jetbrains.jet.plugin.util.DebuggerUtils
+import org.jetbrains.org.objectweb.asm.Type
+
+import java.util.*
+
+import org.jetbrains.jet.codegen.binding.CodegenBinding.asmTypeForAnonymousClass
+import org.jetbrains.jet.plugin.stubindex.PackageIndexUtil
+import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor
+import com.intellij.psi.stubs.StubElement
+import org.jetbrains.jet.plugin.util.application.runReadAction
+
+public class JetPositionManager(private val myDebugProcess: DebugProcess) : PositionManager {
+ private val myTypeMappers = WeakHashMap, CachedValue>()
+
+ override fun getSourcePosition(location: Location?): SourcePosition? {
+ if (location == null) {
+ throw NoDataException()
+ }
+ val psiFile = getPsiFileByLocation(location)
+ if (psiFile == null) {
+ throw NoDataException()
+ }
+
+ val lineNumber = try {
+ location.lineNumber() - 1
+ }
+ catch (e: InternalError) {
+ -1
+ }
+
+
+ if (lineNumber >= 0) {
+ val lambdaIfInside = getLambdaIfInside(location, psiFile as JetFile, lineNumber)
+ if (lambdaIfInside != null) {
+ return SourcePosition.createFromElement(lambdaIfInside.getBodyExpression().getStatements().get(0))
+ }
+ return SourcePosition.createFromLine(psiFile, lineNumber)
+ }
+
+ throw NoDataException()
+ }
+
+ private fun getLambdaIfInside(location: Location, file: JetFile, lineNumber: Int): JetFunctionLiteral? {
+ val currentLocationFqName = location.declaringType().name()
+ if (currentLocationFqName == null) return null
+
+ val start = CodeInsightUtils.getStartLineOffset(file, lineNumber)
+ val end = CodeInsightUtils.getEndLineOffset(file, lineNumber)
+ if (start == null || end == null) return null
+
+ val literals = CodeInsightUtils.findElementsOfClassInRange(file, start, end, javaClass())
+ if (literals == null || literals.size() == 0) return null
+
+ val isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null
+ val typeMapper = if (!isInLibrary)
+ prepareTypeMapper(file)
+ else
+ createTypeMapperForLibraryFile(file.findElementAt(start), file)
+
+ val currentLocationClassName = JvmClassName.byFqNameWithoutInnerClasses(FqName(currentLocationFqName)).getInternalName()
+ for (literal in literals) {
+ val functionLiteral = literal as JetFunctionLiteral
+ if (isInlinedLambda(functionLiteral, typeMapper.getBindingContext())) {
+ continue
+ }
+
+ val internalClassName = getClassNameForElement(literal.getFirstChild(), typeMapper, file, isInLibrary)
+ if (internalClassName == currentLocationClassName) {
+ return functionLiteral
+ }
+ }
+
+ return null
+ }
+
+ private fun getPsiFileByLocation(location: Location): PsiFile? {
+ val sourceName: String
+ try {
+ sourceName = location.sourceName()
+ }
+ catch (e: AbsentInformationException) {
+ return null
+ }
+
+
+ // JDI names are of form "package.Class$InnerClass"
+ val referenceFqName = location.declaringType().name()
+ val referenceInternalName = referenceFqName.replace('.', '/')
+ val className = JvmClassName.byInternalName(referenceInternalName)
+
+ val project = myDebugProcess.getProject()
+
+ if (DumbService.getInstance(project).isDumb()) return null
+
+ return DebuggerUtils.findSourceFileForClass(project, GlobalSearchScope.allScope(project), className, sourceName, location.lineNumber() - 1)
+ }
+
+ override fun getAllClasses(sourcePosition: SourcePosition): List {
+ if (sourcePosition.getFile() !is JetFile) {
+ throw NoDataException()
+ }
+ val name = classNameForPosition(sourcePosition)
+ val result = ArrayList()
+ if (name != null) {
+ result.addAll(myDebugProcess.getVirtualMachineProxy().classesByName(name))
+ }
+ return result
+ }
+
+ private fun classNameForPosition(sourcePosition: SourcePosition): String? {
+ return runReadAction {
+ val file = sourcePosition.getFile() as JetFile
+ val isInLibrary = LibraryUtil.findLibraryEntry(file.getVirtualFile(), file.getProject()) != null
+ val typeMapper = if (!isInLibrary) prepareTypeMapper(file) else createTypeMapperForLibraryFile(sourcePosition.getElementAt(), file)
+ getClassNameForElement(sourcePosition.getElementAt(), typeMapper, file, isInLibrary)
+ }
+ }
+
+ private fun prepareTypeMapper(file: JetFile): JetTypeMapper {
+ val key = createKeyForTypeMapper(file)
+
+ var value: CachedValue? = myTypeMappers.get(key)
+ if (value == null) {
+ value = CachedValuesManager.getManager(file.getProject()).createCachedValue(
+ {() ->
+ val typeMapper = createTypeMapper(file, key.second)
+ CachedValueProvider.Result(typeMapper, PsiModificationTracker.MODIFICATION_COUNT)
+ }, false)
+
+ myTypeMappers.put(key, value)
+ }
+
+ return value!!.getValue()
+ }
+
+ override fun locationsOfLine(type: ReferenceType, position: SourcePosition): List {
+ if (position.getFile() !is JetFile) {
+ throw NoDataException()
+ }
+ try {
+ val line = position.getLine() + 1
+ val locations = if (myDebugProcess.getVirtualMachineProxy().versionHigher("1.4"))
+ type.locationsOfLine(DebugProcess.JAVA_STRATUM, null, line)
+ else
+ type.locationsOfLine(line)
+ if (locations == null || locations.isEmpty()) throw NoDataException()
+ return locations
+ }
+ catch (e: AbsentInformationException) {
+ throw NoDataException()
+ }
+ }
+
+ override fun createPrepareRequest(classPrepareRequestor: ClassPrepareRequestor, sourcePosition: SourcePosition): ClassPrepareRequest? {
+ if (sourcePosition.getFile() !is JetFile) {
+ throw NoDataException()
+ }
+ val className = classNameForPosition(sourcePosition)
+ if (className == null) {
+ return null
+ }
+ return myDebugProcess.getRequestsManager().createClassPrepareRequest(classPrepareRequestor, className.replace('/', '.'))
+ }
+
+ TestOnly
+ public fun addTypeMapper(file: JetFile, typeMapper: JetTypeMapper) {
+ val value = CachedValuesManager.getManager(file.getProject()).createCachedValue(
+ { () -> CachedValueProvider.Result(typeMapper, PsiModificationTracker.MODIFICATION_COUNT) }, false)
+ val key = createKeyForTypeMapper(file)
+ myTypeMappers.put(key, value)
+ }
+
+ class object {
+ public fun createTypeMapper(file: JetFile, moduleInfo: IdeaModuleInfo): JetTypeMapper {
+ val project = file.getProject()
+ val packageFacadeScope = moduleInfo.contentScope()
+ val packageFiles = PackageIndexUtil.findFilesWithExactPackage(file.getPackageFqName(), packageFacadeScope, project)
+
+ val analysisResult = KotlinCacheService.getInstance(project).getAnalysisResults(packageFiles)
+ analysisResult.throwIfError()
+
+ val state = GenerationState(project, ClassBuilderFactories.THROW_EXCEPTION, analysisResult.moduleDescriptor,
+ analysisResult.bindingContext, packageFiles.toList())
+ state.beforeCompile()
+ return state.getTypeMapper()
+ }
+
+ public fun getClassNameForElement(notPositionedElement: PsiElement?, typeMapper: JetTypeMapper, file: JetFile, isInLibrary: Boolean): String? {
+ val element = getElementToCalculateClassName(notPositionedElement)
+ when {
+ element is JetClassOrObject -> return getJvmInternalNameForImpl(typeMapper, element)
+ element is JetFunctionLiteral -> {
+ if (isInlinedLambda(element, typeMapper.getBindingContext())) {
+ return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary)
+ }
+ else {
+ val asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), element)
+ return asmType.getInternalName()
+ }
+ }
+ element is JetClassInitializer -> {
+ val parent = getElementToCalculateClassName(element.getParent())
+ // Class-object initializer
+ if (parent is JetObjectDeclaration && parent.isClassObject()) {
+ return getClassNameForElement(parent.getParent(), typeMapper, file, isInLibrary)
+ }
+ return getClassNameForElement(element, typeMapper, file, isInLibrary)
+ }
+ element is JetProperty && (!element.isTopLevel() || !isInLibrary) -> {
+ if (isInPropertyAccessor(notPositionedElement)) {
+ val classOrObject = PsiTreeUtil.getParentOfType(element, javaClass())
+ if (classOrObject != null) {
+ return getJvmInternalNameForImpl(typeMapper, classOrObject)
+ }
+ }
+
+ val descriptor = typeMapper.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, element)
+ if (descriptor !is PropertyDescriptor) {
+ return getClassNameForElement(element.getParent(), typeMapper, file, isInLibrary)
+ }
+
+ return getJvmInternalNameForPropertyOwner(typeMapper, descriptor)
+ }
+ element is JetNamedFunction -> {
+ val parent = getElementToCalculateClassName(element)
+ if (parent is JetClassOrObject) {
+ return getJvmInternalNameForImpl(typeMapper, parent)
+ }
+ else if (parent != null) {
+ val asmType = asmTypeForAnonymousClass(typeMapper.getBindingContext(), element)
+ return asmType.getInternalName()
+ }
+ }
+ }
+
+ if (isInLibrary) {
+ val elementAtForLibraryFile = getElementToCreateTypeMapperForLibraryFile(notPositionedElement)
+ assert(elementAtForLibraryFile != null) {
+ "Couldn't find element at breakpoint for library file " + file.getName() +
+ (if (notPositionedElement == null) "" else ", notPositionedElement = " + JetPsiUtil.getElementTextWithContext(notPositionedElement))
+ }
+ return findPackagePartInternalNameForLibraryFile(elementAtForLibraryFile!!)
+ }
+
+ return PackagePartClassUtils.getPackagePartInternalName(file)
+ }
+
+ private fun getElementToCalculateClassName(notPositionedElement: PsiElement?) =
+ PsiTreeUtil.getParentOfType(notPositionedElement,
+ javaClass(),
+ javaClass(),
+ javaClass(),
+ javaClass(),
+ javaClass())
+
+ public fun getJvmInternalNameForPropertyOwner(typeMapper: JetTypeMapper, descriptor: PropertyDescriptor): String {
+ return typeMapper.mapOwner(
+ if (AsmUtil.isPropertyWithBackingFieldInOuterClass(descriptor)) descriptor.getContainingDeclaration() else descriptor,
+ true).getInternalName()
+ }
+
+ private fun isInPropertyAccessor(element: PsiElement?) =
+ element is JetPropertyAccessor ||
+ PsiTreeUtil.getParentOfType(element, javaClass(), javaClass()) is JetPropertyAccessor
+
+ private fun getElementToCreateTypeMapperForLibraryFile(element: PsiElement?) =
+ if (element is JetElement) element else PsiTreeUtil.getParentOfType(element, javaClass())
+
+ private fun getJvmInternalNameForImpl(typeMapper: JetTypeMapper, jetClass: JetClassOrObject): String? {
+ val classDescriptor = typeMapper.getBindingContext().get(BindingContext.CLASS, jetClass)
+ if (classDescriptor == null) {
+ return null
+ }
+
+ if (jetClass is JetClass && jetClass.isTrait()) {
+ return typeMapper.mapTraitImpl(classDescriptor).getInternalName()
+ }
+
+ return typeMapper.mapClass(classDescriptor).getInternalName()
+ }
+
+ private fun createTypeMapperForLibraryFile(notPositionedElement: PsiElement?, file: JetFile): JetTypeMapper {
+ val element = getElementToCreateTypeMapperForLibraryFile(notPositionedElement)
+ val analysisResult = element!!.analyzeAndGetResult()
+
+ val state = GenerationState(file.getProject(), ClassBuilderFactories.THROW_EXCEPTION,
+ analysisResult.moduleDescriptor, analysisResult.bindingContext, listOf(file))
+ state.beforeCompile()
+ return state.getTypeMapper()
+ }
+
+ public fun isInlinedLambda(functionLiteral: JetFunctionLiteral, context: BindingContext): Boolean {
+ val functionLiteralExpression = functionLiteral.getParent()
+ if (functionLiteralExpression == null) return false
+
+ var parent = functionLiteralExpression.getParent()
+
+ var valueArgument: PsiElement = functionLiteralExpression
+ while (parent is JetParenthesizedExpression || parent is JetBinaryExpressionWithTypeRHS || parent is JetLabeledExpression) {
+ valueArgument = parent
+ parent = parent.getParent()
+ }
+
+ while (parent is ValueArgument || parent is JetValueArgumentList) {
+ parent = parent.getParent()
+ }
+
+ if (parent !is JetElement) return false
+
+ val call = (parent as JetElement).getResolvedCall(context)
+ if (call == null) return false
+
+ val inlineType = InlineUtil.getInlineType(call.getResultingDescriptor())
+ if (!inlineType.isInline()) return false
+
+ for ((valueParameterDescriptor, resolvedValueArgument) in call.getValueArguments()) {
+ for (next in resolvedValueArgument.getArguments()) {
+ val expression = next.getArgumentExpression()
+ if (valueArgument == expression) {
+ return InlineAnalyzerExtension.checkInlinableParameter(valueParameterDescriptor, expression, call.getResultingDescriptor(), null)
+ }
+ }
+ }
+ return false
+ }
+
+ private fun createKeyForTypeMapper(file: JetFile) = Pair(file.getPackageFqName(), file.getModuleInfo())
+ }
+}
diff --git a/idea/testData/coverage/outputFiles/lambda.expected.txt b/idea/testData/coverage/outputFiles/lambda.expected.txt
new file mode 100644
index 00000000000..39ea5e49821
--- /dev/null
+++ b/idea/testData/coverage/outputFiles/lambda.expected.txt
@@ -0,0 +1,2 @@
+org/demo/coverage/Foo
+org/demo/coverage/Foo$bar$1
diff --git a/idea/testData/coverage/outputFiles/lambda.kt b/idea/testData/coverage/outputFiles/lambda.kt
new file mode 100644
index 00000000000..3007ac1e940
--- /dev/null
+++ b/idea/testData/coverage/outputFiles/lambda.kt
@@ -0,0 +1,12 @@
+package org.demo.coverage
+
+public class Foo {
+ public fun forEach(fn: (Any?) -> Unit): Unit {
+ }
+
+ public fun bar() {
+ forEach {
+ println("foo")
+ }
+ }
+}
diff --git a/idea/tests/org/jetbrains/jet/plugin/coverage/AbstractKotlinCoverageOutputFilesTest.kt b/idea/tests/org/jetbrains/jet/plugin/coverage/AbstractKotlinCoverageOutputFilesTest.kt
new file mode 100644
index 00000000000..09f0fc81dae
--- /dev/null
+++ b/idea/tests/org/jetbrains/jet/plugin/coverage/AbstractKotlinCoverageOutputFilesTest.kt
@@ -0,0 +1,40 @@
+/*
+ * 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.coverage
+
+import org.jetbrains.jet.plugin.JetLightCodeInsightFixtureTestCase
+import org.jetbrains.jet.plugin.PluginTestCaseBase
+import org.jetbrains.jet.lang.psi.JetFile
+import kotlin.test.assertNotNull
+import com.intellij.openapi.util.io.FileUtil
+import com.intellij.openapi.fileEditor.impl.LoadTextUtil
+import kotlin.test.assertEquals
+import java.io.File
+import com.intellij.testFramework.UsefulTestCase
+import org.jetbrains.jet.JetTestUtils
+
+public abstract class AbstractKotlinCoverageOutputFilesTest(): JetLightCodeInsightFixtureTestCase() {
+ private val TEST_DATA_PATH = PluginTestCaseBase.getTestDataPathBase() + "/coverage/outputFiles"
+
+ override fun getTestDataPath(): String? = TEST_DATA_PATH
+
+ public fun doTest(path: String) {
+ val kotlinFile = myFixture.configureByFile(path) as JetFile
+ val actualClasses = KotlinCoverageExtension.collectOutputClassNames(kotlinFile)
+ JetTestUtils.assertEqualsToFile(File(path.replace(".kt", ".expected.txt")), actualClasses.join("\n"))
+ }
+}
diff --git a/idea/tests/org/jetbrains/jet/plugin/coverage/KotlinCoverageOutputFilesTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/coverage/KotlinCoverageOutputFilesTestGenerated.java
new file mode 100644
index 00000000000..ec317bac214
--- /dev/null
+++ b/idea/tests/org/jetbrains/jet/plugin/coverage/KotlinCoverageOutputFilesTestGenerated.java
@@ -0,0 +1,44 @@
+/*
+ * 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.coverage;
+
+import com.intellij.testFramework.TestDataPath;
+import org.jetbrains.jet.JUnit3RunnerWithInners;
+import org.jetbrains.jet.JetTestUtils;
+import org.jetbrains.jet.test.InnerTestClasses;
+import org.jetbrains.jet.test.TestMetadata;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.util.regex.Pattern;
+
+/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
+@SuppressWarnings("all")
+@TestMetadata("idea/testData/coverage/outputFiles")
+@TestDataPath("$PROJECT_ROOT")
+@RunWith(JUnit3RunnerWithInners.class)
+public class KotlinCoverageOutputFilesTestGenerated extends AbstractKotlinCoverageOutputFilesTest {
+ public void testAllFilesPresentInOutputFiles() throws Exception {
+ JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/coverage/outputFiles"), Pattern.compile("^(.+)\\.kt$"), true);
+ }
+
+ @TestMetadata("lambda.kt")
+ public void testLambda() throws Exception {
+ String fileName = JetTestUtils.navigationMetadata("idea/testData/coverage/outputFiles/lambda.kt");
+ doTest(fileName);
+ }
+}