mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
new api for file processing compilers
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+119
@@ -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);
|
||||
}
|
||||
}
|
||||
+48
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -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;
|
||||
}
|
||||
}
|
||||
+44
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user