supported per-module encoding detection in jps

This commit is contained in:
nik
2012-05-15 12:31:59 +04:00
parent 9c1710a515
commit 239a869003
8 changed files with 138 additions and 0 deletions
@@ -1,5 +1,6 @@
package org.jetbrains.jps.incremental;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.jps.idea.OwnServiceLoader;
import java.util.*;
@@ -65,6 +66,10 @@ public class BuilderRegistry {
return Collections.unmodifiableList(myModuleLevelBuilders.get(category)); // todo
}
public List<ModuleLevelBuilder> getAllModuleLevelBuilders() {
return ContainerUtil.concat(myModuleLevelBuilders.values());
}
public List<ProjectLevelBuilder> getProjectLevelBuilders() {
return myProjectLevelBuilders;
}
@@ -0,0 +1,107 @@
package org.jetbrains.jps.incremental;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.containers.ContainerUtil;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.Module;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.incremental.fs.RootDescriptor;
import java.io.File;
import java.util.*;
/**
* @author nik
*/
public class CompilerEncodingConfiguration {
private final Map<String, String> myFilePathToCharset;
private final ModuleRootsIndex myRootsIndex;
private Map<String, Set<String>> myModuleCharsetMap;
public CompilerEncodingConfiguration(Map<String, String> filePathToCharset, ModuleRootsIndex rootsIndex) {
myFilePathToCharset = filePathToCharset;
myRootsIndex = rootsIndex;
}
public Map<String, Set<String>> getModuleCharsetMap() {
if (myModuleCharsetMap == null) {
myModuleCharsetMap = computeModuleCharsetMap();
}
return myModuleCharsetMap;
}
private Map<String, Set<String>> computeModuleCharsetMap() {
final Map<String, Set<String>> map = new THashMap<String, Set<String>>();
final List<ModuleLevelBuilder> builders = BuilderRegistry.getInstance().getAllModuleLevelBuilders();
for (Map.Entry<String, String> entry : myFilePathToCharset.entrySet()) {
final String filePath = entry.getKey();
final String charset = entry.getValue();
File file = new File(FileUtil.toSystemDependentName(filePath));
if (charset == null || (!file.isDirectory() && !shouldHonorEncodingForCompilation(builders, file))) continue;
final RootDescriptor rootDescriptor = myRootsIndex.getModuleAndRoot(file);
if (rootDescriptor == null) continue;
final String module = rootDescriptor.module;
Set<String> set = map.get(module);
if (set == null) {
set = new LinkedHashSet<String>();
map.put(module, set);
final File sourceRoot = rootDescriptor.root;
File current = FileUtil.getParentFile(file);
String parentCharset = null;
while (current != null) {
final String currentCharset = myFilePathToCharset.get(FileUtil.toSystemIndependentName(current.getAbsolutePath()));
if (currentCharset != null) {
parentCharset = currentCharset;
}
if (FileUtil.filesEqual(current, sourceRoot)) {
break;
}
current = FileUtil.getParentFile(current);
}
if (parentCharset != null) {
set.add(parentCharset);
}
}
set.add(charset);
}
return map;
}
private static boolean shouldHonorEncodingForCompilation(List<ModuleLevelBuilder> builders, File file) {
for (ModuleLevelBuilder builder : builders) {
if (builder.shouldHonorFileEncodingForCompilation(file)) {
return true;
}
}
return false;
}
@Nullable
public String getPreferredModuleChunkEncoding(@NotNull ModuleChunk moduleChunk) {
for (Module module : moduleChunk.getModules()) {
final Set<String> encodings = getModuleCharsetMap().get(module.getName());
final String encoding = ContainerUtil.getFirstItem(encodings, null);
if (encoding != null) return encoding;
}
return null;
}
@NotNull
public Set<String> getAllModuleChunkEncodings(@NotNull ModuleChunk moduleChunk) {
final Map<String, Set<String>> map = getModuleCharsetMap();
Set<String> encodings = new HashSet<String>();
for (Module module : moduleChunk.getModules()) {
final Set<String> moduleEncodings = map.get(module.getName());
if (moduleEncodings != null) {
encodings.addAll(moduleEncodings);
}
}
return encodings;
}
}
@@ -41,6 +41,10 @@ public abstract class ModuleLevelBuilder extends Builder {
public abstract ExitCode build(CompileContext context, ModuleChunk chunk) throws ProjectBuildException;
public boolean shouldHonorFileEncodingForCompilation(File file) {
return false;
}
public final BuilderCategory getCategory() {
return myCategory;
}
@@ -223,6 +223,11 @@ public class JavaBuilder extends ModuleLevelBuilder {
}
}
@Override
public boolean shouldHonorFileEncodingForCompilation(File file) {
return JAVA_SOURCES_FILTER.accept(file) || FORM_SOURCES_FILTER.accept(file);
}
@Nullable
private static File getBoundSource(File srcRoot, File formFile) throws IOException {
final String boundClassName = FormsParsing.readBoundClassName(formFile);
@@ -5,6 +5,7 @@ import org.jetbrains.jps.Module;
import org.jetbrains.jps.Project;
import org.jetbrains.jps.Sdk;
import org.jetbrains.jps.incremental.BuildLoggingManager;
import org.jetbrains.jps.incremental.CompilerEncodingConfiguration;
import org.jetbrains.jps.incremental.ModuleRootsIndex;
import org.jetbrains.jps.incremental.fs.BuildFSState;
import org.jetbrains.jps.incremental.storage.BuildDataManager;
@@ -27,6 +28,7 @@ public final class ProjectDescriptor {
public ModuleRootsIndex rootsIndex;
private int myUseCounter = 1;
private Set<JavaSdk> myProjectJavaSdks;
private CompilerEncodingConfiguration myEncodingConfiguration;
public ProjectDescriptor(Project project,
BuildFSState fsState,
@@ -40,6 +42,7 @@ public final class ProjectDescriptor {
myLoggingManager = loggingManager;
this.rootsIndex = new ModuleRootsIndex(project);
myProjectJavaSdks = new HashSet<JavaSdk>();
myEncodingConfiguration = new CompilerEncodingConfiguration(project.getFilePathToCharset(), rootsIndex);
for (Module module : project.getModules().values()) {
final Sdk sdk = module.getSdk();
if (sdk instanceof JavaSdk && !myProjectJavaSdks.contains(sdk)) {
@@ -51,6 +54,10 @@ public final class ProjectDescriptor {
}
}
public CompilerEncodingConfiguration getEncodingConfiguration() {
return myEncodingConfiguration;
}
public Set<JavaSdk> getProjectJavaSdks() {
return myProjectJavaSdks;
}
@@ -22,6 +22,7 @@ class Project {
final IgnoredFilePatterns ignoredFilePatterns = new IgnoredFilePatterns()
String projectCharset; // contains project charset, if not specified default charset will be used (used by compilers)
Map<String, String> filePathToCharset = [:];
def Project() {
}
@@ -340,6 +340,10 @@ public class IdeaProjectLoader {
if ("PROJECT".equals(url)) {
project.projectCharset = charset;
}
else {
def path = projectMacroExpander.expandMacros(IdeaProjectLoadingUtil.pathFromUrl(url));
project.filePathToCharset[path] = charset;
}
}
}
@@ -132,6 +132,11 @@ public class GroovyBuilder extends ModuleLevelBuilder {
return moduleOutputPath.endsWith("/") ? moduleOutputPath : moduleOutputPath + "/";
}
@Override
public boolean shouldHonorFileEncodingForCompilation(File file) {
return isGroovyFile(file.getAbsolutePath());
}
private String getCompilerOutput(String moduleOutputDir) throws IOException {
return FileUtil.toCanonicalPath((myForStubs ? FileUtil.createTempDirectory("groovyStubs", null) : new File(moduleOutputDir)).getPath());
}