All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.intellij.uiDesigner.make.Form2SourceCompiler Maven / Gradle / Ivy

Go to download

A packaging of the IntelliJ Community Edition ui-designer library. This is release number 1 of trunk branch 142.

The newest version!
/*
 * Copyright 2000-2009 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 com.intellij.uiDesigner.make;

import com.intellij.compiler.impl.CompilerUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.uiDesigner.FormEditingUtil;
import com.intellij.uiDesigner.GuiDesignerConfiguration;
import com.intellij.uiDesigner.UIDesignerBundle;
import com.intellij.uiDesigner.compiler.AlienFormFileException;
import com.intellij.uiDesigner.compiler.FormErrorInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.incremental.java.CopyResourcesUtil;

import java.io.DataInput;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;

public final class Form2SourceCompiler implements SourceInstrumentingCompiler{

  private static VirtualFile findSourceFile(final CompileContext context, final VirtualFile formFile, final String className) {
    final Module module = context.getModuleByFile(formFile);
    if (module == null) {
      return null;
    }
    final PsiClass aClass = FormEditingUtil.findClassToBind(module, className);
    if (aClass == null) {
      return null;
    }

    final PsiFile containingFile = aClass.getContainingFile();
    if (containingFile == null){
      return null;
    }

    return containingFile.getVirtualFile();
  }

  @NotNull
  public String getDescription() {
    return UIDesignerBundle.message("component.gui.designer.form.to.source.compiler");
  }

  public boolean validateConfiguration(CompileScope scope) {
    return true;
  }

  @NotNull
  public ProcessingItem[] getProcessingItems(final CompileContext context) {
    final Project project = context.getProject();
    if (GuiDesignerConfiguration.getInstance(project).INSTRUMENT_CLASSES) {
      return ProcessingItem.EMPTY_ARRAY;
    }

    final ArrayList items = new ArrayList();

    ApplicationManager.getApplication().runReadAction(new Runnable() {
      public void run() {
        final CompileScope scope = context.getCompileScope();
        final CompileScope projectScope = context.getProjectCompileScope();

        final VirtualFile[] formFiles = projectScope.getFiles(StdFileTypes.GUI_DESIGNER_FORM, true);
        final CompilerManager compilerManager = CompilerManager.getInstance(project);
        final BindingsCache bindingsCache = new BindingsCache(project);

        try {
          final HashMap class2form = new HashMap();

          for (final VirtualFile formFile : formFiles) {
            if (compilerManager.isExcludedFromCompilation(formFile)) {
              continue;
            }

            final String classToBind;
            try {
              classToBind = bindingsCache.getBoundClassName(formFile);
            }
            catch (AlienFormFileException e) {
              // ignore non-IDEA forms
              continue;
            }
            catch (Exception e) {
              addError(context, new FormErrorInfo(null, UIDesignerBundle.message("error.cannot.process.form.file", e)), formFile);
              continue;
            }

            if (classToBind == null) {
              continue;
            }

            final VirtualFile sourceFile = findSourceFile(context, formFile, classToBind);
            if (sourceFile == null) {
              if (scope.belongs(formFile.getUrl())) {
                addError(context, new FormErrorInfo(null, UIDesignerBundle.message("error.class.to.bind.does.not.exist", classToBind)), formFile);
              }
              continue;
            }

            final boolean inScope = scope.belongs(sourceFile.getUrl()) || scope.belongs(formFile.getUrl());

            final VirtualFile alreadyProcessedForm = class2form.get(classToBind);
            if (alreadyProcessedForm != null) {
              if (inScope) {
                addError(context, new FormErrorInfo(null, UIDesignerBundle.message("error.duplicate.bind", classToBind, alreadyProcessedForm.getPresentableUrl())), formFile);
              }
              continue;
            }
            class2form.put(classToBind, formFile);

            if (!inScope) {
              continue;
            }

            items.add(new MyInstrumentationItem(sourceFile, formFile));
          }
        }
        finally {
          bindingsCache.close();
        }
      }
    });

    return items.toArray(new ProcessingItem[items.size()]);
  }

  public ProcessingItem[] process(final CompileContext context, final ProcessingItem[] items) {
    final ArrayList compiledItems = new ArrayList();

    context.getProgressIndicator().setText(UIDesignerBundle.message("progress.compiling.ui.forms"));

    int formsProcessed = 0;

    final Project project = context.getProject();
    final FormSourceCodeGenerator generator = new FormSourceCodeGenerator(project);

    final HashSet processedModules = new HashSet();

    final List filesToRefresh = new ArrayList();
    for (ProcessingItem item1 : items) {
      context.getProgressIndicator().setFraction((double)(++formsProcessed) / ((double)items.length));

      final MyInstrumentationItem item = (MyInstrumentationItem)item1;

      final VirtualFile formFile = item.getFormFile();

      if (GuiDesignerConfiguration.getInstance(project).COPY_FORMS_RUNTIME_TO_OUTPUT) {
        ApplicationManager.getApplication().runReadAction(new Runnable() {
          public void run() {
            final Module module = ModuleUtilCore.findModuleForFile(formFile, project);
            if (module != null && !processedModules.contains(module)) {
              processedModules.add(module);
              final String moduleOutputPath = CompilerPaths.getModuleOutputPath(module, false);
              try {
                if (moduleOutputPath != null) {
                  filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(moduleOutputPath, false));
                }
                final String testsOutputPath = CompilerPaths.getModuleOutputPath(module, true);
                if (testsOutputPath != null && !testsOutputPath.equals(moduleOutputPath)) {
                  filesToRefresh.addAll(CopyResourcesUtil.copyFormsRuntime(testsOutputPath, false));
                }
              }
              catch (IOException e) {
                addError(
                  context,
                  new FormErrorInfo(null, UIDesignerBundle.message("error.cannot.copy.gui.designer.form.runtime",
                                           module.getName(), e.toString())),
                  null
                );
              }
            }
          }
        });
      }

      ApplicationManager.getApplication().invokeAndWait(new Runnable() {
        public void run() {
          CommandProcessor.getInstance().executeCommand(project, new Runnable() {
            public void run() {
              ApplicationManager.getApplication().runWriteAction(new Runnable() {
                public void run() {
                  PsiDocumentManager.getInstance(project).commitAllDocuments();
                  generator.generate(formFile);
                  final ArrayList errors = generator.getErrors();
                  if (errors.size() == 0) {
                    compiledItems.add(item);
                  }
                  else {
                    for (final FormErrorInfo e : errors) {
                      addError(context, e, formFile);
                    }
                  }
                }
              });
            }
          }, "", null);
          FileDocumentManager.getInstance().saveAllDocuments();
        }
      }, ModalityState.NON_MODAL);
    }

    CompilerUtil.refreshIOFiles(filesToRefresh);
    return compiledItems.toArray(new ProcessingItem[compiledItems.size()]);
  }

  private static void addError(final CompileContext context, final FormErrorInfo e, final VirtualFile formFile) {
    if (formFile != null) {
      FormElementNavigatable navigatable = new FormElementNavigatable(context.getProject(), formFile, e.getComponentId());
      context.addMessage(CompilerMessageCategory.ERROR,
                         formFile.getPresentableUrl() + ": " + e.getErrorMessage(), 
                         formFile.getUrl(), -1, -1, navigatable);
    }
    else {
      context.addMessage(CompilerMessageCategory.ERROR, e.getErrorMessage(), null, -1, -1);
    }
  }

  public ValidityState createValidityState(final DataInput in) throws IOException {
    return TimestampValidityState.load(in);
  }

  private static final class MyInstrumentationItem implements ProcessingItem {
    @NotNull private final VirtualFile mySourceFile;
    private final VirtualFile myFormFile;
    private final TimestampValidityState myState;

    public MyInstrumentationItem(@NotNull final VirtualFile sourceFile, final VirtualFile formFile) {
      mySourceFile = sourceFile;
      myFormFile = formFile;
      myState = new TimestampValidityState(formFile.getTimeStamp());
    }

    @NotNull
    public VirtualFile getFile() {
      return mySourceFile;
    }

    public VirtualFile getFormFile() {
      return myFormFile;
    }

    public ValidityState getValidityState() {
      return myState;
    }
  }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy