github.com/sercand/please@v13.4.0+incompatible/src/ide/intellij/intellij.go (about)

     1  package intellij
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"gopkg.in/op/go-logging.v1"
    11  
    12  	"github.com/thought-machine/please/src/core"
    13  )
    14  
    15  var log = logging.MustGetLogger("intellij")
    16  
    17  // ExportIntellijStructure creates a set of modules and libraries that makes it nicer to work with Please projects
    18  // in IntelliJ.
    19  func ExportIntellijStructure(config *core.Configuration, graph *core.BuildGraph, originalLabels core.BuildLabels) {
    20  	os.RemoveAll(projectLocation())
    21  
    22  	if _, err := os.Stat(projectLocation()); os.IsNotExist(err) {
    23  		os.MkdirAll(projectLocation(), core.DirPermissions)
    24  	}
    25  
    26  	// Write misc.xml
    27  	javaSourceLevel, err := strconv.Atoi(config.Java.SourceLevel)
    28  	if err != nil {
    29  		log.Fatal("Unable to determine java source level - ", err)
    30  	}
    31  	misc := newMisc(javaSourceLevel)
    32  
    33  	f, err := os.Create(miscFileLocation())
    34  	if err != nil {
    35  		log.Fatal("Unable to create misc.xml - ", err)
    36  	}
    37  	misc.toXML(f)
    38  	f.Close()
    39  
    40  	// moduleTargets exist only for the modules we actually built, to keep the size down.
    41  	moduleTargets := []*core.BuildTarget{}
    42  	targetsToVisit := []core.BuildLabel{}
    43  
    44  	// For each target:
    45  	for _, buildLabel := range originalLabels {
    46  		targetsToVisit = append(targetsToVisit, buildLabel)
    47  	}
    48  
    49  	visitTargetsAndDependenciesOnce(graph, targetsToVisit, func(label core.BuildLabel) {
    50  		buildTarget := graph.TargetOrDie(label)
    51  		m := toModule(graph, buildTarget)
    52  
    53  		// Possibly write .iml
    54  		if m != nil {
    55  			if _, err := os.Stat(filepath.Dir(moduleFileLocation(label))); os.IsNotExist(err) {
    56  				os.MkdirAll(filepath.Dir(moduleFileLocation(label)), core.DirPermissions)
    57  			}
    58  			f, err := os.Create(moduleFileLocation(label))
    59  			if err != nil {
    60  				log.Fatal("Unable to write module file for", label, "-", err)
    61  			}
    62  			m.toXML(f)
    63  			f.Close()
    64  
    65  			moduleTargets = append(moduleTargets, buildTarget)
    66  		}
    67  
    68  		// Possibly write library .xml
    69  		if shouldMakeLibrary(buildTarget) {
    70  			if _, err := os.Stat(libraryDirLocation()); os.IsNotExist(err) {
    71  				os.MkdirAll(libraryDirLocation(), core.DirPermissions)
    72  			}
    73  			f, err := os.Create(libraryFileLocation(buildTarget))
    74  			if err != nil {
    75  				log.Fatal("Unable to write library file for", buildTarget.Label, "-", err)
    76  			}
    77  
    78  			library := newLibrary(graph, buildTarget)
    79  			library.toXML(f)
    80  			f.Close()
    81  		}
    82  	})
    83  
    84  	// Write modules.xml
    85  	modules := newModules(moduleTargets)
    86  	if _, err := os.Stat(filepath.Dir(modulesFileLocation())); os.IsNotExist(err) {
    87  		os.MkdirAll(filepath.Dir(modulesFileLocation()), core.DirPermissions)
    88  	}
    89  	f, err = os.Create(modulesFileLocation())
    90  	if err != nil {
    91  		log.Fatal("Unable to write modules file", err)
    92  	}
    93  	modules.toXML(f)
    94  	f.Close()
    95  }
    96  
    97  func visitTargetsAndDependenciesOnce(graph *core.BuildGraph, original []core.BuildLabel, visitor func(label core.BuildLabel)) {
    98  	targetsVisited := map[core.BuildLabel]core.BuildLabel{}
    99  	for len(original) > 0 {
   100  		var buildLabel core.BuildLabel
   101  		buildLabel, original = original[0], original[1:]
   102  
   103  		if _, ok := targetsVisited[buildLabel]; ok {
   104  			continue
   105  		}
   106  
   107  		targetsVisited[buildLabel] = buildLabel
   108  
   109  		visitor(buildLabel)
   110  
   111  		original = append(original, graph.TargetOrDie(buildLabel).DeclaredDependencies()...)
   112  	}
   113  }
   114  
   115  func outputLocation() string {
   116  	return filepath.Join(core.RepoRoot, "plz-out", "intellij")
   117  }
   118  
   119  func projectLocation() string {
   120  	return filepath.Join(outputLocation(), ".idea")
   121  }
   122  
   123  func moduleName(buildLabel core.BuildLabel) string {
   124  	label := buildLabel.PackageName + "_" + buildLabel.Name
   125  	label = strings.Replace(label, "/", "_", -1)
   126  	label = strings.Replace(label, "#", "_", -1)
   127  	return label
   128  }
   129  
   130  func moduleDirLocation(target *core.BuildTarget) string {
   131  	return filepath.Join(outputLocation(), target.Label.PackageDir())
   132  }
   133  
   134  func moduleFileLocation(label core.BuildLabel) string {
   135  	return filepath.Join(outputLocation(), label.PackageDir(), fmt.Sprintf("%s.iml", moduleName(label)))
   136  }
   137  
   138  func libraryDirLocation() string {
   139  	return filepath.Join(projectLocation(), "libraries")
   140  }
   141  
   142  func libraryName(target *core.BuildTarget) string {
   143  	label := target.Label.PackageName + "_" + target.Label.Name
   144  	label = strings.Replace(label, "/", "_", -1)
   145  	label = strings.Replace(label, ".", "_", -1)
   146  	return label
   147  }
   148  
   149  func libraryFileLocation(target *core.BuildTarget) string {
   150  	return filepath.Join(libraryDirLocation(), fmt.Sprintf("%s.xml", libraryName(target)))
   151  }
   152  
   153  func miscFileLocation() string {
   154  	return filepath.Join(projectLocation(), "misc.xml")
   155  }
   156  
   157  func modulesFileLocation() string {
   158  	return filepath.Join(projectLocation(), "modules.xml")
   159  }