summaryrefslogtreecommitdiff
path: root/jps
diff options
context:
space:
mode:
authorJean-Baptiste Queru <jbq@google.com>2013-02-08 15:14:04 -0800
committerJean-Baptiste Queru <jbq@google.com>2013-02-08 15:14:04 -0800
commit9edc8f6b58f71ec510ba36b838f115718d9a174d (patch)
tree06f6df92024fa534ff27e1c0b5fc8b2002848093 /jps
parentb56ea2a18f232d79481e778085fd64e8ae486fc3 (diff)
downloadidea-9edc8f6b58f71ec510ba36b838f115718d9a174d.tar.gz
Snapshot of commit 84dc01e773388c2c72a1fc437f313dd5747e7809
from branch master of git://git.jetbrains.org/idea/community.git
Diffstat (limited to 'jps')
-rw-r--r--jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaBuilderExtension1
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/api/CmdlineProtoUtil.java10
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java13
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootIndex.java7
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootDescriptorImpl.java13
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java77
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderExtension.java36
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderExtensionImpl.java39
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java8
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceTransformer.java28
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java10
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java8
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java7
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java74
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java63
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java7
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java33
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java12
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java12
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/GlobalContextKey.java34
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java26
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java13
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java10
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java32
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java18
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java7
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java9
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java2
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootDescriptor.java17
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java7
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java5
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SourceFileFilter.java14
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java40
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java3
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java7
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/ExternalJavacDescriptor.java4
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java58
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java16
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java72
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java38
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/indices/impl/IgnoredFileIndexImpl.java46
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java42
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java26
-rw-r--r--jps/jps-builders/src/org/jetbrains/jps/javac/TransformableJavaFileObject.java111
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java4
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java3
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java4
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/BuildResult.java7
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java55
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java67
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java2
-rw-r--r--jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ModuleBuilder.java173
-rw-r--r--jps/model-api/src/com/intellij/openapi/fileTypes/ExactFileNameMatcher.java74
-rw-r--r--jps/model-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java63
-rw-r--r--jps/model-api/src/com/intellij/openapi/fileTypes/FileNameMatcher.java30
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/fileTypes/FileNameMatcherFactory.java32
-rw-r--r--jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerConfiguration.java3
-rw-r--r--jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory1
-rw-r--r--jps/model-impl/src/com/intellij/openapi/fileTypes/WildcardFileNameMatcher.java140
-rw-r--r--jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java287
-rw-r--r--jps/model-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredPatternSet.java72
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/fileTypes/impl/FileNameMatcherFactoryImpl.java44
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsJavaCompilerConfigurationImpl.java11
-rw-r--r--jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ResourcePatterns.java (renamed from jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcePatterns.java)76
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalLoader.java3
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java3
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java8
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerConfigurationSerializer.java24
-rw-r--r--jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java15
-rw-r--r--jps/model-serialization/testData/duplicatedModuleLibrary/duplicatedModuleLibrary.iml28
-rw-r--r--jps/model-serialization/testData/duplicatedModuleLibrary/duplicatedModuleLibrary.ipr12
-rw-r--r--jps/model-serialization/testData/invalidDependencyScope/invalidDependencyScope.iml21
-rw-r--r--jps/model-serialization/testData/invalidDependencyScope/invalidDependencyScope.ipr12
-rw-r--r--jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java27
74 files changed, 2010 insertions, 406 deletions
diff --git a/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaBuilderExtension b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaBuilderExtension
new file mode 100644
index 000000000000..d01e292381fc
--- /dev/null
+++ b/jps/jps-builders/src/META-INF/services/org.jetbrains.jps.builders.java.JavaBuilderExtension
@@ -0,0 +1 @@
+org.jetbrains.jps.builders.java.JavaBuilderExtensionImpl \ No newline at end of file
diff --git a/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineProtoUtil.java b/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineProtoUtil.java
index bc71808cf346..46397f75509b 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineProtoUtil.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/api/CmdlineProtoUtil.java
@@ -127,7 +127,9 @@ public class CmdlineProtoUtil {
public static CmdlineRemoteProto.Message.Failure createFailure(String description, @Nullable Throwable cause) {
final CmdlineRemoteProto.Message.Failure.Builder builder = CmdlineRemoteProto.Message.Failure.newBuilder();
- builder.setDescription(description);
+ if (description != null) {
+ builder.setDescription(description);
+ }
if (cause != null) {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final PrintStream stream = new PrintStream(baos);
@@ -137,7 +139,11 @@ public class CmdlineProtoUtil {
finally {
stream.close();
}
- builder.setStacktrace(new String(baos.toByteArray()));
+ final String stacktrace = new String(baos.toByteArray());
+ builder.setStacktrace(stacktrace);
+ if (description == null) {
+ builder.setDescription(stacktrace);
+ }
}
return builder.build();
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java
index 001c955249c0..1c1f9aa31fff 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootDescriptor.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.jps.builders;
+import com.intellij.openapi.util.io.FileUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.cmdline.ProjectDescriptor;
@@ -33,7 +34,17 @@ public abstract class BuildRootDescriptor {
public abstract BuildTarget<?> getTarget();
- public abstract FileFilter createFileFilter(@NotNull ProjectDescriptor descriptor);
+ /**
+ * @deprecated override {@link #createFileFilter()} instead
+ */
+ public FileFilter createFileFilter(@NotNull ProjectDescriptor descriptor) {
+ return null;
+ }
+
+ @NotNull
+ public FileFilter createFileFilter() {
+ return FileUtilRt.ALL_FILES;
+ }
/**
* @return the set of excluded directories under this root
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootIndex.java b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootIndex.java
index b8065df7acc6..a02d3520a68a 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootIndex.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/BuildRootIndex.java
@@ -18,7 +18,6 @@ package org.jetbrains.jps.builders;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
-import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.CompileContext;
import java.io.File;
@@ -62,5 +61,9 @@ public interface BuildRootIndex {
JavaSourceRootDescriptor findJavaRootDescriptor(@Nullable CompileContext context, File file);
@NotNull
- FileFilter getRootFilter(@NotNull BuildRootDescriptor descriptor, @NotNull ProjectDescriptor projectDescriptor);
+ FileFilter getRootFilter(@NotNull BuildRootDescriptor descriptor);
+
+ boolean isDirectoryAccepted(@NotNull File dir, @NotNull BuildRootDescriptor descriptor);
+
+ boolean isFileAccepted(@NotNull File file, @NotNull BuildRootDescriptor descriptor);
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootDescriptorImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootDescriptorImpl.java
index 2143410c82ef..84a12e514248 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootDescriptorImpl.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootDescriptorImpl.java
@@ -16,13 +16,10 @@
package org.jetbrains.jps.builders.impl;
import com.intellij.openapi.util.io.FileUtilRt;
-import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildRootDescriptor;
import org.jetbrains.jps.builders.BuildTarget;
-import org.jetbrains.jps.cmdline.ProjectDescriptor;
import java.io.File;
-import java.io.FileFilter;
public class BuildRootDescriptorImpl extends BuildRootDescriptor {
private final File myRoot;
@@ -57,16 +54,6 @@ public class BuildRootDescriptorImpl extends BuildRootDescriptor {
}
@Override
- public FileFilter createFileFilter(@NotNull ProjectDescriptor descriptor) {
- return new FileFilter() {
- @Override
- public boolean accept(@NotNull File pathname) {
- return true;
- }
- };
- }
-
- @Override
public boolean canUseFileCache() {
return myCanUseFileCache;
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java
index bb89a37158a7..b40da51805a0 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/impl/BuildRootIndexImpl.java
@@ -27,10 +27,8 @@ import org.jetbrains.jps.builders.*;
import org.jetbrains.jps.builders.java.JavaModuleBuildTargetType;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.builders.storage.BuildDataPaths;
-import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.BuilderRegistry;
import org.jetbrains.jps.incremental.CompileContext;
-import org.jetbrains.jps.incremental.ModuleBuildTarget;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
import org.jetbrains.jps.model.JpsModel;
@@ -47,12 +45,14 @@ import java.util.concurrent.ConcurrentMap;
public class BuildRootIndexImpl implements BuildRootIndex {
private static final Key<Map<File, BuildRootDescriptor>> ROOT_DESCRIPTOR_MAP = Key.create("_root_to_descriptor_map");
private static final Key<Map<BuildTarget<?>, List<? extends BuildRootDescriptor>>> TEMP_TARGET_ROOTS_MAP = Key.create("_module_to_root_map");
+ private final IgnoredFileIndex myIgnoredFileIndex;
private HashMap<BuildTarget<?>, List<? extends BuildRootDescriptor>> myRootsByTarget;
private THashMap<File,List<BuildRootDescriptor>> myRootToDescriptors;
private ConcurrentMap<BuildRootDescriptor, FileFilter> myFileFilters;
public BuildRootIndexImpl(BuildTargetIndex targetIndex, JpsModel model, ModuleExcludeIndex index,
BuildDataPaths dataPaths, final IgnoredFileIndex ignoredFileIndex) {
+ myIgnoredFileIndex = ignoredFileIndex;
myRootsByTarget = new HashMap<BuildTarget<?>, List<? extends BuildRootDescriptor>>();
myRootToDescriptors = new THashMap<File, List<BuildRootDescriptor>>(FileUtil.FILE_HASHING_STRATEGY);
myFileFilters = new ConcurrentHashMap<BuildRootDescriptor, FileFilter>();
@@ -96,22 +96,6 @@ public class BuildRootIndexImpl implements BuildRootIndex {
list.add(descriptor);
}
- private static Map<String, List<ModuleBuildTarget>> buildModuleNameToTargetsMap(BuildTargetIndex targetIndex) {
- final Map<String, List<ModuleBuildTarget>> moduleNameToTargetsMap = new HashMap<String, List<ModuleBuildTarget>>();
- for (JavaModuleBuildTargetType type : JavaModuleBuildTargetType.ALL_TYPES) {
- for (ModuleBuildTarget target : targetIndex.getAllTargets(type)) {
- final String moduleName = target.getModule().getName();
- List<ModuleBuildTarget> targets = moduleNameToTargetsMap.get(moduleName);
- if (targets == null) {
- targets = new ArrayList<ModuleBuildTarget>();
- moduleNameToTargetsMap.put(moduleName, targets);
- }
- targets.add(target);
- }
- }
- return moduleNameToTargetsMap;
- }
-
@NotNull
@Override
public <R extends BuildRootDescriptor> List<R> getRootDescriptors(@NotNull File root,
@@ -203,27 +187,28 @@ public class BuildRootIndexImpl implements BuildRootIndex {
public <R extends BuildRootDescriptor> R findParentDescriptor(@NotNull File file, @NotNull Collection<? extends BuildTargetType<? extends BuildTarget<R>>> types,
@Nullable CompileContext context) {
File current = file;
+ int depth = 0;
while (current != null) {
- final List<R> descriptors = getRootDescriptors(current, types, context);
+ final List<R> descriptors = filterDescriptorsByFile(getRootDescriptors(current, types, context), file, depth);
if (!descriptors.isEmpty()) {
return descriptors.get(0);
}
current = FileUtilRt.getParentFile(current);
+ depth++;
}
return null;
}
-
-
@Override
@NotNull
public <R extends BuildRootDescriptor> Collection<R> findAllParentDescriptors(@NotNull File file,
@Nullable Collection<? extends BuildTargetType<? extends BuildTarget<R>>> types,
@Nullable CompileContext context) {
File current = file;
- Collection<R> result = null;
+ List<R> result = null;
+ int depth = 0;
while (current != null) {
- List<R> descriptors = getRootDescriptors(current, types, context);
+ List<R> descriptors = filterDescriptorsByFile(getRootDescriptors(current, types, context), file, depth);
if (!descriptors.isEmpty()) {
if (result == null) {
result = descriptors;
@@ -234,11 +219,43 @@ public class BuildRootIndexImpl implements BuildRootIndex {
}
}
current = FileUtilRt.getParentFile(current);
+ depth++;
}
return result != null ? result : Collections.<R>emptyList();
}
@NotNull
+ private <R extends BuildRootDescriptor> List<R> filterDescriptorsByFile(@NotNull List<R> descriptors, File file, int parentsToCheck) {
+ List<R> result = descriptors;
+ for (int i = 0; i < descriptors.size(); i++) {
+ R descriptor = descriptors.get(i);
+ if (isFileAccepted(file, descriptor) && isParentDirectoriesAccepted(file, parentsToCheck, descriptor)) {
+ if (result != descriptors) {
+ result.add(descriptor);
+ }
+ }
+ else if (result == descriptors) {
+ result = new ArrayList<R>(descriptors.size() - 1);
+ for (int j = 0; j < i; j++) {
+ result.add(descriptors.get(j));
+ }
+ }
+ }
+ return result;
+ }
+
+ private boolean isParentDirectoriesAccepted(File file, int parentsToCheck, BuildRootDescriptor descriptor) {
+ File current = file;
+ while (parentsToCheck-- > 0) {
+ current = FileUtil.getParentFile(current);
+ if (!isDirectoryAccepted(current, descriptor)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @NotNull
@Override
public <R extends BuildRootDescriptor> Collection<R> findAllParentDescriptors(@NotNull File file, @Nullable CompileContext context) {
return findAllParentDescriptors(file, null, context);
@@ -265,12 +282,22 @@ public class BuildRootIndexImpl implements BuildRootIndex {
@NotNull
@Override
- public FileFilter getRootFilter(@NotNull BuildRootDescriptor descriptor, @NotNull ProjectDescriptor projectDescriptor) {
+ public FileFilter getRootFilter(@NotNull BuildRootDescriptor descriptor) {
FileFilter filter = myFileFilters.get(descriptor);
if (filter == null) {
- filter = descriptor.createFileFilter(projectDescriptor);
+ filter = descriptor.createFileFilter();
myFileFilters.put(descriptor, filter);
}
return filter;
}
+
+ @Override
+ public boolean isFileAccepted(@NotNull File file, @NotNull BuildRootDescriptor descriptor) {
+ return !myIgnoredFileIndex.isIgnored(file.getName()) && getRootFilter(descriptor).accept(file);
+ }
+
+ @Override
+ public boolean isDirectoryAccepted(@NotNull File dir, @NotNull BuildRootDescriptor descriptor) {
+ return !myIgnoredFileIndex.isIgnored(dir.getName()) && !descriptor.getExcludedRoots().contains(dir);
+ }
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderExtension.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderExtension.java
new file mode 100644
index 000000000000..72bade77d284
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderExtension.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2000-2013 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 org.jetbrains.jps.builders.java;
+
+import org.jetbrains.jps.model.module.JpsModuleType;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public abstract class JavaBuilderExtension {
+
+ public boolean shouldHonorFileEncodingForCompilation(File file) {
+ return true;
+ }
+
+ public Set<? extends JpsModuleType<?>> getCompilableModuleTypes() {
+ return Collections.emptySet();
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderExtensionImpl.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderExtensionImpl.java
new file mode 100644
index 000000000000..28f2c88a19f1
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaBuilderExtensionImpl.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2000-2013 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 org.jetbrains.jps.builders.java;
+
+import org.jetbrains.jps.incremental.java.JavaBuilder;
+import org.jetbrains.jps.model.java.JpsJavaModuleType;
+import org.jetbrains.jps.model.module.JpsModuleType;
+
+import java.io.File;
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * @author nik
+ */
+public class JavaBuilderExtensionImpl extends JavaBuilderExtension {
+ @Override
+ public boolean shouldHonorFileEncodingForCompilation(File file) {
+ return JavaBuilder.JAVA_SOURCES_FILTER.accept(file);
+ }
+
+ @Override
+ public Set<? extends JpsModuleType<?>> getCompilableModuleTypes() {
+ return Collections.singleton(JpsJavaModuleType.INSTANCE);
+ }
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java
index 3cae0f0aedfd..6964b09c14e1 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceRootDescriptor.java
@@ -18,7 +18,7 @@ package org.jetbrains.jps.builders.java;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildRootDescriptor;
-import org.jetbrains.jps.cmdline.ProjectDescriptor;
+import org.jetbrains.jps.incremental.BuilderRegistry;
import org.jetbrains.jps.incremental.ModuleBuildTarget;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
@@ -90,13 +90,15 @@ public class JavaSourceRootDescriptor extends BuildRootDescriptor {
return target;
}
+ @NotNull
@Override
- public FileFilter createFileFilter(@NotNull ProjectDescriptor descriptor) {
+ public FileFilter createFileFilter() {
final JpsCompilerExcludes excludes = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(target.getModule().getProject()).getCompilerExcludes();
+ final FileFilter baseFilter = BuilderRegistry.getInstance().getModuleBuilderFileFilter();
return new FileFilter() {
@Override
public boolean accept(File file) {
- return !excludes.isExcluded(file);
+ return baseFilter.accept(file) && !excludes.isExcluded(file);
}
};
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceTransformer.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceTransformer.java
new file mode 100644
index 000000000000..82efc8ef46e5
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/JavaSourceTransformer.java
@@ -0,0 +1,28 @@
+package org.jetbrains.jps.builders.java;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/7/13
+ */
+public abstract class JavaSourceTransformer {
+
+ public static abstract class TransformError extends IOException {
+ protected TransformError(String message) {
+ super(message);
+ }
+
+ protected TransformError(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ protected TransformError(Throwable cause) {
+ super(cause);
+ }
+ }
+
+
+ public abstract CharSequence transform(File sourceFile, CharSequence content) throws TransformError;
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java
index 949fbc2b4fb4..f3357f0c0c1a 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/ResourceRootDescriptor.java
@@ -18,11 +18,11 @@ package org.jetbrains.jps.builders.java;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildRootDescriptor;
-import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.ResourcesTarget;
import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
+import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
import java.io.File;
import java.io.FileFilter;
@@ -74,14 +74,16 @@ public final class ResourceRootDescriptor extends BuildRootDescriptor {
return myPackagePrefix;
}
+ @NotNull
@Override
- public FileFilter createFileFilter(@NotNull ProjectDescriptor descriptor) {
+ public FileFilter createFileFilter() {
final JpsProject project = myTarget.getModule().getProject();
- final JpsCompilerExcludes excludes = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project).getCompilerExcludes();
+ final JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ final JpsCompilerExcludes excludes = configuration.getCompilerExcludes();
return new FileFilter() {
@Override
public boolean accept(File file) {
- return !excludes.isExcluded(file);
+ return !excludes.isExcluded(file) && configuration.isResourceFile(file, getRootFile());
}
};
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
index d0df19162937..83b1ce253569 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/ClassRepr.java
@@ -80,6 +80,10 @@ public class ClassRepr extends Proto {
return myUsages.add(usage);
}
+ public boolean isInterface() {
+ return (access & Opcodes.ACC_INTERFACE) != 0;
+ }
+
public abstract static class Diff extends Difference {
public abstract Specifier<TypeRepr.AbstractType> interfaces();
@@ -288,10 +292,6 @@ public class ClassRepr extends Proto {
}
}
- public boolean isAnnotation() {
- return (access & Opcodes.ACC_ANNOTATION) > 0;
- }
-
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java
index 0c59a0d0789a..e95258d74823 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Difference.java
@@ -25,9 +25,6 @@ import java.util.*;
* Date: 01.03.11
*/
abstract class Difference {
- public static boolean isPackageLocal(final int access) {
- return (access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0;
- }
public static boolean weakerAccess(final int me, final int then) {
return ((me & Opcodes.ACC_PRIVATE) > 0 && (then & Opcodes.ACC_PRIVATE) == 0) ||
@@ -35,6 +32,10 @@ abstract class Difference {
(isPackageLocal(me) && (then & Opcodes.ACC_PROTECTED) > 0);
}
+ private static boolean isPackageLocal(final int access) {
+ return (access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0;
+ }
+
public static final int NONE = 0;
public static final int ACCESS = 1;
public static final int TYPE = 2;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
index 5c402023c165..fe3f28831ea1 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Mappings.java
@@ -695,8 +695,8 @@ public class Mappings {
}
private static boolean isVisibleIn(final ClassRepr c, final ProtoMember m, final ClassRepr scope) {
- final boolean privacy = ((m.access & Opcodes.ACC_PRIVATE) > 0) && c.name != scope.name;
- final boolean packageLocality = Difference.isPackageLocal(m.access) && !c.getPackageName().equals(scope.getPackageName());
+ final boolean privacy = m.isPrivate() && c.name != scope.name;
+ final boolean packageLocality = m.isPackageLocal() && !c.getPackageName().equals(scope.getPackageName());
return !privacy && !packageLocality;
}
@@ -733,13 +733,13 @@ public class Mappings {
final Util self = new Util();
// Public branch --- hopeless
- if ((member.access & Opcodes.ACC_PUBLIC) > 0) {
+ if (member.isPublic()) {
debug("Public access, switching to a non-incremental mode");
return false;
}
// Protected branch
- if ((member.access & Opcodes.ACC_PROTECTED) > 0) {
+ if (member.isProtected()) {
debug("Protected access, softening non-incremental decision: adding all relevant subclasses for a recompilation");
debug("Root class: ", owner);
@@ -1008,16 +1008,14 @@ public class Mappings {
Ref<ClassRepr> oldItRef = null;
for (final MethodRepr m : added) {
debug("Method: ", m.name);
- if ((it.access & Opcodes.ACC_INTERFACE) > 0 ||
- (it.access & Opcodes.ACC_ABSTRACT) > 0 ||
- (m.access & Opcodes.ACC_ABSTRACT) > 0) {
+ if (it.isInterface() || it.isAbstract() || m.isAbstract()) {
debug("Class is abstract, or is interface, or added method in abstract => affecting all subclasses");
myFuture.affectSubclasses(it.name, myAffectedFiles, state.myAffectedUsages, state.myDependants, false);
}
TIntHashSet propagated = null;
- if ((m.access & Opcodes.ACC_PRIVATE) == 0 && m.name != myInitName) {
+ if (!m.isPrivate() && m.name != myInitName) {
if (oldItRef == null) {
oldItRef = new Ref<ClassRepr>(getReprByName(null, it.name)); // lazy init
}
@@ -1035,7 +1033,7 @@ public class Mappings {
}
}
- if ((m.access & Opcodes.ACC_PRIVATE) == 0) {
+ if (!m.isPrivate()) {
final Collection<Pair<MethodRepr, ClassRepr>> affectedMethods = myFuture.findAllMethodsBySpecificity(m, it);
final MethodRepr.Predicate overrides = MethodRepr.equalByJavaRules(m);
@@ -1147,7 +1145,7 @@ public class Mappings {
for (final Pair<MethodRepr, ClassRepr> overriden : overridenMethods) {
final MethodRepr mm = overriden.first;
- if (mm == MOCK_METHOD || !mm.myType.equals(m.myType) || !isEmpty(mm.signature) || !isEmpty(m.signature)) {
+ if (mm == MOCK_METHOD || !mm.myType.equals(m.myType) || !isEmpty(mm.signature) || !isEmpty(m.signature) || m.isMoreAccessibleThan(mm)) {
clear = false;
break loop;
}
@@ -1171,7 +1169,7 @@ public class Mappings {
}
}
- if ((m.access & Opcodes.ACC_ABSTRACT) == 0) {
+ if (!m.isAbstract()) {
propagated.forEach(new TIntProcedure() {
@Override
public boolean execute(int p) {
@@ -1199,7 +1197,7 @@ public class Mappings {
}
visited = true;
- allAbstract = ((pp.first.access & Opcodes.ACC_ABSTRACT) > 0) || ((cc.access & Opcodes.ACC_INTERFACE) > 0);
+ allAbstract = pp.first.isAbstract() || cc.isInterface();
if (!allAbstract) {
break;
@@ -1345,12 +1343,7 @@ public class Mappings {
for (final FieldRepr f : added) {
debug("Field: ", f.name);
- final boolean fPrivate = (f.access & Opcodes.ACC_PRIVATE) > 0;
- final boolean fProtected = (f.access & Opcodes.ACC_PROTECTED) > 0;
- final boolean fPublic = (f.access & Opcodes.ACC_PUBLIC) > 0;
- final boolean fPLocal = !fPrivate && !fProtected && !fPublic;
-
- if (!fPrivate) {
+ if (!f.isPrivate()) {
final TIntHashSet subClasses = getAllSubclasses(classRepr.name);
subClasses.forEach(new TIntProcedure() {
@Override
@@ -1394,28 +1387,23 @@ public class Mappings {
final FieldRepr ff = p.first;
final ClassRepr cc = p.second;
- final boolean ffPrivate = (ff.access & Opcodes.ACC_PRIVATE) > 0;
- final boolean ffProtected = (ff.access & Opcodes.ACC_PROTECTED) > 0;
- final boolean ffPublic = (ff.access & Opcodes.ACC_PUBLIC) > 0;
- final boolean ffPLocal = Difference.isPackageLocal(ff.access);
-
- if (!ffPrivate) {
+ if (!ff.isPrivate()) {
final TIntHashSet propagated = myPresent.propagateFieldAccess(ff.name, cc.name);
final Set<UsageRepr.Usage> localUsages = new HashSet<UsageRepr.Usage>();
debug("Affecting usages of overridden field in class ", cc.name);
myFuture.affectFieldUsages(ff, propagated, ff.createUsage(myContext, cc.name), localUsages, state.myDependants);
- if (fPrivate || (fPublic && (ffPublic || ffPLocal)) || (fProtected && ffProtected) || (fPLocal && ffPLocal)) {
-
+ if (f.isPrivate() || (f.isPublic() && (ff.isPublic() || ff.isPackageLocal())) || (f.isProtected() && ff.isProtected()) || (f.isPackageLocal() && ff.isPackageLocal())) {
+ // nothing
}
else {
Util.UsageConstraint constaint;
- if ((ffProtected && fPublic) || (fProtected && ffPublic) || (ffPLocal && fProtected)) {
+ if ((ff.isProtected() && f.isPublic()) || (f.isProtected() && ff.isPublic()) || (ff.isPackageLocal() && f.isProtected())) {
constaint = myFuture.new NegationConstraint(myFuture.new InheritanceConstraint(cc.name));
}
- else if (ffPublic && ffPLocal) {
+ else if (ff.isPublic() && ff.isPackageLocal()) {
constaint = myFuture.new NegationConstraint(myFuture.new PackageConstraint(cc.getPackageName()));
}
else {
@@ -1449,7 +1437,7 @@ public class Mappings {
for (final FieldRepr f : removed) {
debug("Field: ", f.name);
- if ((f.access & Opcodes.ACC_PRIVATE) == 0 && (f.access & DESPERATE_MASK) == DESPERATE_MASK && f.hasValue()) {
+ if (!f.isPrivate() && (f.access & DESPERATE_MASK) == DESPERATE_MASK && f.hasValue()) {
debug("Field had value and was (non-private) final static => a switch to non-incremental mode requested");
if (myConstantSearch != null) {
myDelayedWorks.addConstantWork(it.name, f, true, false);
@@ -1483,7 +1471,7 @@ public class Mappings {
debug("Field: ", field.name);
- if ((field.access & Opcodes.ACC_PRIVATE) == 0 && (field.access & DESPERATE_MASK) == DESPERATE_MASK) {
+ if (!field.isPrivate() && (field.access & DESPERATE_MASK) == DESPERATE_MASK) {
final int changedModifiers = d.addedModifiers() | d.removedModifiers();
final boolean harmful = (changedModifiers & (Opcodes.ACC_STATIC | Opcodes.ACC_FINAL)) > 0;
final boolean accessChanged = (changedModifiers & (Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED)) > 0;
@@ -1761,13 +1749,35 @@ public class Mappings {
debug("End of removed classes processing.");
}
- private void processAddedClasses(final DiffState state) {
+ private void processAddedClasses(final DiffState state, File srcFile) {
final Collection<ClassRepr> addedClasses = state.myClassDiff.added();
if (addedClasses.isEmpty()) {
return;
}
debug("Processing added classes:");
+
+ if (!myEasyMode) {
+ // checking if this newly added class duplicates already existing one
+ for (ClassRepr c : addedClasses) {
+ if (!c.isLocal() && !c.isAnonymous() && isEmpty(c.getOuterClassName())) {
+ final File currentlyMappedTo = myClassToSourceFile.get(c.name);
+ if (currentlyMappedTo != null && !FileUtil.filesEqual(currentlyMappedTo, srcFile) && currentlyMappedTo.exists()) {
+ if (myFilter == null || myFilter.accept(currentlyMappedTo)) {
+ // Same classes from different source files.
+ // Schedule for recompilation both to make possible 'duplicate sources' error evident
+ debug("Scheduling for recompilation duplicated sources: ", currentlyMappedTo.getPath() + "; " + srcFile.getPath());
+ myAffectedFiles.add(currentlyMappedTo);
+ myAffectedFiles.add(srcFile);
+ myCompiledFiles.remove(srcFile); // this will force sending the file to compilation again
+ return; // do not process this file because it should not be integrated
+ }
+ }
+ break;
+ }
+ }
+ }
+
for (final ClassRepr c : addedClasses) {
debug("Class name: ", c.name);
myDelta.addChangedClass(c.name);
@@ -1898,7 +1908,7 @@ public class Mappings {
}
processRemovedClases(state);
- processAddedClasses(state);
+ processAddedClasses(state, fileName);
if (!myEasyMode) {
calculateAffectedFiles(state);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
index 7a4351542bde..593128edb982 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/builders/java/dependencyView/Proto.java
@@ -60,6 +60,64 @@ class Proto implements RW.Savable, Streamable {
}
}
+ public final boolean isPublic() {
+ return (Opcodes.ACC_PUBLIC & access) != 0;
+ }
+
+ public final boolean isProtected() {
+ return (Opcodes.ACC_PROTECTED & access) != 0;
+ }
+
+ public final boolean isPackageLocal() {
+ return (access & (Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC)) == 0;
+ }
+
+ public final boolean isPrivate() {
+ return (Opcodes.ACC_PRIVATE & access) != 0;
+ }
+
+ public final boolean isAbstract() {
+ return (Opcodes.ACC_ABSTRACT & access) != 0;
+ }
+
+ public final boolean isBridge() {
+ return (Opcodes.ACC_BRIDGE & access) != 0;
+ }
+
+ public final boolean isSynthetic() {
+ return (Opcodes.ACC_SYNTHETIC & access) != 0;
+ }
+
+ public final boolean isAnnotation() {
+ return (Opcodes.ACC_ANNOTATION & access) != 0;
+ }
+
+ public final boolean isFinal() {
+ return (Opcodes.ACC_FINAL & access) != 0;
+ }
+
+ public final boolean isStatic() {
+ return (Opcodes.ACC_STATIC & access) != 0;
+ }
+
+ /**
+ * tests if the accessibility of this Proto is less restricted than the accessibility of the given Proto
+ * @return true means this Proto is less restricted than the proto passed as parameter <br>
+ * false means this Proto has more restricted access than the parameter Proto or they have equal accessibility
+ */
+ public final boolean isMoreAccessibleThan(Proto anotherProto) {
+ if (anotherProto.isPrivate()) {
+ return this.isPackageLocal() || this.isProtected() || this.isPublic();
+ }
+ if (anotherProto.isPackageLocal()) {
+ return this.isProtected() || this.isPublic();
+ }
+ if (anotherProto.isProtected()) {
+ return this.isPublic();
+ }
+ return false;
+ }
+
public Difference difference(final Proto past) {
int diff = Difference.NONE;
@@ -96,10 +154,7 @@ class Proto implements RW.Savable, Streamable {
@Override
public boolean packageLocalOn() {
- return ((past.access & Opcodes.ACC_PRIVATE) != 0 ||
- (past.access & Opcodes.ACC_PUBLIC) != 0 ||
- (past.access & Opcodes.ACC_PROTECTED) != 0) &&
- Difference.isPackageLocal(access);
+ return (past.isPrivate() || past.isPublic() || past.isProtected()) && Proto.this.isPackageLocal();
}
@Override
diff --git a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
index 03a527fdb2d5..034e85120859 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/cmdline/ClasspathBootstrap.java
@@ -31,6 +31,7 @@ import org.jboss.netty.util.Version;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.asm4.ClassVisitor;
import org.jetbrains.asm4.ClassWriter;
+import org.jetbrains.jps.builders.java.JavaSourceTransformer;
import org.jetbrains.jps.javac.JavacServer;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.impl.JpsModelImpl;
@@ -189,6 +190,12 @@ public class ClasspathBootstrap {
}
}
+ final Class<JavaSourceTransformer> transformerClass = JavaSourceTransformer.class;
+ final ServiceLoader<JavaSourceTransformer> loader = ServiceLoader.load(transformerClass, transformerClass.getClassLoader());
+ for (JavaSourceTransformer t : loader) {
+ cp.add(getResourceFile(t.getClass()));
+ }
+
return new ArrayList<File>(cp);
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java
index 218a1013bcf2..7b2436ee58ac 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/BuilderRegistry.java
@@ -16,10 +16,16 @@
package org.jetbrains.jps.incremental;
import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import gnu.trove.THashSet;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.BuildTargetType;
import org.jetbrains.jps.service.JpsServiceManager;
+import java.io.File;
+import java.io.FileFilter;
import java.util.*;
/**
@@ -34,6 +40,7 @@ public class BuilderRegistry {
private final Map<BuilderCategory, List<ModuleLevelBuilder>> myModuleLevelBuilders = new HashMap<BuilderCategory, List<ModuleLevelBuilder>>();
private final List<TargetBuilder<?,?>> myTargetBuilders = new ArrayList<TargetBuilder<?,?>>();
private final Map<String, BuildTargetType<?>> myTargetTypes = new LinkedHashMap<String, BuildTargetType<?>>();
+ private final FileFilter myModuleBuilderFileFilter;
public static BuilderRegistry getInstance() {
return Holder.ourInstance;
@@ -44,10 +51,19 @@ public class BuilderRegistry {
myModuleLevelBuilders.put(category, new ArrayList<ModuleLevelBuilder>());
}
+ Set<String> compilableFileExtensions = new THashSet<String>(FileUtil.PATH_HASHING_STRATEGY);
for (BuilderService service : JpsServiceManager.getInstance().getExtensions(BuilderService.class)) {
myTargetBuilders.addAll(service.createBuilders());
final List<? extends ModuleLevelBuilder> moduleLevelBuilders = service.createModuleLevelBuilders();
for (ModuleLevelBuilder builder : moduleLevelBuilders) {
+ List<String> extensions = builder.getCompilableFileExtensions();
+ if (extensions == null) {
+ LOG.info(builder.getClass().getName() + " builder returns 'null' from 'getCompilableFileExtensions' method so files for module-level builders won't be filtered");
+ compilableFileExtensions = null;
+ }
+ else if (compilableFileExtensions != null) {
+ compilableFileExtensions.addAll(extensions);
+ }
myModuleLevelBuilders.get(builder.getCategory()).add(builder);
}
for (BuildTargetType<?> type : service.getTargetTypes()) {
@@ -58,6 +74,18 @@ public class BuilderRegistry {
}
}
}
+ if (compilableFileExtensions == null) {
+ myModuleBuilderFileFilter = FileUtilRt.ALL_FILES;
+ }
+ else {
+ final Set<String> finalCompilableFileExtensions = compilableFileExtensions;
+ myModuleBuilderFileFilter = new FileFilter() {
+ @Override
+ public boolean accept(File file) {
+ return finalCompilableFileExtensions.contains(FileUtilRt.getExtension(file.getName()));
+ }
+ };
+ }
}
@Nullable
@@ -65,6 +93,11 @@ public class BuilderRegistry {
return myTargetTypes.get(typeId);
}
+ @NotNull
+ public FileFilter getModuleBuilderFileFilter() {
+ return myModuleBuilderFileFilter;
+ }
+
public Collection<BuildTargetType<?>> getTargetTypes() {
return myTargetTypes.values();
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java
index b38230e862d9..ef74b261b00c 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/CompilerEncodingConfiguration.java
@@ -23,11 +23,13 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.builders.BuildRootIndex;
+import org.jetbrains.jps.builders.java.JavaBuilderExtension;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.model.JpsEncodingConfigurationService;
import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
import org.jetbrains.jps.model.JpsModel;
import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.service.JpsServiceManager;
import org.jetbrains.jps.util.JpsPathUtil;
import java.io.File;
@@ -58,12 +60,12 @@ public class CompilerEncodingConfiguration {
private Map<JpsModule, Set<String>> computeModuleCharsetMap() {
final Map<JpsModule, Set<String>> map = new THashMap<JpsModule, Set<String>>();
- final List<ModuleLevelBuilder> builders = BuilderRegistry.getInstance().getModuleLevelBuilders();
+ final Iterable<JavaBuilderExtension> builderExtensions = JpsServiceManager.getInstance().getExtensions(JavaBuilderExtension.class);
for (Map.Entry<String, String> entry : myUrlToCharset.entrySet()) {
final String fileUrl = entry.getKey();
final String charset = entry.getValue();
File file = JpsPathUtil.urlToFile(fileUrl);
- if (charset == null || (!file.isDirectory() && !shouldHonorEncodingForCompilation(builders, file))) continue;
+ if (charset == null || (!file.isDirectory() && !shouldHonorEncodingForCompilation(builderExtensions, file))) continue;
final JavaSourceRootDescriptor rootDescriptor = myRootsIndex.findJavaRootDescriptor(null, file);
if (rootDescriptor == null) continue;
@@ -97,9 +99,9 @@ public class CompilerEncodingConfiguration {
return map;
}
- private static boolean shouldHonorEncodingForCompilation(List<ModuleLevelBuilder> builders, File file) {
- for (ModuleLevelBuilder builder : builders) {
- if (builder.shouldHonorFileEncodingForCompilation(file)) {
+ private static boolean shouldHonorEncodingForCompilation(Iterable<JavaBuilderExtension> builders, File file) {
+ for (JavaBuilderExtension extension : builders) {
+ if (extension.shouldHonorFileEncodingForCompilation(file)) {
return true;
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java
index 3fd4fc9d0099..545cdc762c04 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/FSOperations.java
@@ -15,7 +15,6 @@
*/
package org.jetbrains.jps.incremental;
-import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileSystemUtil;
import com.intellij.openapi.util.io.FileUtil;
import gnu.trove.THashSet;
@@ -23,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.builders.BuildRootDescriptor;
+import org.jetbrains.jps.builders.BuildRootIndex;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.FileProcessor;
import org.jetbrains.jps.builders.impl.BuildTargetChunk;
@@ -44,7 +44,7 @@ import java.util.Set;
* Date: 7/8/12
*/
public class FSOperations {
- public static final Key<Set<File>> ALL_OUTPUTS_KEY = Key.create("_all_project_output_dirs_");
+ public static final GlobalContextKey<Set<File>> ALL_OUTPUTS_KEY = GlobalContextKey.create("_all_project_output_dirs_");
public static void markDirty(CompileContext context, final File file) throws IOException {
final JavaSourceRootDescriptor rd = context.getProjectDescriptor().getBuildRootIndex().findJavaRootDescriptor(context, file);
@@ -161,19 +161,17 @@ public class FSOperations {
@NotNull final Timestamps tsStorage,
final boolean forceDirty,
@Nullable Set<File> currentFiles, @Nullable FileFilter filter, @NotNull FSCache fsCache) throws IOException {
- if (context.getProjectDescriptor().getIgnoredFileIndex().isIgnored(file.getName())) {
- return;
- }
+ BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex();
final File[] children = fsCache.getChildren(file);
if (children != null) { // is directory
- if (children.length > 0 && !rd.getExcludedRoots().contains(file)) {
+ if (children.length > 0 && rootIndex.isDirectoryAccepted(file, rd)) {
for (File child : children) {
traverseRecursively(context, rd, child, tsStorage, forceDirty, currentFiles, filter, fsCache);
}
}
}
else { // is file
- if (filter == null || filter.accept(file)) {
+ if (rootIndex.isFileAccepted(file, rd) && (filter == null || filter.accept(file))) {
boolean markDirty = forceDirty;
if (!markDirty) {
markDirty = tsStorage.getStamp(file, rd.getTarget()) != FileSystemUtil.lastModified(file);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/GlobalContextKey.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/GlobalContextKey.java
new file mode 100644
index 000000000000..e5ec324c6e02
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/GlobalContextKey.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2000-2013 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 org.jetbrains.jps.incremental;
+
+import com.intellij.openapi.util.Key;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ This is type of the key for data that must be visible to all threads
+ */
+public final class GlobalContextKey<T> extends Key<T> {
+ public GlobalContextKey(@NotNull @NonNls String name) {
+ super(name);
+ }
+
+ public static <T> GlobalContextKey<T> create(@NotNull @NonNls String name) {
+ return new GlobalContextKey<T>(name);
+ }
+
+}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
index f2cf3f0c52fe..e16c78813312 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/IncProjectBuilder.java
@@ -16,7 +16,6 @@
package org.jetbrains.jps.incremental;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.LowMemoryWatcher;
import com.intellij.openapi.util.UserDataHolder;
import com.intellij.openapi.util.UserDataHolderBase;
@@ -80,7 +79,7 @@ public class IncProjectBuilder {
private static final String CLASSPATH_INDEX_FINE_NAME = "classpath.index";
private static final boolean GENERATE_CLASSPATH_INDEX = Boolean.parseBoolean(System.getProperty(GlobalOptions.GENERATE_CLASSPATH_INDEX_OPTION, "false"));
- private static final Key<Set<BuildTarget<?>>> TARGET_WITH_CLEARED_OUTPUT = Key.create("_targets_with_cleared_output_");
+ private static final GlobalContextKey<Set<BuildTarget<?>>> TARGET_WITH_CLEARED_OUTPUT = GlobalContextKey.create("_targets_with_cleared_output_");
private static final int MAX_BUILDER_THREADS;
static {
int maxThreads = 6;
@@ -463,10 +462,16 @@ public class IncProjectBuilder {
// do not delete output root itself to avoid lots of unnecessary "roots_changed" events in IDEA
final File[] children = outputRoot.listFiles();
if (children != null) {
- filesToDelete.addAll(Arrays.asList(children));
+ for (File child : children) {
+ if (!child.delete()) {
+ filesToDelete.add(child);
+ }
+ }
}
- else if (outputRoot.isFile()) {
- filesToDelete.add(outputRoot);
+ else { // the output root must be file
+ if (!outputRoot.delete()) {
+ filesToDelete.add(outputRoot);
+ }
}
registerTargetsWithClearedOutput(context, entry.getValue());
}
@@ -1052,14 +1057,6 @@ public class IncProjectBuilder {
BuildOperations.markTargetsUpToDate(context, chunk);
}
- private static final Set<Key> GLOBAL_CONTEXT_KEYS = new HashSet<Key>();
- static {
- // keys for data that must be visible to all threads
- GLOBAL_CONTEXT_KEYS.add(ExternalJavacDescriptor.KEY);
- GLOBAL_CONTEXT_KEYS.add(FSOperations.ALL_OUTPUTS_KEY);
- GLOBAL_CONTEXT_KEYS.add(TARGET_WITH_CLEARED_OUTPUT);
- }
-
private static CompileContext createContextWrapper(final CompileContext delegate) {
final ClassLoader loader = delegate.getClass().getClassLoader();
final UserDataHolderBase localDataHolder = new UserDataHolderBase();
@@ -1072,8 +1069,7 @@ public class IncProjectBuilder {
final Class<?> declaringClass = method.getDeclaringClass();
if (dataHolderInterface.equals(declaringClass)) {
final Object firstArgument = args[0];
- final boolean isGlobalContextKey = firstArgument instanceof Key && GLOBAL_CONTEXT_KEYS.contains((Key)firstArgument);
- if (!isGlobalContextKey) {
+ if (!(firstArgument instanceof GlobalContextKey)) {
final boolean isWriteOperation = args.length == 2 /*&& void.class.equals(method.getReturnType())*/;
if (isWriteOperation) {
if (args[1] == null) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java
index 07095333470c..394ce12e8042 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ModuleLevelBuilder.java
@@ -25,6 +25,7 @@ import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import java.io.File;
import java.io.IOException;
import java.util.Collection;
+import java.util.List;
import java.util.Map;
/**
@@ -64,10 +65,22 @@ public abstract class ModuleLevelBuilder extends Builder {
OutputConsumer outputConsumer)
throws ProjectBuildException, IOException;
+ /**
+ * @deprecated use {@link org.jetbrains.jps.builders.java.JavaBuilderExtension#shouldHonorFileEncodingForCompilation(java.io.File)} instead
+ */
public boolean shouldHonorFileEncodingForCompilation(File file) {
return false;
}
+ /**
+ * <strong>DO NOT RETURN {@code null}</strong> from implementation of this method. If some of builders returns {@code null} no filtering
+ * will be performed for compatibility reasons.
+ * @return list of extensions (without dot) of files which can be compiled by the builder
+ */
+ public List<String> getCompilableFileExtensions() {
+ return null;
+ }
+
public final BuilderCategory getCategory() {
return myCategory;
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java
index 13ee713b2617..15e9a48e2c43 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcesTarget.java
@@ -17,7 +17,6 @@ package org.jetbrains.jps.incremental;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.SmartList;
-import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.BuildRootIndex;
@@ -35,7 +34,6 @@ import org.jetbrains.jps.model.JpsSimpleElement;
import org.jetbrains.jps.model.java.JavaSourceRootProperties;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
-import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
import org.jetbrains.jps.model.module.JpsModule;
import org.jetbrains.jps.model.module.JpsTypedModuleSourceRoot;
import org.jetbrains.jps.service.JpsServiceManager;
@@ -96,8 +94,6 @@ public final class ResourcesTarget extends JVMModuleBuildTarget<ResourceRootDesc
JavaSourceRootType type = isTests() ? JavaSourceRootType.TEST_SOURCE : JavaSourceRootType.SOURCE;
Iterable<ExcludedJavaSourceRootProvider> excludedRootProviders = JpsServiceManager.getInstance().getExtensions(ExcludedJavaSourceRootProvider.class);
- final THashSet<File> addedRoots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
-
roots_loop:
for (JpsTypedModuleSourceRoot<JpsSimpleElement<JavaSourceRootProperties>> sourceRoot : myModule.getSourceRoots(type)) {
for (ExcludedJavaSourceRootProvider provider : excludedRootProviders) {
@@ -108,7 +104,6 @@ public final class ResourcesTarget extends JVMModuleBuildTarget<ResourceRootDesc
final String packagePrefix = sourceRoot.getProperties().getData().getPackagePrefix();
final File rootFile = sourceRoot.getFile();
roots.add(new ResourceRootDescriptor(rootFile, this, false, packagePrefix, computeRootExcludes(rootFile, index)));
- addedRoots.add(rootFile);
}
return roots;
@@ -122,12 +117,7 @@ public final class ResourcesTarget extends JVMModuleBuildTarget<ResourceRootDesc
@Override
public void writeConfiguration(PrintWriter out, BuildDataPaths dataPaths, BuildRootIndex buildRootIndex) {
- final JpsJavaCompilerConfiguration config = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(getModule().getProject());
int fingerprint = 0;
- final List<String> patterns = config.getResourcePatterns();
- for (String pattern : patterns) {
- fingerprint += pattern.hashCode();
- }
final List<ResourceRootDescriptor> roots = buildRootIndex.getTargetRoots(this, null);
for (ResourceRootDescriptor root : roots) {
fingerprint += FileUtil.fileHashCode(root.getRootFile());
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java
index 067a383acf40..572433552d65 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/ArtifactOutputToSourceMapping.java
@@ -15,14 +15,17 @@
*/
package org.jetbrains.jps.incremental.artifacts;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.SmartList;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.IOUtil;
import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.incremental.storage.AbstractStateStorage;
import org.jetbrains.jps.incremental.storage.PathStringDescriptor;
import java.io.*;
+import java.util.Collections;
import java.util.List;
/**
@@ -35,12 +38,37 @@ public class ArtifactOutputToSourceMapping extends AbstractStateStorage<String,
super(storePath, new PathStringDescriptor(), new SourcePathListExternalizer());
}
+ @Override
+ public void update(String path, @Nullable List<SourcePathAndRootIndex> state) throws IOException {
+ super.update(FileUtil.toSystemIndependentName(path), state);
+ }
+
+ @Override
+ public void appendData(String path, List<SourcePathAndRootIndex> data) throws IOException {
+ super.appendData(FileUtil.toSystemIndependentName(path), data);
+ }
+
+ public void appendData(String outputPath, int rootIndex, String sourcePath) throws IOException {
+ super.appendData(outputPath, Collections.singletonList(new SourcePathAndRootIndex(sourcePath, rootIndex)));
+ }
+
+ @Override
+ public void remove(String path) throws IOException {
+ super.remove(FileUtil.toSystemIndependentName(path));
+ }
+
+ @Nullable
+ @Override
+ public List<SourcePathAndRootIndex> getState(String path) throws IOException {
+ return super.getState(FileUtil.toSystemIndependentName(path));
+ }
+
public static class SourcePathAndRootIndex {
private final String myPath;
private final int myRootIndex;
- public SourcePathAndRootIndex(String path, int rootIndex) {
- myPath = path;
+ private SourcePathAndRootIndex(String path, int rootIndex) {
+ myPath = FileUtil.toSystemIndependentName(path);
myRootIndex = rootIndex;
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java
index 207fa138fd6d..6dc56ef587c6 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/IncArtifactBuilder.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.jps.incremental.artifacts;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
@@ -47,6 +48,7 @@ import java.util.*;
* @author nik
*/
public class IncArtifactBuilder extends TargetBuilder<ArtifactRootDescriptor, ArtifactBuildTarget> {
+ private static final Logger LOG = Logger.getInstance(IncArtifactBuilder.class);
public static final String BUILDER_NAME = "Artifacts builder";
public IncArtifactBuilder() {
@@ -77,7 +79,10 @@ public class IncArtifactBuilder extends TargetBuilder<ArtifactRootDescriptor, Ar
try {
final Collection<String> deletedFiles = holder.getRemovedFiles(target);
- context.processMessage(new ProgressMessage("Building artifact '" + artifact.getName() + "'..."));
+ String messageText = "Building artifact '" + artifact.getName() + "'...";
+ context.processMessage(new ProgressMessage(messageText));
+ LOG.debug(messageText);
+
runArtifactTasks(context, target.getArtifact(), ArtifactBuildTaskProvider.ArtifactBuildPhase.PRE_PROCESSING);
final SourceToOutputMapping srcOutMapping = pd.dataManager.getSourceToOutputMap(target);
final ArtifactOutputToSourceMapping outSrcMapping = pd.dataManager.getStorage(target, ArtifactOutToSourceStorageProvider.INSTANCE);
@@ -142,6 +147,12 @@ public class IncArtifactBuilder extends TargetBuilder<ArtifactRootDescriptor, Ar
if (sourcePaths == null) continue;
for (String sourcePath : sourcePaths) {
+ if (!descriptor.getFilter().shouldBeCopied(sourcePath, pd)) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("File " + sourcePath + " will be skipped because it isn't accepted by filter");
+ }
+ continue;
+ }
DestinationInfo destination = descriptor.getDestinationInfo();
if (destination instanceof ExplodedDestinationInfo) {
descriptor.copyFromRoot(sourcePath, descriptor.getRootIndex(), destination.getOutputPath(), context,
@@ -210,10 +221,13 @@ public class IncArtifactBuilder extends TargetBuilder<ArtifactRootDescriptor, Ar
boolean deleted = deletedPaths.contains(filePath);
if (!deleted) {
- deleted = FileUtil.delete(new File(FileUtil.toSystemDependentName(filePath)));
+ deleted = FileUtil.delete(new File(filePath));
}
if (deleted) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Outdated output file deleted: " + filePath);
+ }
outSrcMapping.remove(filePath);
deletedPaths.add(filePath);
for (String sourcePath : filesToDelete.get(filePath)) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java
index 2916a6b6b903..ba43cc7ea05e 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/impl/JarsBuilder.java
@@ -169,8 +169,7 @@ public class JarsBuilder {
else {
final String filePath = FileUtil.toSystemIndependentName(descriptor.getRootFile().getAbsolutePath());
packedFilePaths.add(filePath);
- myOutSrcMapping.appendData(targetJarPath, Collections
- .singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(filePath, rootIndex)));
+ myOutSrcMapping.appendData(targetJarPath, rootIndex, filePath);
extractFileAndAddToJar(jarOutputStream, (JarBasedArtifactRootDescriptor)descriptor, relativePath, writtenPaths);
}
}
@@ -329,7 +328,7 @@ public class JarsBuilder {
List<String> packedFilePaths,
int rootIndex) throws IOException {
final String filePath = FileUtil.toSystemIndependentName(file.getAbsolutePath());
- if (!filter.accept(filePath, myContext.getProjectDescriptor())) {
+ if (!filter.accept(filePath) || !filter.shouldBeCopied(filePath, myContext.getProjectDescriptor())) {
return;
}
@@ -350,7 +349,7 @@ public class JarsBuilder {
final boolean added = ZipUtil.addFileToZip(jarOutputStream, file, relativePath, writtenItemRelativePaths, null);
if (rootIndex != -1) {
- myOutSrcMapping.appendData(targetJarPath, Collections.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(filePath, rootIndex)));
+ myOutSrcMapping.appendData(targetJarPath, rootIndex, filePath);
if (added) {
packedFilePaths.add(filePath);
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java
index 89c64aefa236..ee1ee1798f55 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactCompilerInstructionCreatorBase.java
@@ -119,8 +119,8 @@ public abstract class ArtifactCompilerInstructionCreatorBase implements Artifact
}
@Override
- public boolean accept(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) throws IOException {
- if (myBaseFilter != null && !myBaseFilter.accept(fullFilePath, projectDescriptor)) return false;
+ public boolean accept(@NotNull String fullFilePath) {
+ if (myBaseFilter != null && !myBaseFilter.accept(fullFilePath)) return false;
if (myIgnoredFileIndex.isIgnored(PathUtilRt.getFileName(fullFilePath))) {
return false;
@@ -134,5 +134,10 @@ public abstract class ArtifactCompilerInstructionCreatorBase implements Artifact
}
return true;
}
+
+ @Override
+ public boolean shouldBeCopied(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) throws IOException {
+ return myBaseFilter == null || myBaseFilter.shouldBeCopied(fullFilePath, projectDescriptor);
+ }
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
index 06b1bcd7eabc..ae9993d7214e 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactInstructionsBuilderImpl.java
@@ -80,6 +80,6 @@ public class ArtifactInstructionsBuilderImpl implements ArtifactInstructionsBuil
public JarBasedArtifactRootDescriptor createJarBasedRoot(@NotNull File jarFile,
@NotNull String pathInJar,
@NotNull SourceFileFilter filter, final DestinationInfo destinationInfo) {
- return new JarBasedArtifactRootDescriptor(jarFile, pathInJar, filter, myRootIndex, myBuildTarget, destinationInfo);
+ return new JarBasedArtifactRootDescriptor(jarFile, pathInJar, filter, myRootIndex++, myBuildTarget, destinationInfo);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootDescriptor.java
index 5fe2c1c947a3..24849efae998 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/ArtifactRootDescriptor.java
@@ -18,7 +18,6 @@ package org.jetbrains.jps.incremental.artifacts.instructions;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildOutputConsumer;
import org.jetbrains.jps.builders.BuildRootDescriptor;
-import org.jetbrains.jps.cmdline.ProjectDescriptor;
import org.jetbrains.jps.incremental.CompileContext;
import org.jetbrains.jps.incremental.ProjectBuildException;
import org.jetbrains.jps.incremental.artifacts.ArtifactBuildTarget;
@@ -33,12 +32,6 @@ import java.io.PrintWriter;
* @author nik
*/
public abstract class ArtifactRootDescriptor extends BuildRootDescriptor {
- private static final FileFilter ALL_FILES_FILTER = new FileFilter() {
- @Override
- public boolean accept(File file) {
- return true;
- }
- };
protected final File myRoot;
private final SourceFileFilter myFilter;
private final int myRootIndex;
@@ -77,17 +70,13 @@ public abstract class ArtifactRootDescriptor extends BuildRootDescriptor {
return myTarget;
}
+ @NotNull
@Override
- public FileFilter createFileFilter(@NotNull final ProjectDescriptor descriptor) {
+ public FileFilter createFileFilter() {
return new FileFilter() {
@Override
public boolean accept(File pathname) {
- try {
- return myFilter.accept(pathname.getAbsolutePath(), descriptor);
- }
- catch (IOException e) {
- throw new RuntimeException(e);
- }
+ return myFilter.accept(pathname.getAbsolutePath());
}
};
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java
index ee42cc4da78b..71eb66d1155b 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/FileBasedArtifactRootDescriptor.java
@@ -15,6 +15,7 @@
*/
package org.jetbrains.jps.incremental.artifacts.instructions;
+import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.builders.BuildOutputConsumer;
@@ -34,6 +35,7 @@ import java.util.Collections;
* @author nik
*/
public class FileBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
+ private static final Logger LOG = Logger.getInstance(FileBasedArtifactRootDescriptor.class);
public FileBasedArtifactRootDescriptor(@NotNull File file,
@NotNull SourceFileFilter filter,
int index,
@@ -79,6 +81,9 @@ public class FileBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
FileUtil.copyContent(file, targetFile);
outputConsumer.registerOutputFile(targetFile, Collections.singletonList(filePath));
}
- outSrcMapping.appendData(targetPath, Collections.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(filePath, rootIndex)));
+ else if (LOG.isDebugEnabled()) {
+ LOG.debug("Target path " + targetPath + " is already registered so " + filePath + " won't be copied");
+ }
+ outSrcMapping.appendData(targetPath, rootIndex, filePath);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java
index 7c31153b7058..8485d28901c2 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/JarBasedArtifactRootDescriptor.java
@@ -91,7 +91,7 @@ public class JarBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
processEntries(new EntryProcessor() {
@Override
public void process(@Nullable InputStream inputStream, @NotNull String relativePath, ZipEntry entry) throws IOException {
- final String fullOutputPath = FileUtil.toSystemDependentName(JpsArtifactPathUtil.appendToPath(outputPath, relativePath));
+ final String fullOutputPath = JpsArtifactPathUtil.appendToPath(outputPath, relativePath);
final File outputFile = new File(fullOutputPath);
FileUtil.createParentDirs(outputFile);
@@ -99,7 +99,6 @@ public class JarBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
outputFile.mkdir();
}
else {
- String fullSourcePath = filePath + JarPathUtil.JAR_SEPARATOR + relativePath;
if (outSrcMapping.getState(fullOutputPath) == null) {
final BufferedInputStream from = new BufferedInputStream(inputStream);
final BufferedOutputStream to = new BufferedOutputStream(new FileOutputStream(outputFile));
@@ -112,7 +111,7 @@ public class JarBasedArtifactRootDescriptor extends ArtifactRootDescriptor {
}
outputConsumer.registerOutputFile(outputFile, Collections.singletonList(filePath));
}
- outSrcMapping.appendData(fullOutputPath, Collections.singletonList(new ArtifactOutputToSourceMapping.SourcePathAndRootIndex(fullSourcePath, rootIndex)));
+ outSrcMapping.appendData(fullOutputPath, rootIndex, filePath);
}
}
});
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SourceFileFilter.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SourceFileFilter.java
index 60964afdf726..2e707c712ec9 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SourceFileFilter.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/artifacts/instructions/SourceFileFilter.java
@@ -26,10 +26,20 @@ import java.io.IOException;
public abstract class SourceFileFilter {
public static final SourceFileFilter ALL = new SourceFileFilter() {
@Override
- public boolean accept(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) {
+ public boolean accept(@NotNull String fullFilePath) {
+ return true;
+ }
+
+ @Override
+ public boolean shouldBeCopied(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) throws IOException {
return true;
}
};
- public abstract boolean accept(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) throws IOException;
+ public abstract boolean accept(@NotNull String fullFilePath);
+
+ /**
+ * This additional check is performed during the build phase so this method can use caches generated by previously processed targets
+ */
+ public abstract boolean shouldBeCopied(@NotNull String fullFilePath, ProjectDescriptor projectDescriptor) throws IOException;
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java
index a2942a64d348..e3d974cf5f0e 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/BuildFSState.java
@@ -22,7 +22,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.ModuleChunk;
import org.jetbrains.jps.builders.BuildRootDescriptor;
-import org.jetbrains.jps.builders.BuildRootIndex;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.builders.FileProcessor;
import org.jetbrains.jps.builders.impl.BuildTargetChunk;
@@ -33,7 +32,6 @@ import org.jetbrains.jps.incremental.Utils;
import org.jetbrains.jps.incremental.storage.Timestamps;
import java.io.File;
-import java.io.FileFilter;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
@@ -140,15 +138,13 @@ public class BuildFSState extends FSState {
public <R extends BuildRootDescriptor, T extends BuildTarget<R>> boolean processFilesToRecompile(CompileContext context, final T target, final FileProcessor<R, T> processor) throws IOException {
final Map<BuildRootDescriptor, Set<File>> data = getSourcesToRecompile(context, target);
- BuildRootIndex rootIndex = context.getProjectDescriptor().getBuildRootIndex();
final CompileScope scope = context.getScope();
synchronized (data) {
for (Map.Entry<BuildRootDescriptor, Set<File>> entry : data.entrySet()) {
//noinspection unchecked
R root = (R)entry.getKey();
- FileFilter filter = rootIndex.getRootFilter(root, context.getProjectDescriptor());
for (File file : entry.getValue()) {
- if (!scope.isAffected(target, file) || !filter.accept(file)) {
+ if (!scope.isAffected(target, file)) {
continue;
}
if (!processor.apply(target, file, root)) {
@@ -168,35 +164,29 @@ public class BuildFSState extends FSState {
final FilesDelta delta = getDelta(rd.getTarget());
final Set<File> files = delta.clearRecompile(rd);
if (files != null) {
- FileFilter filter = context.getProjectDescriptor().getBuildRootIndex().getRootFilter(rd, context.getProjectDescriptor());
CompileScope scope = context.getScope();
final long compilationStartStamp = context.getCompilationStartStamp();
for (File file : files) {
- if (filter.accept(file)) {
- if (scope.isAffected(rd.getTarget(), file)) {
- final long currentFileStamp = FileSystemUtil.lastModified(file);
- if (!rd.isGenerated() && (currentFileStamp > compilationStartStamp || getEventRegistrationStamp(file) > compilationStartStamp)) {
- // if the file was modified after the compilation had started,
- // do not save the stamp considering file dirty
- if (Utils.IS_TEST_MODE) {
- LOG.info("Timestamp after compilation started; marking dirty again: " + file.getPath());
- }
- delta.markRecompile(rd, file);
- }
- else {
- marked = true;
- stamps.saveStamp(file, rd.getTarget(), currentFileStamp);
- }
- }
- else {
+ if (scope.isAffected(rd.getTarget(), file)) {
+ final long currentFileStamp = FileSystemUtil.lastModified(file);
+ if (!rd.isGenerated() && (currentFileStamp > compilationStartStamp || getEventRegistrationStamp(file) > compilationStartStamp)) {
+ // if the file was modified after the compilation had started,
+ // do not save the stamp considering file dirty
if (Utils.IS_TEST_MODE) {
- LOG.info("Not affected by compile scope; marking dirty again: " + file.getPath());
+ LOG.info("Timestamp after compilation started; marking dirty again: " + file.getPath());
}
delta.markRecompile(rd, file);
}
+ else {
+ marked = true;
+ stamps.saveStamp(file, rd.getTarget(), currentFileStamp);
+ }
}
else {
- stamps.removeStamp(file, rd.getTarget());
+ if (Utils.IS_TEST_MODE) {
+ LOG.info("Not affected by compile scope; marking dirty again: " + file.getPath());
+ }
+ delta.markRecompile(rd, file);
}
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java
index 79c6ab127ea7..689db8ac814f 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/fs/FilesDelta.java
@@ -134,7 +134,8 @@ final class FilesDelta {
isMarkedDeleted = !myDeletedPaths.isEmpty() && myDeletedPaths.contains(FileUtil.toCanonicalPath(file.getPath()));
}
if (!isMarkedDeleted) {
- return _addToRecompiled(root, file);
+ _addToRecompiled(root, file);
+ return true;
}
return false;
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
index 8131cfd62739..092b002f2384 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/instrumentation/ClassProcessingBuilder.java
@@ -38,6 +38,8 @@ import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
/**
* @author Eugene Zhuravlev
@@ -98,6 +100,11 @@ public abstract class ClassProcessingBuilder extends ModuleLevelBuilder {
return exitCode;
}
+ @Override
+ public List<String> getCompilableFileExtensions() {
+ return Collections.emptyList();
+ }
+
protected abstract ExitCode performBuild(CompileContext context, ModuleChunk chunk, InstrumentationClassFinder finder, OutputConsumer outputConsumer);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ExternalJavacDescriptor.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ExternalJavacDescriptor.java
index 63e468da0af4..b8882decdf4d 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ExternalJavacDescriptor.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/ExternalJavacDescriptor.java
@@ -16,7 +16,7 @@
package org.jetbrains.jps.incremental.java;
import com.intellij.execution.process.BaseOSProcessHandler;
-import com.intellij.openapi.util.Key;
+import org.jetbrains.jps.incremental.GlobalContextKey;
import org.jetbrains.jps.javac.JavacServerClient;
/**
@@ -24,7 +24,7 @@ import org.jetbrains.jps.javac.JavacServerClient;
* Date: 1/24/12
*/
public class ExternalJavacDescriptor {
- public static final Key<ExternalJavacDescriptor> KEY = Key.create("_external_javac_descriptor_");
+ public static final GlobalContextKey<ExternalJavacDescriptor> KEY = GlobalContextKey.create("_external_javac_descriptor_");
public final BaseOSProcessHandler process;
public final JavacServerClient client;
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
index b4870b523ff3..46921cf25856 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/JavaBuilder.java
@@ -36,6 +36,7 @@ import org.jetbrains.jps.api.RequestFuture;
import org.jetbrains.jps.builders.BuildRootIndex;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.FileProcessor;
+import org.jetbrains.jps.builders.java.JavaBuilderExtension;
import org.jetbrains.jps.builders.java.JavaBuilderUtil;
import org.jetbrains.jps.builders.java.JavaSourceRootDescriptor;
import org.jetbrains.jps.builders.java.dependencyView.Callbacks;
@@ -55,6 +56,8 @@ import org.jetbrains.jps.model.java.LanguageLevel;
import org.jetbrains.jps.model.java.compiler.*;
import org.jetbrains.jps.model.library.sdk.JpsSdk;
import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsModuleType;
+import org.jetbrains.jps.service.JpsServiceManager;
import javax.tools.*;
import java.io.*;
@@ -71,7 +74,8 @@ import java.util.concurrent.atomic.AtomicReference;
public class JavaBuilder extends ModuleLevelBuilder {
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.java.JavaBuilder");
public static final String BUILDER_NAME = "java";
- private static final String JAVA_EXTENSION = ".java";
+ private static final String JAVA_EXTENSION = "java";
+ private static final String DOT_JAVA_EXTENSION = "." + JAVA_EXTENSION;
public static final boolean USE_EMBEDDED_JAVAC = System.getProperty(GlobalOptions.USE_EXTERNAL_JAVAC_OPTION) == null;
private static final Key<Integer> JAVA_COMPILER_VERSION_KEY = Key.create("_java_compiler_version_");
private static final Key<Boolean> IS_ENABLED = Key.create("_java_compiler_enabled_");
@@ -84,21 +88,28 @@ public class JavaBuilder extends ModuleLevelBuilder {
"-g", "-deprecation", "-nowarn", "-verbose", "-proc:none", "-proc:only", "-proceedOnError"
));
- private static final FileFilter JAVA_SOURCES_FILTER =
+ public static final FileFilter JAVA_SOURCES_FILTER =
SystemInfo.isFileSystemCaseSensitive?
new FileFilter() {
public boolean accept(File file) {
- return file.getPath().endsWith(JAVA_EXTENSION);
+ return file.getPath().endsWith(DOT_JAVA_EXTENSION);
}
} :
new FileFilter() {
public boolean accept(File file) {
- return StringUtil.endsWithIgnoreCase(file.getPath(), JAVA_EXTENSION);
+ return StringUtil.endsWithIgnoreCase(file.getPath(), DOT_JAVA_EXTENSION);
}
};
private final Executor myTaskRunner;
private static final List<ClassPostProcessor> ourClassProcessors = new ArrayList<ClassPostProcessor>();
+ private static final Set<JpsModuleType<?>> ourCompilableModuleTypes;
+ static {
+ ourCompilableModuleTypes = new HashSet<JpsModuleType<?>>();
+ for (JavaBuilderExtension extension : JpsServiceManager.getInstance().getExtensions(JavaBuilderExtension.class)) {
+ ourCompilableModuleTypes.addAll(extension.getCompilableModuleTypes());
+ }
+ }
public static void registerClassPostProcessor(ClassPostProcessor processor) {
ourClassProcessors.add(processor);
@@ -136,6 +147,11 @@ public class JavaBuilder extends ModuleLevelBuilder {
COMPILER_VERSION_INFO.set(context, new AtomicReference<String>(messageText));
}
+ @Override
+ public List<String> getCompilableFileExtensions() {
+ return Collections.singletonList(JAVA_EXTENSION);
+ }
+
public ExitCode build(final CompileContext context,
final ModuleChunk chunk,
DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
@@ -144,12 +160,12 @@ public class JavaBuilder extends ModuleLevelBuilder {
return ExitCode.NOTHING_DONE;
}
try {
- final Map<File, ModuleBuildTarget> filesToCompile = new THashMap<File, ModuleBuildTarget>(FileUtil.FILE_HASHING_STRATEGY);
+ final Set<File> filesToCompile = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
dirtyFilesHolder.processDirtyFiles(new FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>() {
public boolean apply(ModuleBuildTarget target, File file, JavaSourceRootDescriptor descriptor) throws IOException {
- if (JAVA_SOURCES_FILTER.accept(file)) {
- filesToCompile.put(file, target);
+ if (JAVA_SOURCES_FILTER.accept(file) && ourCompilableModuleTypes.contains(target.getModule().getModuleType())) {
+ filesToCompile.add(file);
}
return true;
}
@@ -159,12 +175,12 @@ public class JavaBuilder extends ModuleLevelBuilder {
final ProjectBuilderLogger logger = context.getLoggingManager().getProjectBuilderLogger();
if (logger.isEnabled()) {
if (filesToCompile.size() > 0) {
- logger.logCompiledFiles(filesToCompile.keySet(), BUILDER_NAME, "Compiling files:");
+ logger.logCompiledFiles(filesToCompile, BUILDER_NAME, "Compiling files:");
}
}
}
- return compile(context, chunk, dirtyFilesHolder, filesToCompile.keySet(), outputConsumer);
+ return compile(context, chunk, dirtyFilesHolder, filesToCompile, outputConsumer);
}
catch (ProjectBuildException e) {
throw e;
@@ -187,12 +203,6 @@ public class JavaBuilder extends ModuleLevelBuilder {
}
}
- @Override
- public boolean shouldHonorFileEncodingForCompilation(File file) {
- return JAVA_SOURCES_FILTER.accept(file);
- }
-
-
private ExitCode compile(final CompileContext context,
ModuleChunk chunk,
DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
@@ -803,9 +813,11 @@ public class JavaBuilder extends ModuleLevelBuilder {
default:
kind = BuildMessage.Kind.INFO;
}
- final JavaFileObject source = diagnostic.getSource();
File sourceFile = null;
try {
+ // for eclipse compiler just an attempt to call getSource() may lead to an NPE,
+ // so calling this method under try/catch to avoid induced compiler errors
+ final JavaFileObject source = diagnostic.getSource();
sourceFile = source != null ? Utils.convertToFile(source.toUri()) : null;
}
catch (Exception e) {
@@ -845,6 +857,20 @@ public class JavaBuilder extends ModuleLevelBuilder {
}
public void save(@NotNull final OutputFileObject fileObject) {
+ if (JavaFileObject.Kind.CLASS != fileObject.getKind()) {
+ // generated sources or resources must be saved synchronously, because some compilers (e.g. eclipse)
+ // may want to read generated text for further compilation
+ try {
+ final BinaryContent content = fileObject.getContent();
+ if (content != null) {
+ content.saveToFile(fileObject.getFile());
+ }
+ }
+ catch (IOException e) {
+ myContext.processMessage(new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, e.getMessage()));
+ }
+ }
+
submitAsyncTask(myContext, new Runnable() {
public void run() {
try {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java
index 9508b86b842f..29ca799bb01c 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/java/OutputFilesSink.java
@@ -15,7 +15,6 @@
*/
package org.jetbrains.jps.incremental.java;
-import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
@@ -40,8 +39,6 @@ import java.util.Set;
* Date: 2/16/12
*/
class OutputFilesSink implements OutputFileConsumer {
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.java.OutputFilesSink");
-
private final CompileContext myContext;
private final ModuleLevelBuilder.OutputConsumer myOutputConsumer;
private final Callbacks.Backend myMappingsCallback;
@@ -92,11 +89,14 @@ class OutputFilesSink implements OutputFileConsumer {
}
}
- try {
- writeToDisk(fileObject, isTemp);
- }
- catch (IOException e) {
- myContext.processMessage(new CompilerMessage(JavaBuilder.BUILDER_NAME, BuildMessage.Kind.ERROR, e.getMessage()));
+ if (outKind == JavaFileObject.Kind.CLASS) {
+ // generated sources and resources are handled separately
+ try {
+ writeToDisk(fileObject, isTemp);
+ }
+ catch (IOException e) {
+ myContext.processMessage(new CompilerMessage(JavaBuilder.BUILDER_NAME, BuildMessage.Kind.ERROR, e.getMessage()));
+ }
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
index f07df2ec467c..37f8bfb09d4a 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/resources/ResourcesBuilder.java
@@ -18,14 +18,15 @@ package org.jetbrains.jps.incremental.resources;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.builders.BuildOutputConsumer;
import org.jetbrains.jps.builders.DirtyFilesHolder;
import org.jetbrains.jps.builders.FileProcessor;
import org.jetbrains.jps.builders.java.ResourceRootDescriptor;
import org.jetbrains.jps.builders.java.ResourcesTargetType;
-import org.jetbrains.jps.builders.storage.SourceToOutputMapping;
-import org.jetbrains.jps.incremental.*;
+import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.ProjectBuildException;
+import org.jetbrains.jps.incremental.ResourcesTarget;
+import org.jetbrains.jps.incremental.TargetBuilder;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.CompilerMessage;
import org.jetbrains.jps.incremental.messages.ProgressMessage;
@@ -54,11 +55,6 @@ public class ResourcesBuilder extends TargetBuilder<ResourceRootDescriptor, Reso
@Override
public void buildStarted(CompileContext context) {
- // init patterns
- ResourcePatterns patterns = ResourcePatterns.KEY.get(context);
- if (patterns == null) {
- ResourcePatterns.KEY.set(context, new ResourcePatterns(context.getProjectDescriptor().getProject()));
- }
}
@Override
@@ -71,18 +67,6 @@ public class ResourcesBuilder extends TargetBuilder<ResourceRootDescriptor, Reso
return;
}
- @Nullable
- final Map<ResourcesTarget, Set<File>> cleanedSources;
- if (context.isProjectRebuild()) {
- cleanedSources = null;
- }
- else {
- cleanedSources = BuildOperations.cleanOutputsCorrespondingToChangedFiles(context, holder);
- }
-
- final ResourcePatterns patterns = ResourcePatterns.KEY.get(context);
- assert patterns != null;
-
try {
holder.processDirtyFiles(new FileProcessor<ResourceRootDescriptor, ResourcesTarget>() {
private final Map<ResourceRootDescriptor, Boolean> mySkippedRoots = new HashMap<ResourceRootDescriptor, Boolean>();
@@ -96,27 +80,17 @@ public class ResourcesBuilder extends TargetBuilder<ResourceRootDescriptor, Reso
if (isSkipped.booleanValue()) {
return true;
}
- if (patterns.isResourceFile(file, sourceRoot.getRootFile())) {
- try {
- copyResource(context, sourceRoot, file, outputConsumer);
- }
- catch (IOException e) {
- LOG.info(e);
- context.processMessage(
- new CompilerMessage(
- "resources", BuildMessage.Kind.ERROR, e.getMessage(), FileUtil.toSystemIndependentName(file.getPath())
- )
- );
- return false;
- }
- finally {
- if (cleanedSources != null) {
- final Set<File> files = cleanedSources.get(target);
- if (files != null) {
- files.remove(file);
- }
- }
- }
+ try {
+ copyResource(context, sourceRoot, file, outputConsumer);
+ }
+ catch (IOException e) {
+ LOG.info(e);
+ context.processMessage(
+ new CompilerMessage(
+ "resources", BuildMessage.Kind.ERROR, e.getMessage(), FileUtil.toSystemIndependentName(file.getPath())
+ )
+ );
+ return false;
}
return !context.getCancelStatus().isCanceled();
}
@@ -124,21 +98,11 @@ public class ResourcesBuilder extends TargetBuilder<ResourceRootDescriptor, Reso
context.checkCanceled();
- if (cleanedSources != null) {
- // cleanup mapping for the files that were copied before but not copied now
- for (Map.Entry<ResourcesTarget, Set<File>> entry : cleanedSources.entrySet()) {
- final Set<File> files = entry.getValue();
- if (!files.isEmpty()) {
- final SourceToOutputMapping mapping = context.getProjectDescriptor().dataManager.getSourceToOutputMap(entry.getKey());
- for (File file : files) {
- mapping.remove(file.getPath());
- }
- }
- }
- }
-
context.processMessage(new ProgressMessage(""));
}
+ catch(ProjectBuildException e) {
+ throw e;
+ }
catch (Exception e) {
throw new ProjectBuildException(e.getMessage(), e);
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java
index 1ed0edbb1bc8..8067aefacd5c 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/incremental/storage/BuildTargetConfiguration.java
@@ -22,9 +22,13 @@ import com.intellij.util.SmartList;
import gnu.trove.THashSet;
import org.jetbrains.jps.builders.BuildTarget;
import org.jetbrains.jps.incremental.CompileContext;
+import org.jetbrains.jps.incremental.GlobalContextKey;
import java.io.*;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
/**
* @author nik
@@ -35,6 +39,7 @@ public class BuildTargetConfiguration {
private final BuildTargetsState myTargetsState;
private String myConfiguration;
private volatile String myCurrentState;
+ private static final GlobalContextKey<Set<File>> ALL_DELETED_ROOTS_KEY = GlobalContextKey.create("_all_deleted_output_roots_");
public BuildTargetConfiguration(BuildTarget<?> target, BuildTargetsState targetsState) {
myTarget = target;
@@ -121,9 +126,7 @@ public class BuildTargetConfiguration {
}
File file = getNonexistentOutputsFile();
if (nonexistentOutputRoots.isEmpty()) {
- if (file.exists()) {
- FileUtil.delete(file);
- }
+ file.delete();
}
else {
FileUtil.writeToFile(file, StringUtil.join(nonexistentOutputRoots, "\n"));
@@ -132,12 +135,31 @@ public class BuildTargetConfiguration {
public boolean outputRootWasDeleted(CompileContext context) throws IOException {
List<String> nonexistentOutputRoots = new SmartList<String>();
- for (File outputRoot : myTarget.getOutputRoots(context)) {
- if (!outputRoot.exists()) {
- nonexistentOutputRoots.add(outputRoot.getAbsolutePath());
+
+ final Collection<File> targetRoots = myTarget.getOutputRoots(context);
+ synchronized (ALL_DELETED_ROOTS_KEY) {
+ Set<File> allDeletedRoots = ALL_DELETED_ROOTS_KEY.get(context);
+ for (File outputRoot : targetRoots) {
+ boolean wasDeleted = allDeletedRoots != null && allDeletedRoots.contains(outputRoot);
+ if (!wasDeleted) {
+ wasDeleted = !outputRoot.exists();
+ if (wasDeleted) {
+ if (allDeletedRoots == null) { // lazy init
+ allDeletedRoots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
+ ALL_DELETED_ROOTS_KEY.set(context, allDeletedRoots);
+ }
+ allDeletedRoots.add(outputRoot);
+ }
+ }
+ if (wasDeleted) {
+ nonexistentOutputRoots.add(outputRoot.getAbsolutePath());
+ }
}
}
- if (nonexistentOutputRoots.isEmpty()) return false;
+
+ if (nonexistentOutputRoots.isEmpty()) {
+ return false;
+ }
Set<String> storedNonExistentOutputs;
File file = getNonexistentOutputsFile();
diff --git a/jps/jps-builders/src/org/jetbrains/jps/indices/impl/IgnoredFileIndexImpl.java b/jps/jps-builders/src/org/jetbrains/jps/indices/impl/IgnoredFileIndexImpl.java
index fec3e344ed37..700f2cc7322d 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/indices/impl/IgnoredFileIndexImpl.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/indices/impl/IgnoredFileIndexImpl.java
@@ -15,60 +15,22 @@
*/
package org.jetbrains.jps.indices.impl;
-import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.fileTypes.impl.IgnoredPatternSet;
import org.jetbrains.jps.indices.IgnoredFileIndex;
import org.jetbrains.jps.model.JpsModel;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.StringTokenizer;
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
/**
* @author nik
*/
public class IgnoredFileIndexImpl implements IgnoredFileIndex {
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.IgnoredFilePatterns");
- private List<Pattern> myPatterns = new ArrayList<Pattern>();
+ private IgnoredPatternSet myIgnoredPatterns = new IgnoredPatternSet();
public IgnoredFileIndexImpl(JpsModel model) {
- loadFromString(model.getGlobal().getFileTypesConfiguration().getIgnoredPatternString());
- }
-
- private void loadFromString(String patterns) {
- myPatterns.clear();
- StringTokenizer tokenizer = new StringTokenizer(patterns, ";");
- while (tokenizer.hasMoreTokens()) {
- String pattern = tokenizer.nextToken();
- if (!StringUtil.isEmptyOrSpaces(pattern)) {
- try {
- myPatterns.add(Pattern.compile(convertToJavaPattern(pattern)));
- }
- catch (PatternSyntaxException e) {
- LOG.info("Cannot load ignored file pattern " + pattern, e);
- }
- }
- }
+ myIgnoredPatterns.setIgnoreMasks(model.getGlobal().getFileTypesConfiguration().getIgnoredPatternString());
}
@Override
public boolean isIgnored(String fileName) {
- for (Pattern pattern : myPatterns) {
- if (pattern.matcher(fileName).matches()) {
- return true;
- }
- }
- return false;
- }
-
- private static String convertToJavaPattern(String wildcardPattern) {
- wildcardPattern = StringUtil.replace(wildcardPattern, ".", "\\.");
- wildcardPattern = StringUtil.replace(wildcardPattern, "*?", ".+");
- wildcardPattern = StringUtil.replace(wildcardPattern, "?*", ".+");
- wildcardPattern = StringUtil.replace(wildcardPattern, "*", ".*");
- wildcardPattern = StringUtil.replace(wildcardPattern, "?", ".");
- return wildcardPattern;
+ return myIgnoredPatterns.isIgnored(fileName);
}
}
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java
index 5175787156b2..03b9d4170aa8 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacFileManager.java
@@ -18,16 +18,14 @@ package org.jetbrains.jps.javac;
import com.intellij.openapi.util.io.FileUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.jps.builders.java.JavaSourceTransformer;
import org.jetbrains.jps.incremental.Utils;
import javax.tools.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
-import java.util.Collections;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
/**
* @author Eugene Zhuravlev
@@ -36,6 +34,7 @@ import java.util.Set;
class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager> implements StandardJavaFileManager{
private final Context myContext;
+ private final Collection<JavaSourceTransformer> mySourceTransformers;
private Map<File, Set<File>> myOutputsMap = Collections.emptyMap();
interface Context {
@@ -48,9 +47,10 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
void reportMessage(final Diagnostic.Kind kind, String message);
}
- public JavacFileManager(Context context) {
+ public JavacFileManager(Context context, Collection<JavaSourceTransformer> transformers) {
super(context.getStandardFileManager());
myContext = context;
+ mySourceTransformers = transformers;
}
public void setOutputDirectories(final Map<File, Set<File>> outputDirToSrcRoots) throws IOException{
@@ -66,19 +66,19 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
}
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromFiles(Iterable<? extends File> files) {
- return getStdManager().getJavaFileObjectsFromFiles(files);
+ return wrapJavaFileObjects(getStdManager().getJavaFileObjectsFromFiles(files));
}
public Iterable<? extends JavaFileObject> getJavaFileObjects(File... files) {
- return getStdManager().getJavaFileObjects(files);
+ return wrapJavaFileObjects(getStdManager().getJavaFileObjects(files));
}
public Iterable<? extends JavaFileObject> getJavaFileObjectsFromStrings(Iterable<String> names) {
- return getStdManager().getJavaFileObjectsFromStrings(names);
+ return wrapJavaFileObjects(getStdManager().getJavaFileObjectsFromStrings(names));
}
public Iterable<? extends JavaFileObject> getJavaFileObjects(String... names) {
- return getStdManager().getJavaFileObjects(names);
+ return wrapJavaFileObjects(getStdManager().getJavaFileObjects(names));
}
public Iterable<? extends File> getLocation(Location location) {
@@ -104,6 +104,24 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
}
@Override
+ public Iterable<JavaFileObject> list(Location location, String packageName, Set<JavaFileObject.Kind> kinds, boolean recurse) throws IOException {
+ final Iterable<JavaFileObject> objects = super.list(location, packageName, kinds, recurse);
+ //noinspection unchecked
+ return kinds.contains(JavaFileObject.Kind.SOURCE)? (Iterable<JavaFileObject>)wrapJavaFileObjects(objects) : objects;
+ }
+
+ private Iterable<? extends JavaFileObject> wrapJavaFileObjects(Iterable<? extends JavaFileObject> originalObjects) {
+ if (mySourceTransformers.isEmpty()) {
+ return originalObjects;
+ }
+ final List<JavaFileObject> wrapped = new ArrayList<JavaFileObject>();
+ for (JavaFileObject fo : originalObjects) {
+ wrapped.add(JavaFileObject.Kind.SOURCE.equals(fo.getKind())? new TransformableJavaFileObject(fo, mySourceTransformers) : fo);
+ }
+ return wrapped;
+ }
+
+ @Override
public JavaFileObject getJavaFileForInput(Location location, String className, JavaFileObject.Kind kind) throws IOException {
checkCanceled();
final JavaFileObject fo = super.getJavaFileForInput(location, className, kind);
@@ -111,7 +129,7 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
// workaround javac bug (missing null-check): throwing exception here instead of returning null
throw new FileNotFoundException("Java resource does not exist : " + location + '/' + kind + '/' + className);
}
- return fo;
+ return mySourceTransformers.isEmpty()? fo : new TransformableJavaFileObject(fo, mySourceTransformers);
}
public JavaFileObject getJavaFileForOutput(Location location, String className, JavaFileObject.Kind kind, FileObject sibling) throws IOException {
@@ -202,10 +220,6 @@ class JavacFileManager extends ForwardingJavaFileManager<StandardJavaFileManager
return fileManager;
}
- public Iterable<? extends JavaFileObject> toJavaFileObjects(Iterable<? extends File> files) {
- return getStdManager().getJavaFileObjectsFromFiles(files);
- }
-
@Override
public void close() {
try {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java
index f985b2f81699..f298026813a2 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/JavacMain.java
@@ -18,6 +18,7 @@ package org.jetbrains.jps.javac;
import com.intellij.openapi.util.SystemInfo;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.api.CanceledStatus;
+import org.jetbrains.jps.builders.java.JavaSourceTransformer;
import org.jetbrains.jps.cmdline.ClasspathBootstrap;
import org.jetbrains.jps.incremental.LineOutputWriter;
@@ -78,7 +79,10 @@ public class JavacMain {
for (File outputDir : outputDirToRoots.keySet()) {
outputDir.mkdirs();
}
- final JavacFileManager fileManager = new JavacFileManager(new ContextImpl(compiler, outConsumer, outputSink, canceledStatus, nowUsingJavac));
+
+ final List<JavaSourceTransformer> transformers = getSourceTransformers();
+
+ final JavacFileManager fileManager = new JavacFileManager(new ContextImpl(compiler, outConsumer, outputSink, canceledStatus, nowUsingJavac), transformers);
fileManager.handleOption("-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff
fileManager.handleOption("-extdirs", Collections.singleton("").iterator()); // this will clear cached stuff
@@ -138,8 +142,16 @@ public class JavacMain {
try {
final Collection<String> _options = prepareOptions(options, nowUsingJavac);
+
+ // to be on the safe side, we'll have to apply all options _before_ calling any of manager's methods
+ // i.e. getJavaFileObjectsFromFiles()
+ // This way the manager will be properly initialized. Namely, the encoding will be set correctly
+ for (Iterator<String> iterator = _options.iterator(); iterator.hasNext(); ) {
+ fileManager.handleOption(iterator.next(), iterator);
+ }
+
final JavaCompiler.CompilationTask task = compiler.getTask(
- out, fileManager, outConsumer, _options, null, fileManager.toJavaFileObjects(sources)
+ out, fileManager, outConsumer, _options, null, fileManager.getJavaFileObjectsFromFiles(sources)
);
//if (!IS_VM_6_VERSION) { //todo!
@@ -162,6 +174,16 @@ public class JavacMain {
return false;
}
+ private static List<JavaSourceTransformer> getSourceTransformers() {
+ final Class<JavaSourceTransformer> transformerClass = JavaSourceTransformer.class;
+ final ServiceLoader<JavaSourceTransformer> loader = ServiceLoader.load(transformerClass, transformerClass.getClassLoader());
+ final List<JavaSourceTransformer> transformers = new ArrayList<JavaSourceTransformer>();
+ for (JavaSourceTransformer t : loader) {
+ transformers.add(t);
+ }
+ return transformers;
+ }
+
private static boolean isAnnotationProcessingEnabled(final Collection<String> options) {
for (String option : options) {
if ("-proc:none".equals(option)) {
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/TransformableJavaFileObject.java b/jps/jps-builders/src/org/jetbrains/jps/javac/TransformableJavaFileObject.java
new file mode 100644
index 000000000000..673b6e376e45
--- /dev/null
+++ b/jps/jps-builders/src/org/jetbrains/jps/javac/TransformableJavaFileObject.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2000-2013 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 org.jetbrains.jps.javac;
+
+import org.jetbrains.jps.builders.java.JavaSourceTransformer;
+import org.jetbrains.jps.incremental.Utils;
+
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.tools.*;
+import java.io.*;
+import java.net.URI;
+import java.util.Collection;
+
+/**
+ * @author Eugene Zhuravlev
+ * Date: 1/9/13
+ */
+public class TransformableJavaFileObject implements JavaFileObject {
+ private final JavaFileObject myOriginal;
+ private final Collection<JavaSourceTransformer> myTransformers;
+
+ public TransformableJavaFileObject(JavaFileObject original, Collection<JavaSourceTransformer> transformers) {
+ myOriginal = original;
+ myTransformers = transformers;
+ }
+
+ @Override
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ // todo: cache transformed content?
+ final File file = Utils.convertToFile(myOriginal.toUri());
+ CharSequence content = myOriginal.getCharContent(ignoreEncodingErrors);
+ for (JavaSourceTransformer transformer : myTransformers) {
+ content = transformer.transform(file, content);
+ }
+ return content;
+ }
+
+ @Override
+ public InputStream openInputStream() throws IOException {
+ return myOriginal.openInputStream();
+ }
+
+ @Override
+ public Kind getKind() {
+ return myOriginal.getKind();
+ }
+
+ @Override
+ public boolean isNameCompatible(String simpleName, Kind kind) {
+ return myOriginal.isNameCompatible(simpleName, kind);
+ }
+
+ @Override
+ public NestingKind getNestingKind() {
+ return myOriginal.getNestingKind();
+ }
+
+ @Override
+ public Modifier getAccessLevel() {
+ return myOriginal.getAccessLevel();
+ }
+
+ @Override
+ public URI toUri() {
+ return myOriginal.toUri();
+ }
+
+ @Override
+ public String getName() {
+ return myOriginal.getName();
+ }
+
+ @Override
+ public OutputStream openOutputStream() throws IOException {
+ return myOriginal.openOutputStream();
+ }
+
+ @Override
+ public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+ return myOriginal.openReader(ignoreEncodingErrors);
+ }
+
+ @Override
+ public Writer openWriter() throws IOException {
+ return myOriginal.openWriter();
+ }
+
+ @Override
+ public long getLastModified() {
+ return myOriginal.getLastModified();
+ }
+
+ @Override
+ public boolean delete() {
+ return myOriginal.delete();
+ }
+}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java
index 29fed9c6bbed..26f93b216c54 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/CommonTest.java
@@ -101,4 +101,8 @@ public class CommonTest extends IncrementalTestCase {
public void testAddClass() throws Exception {
doTest();
}
+
+ public void testAddDuplicateClass() throws Exception {
+ doTest();
+ }
}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java
index f1cefa112f80..6e38f95a7c52 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/IncrementalTestCase.java
@@ -82,7 +82,8 @@ public abstract class IncrementalTestCase extends JpsBuildTestCase {
return JpsPathUtil.pathToUrl(getAbsolutePath(pathRelativeToProjectRoot));
}
- protected String getAbsolutePath(final String pathRelativeToProjectRoot) {
+ @Override
+ public String getAbsolutePath(final String pathRelativeToProjectRoot) {
return FileUtil.toSystemIndependentName(workDir.getAbsolutePath()) + "/" + pathRelativeToProjectRoot;
}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java b/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java
index 1fd356da4a32..c1c1f81c3cca 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/ether/MemberChangeTest.java
@@ -176,6 +176,10 @@ public class MemberChangeTest extends IncrementalTestCase {
doTest();
}
+ public void testRemoveMoreAccessibleMethod() {
+ doTest();
+ }
+
public void testRenameMethod() {
doTest();
}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/BuildResult.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/BuildResult.java
index 56b936246fd5..4ada300cb65a 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/BuildResult.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/BuildResult.java
@@ -18,11 +18,13 @@ package org.jetbrains.jps.builders;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.util.Function;
import junit.framework.Assert;
+import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.incremental.MessageHandler;
import org.jetbrains.jps.incremental.messages.BuildMessage;
import org.jetbrains.jps.incremental.messages.DoneSomethingNotification;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
/**
@@ -69,4 +71,9 @@ public class BuildResult implements MessageHandler {
Assert.assertTrue("Build failed. \nErrors:\n" + StringUtil.join(myErrorMessages, toStringFunction, "\n") +
"\nInfo messages:\n" + StringUtil.join(myInfoMessages, toStringFunction, "\n"), isSuccessful());
}
+
+ @NotNull
+ public List<BuildMessage> getErrorMessages() {
+ return Collections.unmodifiableList(myErrorMessages);
+ }
}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
index 54528ada8d5e..5751878802f8 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/builders/JpsBuildTestCase.java
@@ -44,15 +44,15 @@ import org.jetbrains.jps.incremental.storage.ProjectTimestamps;
import org.jetbrains.jps.indices.ModuleExcludeIndex;
import org.jetbrains.jps.indices.impl.IgnoredFileIndexImpl;
import org.jetbrains.jps.indices.impl.ModuleExcludeIndexImpl;
-import org.jetbrains.jps.model.JpsDummyElement;
-import org.jetbrains.jps.model.JpsElementFactory;
-import org.jetbrains.jps.model.JpsModel;
-import org.jetbrains.jps.model.JpsProject;
+import org.jetbrains.jps.model.*;
import org.jetbrains.jps.model.java.*;
import org.jetbrains.jps.model.library.JpsOrderRootType;
import org.jetbrains.jps.model.library.JpsTypedLibrary;
import org.jetbrains.jps.model.library.sdk.JpsSdk;
+import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
import org.jetbrains.jps.model.module.JpsModule;
+import org.jetbrains.jps.model.module.JpsSdkReferencesTable;
import org.jetbrains.jps.model.serialization.JpsProjectLoader;
import org.jetbrains.jps.model.serialization.PathMacroUtil;
import org.jetbrains.jps.util.JpsPathUtil;
@@ -73,9 +73,11 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
protected JpsProject myProject;
protected JpsModel myModel;
private JpsSdk<JpsDummyElement> myJdk;
- private File myDataStorageRoot;
+ protected File myDataStorageRoot;
private TestProjectBuilderLogger myLogger;
+ protected Map<String, String> myBuildParams;
+
@Override
protected void setUp() throws Exception {
super.setUp();
@@ -83,6 +85,7 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
myProject = myModel.getProject();
myDataStorageRoot = FileUtil.createTempDirectory("compile-server-" + getProjectName(), null);
myLogger = new TestProjectBuilderLogger();
+ myBuildParams = new HashMap<String, String>();
}
@Override
@@ -215,15 +218,23 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
return null;
}
- protected JpsModule addModule(String moduleName,
- String[] srcPaths,
- @Nullable String outputPath,
- @Nullable String testOutputPath,
- JpsSdk<JpsDummyElement> jdk) {
+ protected <T extends JpsElement> JpsModule addModule(String moduleName,
+ String[] srcPaths,
+ @Nullable String outputPath,
+ @Nullable String testOutputPath,
+ JpsSdk<T> sdk) {
JpsModule module = myProject.addModule(moduleName, JpsJavaModuleType.INSTANCE);
- module.getSdkReferencesTable().setSdkReference(JpsJavaSdkType.INSTANCE, jdk.createReference());
- module.getDependenciesList().addSdkDependency(JpsJavaSdkType.INSTANCE);
- if (srcPaths.length > 0) {
+ final JpsSdkType<T> sdkType = sdk.getSdkType();
+ final JpsSdkReferencesTable sdkTable = module.getSdkReferencesTable();
+ sdkTable.setSdkReference(sdkType, sdk.createReference());
+
+ if (sdkType instanceof JpsJavaSdkTypeWrapper) {
+ final JpsSdkReference<T> wrapperRef = sdk.createReference();
+ sdkTable.setSdkReference(JpsJavaSdkType.INSTANCE, JpsJavaExtensionService.
+ getInstance().createWrappedJavaSdkReference((JpsJavaSdkTypeWrapper)sdkType, wrapperRef));
+ }
+ module.getDependenciesList().addSdkDependency(sdkType);
+ if (srcPaths.length > 0 || outputPath != null) {
for (String srcPath : srcPaths) {
module.getContentRootsList().addUrl(JpsPathUtil.pathToUrl(srcPath));
module.addSourceRoot(JpsPathUtil.pathToUrl(srcPath), JavaSourceRootType.SOURCE);
@@ -264,7 +275,7 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
}
}
- protected void assertCompiled(String builderName, String... paths) {
+ public void assertCompiled(String builderName, String... paths) {
myLogger.assertCompiled(builderName, new File[]{myProjectDir, myDataStorageRoot}, paths);
}
@@ -273,7 +284,7 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
}
protected BuildResult doBuild(final ProjectDescriptor descriptor, CompileScopeTestBuilder scopeBuilder) {
- IncProjectBuilder builder = new IncProjectBuilder(descriptor, BuilderRegistry.getInstance(), Collections.<String, String>emptyMap(), CanceledStatus.NULL, null);
+ IncProjectBuilder builder = new IncProjectBuilder(descriptor, BuilderRegistry.getInstance(), myBuildParams, CanceledStatus.NULL, null);
BuildResult result = new BuildResult();
builder.addMessageHandler(result);
try {
@@ -289,7 +300,7 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
return createFile(relativePath, "");
}
- protected String createFile(String relativePath, final String text) {
+ public String createFile(String relativePath, final String text) {
try {
File file = new File(getOrCreateProjectDir(), relativePath);
FileUtil.writeToFile(file, text);
@@ -301,7 +312,7 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
}
protected String copyToProject(String relativeSourcePath, String relativeTargetPath) {
- File source = PathManagerEx.findFileUnderProjectHome(relativeSourcePath, getClass());
+ File source = findFindUnderProjectHome(relativeSourcePath);
String fullTargetPath = getAbsolutePath(relativeTargetPath);
File target = new File(fullTargetPath);
try {
@@ -318,7 +329,11 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
return fullTargetPath;
}
- private File getOrCreateProjectDir() {
+ protected File findFindUnderProjectHome(String relativeSourcePath) {
+ return PathManagerEx.findFileUnderProjectHome(relativeSourcePath, getClass());
+ }
+
+ public File getOrCreateProjectDir() {
if (myProjectDir == null) {
try {
myProjectDir = doGetProjectDir();
@@ -334,11 +349,11 @@ public abstract class JpsBuildTestCase extends UsefulTestCase {
return FileUtil.createTempDirectory("prj", null);
}
- protected String getAbsolutePath(final String pathRelativeToProjectRoot) {
+ public String getAbsolutePath(final String pathRelativeToProjectRoot) {
return FileUtil.toSystemIndependentName(new File(getOrCreateProjectDir(), pathRelativeToProjectRoot).getAbsolutePath());
}
- protected JpsModule addModule(String moduleName, String... srcPaths) {
+ public JpsModule addModule(String moduleName, String... srcPaths) {
if (myJdk == null) {
myJdk = addJdk("1.6");
}
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java
index 0c27e91e532d..ee9ad9ad0d28 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderOverwriteTest.java
@@ -15,9 +15,17 @@
*/
package org.jetbrains.jps.incremental.artifacts;
+import com.intellij.openapi.util.io.FileUtil;
import com.intellij.util.PathUtil;
+import com.intellij.util.text.CharsetUtil;
import org.jetbrains.jps.model.artifact.JpsArtifact;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+
import static com.intellij.util.io.TestFileSystemBuilder.fs;
import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root;
@@ -121,6 +129,65 @@ public class ArtifactBuilderOverwriteTest extends ArtifactBuilderTestCase {
buildAllAndAssertUpToDate();
}
+ public void testOverwriteCopiedFileByExtracted() {
+ String jar = createArchive("x.jar", "x.txt", "1");
+ String file = createFile("x.txt", "2");
+ JpsArtifact a = addArtifact(root().extractedDir(jar, "").fileCopy(file));
+ buildAll();
+ assertOutput(a, fs().file("x.txt", "1"));
+ buildAllAndAssertUpToDate();
+
+ change(file, "3");
+ buildAllAndAssertUpToDate();
+ assertOutput(a, fs().file("x.txt", "1"));
+
+ delete(jar);
+ createArchive("x.jar", "x.txt", "4");
+ buildAll();
+ assertOutput(a, fs().file("x.txt", "4"));
+
+ delete(jar);
+ buildAll();
+ assertOutput(a, fs().file("x.txt", "3"));
+ }
+
+ public void testOverwriteExtractedFileByCopied() {
+ String file = createFile("x.txt", "1");
+ String jar = createArchive("x.jar", "x.txt", "2");
+ JpsArtifact a = addArtifact(root().fileCopy(file).extractedDir(jar, ""));
+ buildAll();
+ assertOutput(a, fs().file("x.txt", "1"));
+ buildAllAndAssertUpToDate();
+
+ delete(jar);
+ createArchive("x.jar", "x.txt", "3");
+ buildAll();
+ assertOutput(a, fs().file("x.txt", "1"));
+
+ delete(file);
+ buildAll();
+ assertOutput(a, fs().file("x.txt", "3"));
+ }
+
+ private String createArchive(String relativeArchivePath, String fileNameInArchive, String text) {
+ try {
+ File file = new File(getOrCreateProjectDir(), relativeArchivePath);
+ ZipOutputStream output = new ZipOutputStream(new FileOutputStream(file));
+ try {
+ output.putNextEntry(new ZipEntry(fileNameInArchive));
+ output.write(text.getBytes(CharsetUtil.UTF8));
+ output.closeEntry();
+ }
+ finally {
+ output.close();
+ }
+ return FileUtil.toSystemIndependentName(file.getAbsolutePath());
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
public void testFileOrder() {
final String firstFile = createFile("d1/xxx.txt", "first");
final String secondFile = createFile("d2/xxx.txt", "second");
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java
index 473c09d606cb..239b561ec66c 100644
--- a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ArtifactBuilderTestCase.java
@@ -54,7 +54,7 @@ public abstract class ArtifactBuilderTestCase extends JpsBuildTestCase {
super.tearDown();
}
- protected JpsArtifact addArtifact(LayoutElementTestUtil.LayoutElementCreator root) {
+ public JpsArtifact addArtifact(LayoutElementTestUtil.LayoutElementCreator root) {
Set<String> usedNames = getArtifactNames();
final String name = UniqueNameGenerator.generateUniqueName("a", usedNames);
return addArtifact(name, root);
diff --git a/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ModuleBuilder.java b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ModuleBuilder.java
new file mode 100644
index 000000000000..fe600f20a981
--- /dev/null
+++ b/jps/jps-builders/testSrc/org/jetbrains/jps/incremental/artifacts/ModuleBuilder.java
@@ -0,0 +1,173 @@
+package org.jetbrains.jps.incremental.artifacts;
+
+import com.intellij.openapi.Disposable;
+import com.intellij.openapi.util.Disposer;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.JpsModuleRootModificationUtil;
+import org.jetbrains.jps.model.artifact.JpsArtifact;
+import org.jetbrains.jps.model.artifact.elements.JpsPackagingElement;
+import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
+import org.jetbrains.jps.model.module.JpsModule;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.jetbrains.jps.incremental.artifacts.LayoutElementTestUtil.root;
+
+public class ModuleBuilder {
+ private static Map<ArtifactBuilderTestCase, Pair<AtomicInteger, AtomicInteger>> testCaseToNameCounter = new THashMap<ArtifactBuilderTestCase, Pair<AtomicInteger, AtomicInteger>>();
+
+ private final ArtifactBuilderTestCase testCase;
+ private final String builderName;
+
+ private String name;
+ private JpsModule module;
+ private File sourceRoot;
+ private String sourceRootRelativeToProject;
+
+ private String fromSourceRoot;
+
+ private JpsArtifact mainArtifact;
+
+ public ModuleBuilder(String builderName, ArtifactBuilderTestCase testCase) {
+ this(builderName, testCase, null);
+ }
+
+ public ModuleBuilder(String builderName, ArtifactBuilderTestCase testCase, String fromSourceRoot) {
+ this.builderName = builderName;
+ this.testCase = testCase;
+ this.fromSourceRoot = fromSourceRoot;
+ }
+
+ public static JpsArtifact createArtifact(ModuleBuilder... builders) {
+ LayoutElementTestUtil.LayoutElementCreator root = root();
+ String name = "";
+ for (ModuleBuilder builder : builders) {
+ root.element(builder.createPackagingElement(builder.get()));
+ name += "_" + builder.get().getName();
+ }
+ return builders[0].testCase.addArtifact(name.substring(1), root);
+ }
+
+ public String getName() {
+ return get().getName();
+ }
+
+ public ModuleBuilder name(@NotNull String name) {
+ this.name = name;
+ return this;
+ }
+
+ public JpsModule get() {
+ if (module == null) {
+ module = testCase.addModule(getOrCreateModuleName(), FileUtilRt.toSystemIndependentName(getSourceRoot().getPath()));
+ moduleCreated(module);
+ }
+ return module;
+ }
+
+ public JpsArtifact createArtifact() {
+ JpsArtifact artifact = testCase.addArtifact(generateName(false), root().element(createPackagingElement(get())));
+ if (mainArtifact == null) {
+ mainArtifact = artifact;
+ }
+ return artifact;
+ }
+
+ public ModuleBuilder artifact() {
+ createArtifact();
+ return this;
+ }
+
+ public JpsArtifact getArtifact() {
+ return mainArtifact;
+ }
+
+ protected JpsPackagingElement createPackagingElement(JpsModule module) {
+ throw new AbstractMethodError();
+ }
+
+ protected void moduleCreated(JpsModule module) {
+ }
+
+ public ModuleBuilder sourceRoot(String path) {
+ assert sourceRoot == null;
+ sourceRoot = new File(path);
+ sourceRootRelativeToProject = FileUtil.getRelativePath(testCase.getOrCreateProjectDir(), sourceRoot);
+ return this;
+ }
+
+ private File getSourceRoot() {
+ if (sourceRoot == null) {
+ sourceRootRelativeToProject = getOrCreateModuleName() + "-src";
+ sourceRoot = new File(testCase.getAbsolutePath(sourceRootRelativeToProject));
+ }
+ return sourceRoot;
+ }
+
+ private String getOrCreateModuleName() {
+ if (name == null) {
+ name = generateName(true);
+ }
+ return name;
+ }
+
+ private String generateName(boolean module) {
+ Pair<AtomicInteger, AtomicInteger> counter = testCaseToNameCounter.get(testCase);
+ if (counter == null) {
+ counter = Pair.create(new AtomicInteger(0), new AtomicInteger(0));
+ testCaseToNameCounter.put(testCase, counter);
+ Disposer.register(testCase.getTestRootDisposable(), new Disposable() {
+ @Override
+ public void dispose() {
+ testCaseToNameCounter.remove(testCase);
+ }
+ });
+ }
+ return (module ? "m" : "a") + (module ? counter.first : counter.second).getAndIncrement();
+ }
+
+ public ModuleBuilder copy(String file) throws IOException {
+ FileUtil.copy(fromSourceRoot == null ? new File(file) : new File(fromSourceRoot, file), new File(getSourceRoot(), file));
+ return this;
+ }
+
+ public ModuleBuilder file(String pathRelativeToModuleSourceRoot, String text) throws IOException {
+ doCreateFile(pathRelativeToModuleSourceRoot, text);
+ return this;
+ }
+
+ public String createFile(String pathRelativeToModuleSourceRoot, String text) throws IOException {
+ return FileUtil.toSystemIndependentName(doCreateFile(pathRelativeToModuleSourceRoot, text).getAbsolutePath());
+ }
+
+ private File doCreateFile(String pathRelativeToModuleSourceRoot, String text) throws IOException {
+ File file = new File(getSourceRoot(), pathRelativeToModuleSourceRoot);
+ FileUtil.writeToFile(file, text);
+ return file;
+ }
+
+ public void assertCompiled(String... modulePaths) {
+ String[] paths = new String[modulePaths.length];
+ for (int i = 0; i < modulePaths.length; i++) {
+ paths[i] = sourceRootRelativeToProject + '/' + modulePaths[i];
+ }
+ testCase.assertCompiled(builderName, paths);
+ }
+
+ public ModuleBuilder dependsOn(ModuleBuilder dependency) {
+ JpsModuleRootModificationUtil.addDependency(get(), dependency.get());
+ return this;
+ }
+
+ public ModuleBuilder dependsOnAndExports(ModuleBuilder dependency) {
+ JpsModuleRootModificationUtil.addDependency(get(), dependency.get(), JpsJavaDependencyScope.COMPILE, true);
+ return this;
+ }
+}
diff --git a/jps/model-api/src/com/intellij/openapi/fileTypes/ExactFileNameMatcher.java b/jps/model-api/src/com/intellij/openapi/fileTypes/ExactFileNameMatcher.java
new file mode 100644
index 000000000000..117ab4087f52
--- /dev/null
+++ b/jps/model-api/src/com/intellij/openapi/fileTypes/ExactFileNameMatcher.java
@@ -0,0 +1,74 @@
+/*
+ * 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.
+ */
+
+/*
+ * @author max
+ */
+package com.intellij.openapi.fileTypes;
+
+import com.intellij.openapi.util.Comparing;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+public class ExactFileNameMatcher implements FileNameMatcher {
+ private final String myFileName;
+ private final boolean myIgnoreCase;
+
+ public ExactFileNameMatcher(@NotNull @NonNls final String fileName) {
+ myFileName = fileName;
+ myIgnoreCase = false;
+ }
+
+ public ExactFileNameMatcher(@NotNull @NonNls final String fileName, final boolean ignoreCase) {
+ myFileName = fileName;
+ myIgnoreCase = ignoreCase;
+ }
+
+ public boolean accept(@NonNls @NotNull final String fileName) {
+ return Comparing.equal(fileName, myFileName, !myIgnoreCase);
+ }
+
+ @NonNls
+ @NotNull
+ public String getPresentableString() {
+ return myFileName;
+ }
+
+ public String getFileName() {
+ return myFileName;
+ }
+
+ public boolean isIgnoreCase() {
+ return myIgnoreCase;
+ }
+
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final ExactFileNameMatcher that = (ExactFileNameMatcher)o;
+
+ if (!myFileName.equals(that.myFileName)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return myFileName.hashCode();
+ }
+} \ No newline at end of file
diff --git a/jps/model-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java b/jps/model-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java
new file mode 100644
index 000000000000..fb1f1d8ab1b5
--- /dev/null
+++ b/jps/model-api/src/com/intellij/openapi/fileTypes/ExtensionFileNameMatcher.java
@@ -0,0 +1,63 @@
+/*
+ * 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.openapi.fileTypes;
+
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public class ExtensionFileNameMatcher implements FileNameMatcher {
+ private final String myExtension;
+ private final String myDotExtension;
+
+ public ExtensionFileNameMatcher(@NotNull @NonNls String extension) {
+ myExtension = extension.toLowerCase();
+ myDotExtension = "." + myExtension;
+ }
+
+ public boolean accept(@NotNull @NonNls String fileName) {
+ return fileName.regionMatches(true, fileName.length() - myDotExtension.length(), myDotExtension, 0, myDotExtension.length());
+ }
+
+ @NonNls
+ @NotNull
+ public String getPresentableString() {
+ return "*." + myExtension;
+ }
+
+ public String getExtension() {
+ return myExtension;
+ }
+
+
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final ExtensionFileNameMatcher that = (ExtensionFileNameMatcher)o;
+
+ if (!myExtension.equals(that.myExtension)) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return myExtension.hashCode();
+ }
+}
diff --git a/jps/model-api/src/com/intellij/openapi/fileTypes/FileNameMatcher.java b/jps/model-api/src/com/intellij/openapi/fileTypes/FileNameMatcher.java
new file mode 100644
index 000000000000..9b28a1622e10
--- /dev/null
+++ b/jps/model-api/src/com/intellij/openapi/fileTypes/FileNameMatcher.java
@@ -0,0 +1,30 @@
+/*
+ * 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.openapi.fileTypes;
+
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+/**
+ * @author max
+ */
+public interface FileNameMatcher {
+ boolean accept(@NonNls @NotNull String fileName);
+
+ @NonNls @NotNull
+ String getPresentableString();
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/fileTypes/FileNameMatcherFactory.java b/jps/model-api/src/org/jetbrains/jps/model/fileTypes/FileNameMatcherFactory.java
new file mode 100644
index 000000000000..2e7d8221f241
--- /dev/null
+++ b/jps/model-api/src/org/jetbrains/jps/model/fileTypes/FileNameMatcherFactory.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2000-2013 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 org.jetbrains.jps.model.fileTypes;
+
+import com.intellij.openapi.fileTypes.FileNameMatcher;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.service.JpsServiceManager;
+
+/**
+ * @author nik
+ */
+public abstract class FileNameMatcherFactory {
+ public static FileNameMatcherFactory getInstance() {
+ return JpsServiceManager.getInstance().getService(FileNameMatcherFactory.class);
+ }
+
+ @NotNull
+ public abstract FileNameMatcher createMatcher(@NotNull String pattern);
+}
diff --git a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerConfiguration.java b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerConfiguration.java
index 8aaf77b1687d..27f5e86053cd 100644
--- a/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerConfiguration.java
+++ b/jps/model-api/src/org/jetbrains/jps/model/java/compiler/JpsJavaCompilerConfiguration.java
@@ -20,6 +20,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsElement;
import org.jetbrains.jps.model.module.JpsModule;
+import java.io.File;
import java.util.Collection;
import java.util.List;
@@ -55,7 +56,7 @@ public interface JpsJavaCompilerConfiguration extends JpsElement {
void addResourcePattern(String pattern);
List<String> getResourcePatterns();
-
+ boolean isResourceFile(@NotNull File file, @NotNull File srcRoot);
@Nullable
String getByteCodeTargetLevel(String moduleName);
diff --git a/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory
new file mode 100644
index 000000000000..91405169453b
--- /dev/null
+++ b/jps/model-impl/src/META-INF/services/org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory
@@ -0,0 +1 @@
+org.jetbrains.jps.model.fileTypes.impl.FileNameMatcherFactoryImpl \ No newline at end of file
diff --git a/jps/model-impl/src/com/intellij/openapi/fileTypes/WildcardFileNameMatcher.java b/jps/model-impl/src/com/intellij/openapi/fileTypes/WildcardFileNameMatcher.java
new file mode 100644
index 000000000000..afbaaafbd292
--- /dev/null
+++ b/jps/model-impl/src/com/intellij/openapi/fileTypes/WildcardFileNameMatcher.java
@@ -0,0 +1,140 @@
+/*
+ * 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.openapi.fileTypes;
+
+import com.intellij.util.PatternUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.regex.Matcher;
+
+/**
+ * @author max
+ */
+public class WildcardFileNameMatcher implements FileNameMatcher {
+ private final String myPattern;
+ private final MaskMatcher myMatcher;
+
+ private interface MaskMatcher {
+ boolean matches(String filename);
+ }
+
+ private static final class RegexpMatcher implements MaskMatcher {
+ private final Matcher myMatcher;
+
+ private RegexpMatcher(String pattern) {
+ myMatcher = PatternUtil.fromMask(pattern).matcher("");
+ }
+
+ public boolean matches(final String filename) {
+ synchronized (myMatcher) {
+ myMatcher.reset(filename);
+ return myMatcher.matches();
+ }
+ }
+ }
+
+ private static final class SuffixMatcher implements MaskMatcher {
+ private final String mySuffix;
+
+ private SuffixMatcher(final String suffix) {
+ mySuffix = suffix;
+ }
+
+ public boolean matches(final String filename) {
+ return filename.endsWith(mySuffix);
+ }
+ }
+
+ private static final class PrefixMatcher implements MaskMatcher {
+ private final String myPrefix;
+
+ private PrefixMatcher(final String prefix) {
+ myPrefix = prefix;
+ }
+
+ public boolean matches(final String filename) {
+ return filename.startsWith(myPrefix);
+ }
+ }
+
+ private static final class InfixMatcher implements MaskMatcher {
+ private final String myInfix;
+
+ private InfixMatcher(final String infix) {
+ myInfix = infix;
+ }
+
+ public boolean matches(final String filename) {
+ return filename.contains(myInfix);
+ }
+ }
+
+ /**
+ * Use {@link org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory#createMatcher(String)} instead of direct call to constructor
+ */
+ public WildcardFileNameMatcher(@NotNull @NonNls String pattern) {
+ myPattern = pattern;
+ myMatcher = createMatcher(pattern);
+ }
+
+ private static MaskMatcher createMatcher(final String pattern) {
+ int len = pattern.length();
+ if (len > 1 && pattern.indexOf('?') < 0) {
+ if (pattern.charAt(0) == '*' && pattern.indexOf('*', 1) < 0) {
+ return new SuffixMatcher(pattern.substring(1));
+ }
+ if (pattern.indexOf('*') == len - 1) {
+ return new PrefixMatcher(pattern.substring(0, len - 1));
+ }
+ if (len > 2 && pattern.charAt(0) == '*' && pattern.indexOf('*', 1) == len - 1) {
+ return new InfixMatcher(pattern.substring(1, len - 1));
+ }
+ }
+ return new RegexpMatcher(pattern);
+ }
+
+ public boolean accept(@NotNull String fileName) {
+ return myMatcher.matches(fileName);
+ }
+
+ @NonNls
+ @NotNull
+ public String getPresentableString() {
+ return myPattern;
+ }
+
+
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final WildcardFileNameMatcher that = (WildcardFileNameMatcher)o;
+
+ if (!myPattern.equals(that.myPattern)) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ return myPattern.hashCode();
+ }
+
+ public String getPattern() {
+ return myPattern;
+ }
+}
diff --git a/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java
new file mode 100644
index 000000000000..8f6e14b55471
--- /dev/null
+++ b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/FileTypeAssocTable.java
@@ -0,0 +1,287 @@
+/*
+ * 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.openapi.fileTypes.impl;
+
+import com.intellij.openapi.fileTypes.ExactFileNameMatcher;
+import com.intellij.openapi.fileTypes.ExtensionFileNameMatcher;
+import com.intellij.openapi.fileTypes.FileNameMatcher;
+import com.intellij.openapi.util.Pair;
+import com.intellij.openapi.util.io.FileUtilRt;
+import com.intellij.util.ArrayUtil;
+import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
+import gnu.trove.THashMap;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.*;
+
+/**
+ * @author max
+ */
+public class FileTypeAssocTable<T> {
+ private final Map<String, T> myExtensionMappings;
+ private final Map<String, T> myExactFileNameMappings;
+ private final Map<String, T> myExactFileNameAnyCaseMappings;
+ private boolean myHasAnyCaseExactMappings;
+ private final List<Pair<FileNameMatcher, T>> myMatchingMappings;
+
+ private FileTypeAssocTable(Map<String, T> extensionMappings, Map<String, T> exactFileNameMappings, Map<String, T> exactFileNameAnyCaseMappings, List<Pair<FileNameMatcher, T>> matchingMappings) {
+ myExtensionMappings = new THashMap<String, T>(extensionMappings);
+ myExactFileNameMappings = new THashMap<String, T>(exactFileNameMappings);
+ myExactFileNameAnyCaseMappings = new THashMap<String, T>(exactFileNameAnyCaseMappings, CaseInsensitiveStringHashingStrategy.INSTANCE) {
+ @Override
+ public T remove(Object key) {
+ T removed = super.remove(key);
+ myHasAnyCaseExactMappings = size() > 0;
+ return removed;
+ }
+
+ @Override
+ public T put(String key, T value) {
+ T result = super.put(key, value);
+ myHasAnyCaseExactMappings = true;
+ return result;
+ }
+ };
+ myMatchingMappings = new ArrayList<Pair<FileNameMatcher, T>>(matchingMappings);
+ }
+
+ public FileTypeAssocTable() {
+ this(Collections.<String, T>emptyMap(), Collections.<String, T>emptyMap(), Collections.<String, T>emptyMap(), Collections.<Pair<FileNameMatcher, T>>emptyList());
+ }
+
+ public boolean isAssociatedWith(T type, FileNameMatcher matcher) {
+ if (matcher instanceof ExtensionFileNameMatcher || matcher instanceof ExactFileNameMatcher) {
+ return findAssociatedFileType(matcher) == type;
+ }
+
+ for (Pair<FileNameMatcher, T> mapping : myMatchingMappings) {
+ if (matcher.equals(mapping.getFirst()) && type == mapping.getSecond()) return true;
+ }
+
+ return false;
+ }
+
+ public void addAssociation(FileNameMatcher matcher, T type) {
+ if (matcher instanceof ExtensionFileNameMatcher) {
+ myExtensionMappings.put(((ExtensionFileNameMatcher)matcher).getExtension(), type);
+ }
+ else if (matcher instanceof ExactFileNameMatcher) {
+ final ExactFileNameMatcher exactFileNameMatcher = (ExactFileNameMatcher)matcher;
+
+ if (exactFileNameMatcher.isIgnoreCase()) {
+ myExactFileNameAnyCaseMappings.put(exactFileNameMatcher.getFileName(), type);
+ } else {
+ myExactFileNameMappings.put(exactFileNameMatcher.getFileName(), type);
+ }
+ } else {
+ myMatchingMappings.add(new Pair<FileNameMatcher, T>(matcher, type));
+ }
+ }
+
+ public boolean removeAssociation(FileNameMatcher matcher, T type) {
+ if (matcher instanceof ExtensionFileNameMatcher) {
+ String extension = ((ExtensionFileNameMatcher)matcher).getExtension();
+ if (myExtensionMappings.get(extension) == type) {
+ myExtensionMappings.remove(extension);
+ return true;
+ }
+ return false;
+ }
+
+ if (matcher instanceof ExactFileNameMatcher) {
+ final ExactFileNameMatcher exactFileNameMatcher = (ExactFileNameMatcher)matcher;
+ final Map<String, T> mapToUse;
+ String fileName = exactFileNameMatcher.getFileName();
+
+ if (exactFileNameMatcher.isIgnoreCase()) {
+ mapToUse = myExactFileNameAnyCaseMappings;
+ } else {
+ mapToUse = myExactFileNameMappings;
+ }
+ if(mapToUse.get(fileName) == type) {
+ mapToUse.remove(fileName);
+ return true;
+ }
+ return false;
+ }
+
+ List<Pair<FileNameMatcher, T>> copy = new ArrayList<Pair<FileNameMatcher, T>>(myMatchingMappings);
+ for (Pair<FileNameMatcher, T> assoc : copy) {
+ if (matcher.equals(assoc.getFirst())) {
+ myMatchingMappings.remove(assoc);
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ public boolean removeAllAssociations(T type) {
+ boolean changed = removeAssociationsFromMap(myExtensionMappings, type, false);
+
+ changed = removeAssociationsFromMap(myExactFileNameAnyCaseMappings, type, changed);
+ changed = removeAssociationsFromMap(myExactFileNameMappings, type, changed);
+
+ List<Pair<FileNameMatcher, T>> copy = new ArrayList<Pair<FileNameMatcher, T>>(myMatchingMappings);
+ for (Pair<FileNameMatcher, T> assoc : copy) {
+ if (assoc.getSecond() == type) {
+ myMatchingMappings.remove(assoc);
+ changed = true;
+ }
+ }
+
+ return changed;
+ }
+
+ private boolean removeAssociationsFromMap(Map<String, T> extensionMappings, T type, boolean changed) {
+ Set<String> exts = extensionMappings.keySet();
+ String[] extsStrings = ArrayUtil.toStringArray(exts);
+ for (String s : extsStrings) {
+ if (extensionMappings.get(s) == type) {
+ extensionMappings.remove(s);
+ changed = true;
+ }
+ }
+ return changed;
+ }
+
+ @Nullable
+ public T findAssociatedFileType(@NotNull @NonNls String fileName) {
+ T t = myExactFileNameMappings.get(fileName);
+ if (t != null) return t;
+
+ if (myHasAnyCaseExactMappings) { // even hash lookup with case insensitive hasher is costly for isIgnored checks during compile
+ t = myExactFileNameAnyCaseMappings.get(fileName);
+ if (t != null) return t;
+ }
+
+ //noinspection ForLoopReplaceableByForEach
+ for (int i = 0, n = myMatchingMappings.size(); i < n; i++) {
+ final Pair<FileNameMatcher, T> mapping = myMatchingMappings.get(i);
+ if (mapping.getFirst().accept(fileName)) return mapping.getSecond();
+ }
+
+ return myExtensionMappings.get(FileUtilRt.getExtension(fileName).toLowerCase());
+ }
+
+ @Nullable
+ public T findAssociatedFileType(final FileNameMatcher matcher) {
+ if (matcher instanceof ExtensionFileNameMatcher) {
+ return myExtensionMappings.get(((ExtensionFileNameMatcher)matcher).getExtension());
+ }
+
+ if (matcher instanceof ExactFileNameMatcher) {
+ final ExactFileNameMatcher exactFileNameMatcher = (ExactFileNameMatcher)matcher;
+
+ if (exactFileNameMatcher.isIgnoreCase()) {
+ return myExactFileNameAnyCaseMappings.get(exactFileNameMatcher.getFileName());
+ } else {
+ return myExactFileNameMappings.get(exactFileNameMatcher.getFileName());
+ }
+ }
+
+ for (Pair<FileNameMatcher, T> mapping : myMatchingMappings) {
+ if (matcher.equals(mapping.getFirst())) return mapping.getSecond();
+ }
+
+ return null;
+ }
+
+ @Deprecated
+ @NotNull
+ public String[] getAssociatedExtensions(T type) {
+ Map<String, T> extMap = myExtensionMappings;
+
+ List<String> exts = new ArrayList<String>();
+ for (String ext : extMap.keySet()) {
+ if (extMap.get(ext) == type) {
+ exts.add(ext);
+ }
+ }
+ return ArrayUtil.toStringArray(exts);
+ }
+
+ @NotNull
+ public FileTypeAssocTable<T> copy() {
+ return new FileTypeAssocTable<T>(myExtensionMappings, myExactFileNameMappings, myExactFileNameAnyCaseMappings, myMatchingMappings);
+ }
+
+ @NotNull
+ public List<FileNameMatcher> getAssociations(final T type) {
+ List<FileNameMatcher> result = new ArrayList<FileNameMatcher>();
+ for (Pair<FileNameMatcher, T> mapping : myMatchingMappings) {
+ if (mapping.getSecond() == type) {
+ result.add(mapping.getFirst());
+ }
+ }
+
+ for (Map.Entry<String, T> entries : myExactFileNameMappings.entrySet()) {
+ if (entries.getValue() == type) {
+ result.add(new ExactFileNameMatcher(entries.getKey()));
+ }
+ }
+
+ for (Map.Entry<String, T> entries : myExactFileNameAnyCaseMappings.entrySet()) {
+ if (entries.getValue() == type) {
+ result.add(new ExactFileNameMatcher(entries.getKey(), true));
+ }
+ }
+
+ for (Map.Entry<String, T> entries : myExtensionMappings.entrySet()) {
+ if (entries.getValue() == type) {
+ result.add(new ExtensionFileNameMatcher(entries.getKey()));
+ }
+ }
+
+ return result;
+ }
+
+ public boolean hasAssociationsFor(final T fileType) {
+ if (myExtensionMappings.values().contains(fileType)) return true;
+ if (myExactFileNameMappings.values().contains(fileType)) return true;
+ if (myExactFileNameAnyCaseMappings.values().contains(fileType)) return true;
+ for (Pair<FileNameMatcher, T> mapping : myMatchingMappings) {
+ if (mapping.getSecond() == fileType) return true;
+ }
+ return false;
+ }
+
+ public boolean equals(final Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+
+ final FileTypeAssocTable that = (FileTypeAssocTable)o;
+
+ if (!myExtensionMappings.equals(that.myExtensionMappings)) return false;
+ if (!myMatchingMappings.equals(that.myMatchingMappings)) return false;
+ if (!myExactFileNameMappings.equals(that.myExactFileNameMappings)) return false;
+ if (!myExactFileNameAnyCaseMappings.equals(that.myExactFileNameAnyCaseMappings)) return false;
+
+ return true;
+ }
+
+ public int hashCode() {
+ int result;
+ result = myExtensionMappings.hashCode();
+ result = 31 * result + myMatchingMappings.hashCode();
+ result = 31 * result + myExactFileNameMappings.hashCode();
+ result = 31 * result + myExactFileNameAnyCaseMappings.hashCode();
+ return result;
+ }
+}
diff --git a/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredPatternSet.java b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredPatternSet.java
new file mode 100644
index 000000000000..8fd023eba207
--- /dev/null
+++ b/jps/model-impl/src/com/intellij/openapi/fileTypes/impl/IgnoredPatternSet.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2000-2011 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.openapi.fileTypes.impl;
+
+import com.intellij.openapi.util.io.FileUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory;
+
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+/**
+ * @author peter
+ */
+public class IgnoredPatternSet {
+ private final Set<String> myMasks = new LinkedHashSet<String>();
+ private final FileTypeAssocTable<Boolean> myIgnorePatterns = new FileTypeAssocTable<Boolean>().copy();
+
+ Set<String> getIgnoreMasks() {
+ return Collections.unmodifiableSet(myMasks);
+ }
+
+ public void setIgnoreMasks(@NotNull String list) {
+ clearPatterns();
+
+ StringTokenizer tokenizer = new StringTokenizer(list, ";");
+ while (tokenizer.hasMoreTokens()) {
+ String ignoredFile = tokenizer.nextToken();
+ if (ignoredFile != null) {
+ addIgnoreMask(ignoredFile);
+ }
+ }
+
+ }
+
+ void addIgnoreMask(@NotNull String ignoredFile) {
+ if (myIgnorePatterns.findAssociatedFileType(ignoredFile) == null) {
+ myMasks.add(ignoredFile);
+ myIgnorePatterns.addAssociation(FileNameMatcherFactory.getInstance().createMatcher(ignoredFile), Boolean.TRUE);
+ }
+ }
+
+ public boolean isIgnored(@NotNull String fileName) {
+ if (myIgnorePatterns.findAssociatedFileType(fileName) == Boolean.TRUE) {
+ return true;
+ }
+
+ //Quite a hack, but still we need to have some name, which
+ //won't be catched by VFS for sure.
+ return fileName.endsWith(FileUtil.ASYNC_DELETE_EXTENSION);
+ }
+
+ void clearPatterns() {
+ myMasks.clear();
+ myIgnorePatterns.removeAllAssociations(Boolean.TRUE);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/fileTypes/impl/FileNameMatcherFactoryImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/fileTypes/impl/FileNameMatcherFactoryImpl.java
new file mode 100644
index 000000000000..d3c1afcae509
--- /dev/null
+++ b/jps/model-impl/src/org/jetbrains/jps/model/fileTypes/impl/FileNameMatcherFactoryImpl.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2000-2013 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 org.jetbrains.jps.model.fileTypes.impl;
+
+import com.intellij.openapi.fileTypes.ExactFileNameMatcher;
+import com.intellij.openapi.fileTypes.ExtensionFileNameMatcher;
+import com.intellij.openapi.fileTypes.FileNameMatcher;
+import com.intellij.openapi.fileTypes.WildcardFileNameMatcher;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.jps.model.fileTypes.FileNameMatcherFactory;
+
+/**
+ * @author nik
+ */
+public class FileNameMatcherFactoryImpl extends FileNameMatcherFactory {
+ @NotNull
+ public FileNameMatcher createMatcher(@NotNull String pattern) {
+ if (pattern.startsWith("*.") &&
+ pattern.indexOf('*', 2) < 0 &&
+ pattern.indexOf('.', 2) < 0 &&
+ pattern.indexOf('?', 2) < 0) {
+ return new ExtensionFileNameMatcher(pattern.substring(2).toLowerCase());
+ }
+
+ if (pattern.contains("*") || pattern.contains("?")) {
+ return new WildcardFileNameMatcher(pattern);
+ }
+
+ return new ExactFileNameMatcher(pattern);
+ }
+}
diff --git a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsJavaCompilerConfigurationImpl.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsJavaCompilerConfigurationImpl.java
index 12d01689ea0a..dfebfa2ce83c 100644
--- a/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsJavaCompilerConfigurationImpl.java
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/JpsJavaCompilerConfigurationImpl.java
@@ -26,6 +26,7 @@ import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerOptions;
import org.jetbrains.jps.model.java.compiler.ProcessorConfigProfile;
import org.jetbrains.jps.model.module.JpsModule;
+import java.io.File;
import java.util.*;
/**
@@ -44,6 +45,7 @@ public class JpsJavaCompilerConfigurationImpl extends JpsCompositeElementBase<Jp
private Map<String, JpsJavaCompilerOptions> myCompilerOptions = new HashMap<String, JpsJavaCompilerOptions>();
private String myJavaCompilerId = "Javac";
private Map<JpsModule, ProcessorConfigProfile> myAnnotationProcessingProfileMap;
+ private ResourcePatterns myCompiledPatterns;
public JpsJavaCompilerConfigurationImpl() {
}
@@ -107,6 +109,15 @@ public class JpsJavaCompilerConfigurationImpl extends JpsCompositeElementBase<Jp
}
@Override
+ public boolean isResourceFile(@NotNull File file, @NotNull File srcRoot) {
+ ResourcePatterns patterns = myCompiledPatterns;
+ if (patterns == null) {
+ myCompiledPatterns = patterns = new ResourcePatterns(this);
+ }
+ return patterns.isResourceFile(file, srcRoot);
+ }
+
+ @Override
@Nullable
public String getByteCodeTargetLevel(String moduleName) {
String level = myModulesByteCodeTargetLevels.get(moduleName);
diff --git a/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcePatterns.java b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ResourcePatterns.java
index 100568f95d90..ed62fa4e6561 100644
--- a/jps/jps-builders/src/org/jetbrains/jps/incremental/ResourcePatterns.java
+++ b/jps/model-impl/src/org/jetbrains/jps/model/java/impl/compiler/ResourcePatterns.java
@@ -13,18 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.jetbrains.jps.incremental;
+package org.jetbrains.jps.model.java.impl.compiler;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
-import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
-import org.jetbrains.jps.model.JpsProject;
-import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
import java.io.File;
@@ -37,18 +34,15 @@ import java.util.regex.Pattern;
* Date: 10/6/11
*/
public class ResourcePatterns {
- public static final Key<ResourcePatterns> KEY = Key.create("_resource_patterns_");
+ private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.model.java.impl.compiler.ResourcePatterns");
- private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.ResourcePatterns");
+ private final List<CompiledPattern> myCompiledPatterns = new ArrayList<CompiledPattern>();
+ private final List<CompiledPattern> myNegatedCompiledPatterns = new ArrayList<CompiledPattern>();
- private final List<Pair<Pattern, Pattern>> myCompiledPatterns = new ArrayList<Pair<Pattern, Pattern>>();
- private final List<Pair<Pattern, Pattern>> myNegatedCompiledPatterns = new ArrayList<Pair<Pattern, Pattern>>();
-
- public ResourcePatterns(JpsProject project) {
- JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
+ public ResourcePatterns(final JpsJavaCompilerConfiguration configuration) {
final List<String> patterns = configuration.getResourcePatterns();
for (String pattern : patterns) {
- final Pair<Pattern, Pattern> regexp = convertToRegexp(pattern);
+ final CompiledPattern regexp = convertToRegexp(pattern);
if (isPatternNegated(pattern)) {
myNegatedCompiledPatterns.add(regexp);
}
@@ -63,14 +57,13 @@ public class ResourcePatterns {
final String relativePathToParent;
final String parentPath = file.getParent();
if (parentPath != null) {
- relativePathToParent = "/" + FileUtil.getRelativePath(FileUtil.toSystemIndependentName(srcRoot.getAbsolutePath()),
- FileUtil.toSystemIndependentName(parentPath), '/', SystemInfo.isFileSystemCaseSensitive);
+ relativePathToParent = "/" + FileUtilRt.getRelativePath(FileUtilRt.toSystemIndependentName(srcRoot.getAbsolutePath()), FileUtilRt.toSystemIndependentName(parentPath), '/', SystemInfo.isFileSystemCaseSensitive);
}
else {
relativePathToParent = null;
}
- for (Pair<Pattern, Pattern> pair : myCompiledPatterns) {
- if (matches(name, relativePathToParent, pair)) {
+ for (CompiledPattern pair : myCompiledPatterns) {
+ if (matches(name, relativePathToParent, srcRoot, pair)) {
return true;
}
}
@@ -81,25 +74,29 @@ public class ResourcePatterns {
//noinspection ForLoopReplaceableByForEach
for (int i = 0; i < myNegatedCompiledPatterns.size(); i++) {
- if (matches(name, relativePathToParent, myNegatedCompiledPatterns.get(i))) {
+ if (matches(name, relativePathToParent, srcRoot, myNegatedCompiledPatterns.get(i))) {
return false;
}
}
return true;
}
- private boolean matches(String name, String parentRelativePath, Pair<Pattern, Pattern> nameDirPatternPair) {
- if (!matches(name, nameDirPatternPair.getFirst())) {
+ private static boolean matches(String name, String parentRelativePath, @NotNull File srcRoot, CompiledPattern pattern) {
+ if (!matches(name, pattern.fileName)) {
return false;
}
- final Pattern dirPattern = nameDirPatternPair.getSecond();
- if (dirPattern == null || parentRelativePath == null) {
- return true;
+ if (parentRelativePath != null) {
+ if (pattern.dir != null && !matches(parentRelativePath, pattern.dir)) {
+ return false;
+ }
+ if (pattern.srcRoot != null && !matches(srcRoot.getName(), pattern.srcRoot)) {
+ return false;
+ }
}
- return matches(parentRelativePath, dirPattern);
+ return true;
}
- private boolean matches(String s, Pattern p) {
+ private static boolean matches(String s, Pattern p) {
try {
return p.matcher(s).matches();
}
@@ -109,13 +106,20 @@ public class ResourcePatterns {
}
}
- private static Pair<Pattern, Pattern> convertToRegexp(String wildcardPattern) {
+ private static CompiledPattern convertToRegexp(String wildcardPattern) {
if (isPatternNegated(wildcardPattern)) {
wildcardPattern = wildcardPattern.substring(1);
}
- wildcardPattern = FileUtil.toSystemIndependentName(wildcardPattern);
+ wildcardPattern = FileUtilRt.toSystemIndependentName(wildcardPattern);
+ String srcRoot = null;
+ int colon = wildcardPattern.indexOf(":");
+ if (colon > 0) {
+ srcRoot = wildcardPattern.substring(0, colon);
+ wildcardPattern = wildcardPattern.substring(colon + 1);
+ }
+
String dirPattern = null;
int slash = wildcardPattern.lastIndexOf('/');
if (slash >= 0) {
@@ -138,7 +142,8 @@ public class ResourcePatterns {
wildcardPattern = optimize(wildcardPattern);
final Pattern dirCompiled = dirPattern == null ? null : compilePattern(dirPattern);
- return Pair.create(compilePattern(wildcardPattern), dirCompiled);
+ final Pattern srcCompiled = srcRoot == null ? null : compilePattern(optimize(normalizeWildcards(srcRoot)));
+ return new CompiledPattern(compilePattern(wildcardPattern), dirCompiled, srcCompiled);
}
private static String optimize(String wildcardPattern) {
@@ -162,4 +167,17 @@ public class ResourcePatterns {
private static Pattern compilePattern(@NonNls String s) {
return Pattern.compile(s, SystemInfo.isFileSystemCaseSensitive ? 0 : Pattern.CASE_INSENSITIVE);
}
+
+ private static class CompiledPattern {
+ @NotNull final Pattern fileName;
+ @Nullable final Pattern dir;
+ @Nullable final Pattern srcRoot;
+
+ CompiledPattern(@NotNull Pattern fileName, @Nullable Pattern dir, @Nullable Pattern srcRoot) {
+ this.fileName = fileName;
+ this.dir = dir;
+ this.srcRoot = srcRoot;
+ }
+ }
+
}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalLoader.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalLoader.java
index 2f2057082c4c..ef510e534a1e 100644
--- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalLoader.java
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsGlobalLoader.java
@@ -40,6 +40,7 @@ public class JpsGlobalLoader extends JpsLoaderBase {
private static final JpsGlobalExtensionSerializer[] SERIALIZERS = {
new GlobalLibrariesSerializer(), new SdkTableSerializer(), new FileTypesSerializer()
};
+ public static final String FILE_TYPES_COMPONENT_NAME_KEY = "jps.file.types.component.name";
private final JpsGlobal myGlobal;
public JpsGlobalLoader(JpsGlobal global, Map<String, String> pathVariables) {
@@ -108,7 +109,7 @@ public class JpsGlobalLoader extends JpsLoaderBase {
private static class FileTypesSerializer extends JpsGlobalExtensionSerializer {
private FileTypesSerializer() {
- super("filetypes.xml", "FileTypeManager");
+ super("filetypes.xml", System.getProperty(FILE_TYPES_COMPONENT_NAME_KEY, "FileTypeManager"));
}
@Override
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java
index bda75b69ac7a..a19e607f9161 100644
--- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/JpsLoaderBase.java
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.JDOMUtil;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.io.FileUtilRt;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jetbrains.jps.model.JpsElement;
@@ -78,6 +79,6 @@ public abstract class JpsLoaderBase {
}
protected static boolean isXmlFile(File file) {
- return file.isFile() && FileUtil.getExtension(file.getName()).equalsIgnoreCase("xml");
+ return file.isFile() && FileUtilRt.extensionEquals(file.getName(), "xml");
}
}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java
index 90bfa354af09..a7a8a7cc6ed7 100644
--- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/JpsJavaModelSerializerExtension.java
@@ -82,7 +82,13 @@ public class JpsJavaModelSerializerExtension extends JpsModelSerializerExtension
public void loadModuleDependencyProperties(JpsDependencyElement dependency, Element entry) {
boolean exported = entry.getAttributeValue(EXPORTED_ATTRIBUTE) != null;
String scopeName = entry.getAttributeValue(SCOPE_ATTRIBUTE);
- JpsJavaDependencyScope scope = scopeName != null ? JpsJavaDependencyScope.valueOf(scopeName) : JpsJavaDependencyScope.COMPILE;
+ JpsJavaDependencyScope scope = null;
+ try {
+ scope = scopeName != null ? JpsJavaDependencyScope.valueOf(scopeName) : JpsJavaDependencyScope.COMPILE;
+ }
+ catch (IllegalArgumentException e) {
+ scope = JpsJavaDependencyScope.COMPILE;
+ }
final JpsJavaDependencyExtension extension = getService().getOrCreateDependencyExtension(dependency);
extension.setExported(exported);
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerConfigurationSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerConfigurationSerializer.java
index b5cefb3b8b06..d1f6d058ad2d 100644
--- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerConfigurationSerializer.java
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/java/compiler/JpsJavaCompilerConfigurationSerializer.java
@@ -22,6 +22,7 @@ import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jps.model.JpsProject;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
+import org.jetbrains.jps.model.java.compiler.JpsCompilerExcludes;
import org.jetbrains.jps.model.java.compiler.JpsJavaCompilerConfiguration;
import org.jetbrains.jps.model.serialization.JpsProjectExtensionSerializer;
@@ -55,16 +56,7 @@ public class JpsJavaCompilerConfigurationSerializer extends JpsProjectExtensionS
configuration.setAddNotNullAssertions(Boolean.parseBoolean(addNotNullTag.getAttributeValue(ENABLED, "true")));
}
- Element excludeFromCompileTag = componentTag.getChild(EXCLUDE_FROM_COMPILE);
- if (excludeFromCompileTag != null) {
- for (Element fileTag : JDOMUtil.getChildren(excludeFromCompileTag, "file")) {
- configuration.getCompilerExcludes().addExcludedFile(fileTag.getAttributeValue("url"));
- }
- for (Element directoryTag : JDOMUtil.getChildren(excludeFromCompileTag, "directory")) {
- boolean recursively = Boolean.parseBoolean(directoryTag.getAttributeValue("includeSubdirectories"));
- configuration.getCompilerExcludes().addExcludedDirectory(directoryTag.getAttributeValue("url"), recursively);
- }
- }
+ readExcludes(componentTag.getChild(EXCLUDE_FROM_COMPILE), configuration.getCompilerExcludes());
Element resourcePatternsTag = componentTag.getChild(WILDCARD_RESOURCE_PATTERNS);
for (Element entry : JDOMUtil.getChildren(resourcePatternsTag, ENTRY)) {
@@ -105,6 +97,18 @@ public class JpsJavaCompilerConfigurationSerializer extends JpsProjectExtensionS
}
}
+ public static void readExcludes(Element excludeFromCompileTag, JpsCompilerExcludes excludes) {
+ if (excludeFromCompileTag != null) {
+ for (Element fileTag : JDOMUtil.getChildren(excludeFromCompileTag, "file")) {
+ excludes.addExcludedFile(fileTag.getAttributeValue("url"));
+ }
+ for (Element directoryTag : JDOMUtil.getChildren(excludeFromCompileTag, "directory")) {
+ boolean recursively = Boolean.parseBoolean(directoryTag.getAttributeValue("includeSubdirectories"));
+ excludes.addExcludedDirectory(directoryTag.getAttributeValue("url"), recursively);
+ }
+ }
+ }
+
@Override
public void saveExtension(@NotNull JpsProject project, @NotNull Element componentTag) {
}
diff --git a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
index 2f281130f0ff..183ad94d0b8f 100644
--- a/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
+++ b/jps/model-serialization/src/org/jetbrains/jps/model/serialization/module/JpsModuleRootModelSerializer.java
@@ -17,6 +17,7 @@ package org.jetbrains.jps.model.serialization.module;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.util.text.UniqueNameGenerator;
import org.jdom.Element;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jps.model.JpsCompositeElement;
@@ -29,16 +30,14 @@ import org.jetbrains.jps.model.java.JpsJavaSdkType;
import org.jetbrains.jps.model.java.JpsJavaSdkTypeWrapper;
import org.jetbrains.jps.model.library.JpsLibrary;
import org.jetbrains.jps.model.library.JpsLibraryReference;
-import org.jetbrains.jps.model.library.sdk.JpsSdkType;
import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
+import org.jetbrains.jps.model.library.sdk.JpsSdkType;
import org.jetbrains.jps.model.module.*;
import org.jetbrains.jps.model.serialization.JpsModelSerializerExtension;
import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
import org.jetbrains.jps.model.serialization.library.JpsSdkTableSerializer;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
+import java.util.*;
import static com.intellij.openapi.util.JDOMUtil.getChildren;
@@ -89,7 +88,7 @@ public class JpsModuleRootModelSerializer {
final JpsDependenciesList dependenciesList = module.getDependenciesList();
dependenciesList.clear();
final JpsElementFactory elementFactory = JpsElementFactory.getInstance();
- int moduleLibraryNum = 0;
+ UniqueNameGenerator nameGenerator = new UniqueNameGenerator();
for (Element orderEntry : getChildren(rootModelComponent, ORDER_ENTRY_TAG)) {
String type = orderEntry.getAttributeValue(TYPE_ATTRIBUTE);
if (SOURCE_FOLDER_TYPE.equals(type)) {
@@ -120,14 +119,14 @@ public class JpsModuleRootModelSerializer {
final Element moduleLibraryElement = orderEntry.getChild(LIBRARY_TAG);
String name = moduleLibraryElement.getAttributeValue(NAME_ATTRIBUTE);
if (name == null) {
- name = GENERATED_LIBRARY_NAME_PREFIX + (moduleLibraryNum++);
+ name = GENERATED_LIBRARY_NAME_PREFIX;
}
- final JpsLibrary library = JpsLibraryTableSerializer.loadLibrary(moduleLibraryElement, name);
+ String uniqueName = nameGenerator.generateUniqueName(name);
+ final JpsLibrary library = JpsLibraryTableSerializer.loadLibrary(moduleLibraryElement, uniqueName);
module.addModuleLibrary(library);
final JpsLibraryDependency dependency = dependenciesList.addLibraryDependency(library);
loadModuleDependencyProperties(dependency, orderEntry);
- moduleLibraryNum++;
}
else if (MODULE_TYPE.equals(type)) {
String name = orderEntry.getAttributeValue(MODULE_NAME_ATTRIBUTE);
diff --git a/jps/model-serialization/testData/duplicatedModuleLibrary/duplicatedModuleLibrary.iml b/jps/model-serialization/testData/duplicatedModuleLibrary/duplicatedModuleLibrary.iml
new file mode 100644
index 000000000000..fcefc008fcc5
--- /dev/null
+++ b/jps/model-serialization/testData/duplicatedModuleLibrary/duplicatedModuleLibrary.iml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$" />
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module-library">
+ <library name="xxx">
+ <CLASSES>
+ <root url="file://$MODULE_DIR$/data/lib1" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="module-library">
+ <library name="xxx">
+ <CLASSES>
+ <root url="file://$MODULE_DIR$/data/lib2" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testData/duplicatedModuleLibrary/duplicatedModuleLibrary.ipr b/jps/model-serialization/testData/duplicatedModuleLibrary/duplicatedModuleLibrary.ipr
new file mode 100644
index 000000000000..356fca8c2362
--- /dev/null
+++ b/jps/model-serialization/testData/duplicatedModuleLibrary/duplicatedModuleLibrary.ipr
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/duplicatedModuleLibrary.iml" filepath="$PROJECT_DIR$/duplicatedModuleLibrary.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.4" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testData/invalidDependencyScope/invalidDependencyScope.iml b/jps/model-serialization/testData/invalidDependencyScope/invalidDependencyScope.iml
new file mode 100644
index 000000000000..dd81f9b72227
--- /dev/null
+++ b/jps/model-serialization/testData/invalidDependencyScope/invalidDependencyScope.iml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module-library" scope="test">
+ <library>
+ <CLASSES>
+ <root url="file://$MODULE_DIR$/lib/data" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ </component>
+</module>
+
diff --git a/jps/model-serialization/testData/invalidDependencyScope/invalidDependencyScope.ipr b/jps/model-serialization/testData/invalidDependencyScope/invalidDependencyScope.ipr
new file mode 100644
index 000000000000..b28c35795b23
--- /dev/null
+++ b/jps/model-serialization/testData/invalidDependencyScope/invalidDependencyScope.ipr
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+ <component name="ProjectModuleManager">
+ <modules>
+ <module fileurl="file://$PROJECT_DIR$/invalidDependencyScope.iml" filepath="$PROJECT_DIR$/invalidDependencyScope.iml" />
+ </modules>
+ </component>
+ <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.4" project-jdk-type="JavaSDK">
+ <output url="file://$PROJECT_DIR$/out" />
+ </component>
+</project>
+
diff --git a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java
index 32719f02ef6d..3ed4336709c4 100644
--- a/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java
+++ b/jps/model-serialization/testSrc/org/jetbrains/jps/model/serialization/JpsProjectSerializationTest.java
@@ -23,9 +23,12 @@ import org.jetbrains.jps.model.JpsDummyElement;
import org.jetbrains.jps.model.JpsEncodingConfigurationService;
import org.jetbrains.jps.model.JpsEncodingProjectConfiguration;
import org.jetbrains.jps.model.artifact.JpsArtifactService;
+import org.jetbrains.jps.model.java.JpsJavaDependencyExtension;
+import org.jetbrains.jps.model.java.JpsJavaDependencyScope;
import org.jetbrains.jps.model.java.JpsJavaExtensionService;
import org.jetbrains.jps.model.java.JpsJavaSdkType;
import org.jetbrains.jps.model.library.JpsLibrary;
+import org.jetbrains.jps.model.library.JpsOrderRootType;
import org.jetbrains.jps.model.library.sdk.JpsSdkReference;
import org.jetbrains.jps.model.module.*;
import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
@@ -108,6 +111,30 @@ public class JpsProjectSerializationTest extends JpsSerializationTestCase {
assertEquals("1.6", reference.getSdkName());
}
+ public void testInvalidDependencyScope() {
+ loadProject("/jps/model-serialization/testData/invalidDependencyScope/invalidDependencyScope.ipr");
+ JpsModule module = assertOneElement(myProject.getModules());
+ List<JpsDependencyElement> dependencies = module.getDependenciesList().getDependencies();
+ assertEquals(3, dependencies.size());
+ JpsJavaDependencyExtension extension = JpsJavaExtensionService.getInstance().getDependencyExtension(dependencies.get(2));
+ assertNotNull(extension);
+ assertEquals(JpsJavaDependencyScope.COMPILE, extension.getScope());
+ }
+
+ public void testDuplicatedModuleLibrary() {
+ loadProject("/jps/model-serialization/testData/duplicatedModuleLibrary/duplicatedModuleLibrary.ipr");
+ JpsModule module = assertOneElement(myProject.getModules());
+ List<JpsDependencyElement> dependencies = module.getDependenciesList().getDependencies();
+ assertEquals(4, dependencies.size());
+ JpsLibrary lib1 = assertInstanceOf(dependencies.get(2), JpsLibraryDependency.class).getLibrary();
+ assertNotNull(lib1);
+ assertSameElements(lib1.getRootUrls(JpsOrderRootType.COMPILED), getUrl("data/lib1"));
+ JpsLibrary lib2 = assertInstanceOf(dependencies.get(3), JpsLibraryDependency.class).getLibrary();
+ assertNotSame(lib1, lib2);
+ assertNotNull(lib2);
+ assertSameElements(lib2.getRootUrls(JpsOrderRootType.COMPILED), getUrl("data/lib2"));
+ }
+
public void testLoadEncoding() {
loadProject(SAMPLE_PROJECT_PATH);
JpsEncodingConfigurationService service = JpsEncodingConfigurationService.getInstance();