new api for file processing compilers

This commit is contained in:
nik
2010-07-28 13:21:22 +04:00
parent ea83ef22a7
commit 72fedc5d1f
13 changed files with 898 additions and 4 deletions
@@ -24,6 +24,7 @@ package com.intellij.compiler.impl;
import com.intellij.CommonBundle;
import com.intellij.analysis.AnalysisScope;
import com.intellij.compiler.*;
import com.intellij.compiler.impl.newApi.NewCompiler;
import com.intellij.compiler.make.CacheCorruptedException;
import com.intellij.compiler.make.CacheUtils;
import com.intellij.compiler.make.DependencyCache;
@@ -560,7 +561,7 @@ public class CompileDriver {
return CompilerBundle.message("status.compilation.completed.successfully.with.warnings.and.errors", errorCount, warningCount);
}
private static class ExitStatus {
static class ExitStatus {
private final String myName;
private ExitStatus(@NonNls String name) {
@@ -577,10 +578,10 @@ public class CompileDriver {
public static final ExitStatus UP_TO_DATE = new ExitStatus("UP_TO_DATE");
}
private static class ExitException extends Exception {
static class ExitException extends Exception {
private final ExitStatus myStatus;
private ExitException(ExitStatus status) {
ExitException(ExitStatus status) {
myStatus = status;
}
@@ -724,7 +725,7 @@ public class CompileDriver {
boolean didSomething = false;
final CompilerManager compilerManager = CompilerManager.getInstance(myProject);
NewCompilerRunner runner = new NewCompilerRunner(context, compilerManager, forceCompile, onlyCheckStatus);
try {
didSomething |= generateSources(compilerManager, context, forceCompile, onlyCheckStatus);
@@ -746,19 +747,23 @@ public class CompileDriver {
didSomething |= invokeFileProcessingCompilers(compilerManager, context, ClassInstrumentingCompiler.class,
FILE_PROCESSING_COMPILER_ADAPTER_FACTORY, isRebuild, false, onlyCheckStatus);
didSomething |= runner.invokeCompilers(NewCompiler.CompileOrderPlace.CLASS_INSTRUMENTING);
// explicitly passing forceCompile = false because in scopes that is narrower than ProjectScope it is impossible
// to understand whether the class to be processed is in scope or not. Otherwise compiler may process its items even if
// there were changes in completely independent files.
didSomething |= invokeFileProcessingCompilers(compilerManager, context, ClassPostProcessingCompiler.class,
FILE_PROCESSING_COMPILER_ADAPTER_FACTORY, isRebuild, false, onlyCheckStatus);
didSomething |= runner.invokeCompilers(NewCompiler.CompileOrderPlace.CLASS_POST_PROCESSING);
didSomething |= invokeFileProcessingCompilers(compilerManager, context, PackagingCompiler.class,
FILE_PACKAGING_COMPILER_ADAPTER_FACTORY,
isRebuild, false, onlyCheckStatus);
didSomething |= runner.invokeCompilers(NewCompiler.CompileOrderPlace.PACKAGING);
didSomething |= invokeFileProcessingCompilers(compilerManager, context, Validator.class, FILE_PROCESSING_COMPILER_ADAPTER_FACTORY,
forceCompile, true, onlyCheckStatus);
didSomething |= runner.invokeCompilers(NewCompiler.CompileOrderPlace.VALIDATING);
}
catch (ExitException e) {
if (LOG.isDebugEnabled()) {
@@ -15,6 +15,8 @@
*/
package com.intellij.compiler.impl;
import com.intellij.compiler.impl.newApi.NewCompiler;
import com.intellij.compiler.impl.newApi.NewCompilerCache;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.compiler.Compiler;
@@ -42,6 +44,7 @@ import java.util.Map;
public class CompilerCacheManager implements ProjectComponent {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.CompilerCacheManager");
private final Map<Compiler, Object> myCompilerToCacheMap = new HashMap<Compiler, Object>();
private final Map<NewCompiler<?,?>, NewCompilerCache<?,?>> myNewCachesMap = new HashMap<NewCompiler<?,?>, NewCompilerCache<?,?>>();
private final List<Disposable> myCacheDisposables = new ArrayList<Disposable>();
private final File myCachesRoot;
private final Runnable myShutdownTask = new Runnable() {
@@ -49,8 +52,10 @@ public class CompilerCacheManager implements ProjectComponent {
flushCaches();
}
};
private final Project myProject;
public CompilerCacheManager(Project project) {
myProject = project;
myCachesRoot = CompilerPaths.getCacheStoreDirectory(project);
}
@@ -85,6 +90,23 @@ public class CompilerCacheManager implements ProjectComponent {
return dir;
}
public synchronized <Key, State> NewCompilerCache<Key, State> getNewCompilerCache(NewCompiler<Key, State> compiler) throws IOException {
NewCompilerCache<?, ?> cache = myNewCachesMap.get(compiler);
if (cache == null) {
final NewCompilerCache<?, ?> newCache = new NewCompilerCache<Key, State>(compiler, NewCompilerRunner.getNewCompilerCacheDir(myProject, compiler));
myNewCachesMap.put(compiler, newCache);
myCacheDisposables.add(new Disposable() {
@Override
public void dispose() {
newCache.close();
}
});
cache = newCache;
}
//noinspection unchecked
return (NewCompilerCache<Key, State>)cache;
}
public synchronized FileProcessingCompilerStateCache getFileProcessingCompilerCache(FileProcessingCompiler compiler) throws IOException {
Object cache = myCompilerToCacheMap.get(compiler);
if (cache == null) {
@@ -0,0 +1,246 @@
/*
* Copyright 2000-2010 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.compiler.impl;
import com.intellij.compiler.impl.newApi.*;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.*;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.Ref;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Processor;
import com.intellij.util.io.KeyDescriptor;
import gnu.trove.THashSet;
import gnu.trove.TObjectHashingStrategy;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.io.IOException;
import java.util.*;
/**
* @author nik
*/
public class NewCompilerRunner {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.NewCompilerRunner");
private CompileContext myContext;
private final boolean myForceCompile;
private final boolean myOnlyCheckStatus;
private final NewCompiler<?,?>[] myCompilers;
private final Project myProject;
public NewCompilerRunner(CompileContext context, CompilerManager compilerManager, boolean forceCompile, boolean onlyCheckStatus) {
myContext = context;
myForceCompile = forceCompile;
myOnlyCheckStatus = onlyCheckStatus;
myCompilers = compilerManager.getCompilers(NewCompiler.class);
myProject = myContext.getProject();
}
public boolean invokeCompilers(NewCompiler.CompileOrderPlace place) throws CompileDriver.ExitException {
boolean didSomething = false;
try {
for (NewCompiler<?, ?> compiler : myCompilers) {
if (compiler.getOrderPlace().equals(place)) {
didSomething = invokeCompiler(compiler);
}
}
}
catch (IOException e) {
LOG.info(e);
myContext.requestRebuildNextTime(e.getMessage());
throw new CompileDriver.ExitException(CompileDriver.ExitStatus.ERRORS);
}
catch (CompileDriver.ExitException e) {
throw e;
}
catch (ProcessCanceledException e) {
throw e;
}
catch (Exception e) {
LOG.info(e);
myContext.addMessage(CompilerMessageCategory.ERROR, CompilerBundle.message("compiler.error.exception", e.getMessage()), null, -1, -1);
}
return didSomething;
}
private <T extends BuildTarget, Key, State> boolean invokeCompiler(NewCompiler<Key, State> compiler) throws IOException, CompileDriver.ExitException {
return invokeCompiler(compiler, compiler.createInstance(myContext));
}
private <T extends BuildTarget, Item extends CompileItem<Key, State>, Key, State>
boolean invokeCompiler(NewCompiler<Key, State> compiler, CompilerInstance<T, Item, Key, State> instance) throws IOException, CompileDriver.ExitException {
NewCompilerCache<Key, State> cache = CompilerCacheManager.getInstance(myProject).getNewCompilerCache(compiler);
NewCompilerPersistentData data = new NewCompilerPersistentData(getNewCompilerCacheDir(myProject, compiler), compiler.getVersion());
if (data.isVersionChanged()) {
LOG.info("Clearing cache for " + compiler.getDescription());
cache.wipe();
}
Set<String> targetsToRemove = new HashSet<String>(data.getAllTargets());
for (T target : instance.getAllTargets()) {
targetsToRemove.remove(target.getId());
}
if (!myOnlyCheckStatus) {
for (String target : targetsToRemove) {
int id = data.removeId(target);
if (LOG.isDebugEnabled()) {
LOG.debug("Removing obsolete target '" + target + "' (id=" + id + ")");
}
List<Key> keys = new ArrayList<Key>();
cache.processSources(id, new CommonProcessors.CollectProcessor<Key>(keys));
List<Pair<Key, State>> obsoleteSources = new ArrayList<Pair<Key, State>>();
for (Key key : keys) {
final State state = cache.getState(id, key);
obsoleteSources.add(Pair.create(key, state));
}
instance.processObsoleteTarget(target, obsoleteSources);
if (myContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
return true;
}
for (Key key : keys) {
cache.remove(id, key);
}
}
}
boolean didSomething = false;
for (T target : instance.getSelectedTargets()) {
int id = data.getId(target.getId());
didSomething |= processTarget(target, id, compiler, instance, cache);
}
data.save();
return didSomething;
}
public static File getNewCompilerCacheDir(Project project, NewCompiler<?, ?> compiler) {
return new File(CompilerPaths.getCacheStoreDirectory(project), compiler.getId());
}
private <T extends BuildTarget, Item extends CompileItem<Key, State>, Key, State>
boolean processTarget(T target, final int targetId, final NewCompiler<Key, State> compiler, final CompilerInstance<T, Item, Key, State> instance,
final NewCompilerCache<Key, State> cache) throws IOException, CompileDriver.ExitException {
if (LOG.isDebugEnabled()) {
LOG.debug("Processing target '" + target + "' (id=" + targetId + ")");
}
final List<Item> items = instance.getItems(target);
if (myContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) return true;
final List<Pair<Item, State>> toProcess = new ArrayList<Pair<Item, State>>();
final THashSet<Key> keySet = new THashSet<Key>(new SourceItemHashingStrategy<Key>(compiler));
final Ref<IOException> exception = Ref.create(null);
DumbService.getInstance(myProject).waitForSmartMode();
ApplicationManager.getApplication().runReadAction(new Runnable() {
@Override
public void run() {
try {
for (Item item : items) {
final Key key = item.getKey();
keySet.add(key);
State output = cache.getState(targetId, key);
if (myForceCompile || output == null || !item.isUpToDate(output)) {
toProcess.add(Pair.create(item, output));
}
}
}
catch (IOException e) {
exception.set(e);
}
}
});
if (!exception.isNull()) {
throw exception.get();
}
final List<Key> toRemove = new ArrayList<Key>();
cache.processSources(targetId, new Processor<Key>() {
@Override
public boolean process(Key key) {
if (!keySet.contains(key)) {
toRemove.add(key);
}
return true;
}
});
if (LOG.isDebugEnabled()) {
LOG.debug(toProcess.size() + " items will be processed, " + toRemove.size() + " items will be removed");
}
if (toProcess.isEmpty() && toRemove.isEmpty()) {
return false;
}
if (myOnlyCheckStatus) {
throw new CompileDriver.ExitException(CompileDriver.ExitStatus.CANCELLED);
}
List<Pair<Key, State>> obsoleteItems = new ArrayList<Pair<Key, State>>();
for (Key key : toRemove) {
obsoleteItems.add(Pair.create(key, cache.getState(targetId, key)));
}
final List<Item> processedItems = new ArrayList<Item>();
final List<File> toRefresh = new ArrayList<File>();
instance.processItems(target, toProcess, obsoleteItems, new CompilerInstance.OutputConsumer<Item>() {
@Override
public void addFileToRefresh(@NotNull File file) {
toRefresh.add(file);
}
@Override
public void addProcessedItem(@NotNull Item sourceItem) {
processedItems.add(sourceItem);
}
});
if (myContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
return true;
}
for (Key key : toRemove) {
cache.remove(targetId, key);
}
CompilerUtil.refreshIOFiles(toRefresh);
for (Item item : processedItems) {
cache.putOutput(targetId, item.getKey(), item.computeState());
}
return true;
}
private class SourceItemHashingStrategy<S> implements TObjectHashingStrategy<S> {
private KeyDescriptor<S> myKeyDescriptor;
public SourceItemHashingStrategy(NewCompiler<S, ?> compiler) {
myKeyDescriptor = compiler.getItemKeyDescriptor();
}
@Override
public int computeHashCode(S object) {
return myKeyDescriptor.getHashCode(object);
}
@Override
public boolean equals(S o1, S o2) {
return myKeyDescriptor.isEqual(o1, o2);
}
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class BuildTarget {
public static final BuildTarget DEFAULT = new BuildTarget() {
@NotNull
@Override
public String getId() {
return "<default>";
}
};
@NotNull
public abstract String getId();
@Override
public String toString() {
return "Build Target: " + getId();
}
}
@@ -0,0 +1,31 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class CompileItem<Key, State> {
@NotNull
public abstract Key getKey();
public abstract boolean isUpToDate(@NotNull State state);
@NotNull
public abstract State computeState();
}
@@ -0,0 +1,60 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.util.List;
/**
* @author nik
*/
public abstract class CompilerInstance<T extends BuildTarget, Item extends CompileItem<Key, State>, Key, State> {
protected final CompileContext myContext;
protected CompilerInstance(CompileContext context) {
myContext = context;
}
protected Project getProject() {
return myContext.getProject();
}
@NotNull
public abstract List<T> getAllTargets();
@NotNull
public abstract List<T> getSelectedTargets();
public abstract void processObsoleteTarget(@NotNull String targetId, @NotNull List<Pair<Key, State>> obsoleteItems);
@NotNull
public abstract List<Item> getItems(@NotNull T target);
public abstract void processItems(@NotNull T target, @NotNull List<Pair<Item, State>> changedItems, @NotNull List<Pair<Key, State>> obsoleteItems,
@NotNull OutputConsumer<Item> consumer);
public interface OutputConsumer<Item extends CompileItem<?,?>> {
void addFileToRefresh(@NotNull File file);
void addProcessedItem(@NotNull Item sourceItem);
}
}
@@ -0,0 +1,62 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.Compiler;
import com.intellij.util.io.DataExternalizer;
import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class NewCompiler<Key, State> implements Compiler {
private final String myId;
private final int myVersion;
private final CompileOrderPlace myOrderPlace;
protected NewCompiler(@NotNull String id, int version, @NotNull CompileOrderPlace orderPlace) {
myId = id;
myVersion = version;
myOrderPlace = orderPlace;
}
@NotNull
public abstract KeyDescriptor<Key> getItemKeyDescriptor();
@NotNull
public abstract DataExternalizer<State> getItemStateExternalizer();
@NotNull
public abstract CompilerInstance<?, ? extends CompileItem<Key, State>, Key, State> createInstance(@NotNull CompileContext context);
public final String getId() {
return myId;
}
public final int getVersion() {
return myVersion;
}
public CompileOrderPlace getOrderPlace() {
return myOrderPlace;
}
public static enum CompileOrderPlace {
CLASS_INSTRUMENTING, CLASS_POST_PROCESSING, PACKAGING, VALIDATING
}
}
@@ -0,0 +1,132 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.Processor;
import com.intellij.util.io.KeyDescriptor;
import com.intellij.util.io.PersistentHashMap;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.IOException;
/**
* @author nik
*/
public class NewCompilerCache<Key, State> {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.newApi.NewCompilerCache");
private PersistentHashMap<KeyAndTargetData<Key>, State> myPersistentMap;
private File myCacheFile;
private final NewCompiler<Key, State> myCompiler;
public NewCompilerCache(NewCompiler<Key, State> compiler, final File compilerCacheDir) throws IOException {
myCompiler = compiler;
myCacheFile = new File(compilerCacheDir, "timestamps");
createMap();
}
private void createMap() throws IOException {
myPersistentMap = new PersistentHashMap<KeyAndTargetData<Key>, State>(myCacheFile, new SourceItemDataDescriptor(myCompiler.getItemKeyDescriptor()),
myCompiler.getItemStateExternalizer());
}
private KeyAndTargetData<Key> getKeyAndTargetData(Key key, int target) {
KeyAndTargetData<Key> data = new KeyAndTargetData<Key>();
data.myTarget = target;
data.myKey = key;
return data;
}
public void wipe() throws IOException {
try {
myPersistentMap.close();
}
catch (IOException ignored) {
}
PersistentHashMap.deleteFilesStartingWith(myCacheFile);
createMap();
}
public void close() {
try {
myPersistentMap.close();
}
catch (IOException e) {
LOG.info(e);
}
}
public void remove(int targetId, Key key) throws IOException {
myPersistentMap.remove(getKeyAndTargetData(key, targetId));
}
public State getState(int targetId, Key key) throws IOException {
return myPersistentMap.get(getKeyAndTargetData(key, targetId));
}
public void processSources(final int targetId, final Processor<Key> processor) throws IOException {
myPersistentMap.processKeys(new Processor<KeyAndTargetData<Key>>() {
@Override
public boolean process(KeyAndTargetData<Key> data) {
return targetId == data.myTarget ? processor.process(data.myKey) : true;
}
});
}
public void putOutput(int targetId, Key key, State outputItem) throws IOException {
myPersistentMap.put(getKeyAndTargetData(key, targetId), outputItem);
}
private static class KeyAndTargetData<Key> {
public int myTarget;
public Key myKey;
}
private class SourceItemDataDescriptor implements KeyDescriptor<KeyAndTargetData<Key>> {
private final KeyDescriptor<Key> myKeyDescriptor;
public SourceItemDataDescriptor(KeyDescriptor<Key> keyDescriptor) {
myKeyDescriptor = keyDescriptor;
}
@Override
public boolean isEqual(KeyAndTargetData<Key> val1, KeyAndTargetData<Key> val2) {
return val1.myTarget == val2.myTarget;
}
@Override
public int getHashCode(KeyAndTargetData<Key> value) {
return value.myTarget + 239 * myKeyDescriptor.getHashCode(value.myKey);
}
@Override
public void save(DataOutput out, KeyAndTargetData<Key> value) throws IOException {
out.writeInt(value.myTarget);
myKeyDescriptor.save(out, value.myKey);
}
@Override
public KeyAndTargetData<Key> read(DataInput in) throws IOException {
int target = in.readInt();
final Key item = myKeyDescriptor.read(in);
return getKeyAndTargetData(item, target);
}
}
}
@@ -0,0 +1,119 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.util.io.IOUtil;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @author nik
*/
public class NewCompilerPersistentData {
private static final Logger LOG = Logger.getInstance("#com.intellij.compiler.impl.newApi.NewCompilerPersistentData");
private static final int VERSION = 0;
private File myFile;
private Map<String, Integer> myTarget2Id = new HashMap<String, Integer>();
private TIntHashSet myUsedIds = new TIntHashSet();
private boolean myVersionChanged;
private final int myCompilerVersion;
public NewCompilerPersistentData(File cacheStoreDirectory, int compilerVersion) throws IOException {
myCompilerVersion = compilerVersion;
myFile = new File(cacheStoreDirectory, "info");
if (!myFile.exists()) {
LOG.info("Compiler info file doesn't exists: " + myFile.getAbsolutePath());
myVersionChanged = true;
return;
}
DataInputStream input = new DataInputStream(new FileInputStream(myFile));
try {
final int dataVersion = input.readInt();
if (dataVersion != VERSION) {
LOG.info("Version of compiler info file (" + myFile.getAbsolutePath() + ") changed: " + dataVersion + " -> " + VERSION);
myVersionChanged = true;
return;
}
final int savedCompilerVersion = input.readInt();
if (savedCompilerVersion != compilerVersion) {
LOG.info("Compiler caches version changed (" + myFile.getAbsolutePath() + "): " + savedCompilerVersion + " -> " + compilerVersion);
myVersionChanged = true;
return;
}
int size = input.readInt();
while (size-- > 0) {
final String target = IOUtil.readString(input);
final int id = input.readInt();
myTarget2Id.put(target, id);
myUsedIds.add(id);
}
}
finally {
input.close();
}
}
public boolean isVersionChanged() {
return myVersionChanged;
}
public void save() throws IOException {
final DataOutputStream output = new DataOutputStream(new FileOutputStream(myFile));
try {
output.writeInt(VERSION);
output.writeInt(myCompilerVersion);
output.writeInt(myTarget2Id.size());
for (Map.Entry<String, Integer> entry : myTarget2Id.entrySet()) {
IOUtil.writeString(entry.getKey(), output);
output.writeInt(entry.getValue());
}
}
finally {
output.close();
}
}
public int getId(@NotNull String target) {
if (myTarget2Id.containsKey(target)) {
return myTarget2Id.get(target);
}
int id = 0;
while (myUsedIds.contains(id)) {
id++;
}
myTarget2Id.put(target, id);
myUsedIds.add(id);
return id;
}
public Set<String> getAllTargets() {
return myTarget2Id.keySet();
}
public int removeId(String target) {
return myTarget2Id.remove(target);
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.util.Pair;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
/**
* @author nik
*/
public abstract class SingleTargetCompilerInstance<Item extends CompileItem<S,O>, S, O> extends CompilerInstance<BuildTarget, Item, S, O> {
protected SingleTargetCompilerInstance(CompileContext context) {
super(context);
}
@NotNull
@Override
public List<BuildTarget> getAllTargets() {
return Collections.singletonList(BuildTarget.DEFAULT);
}
@NotNull
@Override
public List<BuildTarget> getSelectedTargets() {
return getAllTargets();
}
@Override
public void processObsoleteTarget(@NotNull String targetId, @NotNull List<Pair<S, O>> obsoleteItems) {
}
}
@@ -0,0 +1,55 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.io.EnumeratorStringDescriptor;
import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull;
/**
* @author nik
*/
public abstract class VirtualFileCompileItem<State extends VirtualFilePersistentState> extends CompileItem<String, State> {
public static final KeyDescriptor<String> KEY_DESCRIPTOR = new EnumeratorStringDescriptor();
protected final VirtualFile myFile;
public VirtualFileCompileItem(@NotNull VirtualFile file) {
myFile = file;
}
@NotNull
public VirtualFile getFile() {
return myFile;
}
@Override
public final boolean isUpToDate(@NotNull State state) {
if (myFile.getTimeStamp() != state.getSourceTimestamp()) {
return false;
}
return isStateUpToDate(state);
}
protected abstract boolean isStateUpToDate(State state);
@NotNull
@Override
public String getKey() {
return myFile.getUrl();
}
}
@@ -0,0 +1,31 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
/**
* @author nik
*/
public class VirtualFilePersistentState {
private final long mySourceTimestamp;
public VirtualFilePersistentState(long sourceTimestamp) {
mySourceTimestamp = sourceTimestamp;
}
public final long getSourceTimestamp() {
return mySourceTimestamp;
}
}
@@ -0,0 +1,44 @@
/*
* Copyright 2000-2010 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.compiler.impl.newApi;
import com.intellij.util.io.DataExternalizer;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
/**
* @author nik
*/
public abstract class VirtualFileStateExternalizer<State extends VirtualFilePersistentState> implements DataExternalizer<State> {
protected abstract void doSave(DataOutput out, State value) throws IOException;
protected abstract State doRead(DataInput in, long sourceTimestamp) throws IOException;
@Override
public final void save(DataOutput out, State value) throws IOException {
out.writeLong(value.getSourceTimestamp());
doSave(out, value);
}
@Override
public final State read(DataInput in) throws IOException {
final long sourceTimestamp = in.readLong();
return doRead(in, sourceTimestamp);
}
}