@Nullable private HyperlinkInfo createHyperlinkInfo(@NotNull String line) { Project project = searchScope.getProject(); if (project == null) return null; StackTraceElement element = parseStackTraceLine(line); if (element == null) return null; // All true classes should be handled correctly in the default ExceptionFilter. Special cases: // - static facades; // - package facades / package parts (generated by pre-M13 compiled); // - local classes (and closures) in top-level function and property declarations. String fileName = element.getFileName(); // fullyQualifiedName is of format "package.Class$Inner" String fullyQualifiedName = element.getClassName(); int lineNumber = element.getLineNumber() - 1; String internalName = fullyQualifiedName.replace('.', '/'); JvmClassName jvmClassName = JvmClassName.byInternalName(internalName); JetFile file = DebuggerUtils.findSourceFileForClass(project, searchScope, jvmClassName, fileName); if (file == null) return null; VirtualFile virtualFile = file.getVirtualFile(); if (virtualFile == null) return null; return new OpenFileHyperlinkInfo(project, virtualFile, lineNumber); }
// TODO: check it's external module // TODO?: assert method exists in facade? public String changeOwnerForExternalPackage(String type, int opcode) { if (isSameModule || (opcode & Opcodes.INVOKESTATIC) == 0) { return type; } JvmClassName name = JvmClassName.byInternalName(type); String packageClassInternalName = PackageClassUtils.getPackageClassInternalName(name.getPackageFqName()); if (type.startsWith(packageClassInternalName + '$')) { VirtualFile virtualFile = InlineCodegenUtil.findVirtualFile(inliningContext.state.getProject(), type); if (virtualFile != null) { KotlinJvmBinaryClass klass = KotlinBinaryClassCache.getKotlinBinaryClass(virtualFile); if (klass != null && klass.getClassHeader().getSyntheticClassKind() == KotlinSyntheticClass.Kind.PACKAGE_PART) { return packageClassInternalName; } } } return type; }
@Nullable public static VirtualFile findVirtualFile( @NotNull Project project, @NotNull String internalClassName) { FqName packageFqName = JvmClassName.byInternalName(internalClassName).getPackageFqName(); String classNameWithDollars = StringsKt.substringAfterLast(internalClassName, "/", internalClassName); JvmVirtualFileFinder fileFinder = JvmVirtualFileFinder.SERVICE.getInstance(project); // TODO: we cannot construct proper classId at this point, we need to read InnerClasses info // from class file // we construct valid.package.name/RelativeClassNameAsSingleName that should work in compiler, // but fails for inner classes in IDE return fileFinder.findVirtualFileWithHeader( new ClassId(packageFqName, Name.identifier(classNameWithDollars))); }
@NotNull private static GenerationState generate( @NotNull KotlinCoreEnvironment environment, @NotNull AnalysisResult result, @NotNull List<KtFile> sourceFiles, @Nullable Module module, File outputDirectory, String moduleName) { CompilerConfiguration configuration = environment.getConfiguration(); IncrementalCompilationComponents incrementalCompilationComponents = configuration.get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS); Collection<FqName> packagesWithObsoleteParts; List<FqName> obsoleteMultifileClasses; TargetId targetId = null; if (module == null || incrementalCompilationComponents == null) { packagesWithObsoleteParts = Collections.emptySet(); obsoleteMultifileClasses = Collections.emptyList(); } else { targetId = TargetIdKt.TargetId(module); IncrementalCache incrementalCache = incrementalCompilationComponents.getIncrementalCache(targetId); packagesWithObsoleteParts = new HashSet<FqName>(); for (String internalName : incrementalCache.getObsoletePackageParts()) { packagesWithObsoleteParts.add(JvmClassName.byInternalName(internalName).getPackageFqName()); } obsoleteMultifileClasses = new ArrayList<FqName>(); for (String obsoleteFacadeInternalName : incrementalCache.getObsoleteMultifileClasses()) { obsoleteMultifileClasses.add( JvmClassName.byInternalName(obsoleteFacadeInternalName) .getFqNameForClassNameWithoutDollars()); } } BindingTraceContext diagnosticHolder = new BindingTraceContext(); GenerationState generationState = new GenerationState( environment.getProject(), ClassBuilderFactories.BINARIES, result.getModuleDescriptor(), result.getBindingContext(), sourceFiles, configuration.get(JVMConfigurationKeys.DISABLE_CALL_ASSERTIONS, false), configuration.get(JVMConfigurationKeys.DISABLE_PARAM_ASSERTIONS, false), GenerationState.GenerateClassFilter.GENERATE_ALL, configuration.get(JVMConfigurationKeys.DISABLE_INLINE, false), configuration.get(JVMConfigurationKeys.DISABLE_OPTIMIZATION, false), /* useTypeTableInSerializer = */ false, diagnosticHolder, packagesWithObsoleteParts, obsoleteMultifileClasses, targetId, moduleName, outputDirectory, incrementalCompilationComponents); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); long generationStart = PerformanceCounter.Companion.currentTime(); KotlinCodegenFacade.compileCorrectFiles( generationState, CompilationErrorHandler.THROW_EXCEPTION); long generationNanos = PerformanceCounter.Companion.currentTime() - generationStart; String desc = module != null ? "target " + module.getModuleName() + "-" + module.getModuleType() + " " : ""; String message = "GENERATE: " + sourceFiles.size() + " files (" + environment.countLinesOfCode(sourceFiles) + " lines) " + desc + "in " + TimeUnit.NANOSECONDS.toMillis(generationNanos) + " ms"; K2JVMCompiler.Companion.reportPerf(environment.getConfiguration(), message); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); AnalyzerWithCompilerReport.reportDiagnostics( new FilteredJvmDiagnostics( diagnosticHolder.getBindingContext().getDiagnostics(), result.getBindingContext().getDiagnostics()), environment.getConfiguration().get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY)); ProgressIndicatorAndCompilationCanceledStatus.checkCanceled(); return generationState; }
@NotNull public LineResult eval(@NotNull String line) { ++lineNumber; FqName scriptFqName = new FqName("Line" + lineNumber); Type scriptClassType = asmTypeByFqNameWithoutInnerClasses(scriptFqName); StringBuilder fullText = new StringBuilder(); for (String prevLine : previousIncompleteLines) { fullText.append(prevLine).append("\n"); } fullText.append(line); LightVirtualFile virtualFile = new LightVirtualFile( "line" + lineNumber + JetParserDefinition.STD_SCRIPT_EXT, JetLanguage.INSTANCE, fullText.toString()); virtualFile.setCharset(CharsetToolkit.UTF8_CHARSET); JetFile psiFile = (JetFile) psiFileFactory.trySetupPsiForFile(virtualFile, JetLanguage.INSTANCE, true, false); assert psiFile != null : "Script file not analyzed at line " + lineNumber + ": " + fullText; ReplMessageCollectorWrapper errorCollector = new ReplMessageCollectorWrapper(); AnalyzerWithCompilerReport.SyntaxErrorReport syntaxErrorReport = AnalyzerWithCompilerReport.reportSyntaxErrors( psiFile, errorCollector.getMessageCollector()); if (syntaxErrorReport.isHasErrors() && syntaxErrorReport.isAllErrorsAtEof()) { previousIncompleteLines.add(line); return LineResult.incomplete(); } previousIncompleteLines.clear(); if (syntaxErrorReport.isHasErrors()) { return LineResult.error(errorCollector.getString()); } prepareForTheNextReplLine(topDownAnalysisContext); trace.clearDiagnostics(); //noinspection ConstantConditions psiFile.getScript().putUserData(ScriptPriorities.PRIORITY_KEY, lineNumber); ScriptDescriptor scriptDescriptor = doAnalyze(psiFile, errorCollector); if (scriptDescriptor == null) { return LineResult.error(errorCollector.getString()); } List<Pair<ScriptDescriptor, Type>> earlierScripts = Lists.newArrayList(); for (EarlierLine earlierLine : earlierLines) { earlierScripts.add( Pair.create(earlierLine.getScriptDescriptor(), earlierLine.getClassType())); } GenerationState state = new GenerationState( psiFile.getProject(), ClassBuilderFactories.BINARIES, module, trace.getBindingContext(), Collections.singletonList(psiFile)); compileScript( psiFile.getScript(), scriptClassType, earlierScripts, state, CompilationErrorHandler.THROW_EXCEPTION); for (OutputFile outputFile : state.getFactory().asList()) { classLoader.addClass( JvmClassName.byInternalName(outputFile.getRelativePath().replaceFirst("\\.class$", "")), outputFile.asByteArray()); } try { Class<?> scriptClass = classLoader.loadClass(scriptFqName.asString()); Class<?>[] constructorParams = new Class<?>[earlierLines.size()]; Object[] constructorArgs = new Object[earlierLines.size()]; for (int i = 0; i < earlierLines.size(); ++i) { constructorParams[i] = earlierLines.get(i).getScriptClass(); constructorArgs[i] = earlierLines.get(i).getScriptInstance(); } Constructor<?> scriptInstanceConstructor = scriptClass.getConstructor(constructorParams); Object scriptInstance; try { scriptInstance = scriptInstanceConstructor.newInstance(constructorArgs); } catch (Throwable e) { return LineResult.error(renderStackTrace(e.getCause())); } Field rvField = scriptClass.getDeclaredField("rv"); rvField.setAccessible(true); Object rv = rvField.get(scriptInstance); earlierLines.add( new EarlierLine(line, scriptDescriptor, scriptClass, scriptInstance, scriptClassType)); JetType returnType = scriptDescriptor.getScriptCodeDescriptor().getReturnType(); return LineResult.successful(rv, returnType != null && KotlinBuiltIns.isUnit(returnType)); } catch (Throwable e) { @SuppressWarnings("UseOfSystemOutOrSystemErr") PrintWriter writer = new PrintWriter(System.err); classLoader.dumpClasses(writer); writer.flush(); throw UtilsPackage.rethrow(e); } }