@Nullable
  private static AnalysisResult analyze(
      @NotNull final KotlinCoreEnvironment environment, @Nullable String targetDescription) {
    MessageCollector collector =
        environment.getConfiguration().get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY);
    assert collector != null;

    long analysisStart = PerformanceCounter.Companion.currentTime();
    AnalyzerWithCompilerReport analyzerWithCompilerReport =
        new AnalyzerWithCompilerReport(collector);
    analyzerWithCompilerReport.analyzeAndReport(
        environment.getSourceFiles(),
        new Function0<AnalysisResult>() {
          @NotNull
          @Override
          public AnalysisResult invoke() {
            BindingTrace sharedTrace =
                new CliLightClassGenerationSupport.NoScopeRecordCliBindingTrace();
            ModuleContext moduleContext =
                TopDownAnalyzerFacadeForJVM.createContextWithSealedModule(
                    environment.getProject(), ModuleNameKt.getModuleName(environment));

            return TopDownAnalyzerFacadeForJVM.analyzeFilesWithJavaIntegrationWithCustomContext(
                moduleContext,
                environment.getSourceFiles(),
                sharedTrace,
                environment.getConfiguration().get(JVMConfigurationKeys.MODULES),
                environment
                    .getConfiguration()
                    .get(JVMConfigurationKeys.INCREMENTAL_COMPILATION_COMPONENTS),
                new JvmPackagePartProvider(environment));
          }
        });
    long analysisNanos = PerformanceCounter.Companion.currentTime() - analysisStart;
    String message =
        "ANALYZE: "
            + environment.getSourceFiles().size()
            + " files ("
            + environment.getSourceLinesOfCode()
            + " lines) "
            + (targetDescription != null ? targetDescription : "")
            + "in "
            + TimeUnit.NANOSECONDS.toMillis(analysisNanos)
            + " ms";
    K2JVMCompiler.Companion.reportPerf(environment.getConfiguration(), message);

    AnalysisResult result = analyzerWithCompilerReport.getAnalysisResult();
    assert result != null
        : "AnalysisResult should be non-null, compiling: " + environment.getSourceFiles();

    CompilerPluginContext context =
        new CompilerPluginContext(
            environment.getProject(), result.getBindingContext(), environment.getSourceFiles());
    for (CompilerPlugin plugin :
        environment.getConfiguration().getList(CLIConfigurationKeys.COMPILER_PLUGINS)) {
      plugin.processFiles(context);
    }

    return analyzerWithCompilerReport.hasErrors() ? null : result;
  }
예제 #2
0
  @Nullable
  private ScriptDescriptor doAnalyze(
      @NotNull JetFile psiFile, @NotNull ReplMessageCollectorWrapper messageCollector) {
    scriptDeclarationFactory.setDelegateFactory(
        new FileBasedDeclarationProviderFactory(
            resolveSession.getStorageManager(), Collections.singletonList(psiFile)));

    TopDownAnalysisContext context =
        topDownAnalyzer.analyzeDeclarations(
            topDownAnalysisContext.getTopDownAnalysisMode(), Collections.singletonList(psiFile));

    if (trace.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile) == null) {
      trace.record(
          BindingContext.FILE_TO_PACKAGE_FRAGMENT,
          psiFile,
          resolveSession.getPackageFragment(FqName.ROOT));
    }

    boolean hasErrors =
        AnalyzerWithCompilerReport.reportDiagnostics(
            trace.getBindingContext().getDiagnostics(), messageCollector.getMessageCollector());
    if (hasErrors) {
      return null;
    }

    ScriptDescriptor scriptDescriptor = context.getScripts().get(psiFile.getScript());
    lastLineScope = trace.get(BindingContext.SCRIPT_SCOPE, scriptDescriptor);
    if (lastLineScope == null) {
      throw new IllegalStateException("last line scope is not initialized");
    }

    return scriptDescriptor;
  }
  @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;
  }
예제 #4
0
  @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);
    }
  }