mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'master' of git@git.labs.intellij.net:idea/community
This commit is contained in:
@@ -136,10 +136,12 @@ private def layoutWin(Map args, String home, Paths paths) {
|
||||
patchPropertiesFile(paths.distWin)
|
||||
ant.echo(file: "$paths.distWin/bin/idea.exe.vmoptions", message: args.vmoptions.replace(' ', '\n'))
|
||||
|
||||
ant.zip(zipfile: "$paths.artifacts/idea${args.buildNumber}.win.zip") {
|
||||
def winZipPath = "$paths.artifacts/idea${args.buildNumber}.win.zip"
|
||||
ant.zip(zipfile: winZipPath) {
|
||||
fileset(dir: paths.distAll)
|
||||
fileset(dir: paths.distWin)
|
||||
}
|
||||
notifyArtifactBuilt(winZipPath)
|
||||
}
|
||||
|
||||
private def layoutMac(Map args, String home, Paths paths) {
|
||||
@@ -170,7 +172,8 @@ private def layoutMac(Map args, String home, Paths paths) {
|
||||
|
||||
def root = isEap() ? "${version}-${args.buildNumber}.app" : "IntelliJ IDEA ${version} CE.app"
|
||||
|
||||
ant.zip(zipfile: "$paths.artifacts/idea${args.buildNumber}.mac.zip") {
|
||||
def macZipPath = "$paths.artifacts/idea${args.buildNumber}.mac.zip"
|
||||
ant.zip(zipfile: macZipPath) {
|
||||
[paths.distAll, paths.distMac].each {
|
||||
tarfileset(dir: it, prefix: root) {
|
||||
exclude(name: "bin/*.sh")
|
||||
@@ -183,6 +186,7 @@ private def layoutMac(Map args, String home, Paths paths) {
|
||||
include(name: "Contents/MacOS/idea")
|
||||
}
|
||||
}
|
||||
notifyArtifactBuilt(macZipPath)
|
||||
}
|
||||
|
||||
def layoutLinux(Map args, String home, Paths paths) {
|
||||
@@ -216,7 +220,9 @@ def layoutLinux(Map args, String home, Paths paths) {
|
||||
}
|
||||
}
|
||||
|
||||
ant.gzip(src: tarPath, zipfile: "${tarPath}.gz")
|
||||
def gzPath = "${tarPath}.gz"
|
||||
ant.gzip(src: tarPath, zipfile: gzPath)
|
||||
ant.delete(file: tarPath)
|
||||
notifyArtifactBuilt(gzPath)
|
||||
}
|
||||
|
||||
|
||||
@@ -88,3 +88,11 @@ binding.setVariable("loadProject", {
|
||||
requireProperty("home", guessHome())
|
||||
|
||||
project.builder.buildInfoPrinter = new org.jetbrains.jps.teamcity.TeamcityBuildInfoPrinter()
|
||||
|
||||
binding.setVariable("notifyArtifactBuilt", { String artifactPath ->
|
||||
if (!artifactPath.startsWith(home)) {
|
||||
project.error("Artifact path $artifactPath should start with $home")
|
||||
}
|
||||
def relativePath = artifactPath.substring(home.length())
|
||||
project.info("##teamcity[publishArtifacts '$relativePath']")
|
||||
})
|
||||
@@ -29,7 +29,6 @@ import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.impl.compiler.IncrementalArtifactsCompiler;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Chunk;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -68,7 +67,6 @@ public class CompilerManagerImpl extends CompilerManager {
|
||||
addTranslatingCompiler(new JavaCompiler(project), new HashSet<FileType>(Arrays.asList(StdFileTypes.JAVA)), new HashSet<FileType>(Arrays.asList(StdFileTypes.CLASS)));
|
||||
addCompiler(new ResourceCompiler(project, compilerConfiguration));
|
||||
addCompiler(new RmicCompiler());
|
||||
addCompiler(new IncrementalArtifactsCompiler());
|
||||
|
||||
for(Compiler compiler: Extensions.getExtensions(Compiler.EP_NAME, myProject)) {
|
||||
addCompiler(compiler);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
+8
-2
@@ -16,9 +16,9 @@
|
||||
|
||||
package com.intellij.compiler.impl.packagingCompiler;
|
||||
|
||||
import com.intellij.openapi.deployment.DeploymentUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
@@ -29,12 +29,18 @@ public class JarDestinationInfo extends DestinationInfo {
|
||||
private final JarInfo myJarInfo;
|
||||
|
||||
public JarDestinationInfo(final String pathInJar, final JarInfo jarInfo, DestinationInfo jarDestination) {
|
||||
super(DeploymentUtil.appendToPath(jarDestination.getOutputPath(), pathInJar), jarDestination.getOutputFile(), jarDestination.getOutputFilePath());
|
||||
super(appendPathInJar(jarDestination.getOutputPath(), pathInJar), jarDestination.getOutputFile(), jarDestination.getOutputFilePath());
|
||||
LOG.assertTrue(!pathInJar.startsWith(".."), pathInJar);
|
||||
myPathInJar = StringUtil.startsWithChar(pathInJar, '/') ? pathInJar : "/" + pathInJar;
|
||||
myJarInfo = jarInfo;
|
||||
}
|
||||
|
||||
private static String appendPathInJar(String outputPath, String pathInJar) {
|
||||
LOG.assertTrue(outputPath.length() > 0 && outputPath.charAt(outputPath.length() - 1) != '/');
|
||||
LOG.assertTrue(pathInJar.length() > 0 && pathInJar.charAt(0) != '/');
|
||||
return outputPath + JarFileSystem.JAR_SEPARATOR + pathInJar;
|
||||
}
|
||||
|
||||
public String getPathInJar() {
|
||||
return myPathInJar;
|
||||
}
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public class ArtifactAdditionalCompileScopeProvider extends AdditionalCompileSco
|
||||
if (ArtifactCompileScope.getArtifacts(baseScope) != null) {
|
||||
return null;
|
||||
}
|
||||
final IncrementalArtifactsCompiler compiler = IncrementalArtifactsCompiler.getInstance(project);
|
||||
final ArtifactsCompiler compiler = ArtifactsCompiler.getInstance(project);
|
||||
if (compiler == null || !filter.acceptCompiler(compiler)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.compiler.impl.newApi.BuildTarget;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactBuildTarget extends BuildTarget {
|
||||
private Artifact myArtifact;
|
||||
|
||||
public ArtifactBuildTarget(Artifact artifact) {
|
||||
myArtifact = artifact;
|
||||
}
|
||||
|
||||
public Artifact getArtifact() {
|
||||
return myArtifact;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getId() {
|
||||
return myArtifact.getName();
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.compiler.impl.newApi.VirtualFileCompileItem;
|
||||
import com.intellij.compiler.impl.packagingCompiler.DestinationInfo;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactCompilerCompileItem extends VirtualFileCompileItem<ArtifactPackagingItemOutputState> {
|
||||
public static final DataExternalizer<ArtifactPackagingItemOutputState> OUTPUT_EXTERNALIZER = new ArtifactPackagingItemExternalizer();
|
||||
private final List<DestinationInfo> myDestinations = new SmartList<DestinationInfo>();
|
||||
|
||||
public ArtifactCompilerCompileItem(VirtualFile file) {
|
||||
super(file);
|
||||
}
|
||||
|
||||
public void addDestination(DestinationInfo info) {
|
||||
myDestinations.add(info);
|
||||
}
|
||||
|
||||
public List<DestinationInfo> getDestinations() {
|
||||
return myDestinations;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ArtifactPackagingItemOutputState computeState() {
|
||||
final SmartList<Pair<String, Long>> pairs = new SmartList<Pair<String, Long>>();
|
||||
for (DestinationInfo destination : myDestinations) {
|
||||
destination.update();
|
||||
final VirtualFile outputFile = destination.getOutputFile();
|
||||
long timestamp = outputFile != null ? outputFile.getTimeStamp() : -1;
|
||||
pairs.add(Pair.create(destination.getOutputPath(), timestamp));
|
||||
}
|
||||
return new ArtifactPackagingItemOutputState(myFile.getTimeStamp(), pairs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStateUpToDate(ArtifactPackagingItemOutputState state) {
|
||||
final SmartList<Pair<String, Long>> cachedDestinations = state.myDestinations;
|
||||
if (cachedDestinations.size() != myDestinations.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (DestinationInfo info : myDestinations) {
|
||||
final VirtualFile outputFile = info.getOutputFile();
|
||||
long timestamp = outputFile != null ? outputFile.getTimeStamp() : -1;
|
||||
final String path = info.getOutputPath();
|
||||
boolean found = false;
|
||||
//todo[nik] use map if list contains many items
|
||||
for (Pair<String, Long> cachedDestination : cachedDestinations) {
|
||||
if (cachedDestination.first.equals(path)) {
|
||||
if (cachedDestination.second != timestamp) return false;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.compiler.impl.newApi.VirtualFileStateExternalizer;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactPackagingItemExternalizer
|
||||
extends VirtualFileStateExternalizer<ArtifactPackagingItemOutputState> {
|
||||
private byte[] myBuffer = IOUtil.allocReadWriteUTFBuffer();
|
||||
|
||||
@Override
|
||||
protected void doSave(DataOutput out, ArtifactPackagingItemOutputState value) throws IOException {
|
||||
out.writeInt(value.myDestinations.size());
|
||||
for (Pair<String, Long> pair : value.myDestinations) {
|
||||
IOUtil.writeUTFFast(myBuffer, out, pair.getFirst());
|
||||
out.writeLong(pair.getSecond());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ArtifactPackagingItemOutputState doRead(DataInput in, long sourceTimestamp) throws IOException {
|
||||
int size = in.readInt();
|
||||
SmartList<Pair<String, Long>> destinations = new SmartList<Pair<String, Long>>();
|
||||
while (size-- > 0) {
|
||||
String path = IOUtil.readUTFFast(myBuffer, in);
|
||||
long outputTimestamp = in.readLong();
|
||||
destinations.add(Pair.create(path, outputTimestamp));
|
||||
}
|
||||
return new ArtifactPackagingItemOutputState(sourceTimestamp, destinations);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.compiler.impl.newApi.VirtualFilePersistentState;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.util.SmartList;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactPackagingItemOutputState extends VirtualFilePersistentState {
|
||||
public final SmartList<Pair<String, Long>> myDestinations;
|
||||
|
||||
public ArtifactPackagingItemOutputState(long timestamp, SmartList<Pair<String, Long>> destinations) {
|
||||
super(timestamp);
|
||||
myDestinations = destinations;
|
||||
}
|
||||
}
|
||||
-102
@@ -1,102 +0,0 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.compiler.impl.packagingCompiler.DestinationInfo;
|
||||
import com.intellij.openapi.compiler.ValidityState;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.StringSetSpinAllocator;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactPackagingItemValidityState implements ValidityState {
|
||||
private final SmartList<Pair<String, Long>> myDestinations;
|
||||
|
||||
public ArtifactPackagingItemValidityState(List<DestinationInfo> destinationInfos, boolean sourceFileModified,
|
||||
@Nullable ArtifactPackagingItemValidityState oldState) {
|
||||
myDestinations = new SmartList<Pair<String, Long>>();
|
||||
final Set<String> paths = StringSetSpinAllocator.alloc();
|
||||
try {
|
||||
for (DestinationInfo info : destinationInfos) {
|
||||
final VirtualFile outputFile = info.getOutputFile();
|
||||
long timestamp = outputFile != null ? outputFile.getTimeStamp() : -1;
|
||||
final String path = info.getOutputPath();
|
||||
myDestinations.add(Pair.create(path, timestamp));
|
||||
paths.add(path);
|
||||
}
|
||||
|
||||
if (!sourceFileModified && oldState != null) {
|
||||
for (Pair<String, Long> pair : oldState.myDestinations) {
|
||||
if (!paths.contains(pair.getFirst())) {
|
||||
myDestinations.add(pair);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
StringSetSpinAllocator.dispose(paths);
|
||||
}
|
||||
}
|
||||
|
||||
public ArtifactPackagingItemValidityState(DataInput input) throws IOException {
|
||||
int size = input.readInt();
|
||||
myDestinations = new SmartList<Pair<String, Long>>();
|
||||
while (size-- > 0) {
|
||||
String path = IOUtil.readString(input);
|
||||
long timestamp = input.readLong();
|
||||
myDestinations.add(Pair.create(path, timestamp));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean equalsTo(final ValidityState otherState) {
|
||||
if (!(otherState instanceof ArtifactPackagingItemValidityState)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final SmartList<Pair<String, Long>> otherDestinations = ((ArtifactPackagingItemValidityState)otherState).myDestinations;
|
||||
if (otherDestinations.size() != myDestinations.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (myDestinations.size() == 1) {
|
||||
return myDestinations.get(0).equals(otherDestinations.get(0));
|
||||
}
|
||||
|
||||
return Comparing.haveEqualElements(myDestinations, otherDestinations);
|
||||
}
|
||||
|
||||
|
||||
public void save(final DataOutput output) throws IOException {
|
||||
output.writeInt(myDestinations.size());
|
||||
for (Pair<String, Long> pair : myDestinations) {
|
||||
IOUtil.writeString(pair.getFirst(), output);
|
||||
output.writeLong(pair.getSecond());
|
||||
}
|
||||
}
|
||||
}
|
||||
-96
@@ -1,96 +0,0 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.compiler.impl.FileProcessingCompilerStateCache;
|
||||
import com.intellij.compiler.impl.packagingCompiler.DestinationInfo;
|
||||
import com.intellij.openapi.compiler.FileProcessingCompiler;
|
||||
import com.intellij.openapi.compiler.ValidityState;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.SmartList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactPackagingProcessingItem implements FileProcessingCompiler.ProcessingItem {
|
||||
private final VirtualFile mySourceFile;
|
||||
private final List<Pair<DestinationInfo, Boolean>> myDestinations = new SmartList<Pair<DestinationInfo, Boolean>>();
|
||||
private List<DestinationInfo> myEnabledDestinations;
|
||||
private boolean mySourceFileModified;
|
||||
private ArtifactPackagingItemValidityState myOldState;
|
||||
|
||||
public ArtifactPackagingProcessingItem(final VirtualFile sourceFile) {
|
||||
mySourceFile = sourceFile;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualFile getFile() {
|
||||
return mySourceFile;
|
||||
}
|
||||
|
||||
public void addDestination(DestinationInfo info, boolean enabled) {
|
||||
for (int i = 0; i < myDestinations.size(); i++) {
|
||||
Pair<DestinationInfo, Boolean> pair = myDestinations.get(i);
|
||||
if (info.getOutputPath().equals(pair.getFirst().getOutputPath())) {
|
||||
if (enabled && !pair.getSecond()) {
|
||||
myDestinations.set(i, Pair.create(info, true));
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
myDestinations.add(Pair.create(info, enabled));
|
||||
}
|
||||
|
||||
public List<Pair<DestinationInfo, Boolean>> getDestinations() {
|
||||
return myDestinations;
|
||||
}
|
||||
|
||||
public void init(FileProcessingCompilerStateCache cache) throws IOException {
|
||||
final String url = mySourceFile.getUrl();
|
||||
myOldState = (ArtifactPackagingItemValidityState)cache.getExtState(url);
|
||||
mySourceFileModified = cache.getTimestamp(url) != mySourceFile.getTimeStamp();
|
||||
}
|
||||
|
||||
public void setProcessed() {
|
||||
for (DestinationInfo destination : myEnabledDestinations) {
|
||||
destination.update();
|
||||
}
|
||||
}
|
||||
|
||||
public List<DestinationInfo> getEnabledDestinations() {
|
||||
if (myEnabledDestinations == null) {
|
||||
myEnabledDestinations = new SmartList<DestinationInfo>();
|
||||
for (Pair<DestinationInfo, Boolean> destination : myDestinations) {
|
||||
if (destination.getSecond()) {
|
||||
myEnabledDestinations.add(destination.getFirst());
|
||||
}
|
||||
}
|
||||
}
|
||||
return myEnabledDestinations;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ValidityState getValidityState() {
|
||||
return new ArtifactPackagingItemValidityState(getEnabledDestinations(), mySourceFileModified, myOldState);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.compiler.impl.newApi.CompileItem;
|
||||
import com.intellij.compiler.impl.newApi.CompilerInstance;
|
||||
import com.intellij.compiler.impl.newApi.NewCompiler;
|
||||
import com.intellij.compiler.impl.newApi.VirtualFileCompileItem;
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import com.intellij.openapi.compiler.CompileScope;
|
||||
import com.intellij.openapi.compiler.CompilerManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.util.io.DataExternalizer;
|
||||
import com.intellij.util.io.KeyDescriptor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactsCompiler extends NewCompiler<String, ArtifactPackagingItemOutputState> {
|
||||
static final Key<Set<String>> WRITTEN_PATHS_KEY = Key.create("artifacts_written_paths");
|
||||
static final Key<Set<Artifact>> AFFECTED_ARTIFACTS = Key.create("affected_artifacts");
|
||||
|
||||
public ArtifactsCompiler() {
|
||||
super("artifacts_compiler", 0, NewCompiler.CompileOrderPlace.PACKAGING);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static ArtifactsCompiler getInstance(@NotNull Project project) {
|
||||
final ArtifactsCompiler[] compilers = CompilerManager.getInstance(project).getCompilers(ArtifactsCompiler.class);
|
||||
return compilers.length == 1 ? compilers[0] : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public KeyDescriptor<String> getItemKeyDescriptor() {
|
||||
return VirtualFileCompileItem.KEY_DESCRIPTOR;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DataExternalizer<ArtifactPackagingItemOutputState> getItemStateExternalizer() {
|
||||
return ArtifactCompilerCompileItem.OUTPUT_EXTERNALIZER;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CompilerInstance<ArtifactBuildTarget, ? extends CompileItem<String, ArtifactPackagingItemOutputState>, String, ArtifactPackagingItemOutputState> createInstance(
|
||||
@NotNull CompileContext context) {
|
||||
return new ArtifactsCompilerInstance(context);
|
||||
}
|
||||
|
||||
public boolean validateConfiguration(final CompileScope scope) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDescription() {
|
||||
return "Artifacts Packaging Compiler";
|
||||
}
|
||||
|
||||
public static Set<Artifact> getAffectedArtifacts(final CompileContext compileContext) {
|
||||
return compileContext.getUserData(AFFECTED_ARTIFACTS);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Set<String> getWrittenPaths(@NotNull CompileContext context) {
|
||||
return context.getUserData(WRITTEN_PATHS_KEY);
|
||||
}
|
||||
}
|
||||
+389
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.compiler.CompilerManagerImpl;
|
||||
import com.intellij.compiler.impl.CompilerUtil;
|
||||
import com.intellij.compiler.impl.newApi.CompilerInstance;
|
||||
import com.intellij.compiler.impl.packagingCompiler.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.compiler.CompileContext;
|
||||
import com.intellij.openapi.compiler.CompilerBundle;
|
||||
import com.intellij.openapi.compiler.CompilerMessageCategory;
|
||||
import com.intellij.openapi.compiler.make.BuildParticipant;
|
||||
import com.intellij.openapi.compiler.make.BuildParticipantProvider;
|
||||
import com.intellij.openapi.deployment.DeploymentUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.artifacts.ArtifactManager;
|
||||
import com.intellij.packaging.artifacts.ArtifactProperties;
|
||||
import com.intellij.packaging.artifacts.ArtifactPropertiesProvider;
|
||||
import com.intellij.packaging.elements.CompositePackagingElement;
|
||||
import com.intellij.packaging.elements.PackagingElementResolvingContext;
|
||||
import com.intellij.packaging.impl.artifacts.ArtifactValidationUtil;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactsCompilerInstance extends CompilerInstance<ArtifactBuildTarget, ArtifactCompilerCompileItem,
|
||||
String, ArtifactPackagingItemOutputState> {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.compiler.ArtifactsCompilerInstance");
|
||||
private ArtifactsProcessingItemsBuilderContext myBuilderContext;
|
||||
|
||||
public ArtifactsCompilerInstance(CompileContext context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ArtifactBuildTarget> getAllTargets() {
|
||||
return getArtifactTargets(false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ArtifactBuildTarget> getSelectedTargets() {
|
||||
return getArtifactTargets(true);
|
||||
}
|
||||
|
||||
private List<ArtifactBuildTarget> getArtifactTargets(final boolean selectedOnly) {
|
||||
final List<ArtifactBuildTarget> targets = new ArrayList<ArtifactBuildTarget>();
|
||||
new ReadAction() {
|
||||
protected void run(final Result result) {
|
||||
final Set<Artifact> artifacts;
|
||||
if (selectedOnly) {
|
||||
artifacts = ArtifactCompileScope.getArtifactsToBuild(getProject(), myContext.getCompileScope());
|
||||
}
|
||||
else {
|
||||
artifacts = new HashSet<Artifact>(Arrays.asList(ArtifactManager.getInstance(getProject()).getArtifacts()));
|
||||
}
|
||||
List<Artifact> additionalArtifacts = new ArrayList<Artifact>();
|
||||
for (BuildParticipantProvider provider : BuildParticipantProvider.EXTENSION_POINT_NAME.getExtensions()) {
|
||||
for (Module module : ModuleManager.getInstance(getProject()).getModules()) {
|
||||
final Collection<? extends BuildParticipant> participants = provider.getParticipants(module);
|
||||
for (BuildParticipant participant : participants) {
|
||||
ContainerUtil.addIfNotNull(participant.createArtifact(myContext), additionalArtifacts);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (LOG.isDebugEnabled() && !additionalArtifacts.isEmpty()) {
|
||||
LOG.debug("additional artifacts to build: " + additionalArtifacts);
|
||||
}
|
||||
artifacts.addAll(additionalArtifacts);
|
||||
|
||||
for (Artifact artifact : artifacts) {
|
||||
targets.add(new ArtifactBuildTarget(artifact));
|
||||
}
|
||||
if (selectedOnly) {
|
||||
myContext.putUserData(ArtifactsCompiler.AFFECTED_ARTIFACTS, artifacts);
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
return targets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processObsoleteTarget(@NotNull String targetId, @NotNull List<Pair<String, ArtifactPackagingItemOutputState>> obsoleteItems) {
|
||||
deleteFiles(obsoleteItems, Collections.<Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState>>emptyList());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<ArtifactCompilerCompileItem> getItems(@NotNull ArtifactBuildTarget target) {
|
||||
myBuilderContext = new ArtifactsProcessingItemsBuilderContext(myContext);
|
||||
final Artifact artifact = target.getArtifact();
|
||||
|
||||
final Set<Artifact> selfIncludingArtifacts = new ReadAction<Set<Artifact>>() {
|
||||
protected void run(final Result<Set<Artifact>> result) {
|
||||
result.setResult(ArtifactValidationUtil.getInstance(getProject()).getSelfIncludingArtifacts());
|
||||
}
|
||||
}.execute().getResultObject();
|
||||
if (selfIncludingArtifacts.contains(artifact)) {
|
||||
myContext.addMessage(CompilerMessageCategory.ERROR, "Artifact '" + artifact.getName() + "' includes itself in the output layout", null, -1, -1);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final String outputPath = artifact.getOutputPath();
|
||||
if (outputPath == null || outputPath.length() == 0) {
|
||||
myContext.addMessage(CompilerMessageCategory.ERROR, "Cannot build '" + artifact.getName() + "' artifact: output path is not specified",
|
||||
null, -1, -1);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
new ReadAction() {
|
||||
protected void run(final Result result) {
|
||||
collectItems(artifact, outputPath);
|
||||
}
|
||||
}.execute();
|
||||
return new ArrayList<ArtifactCompilerCompileItem>(myBuilderContext.getProcessingItems());
|
||||
}
|
||||
|
||||
private void collectItems(@NotNull Artifact artifact, @NotNull String outputPath) {
|
||||
final CompositePackagingElement<?> rootElement = artifact.getRootElement();
|
||||
final VirtualFile outputFile = LocalFileSystem.getInstance().findFileByPath(outputPath);
|
||||
final CopyToDirectoryInstructionCreator instructionCreator = new CopyToDirectoryInstructionCreator(myBuilderContext, outputPath, outputFile);
|
||||
final PackagingElementResolvingContext resolvingContext = ArtifactManager.getInstance(getProject()).getResolvingContext();
|
||||
rootElement.computeIncrementalCompilerInstructions(instructionCreator, resolvingContext, myBuilderContext, artifact.getArtifactType());
|
||||
}
|
||||
|
||||
private boolean doBuild(final List<Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState>> changedItems,
|
||||
final Set<ArtifactCompilerCompileItem> processedItems,
|
||||
final Set<String> writtenPaths, final Set<String> deletedJars) {
|
||||
final boolean testMode = ApplicationManager.getApplication().isUnitTestMode();
|
||||
|
||||
final DeploymentUtil deploymentUtil = DeploymentUtil.getInstance();
|
||||
final FileFilter fileFilter = new IgnoredFileFilter();
|
||||
final Set<JarInfo> changedJars = new THashSet<JarInfo>();
|
||||
for (String deletedJar : deletedJars) {
|
||||
ContainerUtil.addIfNotNull(myBuilderContext.getJarInfo(deletedJar), changedJars);
|
||||
}
|
||||
|
||||
try {
|
||||
onBuildStartedOrFinished(false);
|
||||
if (myContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (final Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState> item : changedItems) {
|
||||
final ArtifactCompilerCompileItem sourceItem = item.getFirst();
|
||||
myContext.getProgressIndicator().checkCanceled();
|
||||
|
||||
final Ref<IOException> exception = Ref.create(null);
|
||||
new ReadAction() {
|
||||
protected void run(final Result result) {
|
||||
final File fromFile = VfsUtil.virtualToIoFile(sourceItem.getFile());
|
||||
for (DestinationInfo destination : sourceItem.getDestinations()) {
|
||||
if (destination instanceof ExplodedDestinationInfo) {
|
||||
final ExplodedDestinationInfo explodedDestination = (ExplodedDestinationInfo)destination;
|
||||
File toFile = new File(FileUtil.toSystemDependentName(explodedDestination.getOutputPath()));
|
||||
if (fromFile.exists()) {
|
||||
try {
|
||||
deploymentUtil.copyFile(fromFile, toFile, myContext, writtenPaths, fileFilter);
|
||||
}
|
||||
catch (IOException e) {
|
||||
exception.set(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
changedJars.add(((JarDestinationInfo)destination).getJarInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
if (exception.get() != null) {
|
||||
throw exception.get();
|
||||
}
|
||||
|
||||
myContext.getProgressIndicator().setFraction(++i * 1.0 / changedItems.size());
|
||||
processedItems.add(sourceItem);
|
||||
if (testMode) {
|
||||
CompilerManagerImpl.addRecompiledPath(FileUtil.toSystemDependentName(sourceItem.getFile().getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
JarsBuilder builder = new JarsBuilder(changedJars, fileFilter, myContext);
|
||||
final boolean processed = builder.buildJars(writtenPaths);
|
||||
if (!processed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<VirtualFile> recompiledSources = new HashSet<VirtualFile>();
|
||||
for (JarInfo info : builder.getJarsToBuild()) {
|
||||
for (Pair<String, VirtualFile> pair : info.getPackedFiles()) {
|
||||
recompiledSources.add(pair.getSecond());
|
||||
}
|
||||
}
|
||||
for (VirtualFile source : recompiledSources) {
|
||||
ArtifactCompilerCompileItem item = myBuilderContext.getItemBySource(source);
|
||||
LOG.assertTrue(item != null, source);
|
||||
processedItems.add(item);
|
||||
if (testMode) {
|
||||
CompilerManagerImpl.addRecompiledPath(FileUtil.toSystemDependentName(item.getFile().getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
onBuildStartedOrFinished(true);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info(e);
|
||||
myContext.addMessage(CompilerMessageCategory.ERROR, e.getLocalizedMessage(), null, -1, -1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onBuildStartedOrFinished(final boolean finished) throws Exception {
|
||||
final Set<Artifact> artifacts = myContext.getUserData(ArtifactsCompiler.AFFECTED_ARTIFACTS);
|
||||
if (artifacts != null) {
|
||||
for (Artifact artifact : artifacts) {
|
||||
for (ArtifactPropertiesProvider provider : artifact.getPropertiesProviders()) {
|
||||
final ArtifactProperties<?> properties = artifact.getProperties(provider);
|
||||
if (finished) {
|
||||
properties.onBuildFinished(artifact, myContext);
|
||||
}
|
||||
else {
|
||||
properties.onBuildStarted(artifact, myContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static THashSet<String> createPathsHashSet() {
|
||||
return SystemInfo.isFileSystemCaseSensitive
|
||||
? new THashSet<String>()
|
||||
: new THashSet<String>(CaseInsensitiveStringHashingStrategy.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processItems(@NotNull ArtifactBuildTarget target, @NotNull final List<Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState>> changedItems,
|
||||
@NotNull List<Pair<String, ArtifactPackagingItemOutputState>> obsoleteItems,
|
||||
@NotNull final OutputConsumer<ArtifactCompilerCompileItem> consumer) {
|
||||
|
||||
final THashSet<String> deletedJars = deleteFiles(obsoleteItems, changedItems);
|
||||
|
||||
final Set<String> writtenPaths = createPathsHashSet();
|
||||
final Ref<Boolean> built = Ref.create(false);
|
||||
final Set<ArtifactCompilerCompileItem> processedItems = new HashSet<ArtifactCompilerCompileItem>();
|
||||
CompilerUtil.runInContext(myContext, "Copying files", new ThrowableRunnable<RuntimeException>() {
|
||||
public void run() throws RuntimeException {
|
||||
built.set(doBuild(changedItems, processedItems, writtenPaths, deletedJars));
|
||||
}
|
||||
});
|
||||
if (!built.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
myContext.getProgressIndicator().setText(CompilerBundle.message("packaging.compiler.message.updating.caches"));
|
||||
myContext.getProgressIndicator().setText2("");
|
||||
for (String path : writtenPaths) {
|
||||
consumer.addFileToRefresh(new File(path));
|
||||
}
|
||||
for (ArtifactCompilerCompileItem item : processedItems) {
|
||||
consumer.addProcessedItem(item);
|
||||
}
|
||||
myContext.putUserData(ArtifactsCompiler.WRITTEN_PATHS_KEY, writtenPaths);
|
||||
}
|
||||
|
||||
private THashSet<String> deleteFiles(List<Pair<String, ArtifactPackagingItemOutputState>> obsoleteItems,
|
||||
List<Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState>> changedItems) {
|
||||
myContext.getProgressIndicator().setText(CompilerBundle.message("packaging.compiler.message.deleting.outdated.files"));
|
||||
|
||||
final boolean testMode = ApplicationManager.getApplication().isUnitTestMode();
|
||||
final THashSet<String> deletedJars = new THashSet<String>();
|
||||
final THashSet<String> notDeletedJars = new THashSet<String>();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Deleting outdated files...");
|
||||
}
|
||||
|
||||
Set<String> pathToDelete = new THashSet<String>();
|
||||
for (Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState> item : changedItems) {
|
||||
final ArtifactPackagingItemOutputState cached = item.getSecond();
|
||||
if (cached != null) {
|
||||
for (Pair<String, Long> destination : cached.myDestinations) {
|
||||
pathToDelete.add(destination.getFirst());
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Pair<ArtifactCompilerCompileItem, ArtifactPackagingItemOutputState> item : changedItems) {
|
||||
for (DestinationInfo destination : item.getFirst().getDestinations()) {
|
||||
pathToDelete.remove(destination.getOutputPath());
|
||||
}
|
||||
}
|
||||
for (Pair<String, ArtifactPackagingItemOutputState> item : obsoleteItems) {
|
||||
for (Pair<String, Long> destination : item.getSecond().myDestinations) {
|
||||
pathToDelete.add(destination.getFirst());
|
||||
}
|
||||
}
|
||||
|
||||
int notDeletedFilesCount = 0;
|
||||
List<File> filesToRefresh = new ArrayList<File>();
|
||||
|
||||
for (String fullPath : pathToDelete) {
|
||||
int end = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR);
|
||||
boolean isJar = end != -1;
|
||||
String filePath = isJar ? fullPath.substring(0, end) : fullPath;
|
||||
boolean deleted = false;
|
||||
if (isJar) {
|
||||
if (notDeletedJars.contains(filePath)) {
|
||||
continue;
|
||||
}
|
||||
deleted = deletedJars.contains(filePath);
|
||||
}
|
||||
|
||||
File file = new File(FileUtil.toSystemDependentName(filePath));
|
||||
if (!deleted) {
|
||||
filesToRefresh.add(file);
|
||||
deleted = FileUtil.delete(file);
|
||||
}
|
||||
|
||||
if (deleted) {
|
||||
if (isJar) {
|
||||
deletedJars.add(filePath);
|
||||
}
|
||||
if (testMode) {
|
||||
CompilerManagerImpl.addDeletedPath(file.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (isJar) {
|
||||
notDeletedJars.add(filePath);
|
||||
}
|
||||
if (notDeletedFilesCount++ > 50) {
|
||||
myContext.addMessage(CompilerMessageCategory.WARNING, "Deletion of outdated files stopped because too many files cannot be deleted", null, -1, -1);
|
||||
break;
|
||||
}
|
||||
myContext.addMessage(CompilerMessageCategory.WARNING, "Cannot delete file '" + filePath + "'", null, -1, -1);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Cannot delete file " + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CompilerUtil.refreshIOFiles(filesToRefresh);
|
||||
return deletedJars;
|
||||
}
|
||||
|
||||
}
|
||||
+10
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* 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.
|
||||
@@ -32,15 +32,14 @@ import java.util.Map;
|
||||
* @author nik
|
||||
*/
|
||||
public class ArtifactsProcessingItemsBuilderContext implements ArtifactIncrementalCompilerContext {
|
||||
private boolean myCollectingEnabledItems;
|
||||
protected final Map<VirtualFile, ArtifactPackagingProcessingItem> myItemsBySource;
|
||||
protected final Map<VirtualFile, ArtifactCompilerCompileItem> myItemsBySource;
|
||||
private final Map<String, VirtualFile> mySourceByOutput;
|
||||
private final Map<String, JarInfo> myJarByPath;
|
||||
private final CompileContext myCompileContext;
|
||||
|
||||
public ArtifactsProcessingItemsBuilderContext(CompileContext compileContext) {
|
||||
myCompileContext = compileContext;
|
||||
myItemsBySource = new HashMap<VirtualFile, ArtifactPackagingProcessingItem>();
|
||||
myItemsBySource = new HashMap<VirtualFile, ArtifactCompilerCompileItem>();
|
||||
mySourceByOutput = new HashMap<String, VirtualFile>();
|
||||
myJarByPath = new HashMap<String, JarInfo>();
|
||||
}
|
||||
@@ -51,19 +50,14 @@ public class ArtifactsProcessingItemsBuilderContext implements ArtifactIncrement
|
||||
}
|
||||
|
||||
if (checkOutputPath(destinationInfo.getOutputPath(), sourceFile)) {
|
||||
getOrCreateProcessingItem(sourceFile).addDestination(destinationInfo, myCollectingEnabledItems);
|
||||
getOrCreateProcessingItem(sourceFile).addDestination(destinationInfo);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public ArtifactPackagingProcessingItem[] getProcessingItems() {
|
||||
final Collection<ArtifactPackagingProcessingItem> processingItems = myItemsBySource.values();
|
||||
return processingItems.toArray(new ArtifactPackagingProcessingItem[processingItems.size()]);
|
||||
}
|
||||
|
||||
public void setCollectingEnabledItems(boolean collectingEnabledItems) {
|
||||
myCollectingEnabledItems = collectingEnabledItems;
|
||||
public Collection<ArtifactCompilerCompileItem> getProcessingItems() {
|
||||
return myItemsBySource.values();
|
||||
}
|
||||
|
||||
public boolean checkOutputPath(final String outputPath, final VirtualFile sourceFile) {
|
||||
@@ -76,7 +70,7 @@ public class ArtifactsProcessingItemsBuilderContext implements ArtifactIncrement
|
||||
return false;
|
||||
}
|
||||
|
||||
public ArtifactPackagingProcessingItem getItemBySource(VirtualFile source) {
|
||||
public ArtifactCompilerCompileItem getItemBySource(VirtualFile source) {
|
||||
return myItemsBySource.get(source);
|
||||
}
|
||||
|
||||
@@ -102,10 +96,10 @@ public class ArtifactsProcessingItemsBuilderContext implements ArtifactIncrement
|
||||
return myCompileContext;
|
||||
}
|
||||
|
||||
public ArtifactPackagingProcessingItem getOrCreateProcessingItem(VirtualFile sourceFile) {
|
||||
ArtifactPackagingProcessingItem item = myItemsBySource.get(sourceFile);
|
||||
public ArtifactCompilerCompileItem getOrCreateProcessingItem(VirtualFile sourceFile) {
|
||||
ArtifactCompilerCompileItem item = myItemsBySource.get(sourceFile);
|
||||
if (item == null) {
|
||||
item = new ArtifactPackagingProcessingItem(sourceFile);
|
||||
item = new ArtifactCompilerCompileItem(sourceFile);
|
||||
myItemsBySource.put(sourceFile, item);
|
||||
}
|
||||
return item;
|
||||
|
||||
+2
-1
@@ -29,7 +29,8 @@ public class CopyToDirectoryInstructionCreator extends IncrementalCompilerInstru
|
||||
private final String myOutputPath;
|
||||
private final @Nullable VirtualFile myOutputFile;
|
||||
|
||||
public CopyToDirectoryInstructionCreator(ArtifactsProcessingItemsBuilderContext context, String outputPath, @Nullable VirtualFile outputFile) {
|
||||
public CopyToDirectoryInstructionCreator(ArtifactsProcessingItemsBuilderContext context, String outputPath,
|
||||
@Nullable VirtualFile outputFile) {
|
||||
super(context);
|
||||
myOutputPath = outputPath;
|
||||
myOutputFile = outputFile;
|
||||
|
||||
-583
@@ -1,583 +0,0 @@
|
||||
/*
|
||||
* 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.packaging.impl.compiler;
|
||||
|
||||
import com.intellij.compiler.CompilerManagerImpl;
|
||||
import com.intellij.compiler.impl.CompilerCacheManager;
|
||||
import com.intellij.compiler.impl.CompilerUtil;
|
||||
import com.intellij.compiler.impl.FileProcessingCompilerStateCache;
|
||||
import com.intellij.compiler.impl.packagingCompiler.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.application.Result;
|
||||
import com.intellij.openapi.compiler.*;
|
||||
import com.intellij.openapi.compiler.make.BuildParticipant;
|
||||
import com.intellij.openapi.compiler.make.BuildParticipantProvider;
|
||||
import com.intellij.openapi.deployment.DeploymentUtil;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.module.Module;
|
||||
import com.intellij.openapi.module.ModuleManager;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.JarFileSystem;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VfsUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.newvfs.RefreshQueue;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.packaging.artifacts.ArtifactManager;
|
||||
import com.intellij.packaging.artifacts.ArtifactProperties;
|
||||
import com.intellij.packaging.artifacts.ArtifactPropertiesProvider;
|
||||
import com.intellij.packaging.elements.CompositePackagingElement;
|
||||
import com.intellij.packaging.elements.PackagingElementResolvingContext;
|
||||
import com.intellij.packaging.impl.artifacts.ArtifactValidationUtil;
|
||||
import com.intellij.testFramework.LightVirtualFile;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ThrowableRunnable;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class IncrementalArtifactsCompiler implements PackagingCompiler {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.packaging.impl.compiler.IncrementalArtifactsCompiler");
|
||||
private static final Key<Set<String>> WRITTEN_PATHS_KEY = Key.create("artifacts_written_paths");
|
||||
private static final Key<List<String>> FILES_TO_DELETE_KEY = Key.create("artifacts_files_to_delete");
|
||||
private static final Key<Set<Artifact>> AFFECTED_ARTIFACTS = Key.create("affected_artifacts");
|
||||
private static final Key<ArtifactsProcessingItemsBuilderContext> BUILDER_CONTEXT_KEY = Key.create("artifacts_builder_context");
|
||||
@Nullable private PackagingCompilerCache myOutputItemsCache;
|
||||
|
||||
@Nullable
|
||||
public static IncrementalArtifactsCompiler getInstance(@NotNull Project project) {
|
||||
final IncrementalArtifactsCompiler[] compilers = CompilerManager.getInstance(project).getCompilers(IncrementalArtifactsCompiler.class);
|
||||
return compilers.length == 1 ? compilers[0] : null;
|
||||
}
|
||||
|
||||
private static ArtifactPackagingProcessingItem[] collectItems(ArtifactsProcessingItemsBuilderContext builderContext, final Project project) {
|
||||
final CompileContext context = builderContext.getCompileContext();
|
||||
|
||||
final Set<Artifact> artifactsToBuild = ArtifactCompileScope.getArtifactsToBuild(project, context.getCompileScope());
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("artifacts to build: " + artifactsToBuild);
|
||||
}
|
||||
List<Artifact> additionalArtifacts = new ArrayList<Artifact>();
|
||||
for (BuildParticipantProvider provider : BuildParticipantProvider.EXTENSION_POINT_NAME.getExtensions()) {
|
||||
for (Module module : ModuleManager.getInstance(project).getModules()) {
|
||||
final Collection<? extends BuildParticipant> participants = provider.getParticipants(module);
|
||||
for (BuildParticipant participant : participants) {
|
||||
ContainerUtil.addIfNotNull(participant.createArtifact(context), additionalArtifacts);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (LOG.isDebugEnabled() && !additionalArtifacts.isEmpty()) {
|
||||
LOG.debug("additional artifacts to build: " + additionalArtifacts);
|
||||
}
|
||||
artifactsToBuild.addAll(additionalArtifacts);
|
||||
|
||||
final List<Artifact> allArtifacts = new ArrayList<Artifact>(Arrays.asList(ArtifactManager.getInstance(project).getArtifacts()));
|
||||
allArtifacts.addAll(additionalArtifacts);
|
||||
for (Artifact artifact : allArtifacts) {
|
||||
final String outputPath = artifact.getOutputPath();
|
||||
if (outputPath != null && outputPath.length() != 0) {
|
||||
collectItems(builderContext, artifact, outputPath, project, artifactsToBuild.contains(artifact));
|
||||
}
|
||||
else if (artifactsToBuild.contains(artifact)) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "Cannot build '" + artifact.getName() + "' artifact: output path is not specified",
|
||||
null, -1, -1);
|
||||
}
|
||||
}
|
||||
context.putUserData(AFFECTED_ARTIFACTS, artifactsToBuild);
|
||||
return builderContext.getProcessingItems();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public ProcessingItem[] getProcessingItems(final CompileContext context) {
|
||||
return new ReadAction<ProcessingItem[]>() {
|
||||
protected void run(final Result<ProcessingItem[]> result) {
|
||||
final Project project = context.getProject();
|
||||
final Set<Artifact> selfIncludingArtifacts = ArtifactValidationUtil.getInstance(project).getSelfIncludingArtifacts();
|
||||
if (!selfIncludingArtifacts.isEmpty()) {
|
||||
LOG.info("Self including artifacts: " + selfIncludingArtifacts);
|
||||
if (!ArtifactCompileScope.getArtifactsToBuild(project, context.getCompileScope()).isEmpty()) {
|
||||
for (Artifact artifact : selfIncludingArtifacts) {
|
||||
context.addMessage(CompilerMessageCategory.ERROR, "Artifact '" + artifact.getName() + "' includes itself in the output layout", null, -1, -1);
|
||||
}
|
||||
}
|
||||
result.setResult(ProcessingItem.EMPTY_ARRAY);
|
||||
return;
|
||||
}
|
||||
|
||||
ArtifactsProcessingItemsBuilderContext builderContext = new ArtifactsProcessingItemsBuilderContext(context);
|
||||
context.putUserData(BUILDER_CONTEXT_KEY, builderContext);
|
||||
ArtifactPackagingProcessingItem[] allProcessingItems = collectItems(builderContext, project);
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
int num = Math.min(5000, allProcessingItems.length);
|
||||
LOG.debug("All files (" + num + " of " + allProcessingItems.length + "):");
|
||||
for (int i = 0; i < num; i++) {
|
||||
LOG.debug(allProcessingItems[i].getFile().getPath());
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
final FileProcessingCompilerStateCache cache =
|
||||
CompilerCacheManager.getInstance(project).getFileProcessingCompilerCache(IncrementalArtifactsCompiler.this);
|
||||
for (ArtifactPackagingProcessingItem item : allProcessingItems) {
|
||||
item.init(cache);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
context.requestRebuildNextTime(e.getMessage());
|
||||
context.addMessage(CompilerMessageCategory.ERROR, e.getMessage(), null, -1, -1);
|
||||
result.setResult(ProcessingItem.EMPTY_ARRAY);
|
||||
LOG.info(e);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean hasFilesToDelete = collectFilesToDelete(context, builderContext.getProcessingItems());
|
||||
if (hasFilesToDelete) {
|
||||
MockProcessingItem mockItem = new MockProcessingItem(new LightVirtualFile("239239293"));
|
||||
result.setResult(ArrayUtil.append(allProcessingItems, mockItem, ProcessingItem.class));
|
||||
}
|
||||
else {
|
||||
result.setResult(allProcessingItems);
|
||||
}
|
||||
}
|
||||
}.execute().getResultObject();
|
||||
}
|
||||
|
||||
private static void collectItems(@NotNull ArtifactsProcessingItemsBuilderContext builderContext,
|
||||
@NotNull Artifact artifact,
|
||||
@NotNull String outputPath,
|
||||
final Project project, boolean enable) {
|
||||
final CompositePackagingElement<?> rootElement = artifact.getRootElement();
|
||||
final VirtualFile outputFile = LocalFileSystem.getInstance().findFileByPath(outputPath);
|
||||
final CopyToDirectoryInstructionCreator instructionCreator =
|
||||
new CopyToDirectoryInstructionCreator(builderContext, outputPath, outputFile);
|
||||
final PackagingElementResolvingContext resolvingContext = ArtifactManager.getInstance(project).getResolvingContext();
|
||||
builderContext.setCollectingEnabledItems(enable);
|
||||
rootElement.computeIncrementalCompilerInstructions(instructionCreator, resolvingContext, builderContext, artifact.getArtifactType());
|
||||
}
|
||||
|
||||
public ProcessingItem[] process(final CompileContext context, final ProcessingItem[] items) {
|
||||
final Set<String> deletedJars = deleteOutdatedFiles(context);
|
||||
|
||||
final List<ArtifactPackagingProcessingItem> processedItems = new ArrayList<ArtifactPackagingProcessingItem>();
|
||||
final Set<String> writtenPaths = createPathsHashSet();
|
||||
final Ref<Boolean> built = Ref.create(false);
|
||||
CompilerUtil.runInContext(context, "Copying files", new ThrowableRunnable<RuntimeException>() {
|
||||
public void run() throws RuntimeException {
|
||||
built.set(doBuild(context, items, processedItems, writtenPaths, deletedJars));
|
||||
}
|
||||
});
|
||||
if (!built.get()) {
|
||||
return ProcessingItem.EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
context.getProgressIndicator().setText(CompilerBundle.message("packaging.compiler.message.updating.caches"));
|
||||
context.getProgressIndicator().setText2("");
|
||||
refreshOutputFiles(writtenPaths);
|
||||
new ReadAction() {
|
||||
protected void run(final Result result) {
|
||||
processDestinations(processedItems);
|
||||
}
|
||||
}.execute();
|
||||
removeInvalidItems(processedItems);
|
||||
updateOutputCache(context.getProject(), processedItems);
|
||||
context.putUserData(WRITTEN_PATHS_KEY, writtenPaths);
|
||||
return processedItems.toArray(new ProcessingItem[processedItems.size()]);
|
||||
}
|
||||
|
||||
private static boolean doBuild(final CompileContext context,
|
||||
final ProcessingItem[] items,
|
||||
final List<ArtifactPackagingProcessingItem> processedItems,
|
||||
final Set<String> writtenPaths,
|
||||
final Set<String> deletedJars) {
|
||||
final boolean testMode = ApplicationManager.getApplication().isUnitTestMode();
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
int num = Math.min(200, items.length);
|
||||
LOG.debug("Files to process (" + num + " of " + items.length + "):");
|
||||
for (int i = 0; i < num; i++) {
|
||||
LOG.debug(items[i].getFile().getPath());
|
||||
}
|
||||
}
|
||||
final DeploymentUtil deploymentUtil = DeploymentUtil.getInstance();
|
||||
final FileFilter fileFilter = new IgnoredFileFilter();
|
||||
final ArtifactsProcessingItemsBuilderContext builderContext = context.getUserData(BUILDER_CONTEXT_KEY);
|
||||
final Set<JarInfo> changedJars = new THashSet<JarInfo>();
|
||||
for (String deletedJar : deletedJars) {
|
||||
ContainerUtil.addIfNotNull(builderContext.getJarInfo(deletedJar), changedJars);
|
||||
}
|
||||
|
||||
try {
|
||||
onBuildStartedOrFinished(builderContext, false);
|
||||
if (context.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
for (final ProcessingItem item0 : items) {
|
||||
if (item0 instanceof MockProcessingItem) continue;
|
||||
final ArtifactPackagingProcessingItem item = (ArtifactPackagingProcessingItem)item0;
|
||||
context.getProgressIndicator().checkCanceled();
|
||||
|
||||
final Ref<IOException> exception = Ref.create(null);
|
||||
new ReadAction() {
|
||||
protected void run(final Result result) {
|
||||
final File fromFile = VfsUtil.virtualToIoFile(item.getFile());
|
||||
for (DestinationInfo destination : item.getEnabledDestinations()) {
|
||||
if (destination instanceof ExplodedDestinationInfo) {
|
||||
final ExplodedDestinationInfo explodedDestination = (ExplodedDestinationInfo)destination;
|
||||
File toFile = new File(FileUtil.toSystemDependentName(explodedDestination.getOutputPath()));
|
||||
if (fromFile.exists()) {
|
||||
try {
|
||||
deploymentUtil.copyFile(fromFile, toFile, context, writtenPaths, fileFilter);
|
||||
}
|
||||
catch (IOException e) {
|
||||
exception.set(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
changedJars.add(((JarDestinationInfo)destination).getJarInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
}.execute();
|
||||
if (exception.get() != null) {
|
||||
throw exception.get();
|
||||
}
|
||||
|
||||
context.getProgressIndicator().setFraction(++i * 1.0 / items.length);
|
||||
processedItems.add(item);
|
||||
if (testMode) {
|
||||
CompilerManagerImpl.addRecompiledPath(FileUtil.toSystemDependentName(item.getFile().getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
JarsBuilder builder = new JarsBuilder(changedJars, fileFilter, context);
|
||||
final boolean processed = builder.buildJars(writtenPaths);
|
||||
if (!processed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Set<VirtualFile> recompiledSources = new HashSet<VirtualFile>();
|
||||
for (JarInfo info : builder.getJarsToBuild()) {
|
||||
for (Pair<String, VirtualFile> pair : info.getPackedFiles()) {
|
||||
recompiledSources.add(pair.getSecond());
|
||||
}
|
||||
}
|
||||
for (ArtifactPackagingProcessingItem processedItem : processedItems) {
|
||||
recompiledSources.remove(processedItem.getFile());
|
||||
}
|
||||
for (VirtualFile source : recompiledSources) {
|
||||
ArtifactPackagingProcessingItem item = builderContext.getItemBySource(source);
|
||||
LOG.assertTrue(item != null, source);
|
||||
processedItems.add(item);
|
||||
if (testMode) {
|
||||
CompilerManagerImpl.addRecompiledPath(FileUtil.toSystemDependentName(item.getFile().getPath()));
|
||||
}
|
||||
}
|
||||
|
||||
onBuildStartedOrFinished(builderContext, true);
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.info(e);
|
||||
context.addMessage(CompilerMessageCategory.ERROR, e.getLocalizedMessage(), null, -1, -1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static Set<Artifact> getAffectedArtifacts(final CompileContext compileContext) {
|
||||
return compileContext.getUserData(AFFECTED_ARTIFACTS);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Set<String> getWrittenPaths(@NotNull CompileContext context) {
|
||||
return context.getUserData(WRITTEN_PATHS_KEY);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getDescription() {
|
||||
return "Artifacts Packaging Compiler";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private PackagingCompilerCache getOutputItemsCache(final Project project) {
|
||||
if (myOutputItemsCache == null) {
|
||||
myOutputItemsCache = new PackagingCompilerCache(
|
||||
CompilerPaths.getCompilerSystemDirectory(project).getPath() + File.separator + "incremental_artifacts_timestamp.dat");
|
||||
}
|
||||
return myOutputItemsCache;
|
||||
}
|
||||
|
||||
public void processOutdatedItem(final CompileContext context, final String url, @Nullable final ValidityState state) {
|
||||
}
|
||||
|
||||
private boolean collectFilesToDelete(final CompileContext context, final ArtifactPackagingProcessingItem[] allProcessingItems) {
|
||||
List<String> filesToDelete = new ArrayList<String>();
|
||||
Set<String> outputPaths = createPathsHashSet();
|
||||
for (ArtifactPackagingProcessingItem item : allProcessingItems) {
|
||||
for (Pair<DestinationInfo, Boolean> destinationInfo : item.getDestinations()) {
|
||||
String outputPath = getOutputPathWithJarSeparator(destinationInfo.getFirst());
|
||||
outputPaths.add(outputPath);
|
||||
}
|
||||
}
|
||||
|
||||
final Iterator<String> pathIterator = getOutputItemsCache(context.getProject()).getUrlsIterator();
|
||||
while (pathIterator.hasNext()) {
|
||||
String path = pathIterator.next();
|
||||
if (!outputPaths.contains(path)) {
|
||||
filesToDelete.add(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Files to delete (" + filesToDelete.size() + "):");
|
||||
for (String path : filesToDelete) {
|
||||
LOG.debug(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (filesToDelete.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
context.putUserData(FILES_TO_DELETE_KEY, filesToDelete);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static String getOutputPathWithJarSeparator(DestinationInfo destinationInfo) {
|
||||
String outputPath = destinationInfo.getOutputFilePath();
|
||||
if (destinationInfo instanceof JarDestinationInfo) {
|
||||
final String fullOutputPath = destinationInfo.getOutputPath();
|
||||
final String fileOutputPath = destinationInfo.getOutputFilePath();
|
||||
if (fullOutputPath.startsWith(fileOutputPath)) {
|
||||
outputPath += JarFileSystem.JAR_SEPARATOR + DeploymentUtil.trimForwardSlashes(fullOutputPath.substring(fileOutputPath.length()));
|
||||
}
|
||||
}
|
||||
return outputPath;
|
||||
}
|
||||
|
||||
private static void onBuildStartedOrFinished(ArtifactsProcessingItemsBuilderContext context, final boolean finished) throws Exception {
|
||||
final CompileContext compileContext = context.getCompileContext();
|
||||
final Set<Artifact> artifacts = getAffectedArtifacts(compileContext);
|
||||
for (Artifact artifact : artifacts) {
|
||||
for (ArtifactPropertiesProvider provider : artifact.getPropertiesProviders()) {
|
||||
final ArtifactProperties<?> properties = artifact.getProperties(provider);
|
||||
if (finished) {
|
||||
properties.onBuildFinished(artifact, compileContext);
|
||||
}
|
||||
else {
|
||||
properties.onBuildStarted(artifact, compileContext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static THashSet<String> createPathsHashSet() {
|
||||
return SystemInfo.isFileSystemCaseSensitive
|
||||
? new THashSet<String>()
|
||||
: new THashSet<String>(CaseInsensitiveStringHashingStrategy.INSTANCE);
|
||||
}
|
||||
|
||||
private static void removeInvalidItems(List<ArtifactPackagingProcessingItem> processedItems) {
|
||||
Set<VirtualFile> files = new THashSet<VirtualFile>(processedItems.size());
|
||||
for (ArtifactPackagingProcessingItem item : processedItems) {
|
||||
files.add(item.getFile());
|
||||
}
|
||||
RefreshQueue.getInstance().refresh(false, false, null, VfsUtil.toVirtualFileArray(files));
|
||||
|
||||
final Iterator<ArtifactPackagingProcessingItem> iterator = processedItems.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
ArtifactPackagingProcessingItem item = iterator.next();
|
||||
final VirtualFile file = item.getFile();
|
||||
if (!file.isValid()) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void processDestinations(final List<ArtifactPackagingProcessingItem> items) {
|
||||
for (ArtifactPackagingProcessingItem item : items) {
|
||||
item.setProcessed();
|
||||
}
|
||||
}
|
||||
|
||||
private Set<String> deleteOutdatedFiles(final CompileContext context) {
|
||||
context.getProgressIndicator().setText(CompilerBundle.message("packaging.compiler.message.deleting.outdated.files"));
|
||||
final List<String> filesToDelete = context.getUserData(FILES_TO_DELETE_KEY);
|
||||
final Set<String> deletedJars;
|
||||
if (filesToDelete != null) {
|
||||
deletedJars = deleteFiles(filesToDelete, context);
|
||||
}
|
||||
else {
|
||||
deletedJars = Collections.emptySet();
|
||||
}
|
||||
context.getProgressIndicator().checkCanceled();
|
||||
return deletedJars;
|
||||
}
|
||||
|
||||
private Set<String> deleteFiles(final List<String> paths, CompileContext context) {
|
||||
final Set<Artifact> artifactsToBuild = getAffectedArtifacts(context);
|
||||
|
||||
final boolean testMode = ApplicationManager.getApplication().isUnitTestMode();
|
||||
final THashSet<String> deletedJars = new THashSet<String>();
|
||||
final THashSet<String> notDeletedJars = new THashSet<String>();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Deleting outdated files...");
|
||||
}
|
||||
|
||||
int notDeletedFilesCount = 0;
|
||||
final Artifact[] allArtifacts = ArtifactManager.getInstance(context.getProject()).getArtifacts();
|
||||
List<File> filesToRefresh = new ArrayList<File>();
|
||||
for (String fullPath : paths) {
|
||||
boolean isUnderOutput = false;
|
||||
boolean isInArtifactsToBuild = false;
|
||||
for (Artifact artifact : allArtifacts) {
|
||||
final String path = artifact.getOutputPath();
|
||||
if (!StringUtil.isEmpty(path) && FileUtil.startsWith(fullPath, path)) {
|
||||
isUnderOutput = true;
|
||||
if (artifactsToBuild.contains(artifact)) {
|
||||
isInArtifactsToBuild = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isUnderOutput && !isInArtifactsToBuild) continue;
|
||||
|
||||
int end = fullPath.indexOf(JarFileSystem.JAR_SEPARATOR);
|
||||
boolean isJar = end != -1;
|
||||
String filePath = isJar ? fullPath.substring(0, end) : fullPath;
|
||||
boolean deleted = false;
|
||||
if (isJar) {
|
||||
if (notDeletedJars.contains(filePath)) {
|
||||
continue;
|
||||
}
|
||||
deleted = deletedJars.contains(filePath);
|
||||
}
|
||||
|
||||
File file = new File(FileUtil.toSystemDependentName(filePath));
|
||||
if (!deleted) {
|
||||
filesToRefresh.add(file);
|
||||
deleted = FileUtil.delete(file);
|
||||
}
|
||||
|
||||
if (deleted) {
|
||||
if (isJar) {
|
||||
deletedJars.add(filePath);
|
||||
}
|
||||
if (testMode) {
|
||||
CompilerManagerImpl.addDeletedPath(file.getAbsolutePath());
|
||||
}
|
||||
getOutputItemsCache(context.getProject()).remove(fullPath);
|
||||
}
|
||||
else {
|
||||
if (isJar) {
|
||||
notDeletedJars.add(filePath);
|
||||
}
|
||||
if (notDeletedFilesCount++ > 50) {
|
||||
context.addMessage(CompilerMessageCategory.WARNING, "Deletion of outdated files stopped because too many files cannot be deleted", null, -1, -1);
|
||||
break;
|
||||
}
|
||||
context.addMessage(CompilerMessageCategory.WARNING, "Cannot delete file '" + filePath + "'", null, -1, -1);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Cannot delete file " + file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CompilerUtil.refreshIOFiles(filesToRefresh);
|
||||
return deletedJars;
|
||||
}
|
||||
|
||||
private void updateOutputCache(final Project project, final List<ArtifactPackagingProcessingItem> processedItems) {
|
||||
for (ArtifactPackagingProcessingItem processedItem : processedItems) {
|
||||
for (DestinationInfo destinationInfo : processedItem.getEnabledDestinations()) {
|
||||
final VirtualFile virtualFile = destinationInfo.getOutputFile();
|
||||
if (virtualFile != null) {
|
||||
final String path = getOutputPathWithJarSeparator(destinationInfo);
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("update output cache: file " + path);
|
||||
}
|
||||
getOutputItemsCache(project).update(path, virtualFile.getTimeStamp());
|
||||
}
|
||||
}
|
||||
}
|
||||
saveCacheIfDirty(project);
|
||||
}
|
||||
|
||||
private static void refreshOutputFiles(Set<String> writtenPaths) {
|
||||
final ArrayList<File> filesToRefresh = new ArrayList<File>();
|
||||
for (String path : writtenPaths) {
|
||||
filesToRefresh.add(new File(path));
|
||||
}
|
||||
CompilerUtil.refreshIOFiles(filesToRefresh);
|
||||
}
|
||||
|
||||
private void saveCacheIfDirty(final Project project) {
|
||||
if (getOutputItemsCache(project).isDirty()) {
|
||||
getOutputItemsCache(project).save();
|
||||
}
|
||||
}
|
||||
|
||||
public ValidityState createValidityState(final DataInput is) throws IOException {
|
||||
return new ArtifactPackagingItemValidityState(is);
|
||||
}
|
||||
|
||||
public boolean validateConfiguration(final CompileScope scope) {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static class MockProcessingItem implements ProcessingItem {
|
||||
private final VirtualFile myFile;
|
||||
|
||||
public MockProcessingItem(final VirtualFile file) {
|
||||
myFile = file;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public VirtualFile getFile() {
|
||||
return myFile;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ValidityState getValidityState() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -30,8 +30,8 @@ public class PackIntoArchiveInstructionCreator extends IncrementalCompilerInstru
|
||||
private final JarInfo myJarInfo;
|
||||
private final String myPathInJar;
|
||||
|
||||
public PackIntoArchiveInstructionCreator(ArtifactsProcessingItemsBuilderContext context, JarInfo jarInfo, String pathInJar,
|
||||
DestinationInfo jarDestination) {
|
||||
public PackIntoArchiveInstructionCreator(ArtifactsProcessingItemsBuilderContext context, JarInfo jarInfo,
|
||||
String pathInJar, DestinationInfo jarDestination) {
|
||||
super(context);
|
||||
myJarInfo = jarInfo;
|
||||
myPathInJar = pathInJar;
|
||||
@@ -55,7 +55,8 @@ public class PackIntoArchiveInstructionCreator extends IncrementalCompilerInstru
|
||||
|
||||
public IncrementalCompilerInstructionCreator archive(@NotNull String archiveFileName) {
|
||||
final JarInfo jarInfo = new JarInfo();
|
||||
if (!myContext.registerJarFile(jarInfo, myJarDestination.getOutputPath() + "/" + archiveFileName)) {
|
||||
final String outputPath = myJarDestination.getOutputPath() + "/" + archiveFileName;
|
||||
if (!myContext.registerJarFile(jarInfo, outputPath)) {
|
||||
return new SkipAllInstructionCreator(myContext);
|
||||
}
|
||||
final JarDestinationInfo destination = new JarDestinationInfo(childPathInJar(archiveFileName), myJarInfo, myJarDestination);
|
||||
|
||||
@@ -249,13 +249,19 @@ public class ManifestFileUtil {
|
||||
VirtualFile dir = files[0];
|
||||
try {
|
||||
if (!dir.getName().equals(MANIFEST_DIR_NAME)) {
|
||||
VirtualFile newDir = dir.findChild(MANIFEST_DIR_NAME);
|
||||
if (newDir == null) {
|
||||
newDir = dir.createChildDirectory(this, MANIFEST_DIR_NAME);
|
||||
}
|
||||
dir = newDir;
|
||||
dir = VfsUtil.createDirectoryIfMissing(dir, MANIFEST_DIR_NAME);
|
||||
}
|
||||
result.setResult(dir.createChildData(this, MANIFEST_FILE_NAME));
|
||||
final VirtualFile file = dir.createChildData(this, MANIFEST_FILE_NAME);
|
||||
final OutputStream output = file.getOutputStream(this);
|
||||
try {
|
||||
final Manifest manifest = new Manifest();
|
||||
ManifestBuilder.setVersionAttribute(manifest.getMainAttributes());
|
||||
manifest.write(output);
|
||||
}
|
||||
finally {
|
||||
output.close();
|
||||
}
|
||||
result.setResult(file);
|
||||
}
|
||||
catch (IOException e) {
|
||||
exc.set(e);
|
||||
|
||||
+2
-2
@@ -35,7 +35,7 @@ import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.packaging.artifacts.*;
|
||||
import com.intellij.packaging.impl.compiler.ArtifactAwareCompiler;
|
||||
import com.intellij.packaging.impl.compiler.ArtifactCompileScope;
|
||||
import com.intellij.packaging.impl.compiler.IncrementalArtifactsCompiler;
|
||||
import com.intellij.packaging.impl.compiler.ArtifactsCompiler;
|
||||
import com.intellij.util.concurrency.Semaphore;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashSet;
|
||||
@@ -148,7 +148,7 @@ public class BuildArtifactsBeforeRunTaskProvider extends BeforeRunTaskProvider<B
|
||||
};
|
||||
final CompilerFilter compilerFilter = new CompilerFilter() {
|
||||
public boolean acceptCompiler(Compiler compiler) {
|
||||
return compiler instanceof IncrementalArtifactsCompiler
|
||||
return compiler instanceof ArtifactsCompiler
|
||||
|| compiler instanceof ArtifactAwareCompiler && ((ArtifactAwareCompiler)compiler).shouldRun(artifacts);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -18,6 +18,8 @@ package com.intellij.lang.java.parser;
|
||||
import com.intellij.codeInsight.daemon.JavaErrorMessages;
|
||||
import com.intellij.lang.LighterASTNode;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
@@ -36,6 +38,8 @@ public class DeclarationParser {
|
||||
FILE, CLASS, CODE_BLOCK, ANNOTATION_INTERFACE
|
||||
}
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.lang.java.parser.DeclarationParser");
|
||||
|
||||
private static final TokenSet AFTER_END_DECLARATION_SET = TokenSet.create(JavaElementType.FIELD, JavaElementType.METHOD);
|
||||
|
||||
private DeclarationParser() { }
|
||||
@@ -48,10 +52,11 @@ public class DeclarationParser {
|
||||
marker.drop();
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder builderWrapper = braceMatchingBuilder(builder);
|
||||
if (isEnum) {
|
||||
parseEnumConstants(builder);
|
||||
parseEnumConstants(builderWrapper);
|
||||
}
|
||||
parseClassBodyDeclarations(builder, isAnnotation);
|
||||
parseClassBodyDeclarations(builderWrapper, isAnnotation);
|
||||
|
||||
expectOrError(builder, JavaTokenType.RBRACE, JavaErrorMessages.message("expected.rbrace"));
|
||||
|
||||
@@ -186,10 +191,11 @@ public class DeclarationParser {
|
||||
|
||||
final PsiBuilder.Marker declaration = builder.mark();
|
||||
|
||||
final PsiBuilder.Marker modList = parseModifierList(builder);
|
||||
final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
|
||||
final PsiBuilder.Marker modList = modListInfo.first;
|
||||
|
||||
if (expect(builder, JavaTokenType.AT)) {
|
||||
if (tokenType == JavaTokenType.INTERFACE_KEYWORD) {
|
||||
if (builder.getTokenType() == JavaTokenType.INTERFACE_KEYWORD) {
|
||||
return parseClassFromKeyword(builder, declaration, true);
|
||||
}
|
||||
else {
|
||||
@@ -197,9 +203,8 @@ public class DeclarationParser {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else if (ElementType.CLASS_KEYWORD_BIT_SET.contains(tokenType)) {
|
||||
else if (ElementType.CLASS_KEYWORD_BIT_SET.contains(builder.getTokenType())) {
|
||||
final PsiBuilder.Marker root = parseClassFromKeyword(builder, declaration, false);
|
||||
|
||||
if (context == Context.FILE) {
|
||||
// todo: append following declarations to root
|
||||
boolean declarationsAfterEnd = false;
|
||||
@@ -233,29 +238,113 @@ public class DeclarationParser {
|
||||
}
|
||||
|
||||
if (context == Context.FILE) {
|
||||
if (typeParams == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.class.or.interface"));
|
||||
}
|
||||
else {
|
||||
typeParams.precede().errorBefore(JavaErrorMessages.message("expected.class.or.interface"), typeParams);
|
||||
}
|
||||
error(builder, JavaErrorMessages.message("expected.class.or.interface"), typeParams);
|
||||
declaration.drop();
|
||||
return modList;
|
||||
}
|
||||
|
||||
// todo: implement
|
||||
throw new UnsupportedOperationException(builder.toString() + context);
|
||||
PsiBuilder.Marker type;
|
||||
if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(builder.getTokenType())) {
|
||||
type = parseTypeNotNull(builder);
|
||||
}
|
||||
else if (builder.getTokenType() == JavaTokenType.IDENTIFIER) {
|
||||
final PsiBuilder.Marker idPos = builder.mark();
|
||||
type = parseTypeNotNull(builder);
|
||||
if (builder.getTokenType() == JavaTokenType.LPARENTH) { // constructor
|
||||
if (context == Context.CODE_BLOCK) {
|
||||
declaration.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
idPos.rollbackTo();
|
||||
if (typeParams == null) {
|
||||
emptyElement(builder, JavaElementType.TYPE_PARAMETER_LIST);
|
||||
}
|
||||
builder.advanceLexer();
|
||||
if (builder.getTokenType() != JavaTokenType.LPARENTH) {
|
||||
declaration.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
return parseMethodFromLeftParenth(builder, declaration, false);
|
||||
}
|
||||
idPos.drop();
|
||||
}
|
||||
else if (builder.getTokenType() == JavaTokenType.LBRACE) {
|
||||
if (context == Context.CODE_BLOCK) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier.or.type"), typeParams);
|
||||
declaration.drop();
|
||||
return modList;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker codeBlock = StatementParser.parseCodeBlock(builder);
|
||||
LOG.assertTrue(codeBlock != null);
|
||||
|
||||
if (typeParams != null) {
|
||||
final PsiBuilder.Marker error = typeParams.precede();
|
||||
error.errorBefore(JavaErrorMessages.message("unexpected.token"), codeBlock);
|
||||
}
|
||||
declaration.done(JavaElementType.CLASS_INITIALIZER);
|
||||
return declaration;
|
||||
}
|
||||
else {
|
||||
final PsiBuilder.Marker error;
|
||||
if (typeParams != null) {
|
||||
error = typeParams.precede();
|
||||
}
|
||||
else {
|
||||
error = builder.mark();
|
||||
}
|
||||
error.error(JavaErrorMessages.message("expected.identifier.or.type"));
|
||||
return modList;
|
||||
}
|
||||
|
||||
if (!expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
if (context == Context.CODE_BLOCK && modListInfo.second) {
|
||||
declaration.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
if (typeParams != null) {
|
||||
typeParams.precede().errorBefore(JavaErrorMessages.message("unexpected.token"), type);
|
||||
}
|
||||
builder.error(JavaErrorMessages.message("expected.identifier"));
|
||||
declaration.drop();
|
||||
return modList;
|
||||
}
|
||||
}
|
||||
|
||||
if (builder.getTokenType() == JavaTokenType.LPARENTH) {
|
||||
if (context == Context.CLASS || context == Context.ANNOTATION_INTERFACE) { // method
|
||||
if (typeParams == null) {
|
||||
emptyElement(type, JavaElementType.TYPE_PARAMETER_LIST);
|
||||
}
|
||||
return parseMethodFromLeftParenth(builder, declaration, (context == Context.ANNOTATION_INTERFACE));
|
||||
}
|
||||
}
|
||||
|
||||
if (typeParams != null) {
|
||||
typeParams.precede().errorBefore(JavaErrorMessages.message("unexpected.token"), type);
|
||||
}
|
||||
return parseFieldOrLocalVariable(builder, declaration, context);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseModifierList(final PsiBuilder builder) {
|
||||
private static PsiBuilder.Marker parseTypeNotNull(final PsiBuilder builder) {
|
||||
final ReferenceParser.TypeInfo typeInfo = ReferenceParser.parseType(builder);
|
||||
assert typeInfo != null : builder.getOriginalText();
|
||||
return typeInfo.marker;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Pair<PsiBuilder.Marker, Boolean> parseModifierList(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker modList = builder.mark();
|
||||
boolean isEmpty = true;
|
||||
|
||||
while (true) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == null) break;
|
||||
if (ElementType.MODIFIER_BIT_SET.contains(tokenType)) {
|
||||
builder.advanceLexer();
|
||||
isEmpty = false;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.AT) {
|
||||
final PsiBuilder.Marker pos = builder.mark();
|
||||
@@ -266,6 +355,7 @@ public class DeclarationParser {
|
||||
break;
|
||||
}
|
||||
parseAnnotation(builder);
|
||||
isEmpty = false;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
@@ -273,7 +363,225 @@ public class DeclarationParser {
|
||||
}
|
||||
|
||||
modList.done(JavaElementType.MODIFIER_LIST);
|
||||
return modList;
|
||||
return Pair.create(modList, isEmpty);
|
||||
}
|
||||
|
||||
private static PsiBuilder.Marker parseMethodFromLeftParenth(final PsiBuilder builder, final PsiBuilder.Marker declaration,
|
||||
final boolean anno) {
|
||||
parseParameterList(builder);
|
||||
|
||||
eatBrackets(builder);
|
||||
|
||||
if (areTypeAnnotationsSupported(builder)) {
|
||||
final PsiBuilder.Marker receiver = builder.mark();
|
||||
final PsiBuilder.Marker annotations = parseAnnotations(builder);
|
||||
if (annotations != null) {
|
||||
receiver.done(JavaElementType.METHOD_RECEIVER);
|
||||
}
|
||||
else {
|
||||
receiver.drop();
|
||||
}
|
||||
}
|
||||
|
||||
ReferenceParser.parseReferenceList(builder, JavaTokenType.THROWS_KEYWORD, JavaElementType.THROWS_LIST, JavaTokenType.COMMA);
|
||||
|
||||
if (anno && expect(builder, JavaTokenType.DEFAULT_KEYWORD)) {
|
||||
parseAnnotationValue(builder);
|
||||
}
|
||||
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == JavaTokenType.SEMICOLON) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
else if (tokenType == JavaTokenType.LBRACE) {
|
||||
StatementParser.parseCodeBlock(builder);
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.lbrace.or.semicolon"));
|
||||
// todo: special treatment - like in fields (DeclarationParserTest.testMultiLineUnclosed())
|
||||
}
|
||||
|
||||
declaration.done(anno ? JavaElementType.ANNOTATION_METHOD : JavaElementType.METHOD);
|
||||
return declaration;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseParameterList(final PsiBuilder builder) {
|
||||
assert builder.getTokenType() == JavaTokenType.LPARENTH : builder.getTokenType();
|
||||
final PsiBuilder.Marker paramList = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
PsiBuilder.Marker invalidElements = null;
|
||||
boolean commaExpected = false;
|
||||
int paramCount = 0;
|
||||
while (true) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
if (tokenType == null || tokenType == JavaTokenType.RPARENTH) {
|
||||
boolean noLastParam = !commaExpected && paramCount > 0;
|
||||
if (noLastParam) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier.or.type"));
|
||||
}
|
||||
if (!expect(builder, JavaTokenType.RPARENTH)) {
|
||||
if (!noLastParam) {
|
||||
error(builder, JavaErrorMessages.message("expected.rparen"));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (commaExpected) {
|
||||
if (builder.getTokenType() == JavaTokenType.COMMA) {
|
||||
commaExpected = false;
|
||||
if (invalidElements != null) {
|
||||
invalidElements.error(JavaErrorMessages.message("expected.parameter"));
|
||||
invalidElements = null;
|
||||
}
|
||||
builder.advanceLexer();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
final PsiBuilder.Marker param = parseParameter(builder, true);
|
||||
if (param != null) {
|
||||
commaExpected = true;
|
||||
if (invalidElements != null) {
|
||||
invalidElements.errorBefore(JavaErrorMessages.message("expected.comma"), param);
|
||||
invalidElements = null;
|
||||
}
|
||||
paramCount++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidElements == null) {
|
||||
if (builder.getTokenType() == JavaTokenType.COMMA) {
|
||||
error(builder, JavaErrorMessages.message("expected.parameter"));
|
||||
builder.advanceLexer();
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
invalidElements = builder.mark();
|
||||
}
|
||||
}
|
||||
|
||||
// adding a reference, not simple tokens allows "Browse .." to work well
|
||||
final PsiBuilder.Marker ref = ReferenceParser.parseJavaCodeReference(builder, true, true, false);
|
||||
if (ref == null && builder.getTokenType() != null) {
|
||||
builder.advanceLexer();
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidElements != null) {
|
||||
invalidElements.error(commaExpected ? JavaErrorMessages.message("expected.comma") : JavaErrorMessages.message("expected.parameter"));
|
||||
}
|
||||
|
||||
paramList.done(JavaElementType.PARAMETER_LIST);
|
||||
return paramList;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseParameter(final PsiBuilder builder, final boolean ellipsis) {
|
||||
final PsiBuilder.Marker param = builder.mark();
|
||||
|
||||
final Pair<PsiBuilder.Marker, Boolean> modListInfo = parseModifierList(builder);
|
||||
final PsiBuilder.Marker type = ellipsis ? ReferenceParser.parseTypeWithEllipsis(builder, true, true) :
|
||||
ReferenceParser.parseType(builder, true, true);
|
||||
|
||||
if (type == null && modListInfo.second) {
|
||||
param.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
|
||||
if (type == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.type"));
|
||||
emptyElement(builder, JavaElementType.TYPE);
|
||||
}
|
||||
|
||||
if (expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
eatBrackets(builder);
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
}
|
||||
|
||||
param.done(JavaElementType.PARAMETER);
|
||||
return param;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiBuilder.Marker parseFieldOrLocalVariable(final PsiBuilder builder, final PsiBuilder.Marker declaration,
|
||||
final Context context) {
|
||||
final IElementType varType;
|
||||
if (context == Context.CLASS || context == Context.ANNOTATION_INTERFACE) {
|
||||
varType = JavaElementType.FIELD;
|
||||
}
|
||||
else if (context == Context.CODE_BLOCK) {
|
||||
varType = JavaElementType.LOCAL_VARIABLE;
|
||||
}
|
||||
else {
|
||||
LOG.error("Unexpected context: " + context);
|
||||
declaration.drop();
|
||||
return null;
|
||||
}
|
||||
|
||||
PsiBuilder.Marker variable = declaration;
|
||||
boolean openMarker = true;
|
||||
boolean eatSemicolon = true;
|
||||
boolean expectSemicolon = true;
|
||||
while (true) {
|
||||
if (!eatBrackets(builder)) {
|
||||
expectSemicolon = false;
|
||||
}
|
||||
|
||||
if (expect(builder, JavaTokenType.EQ)) {
|
||||
final PsiBuilder.Marker expr = ExpressionParser.parse(builder);
|
||||
if (expr == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
expectSemicolon = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (builder.getTokenType() == JavaTokenType.COMMA) {
|
||||
variable.done(varType);
|
||||
builder.advanceLexer();
|
||||
variable = builder.mark();
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!expect(builder, JavaTokenType.IDENTIFIER)) {
|
||||
variable.drop();
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
openMarker = false;
|
||||
eatSemicolon = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (eatSemicolon) {
|
||||
if (!expect(builder, JavaTokenType.SEMICOLON) && expectSemicolon) {
|
||||
error(builder, JavaErrorMessages.message("expected.semicolon"));
|
||||
}
|
||||
// todo: special treatment - see DeclarationParserTest.testMultiLineUnclosed()
|
||||
}
|
||||
|
||||
if (openMarker) {
|
||||
variable.done(varType);
|
||||
}
|
||||
|
||||
return declaration;
|
||||
}
|
||||
|
||||
private static boolean eatBrackets(final PsiBuilder builder) {
|
||||
while (expect(builder, JavaTokenType.LBRACKET)) {
|
||||
if (!expect(builder, JavaTokenType.RBRACKET)) {
|
||||
error(builder, JavaErrorMessages.message("expected.rbracket"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -290,6 +598,7 @@ public class DeclarationParser {
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseAnnotation(final PsiBuilder builder) {
|
||||
assert builder.getTokenType() == JavaTokenType.AT : builder.getTokenType();
|
||||
final PsiBuilder.Marker anno = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
@@ -408,6 +717,7 @@ public class DeclarationParser {
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseAnnotationArrayInitializer(final PsiBuilder builder) {
|
||||
assert builder.getTokenType() == JavaTokenType.LBRACE : builder.getTokenType();
|
||||
final PsiBuilder.Marker annoArray = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
*/
|
||||
package com.intellij.lang.java.parser;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.PsiBuilderUtil;
|
||||
import com.intellij.lang.*;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import com.intellij.util.diff.FlyweightCapableTreeStructure;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
public class JavaParserUtil {
|
||||
@@ -40,7 +44,7 @@ public class JavaParserUtil {
|
||||
@NotNull
|
||||
private static LanguageLevel getLanguageLevel(final PsiBuilder builder) {
|
||||
final LanguageLevel level = builder.getUserData(LANG_LEVEL_KEY);
|
||||
assert level != null;
|
||||
assert level != null : builder;
|
||||
return level;
|
||||
}
|
||||
|
||||
@@ -49,6 +53,15 @@ public class JavaParserUtil {
|
||||
builder.mark().error(message);
|
||||
}
|
||||
|
||||
public static void error(final PsiBuilder builder, final String message, @Nullable final PsiBuilder.Marker before) {
|
||||
if (before == null) {
|
||||
error(builder, message);
|
||||
}
|
||||
else {
|
||||
before.precede().errorBefore(message, before);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean expectOrError(final PsiBuilder builder, final IElementType expectedType, final String errorMessage) {
|
||||
if (!PsiBuilderUtil.expect(builder, expectedType)) {
|
||||
error(builder, errorMessage);
|
||||
@@ -60,4 +73,106 @@ public class JavaParserUtil {
|
||||
public static void emptyElement(final PsiBuilder builder, final IElementType type) {
|
||||
builder.mark().done(type);
|
||||
}
|
||||
|
||||
public static void emptyElement(final PsiBuilder.Marker before, final IElementType type) {
|
||||
before.precede().doneBefore(type, before);
|
||||
}
|
||||
|
||||
public static PsiBuilder braceMatchingBuilder(final PsiBuilder builder) {
|
||||
return new PsiBuilderAdapter(builder) {
|
||||
private int braceCount = 1;
|
||||
private int lastOffset = -1;
|
||||
|
||||
@Override
|
||||
public IElementType getTokenType() {
|
||||
final IElementType tokenType = super.getTokenType();
|
||||
if (getCurrentOffset() != lastOffset) {
|
||||
if (tokenType == JavaTokenType.LBRACE) {
|
||||
braceCount++;
|
||||
}
|
||||
else if (tokenType == JavaTokenType.RBRACE) {
|
||||
braceCount--;
|
||||
}
|
||||
lastOffset = getCurrentOffset();
|
||||
}
|
||||
return (braceCount == 0 ? null : tokenType);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static class PsiBuilderAdapter implements PsiBuilder {
|
||||
protected final PsiBuilder myDelegate;
|
||||
|
||||
public PsiBuilderAdapter(final PsiBuilder delegate) {
|
||||
myDelegate = delegate;
|
||||
}
|
||||
|
||||
public CharSequence getOriginalText() {
|
||||
return myDelegate.getOriginalText();
|
||||
}
|
||||
|
||||
public void advanceLexer() {
|
||||
myDelegate.advanceLexer();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public IElementType getTokenType() {
|
||||
return myDelegate.getTokenType();
|
||||
}
|
||||
|
||||
public void setTokenTypeRemapper(final ITokenTypeRemapper remapper) {
|
||||
myDelegate.setTokenTypeRemapper(remapper);
|
||||
}
|
||||
|
||||
@Nullable @NonNls
|
||||
public String getTokenText() {
|
||||
return myDelegate.getTokenText();
|
||||
}
|
||||
|
||||
public int getCurrentOffset() {
|
||||
return myDelegate.getCurrentOffset();
|
||||
}
|
||||
|
||||
public Marker mark() {
|
||||
return myDelegate.mark();
|
||||
}
|
||||
|
||||
public void error(final String messageText) {
|
||||
myDelegate.error(messageText);
|
||||
}
|
||||
|
||||
public boolean eof() {
|
||||
return myDelegate.eof();
|
||||
}
|
||||
|
||||
public ASTNode getTreeBuilt() {
|
||||
return myDelegate.getTreeBuilt();
|
||||
}
|
||||
|
||||
public FlyweightCapableTreeStructure<LighterASTNode> getLightTree() {
|
||||
return myDelegate.getLightTree();
|
||||
}
|
||||
|
||||
public void setDebugMode(final boolean dbgMode) {
|
||||
myDelegate.setDebugMode(dbgMode);
|
||||
}
|
||||
|
||||
public void enforceCommentTokens(final TokenSet tokens) {
|
||||
myDelegate.enforceCommentTokens(tokens);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public LighterASTNode getLatestDoneMarker() {
|
||||
return myDelegate.getLatestDoneMarker();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public <T> T getUserData(@NotNull final Key<T> key) {
|
||||
return myDelegate.getUserData(key);
|
||||
}
|
||||
|
||||
public <T> void putUserData(@NotNull final Key<T> key, @Nullable final T value) {
|
||||
myDelegate.putUserData(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,21 @@ public class ReferenceParser {
|
||||
return typeInfo != null ? typeInfo.marker : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static PsiBuilder.Marker parseTypeWithEllipsis(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard) {
|
||||
final TypeInfo typeInfo = parseTypeWithInfo(builder, eatLastDot, wildcard);
|
||||
if (typeInfo == null) return null;
|
||||
|
||||
PsiBuilder.Marker type = typeInfo.marker;
|
||||
if (builder.getTokenType() == JavaTokenType.ELLIPSIS) {
|
||||
type = typeInfo.marker.precede();
|
||||
builder.advanceLexer();
|
||||
type.done(JavaElementType.TYPE);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static TypeInfo parseTypeWithInfo(final PsiBuilder builder, final boolean eatLastDot, final boolean wildcard) {
|
||||
if (builder.getTokenType() == null) return null;
|
||||
@@ -263,28 +278,26 @@ public class ReferenceParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (expect(builder, JavaTokenType.EXTENDS_KEYWORD)) {
|
||||
parseReferenceList(builder, JavaElementType.EXTENDS_BOUND_LIST, JavaTokenType.AND);
|
||||
}
|
||||
else {
|
||||
emptyElement(builder, JavaElementType.EXTENDS_BOUND_LIST);
|
||||
}
|
||||
parseReferenceList(builder, JavaTokenType.EXTENDS_KEYWORD, JavaElementType.EXTENDS_BOUND_LIST, JavaTokenType.AND);
|
||||
|
||||
param.done(JavaElementType.TYPE_PARAMETER);
|
||||
return param;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiBuilder.Marker parseReferenceList(final PsiBuilder builder, final IElementType type, final IElementType delimiter) {
|
||||
public static PsiBuilder.Marker parseReferenceList(final PsiBuilder builder, final IElementType start,
|
||||
final IElementType type, final IElementType delimiter) {
|
||||
final PsiBuilder.Marker element = builder.mark();
|
||||
|
||||
while (true) {
|
||||
final PsiBuilder.Marker classReference = parseJavaCodeReference(builder, true, true, true);
|
||||
if (classReference == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
}
|
||||
if (!expect(builder, delimiter)) {
|
||||
break;
|
||||
if (expect(builder, start)) {
|
||||
while (true) {
|
||||
final PsiBuilder.Marker classReference = parseJavaCodeReference(builder, true, true, true);
|
||||
if (classReference == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.identifier"));
|
||||
}
|
||||
if (!expect(builder, delimiter)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.lang.java.parser;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.psi.JavaTokenType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
|
||||
public class StatementParser {
|
||||
private StatementParser() { }
|
||||
|
||||
@Nullable
|
||||
public static PsiBuilder.Marker parseCodeBlock(final PsiBuilder builder) {
|
||||
if (builder.getTokenType() != JavaTokenType.LBRACE) return null;
|
||||
|
||||
final PsiBuilder.Marker codeBlock = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
// temp
|
||||
if (builder.getTokenType() == JavaTokenType.RBRACE) {
|
||||
builder.advanceLexer();
|
||||
codeBlock.done(JavaElementType.CODE_BLOCK);
|
||||
return codeBlock;
|
||||
}
|
||||
|
||||
// todo: implement
|
||||
throw new UnsupportedOperationException(builder.toString());
|
||||
}
|
||||
}
|
||||
@@ -705,8 +705,8 @@ public class DeclarationParsing extends Parsing {
|
||||
aClass.rawAddChildren(invalidElementsGroup);
|
||||
while (true) {
|
||||
IElementType tokenType = lexer.getTokenType();
|
||||
if (tokenType == JavaTokenType.IDENTIFIER || tokenType == JavaTokenType.COMMA || tokenType == JavaTokenType.EXTENDS_KEYWORD || tokenType ==
|
||||
JavaTokenType.IMPLEMENTS_KEYWORD) {
|
||||
if (tokenType == JavaTokenType.IDENTIFIER || tokenType == JavaTokenType.COMMA || tokenType == JavaTokenType.EXTENDS_KEYWORD ||
|
||||
tokenType == JavaTokenType.IMPLEMENTS_KEYWORD) {
|
||||
invalidElementsGroup.rawAddChildren(ParseUtil.createTokenElement(lexer, myContext.getCharTable()));
|
||||
}
|
||||
else {
|
||||
@@ -1086,7 +1086,7 @@ public class DeclarationParsing extends Parsing {
|
||||
|
||||
if (type == null) {
|
||||
type = ASTFactory.composite(JavaElementType.TYPE);
|
||||
param.rawAddChildren(Factory.createErrorElement("Parameter type missing"));
|
||||
param.rawAddChildren(Factory.createErrorElement(JavaErrorMessages.message("expected.type")));
|
||||
}
|
||||
|
||||
param.rawAddChildren(type);
|
||||
|
||||
@@ -111,6 +111,7 @@ public class StatementParsing extends Parsing {
|
||||
return dummyRoot.getFirstChildNode();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TreeElement parseCodeBlock(Lexer lexer, boolean deep) {
|
||||
if (lexer.getTokenType() != JavaTokenType.LBRACE) return null;
|
||||
Lexer badLexer = lexer instanceof StoppableLexerAdapter ? ((StoppableLexerAdapter)lexer).getDelegate() : lexer;
|
||||
@@ -151,11 +152,10 @@ public class StatementParsing extends Parsing {
|
||||
List<IElementType> list = new SmartList<IElementType>();
|
||||
while (true) {
|
||||
final IElementType type = lexer.getTokenType();
|
||||
if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(type) || type == JavaTokenType.IDENTIFIER || ElementType.MODIFIER_BIT_SET.contains(type) ||
|
||||
type == JavaTokenType.LT || type == JavaTokenType.GT || type == JavaTokenType.GTGT || type == JavaTokenType.GTGTGT || type ==
|
||||
JavaTokenType.COMMA || type ==
|
||||
JavaTokenType.DOT ||
|
||||
type == JavaTokenType.EXTENDS_KEYWORD || type == JavaTokenType.IMPLEMENTS_KEYWORD) {
|
||||
if (ElementType.PRIMITIVE_TYPE_BIT_SET.contains(type) || ElementType.MODIFIER_BIT_SET.contains(type) ||
|
||||
type == JavaTokenType.IDENTIFIER || type == JavaTokenType.LT || type == JavaTokenType.GT ||
|
||||
type == JavaTokenType.GTGT || type == JavaTokenType.GTGTGT || type == JavaTokenType.COMMA ||
|
||||
type == JavaTokenType.DOT || type == JavaTokenType.EXTENDS_KEYWORD || type == JavaTokenType.IMPLEMENTS_KEYWORD) {
|
||||
list.add(type);
|
||||
lexer.advance();
|
||||
} else {
|
||||
|
||||
@@ -93,7 +93,7 @@ public interface JavaElementType {
|
||||
IElementType CLASS_OBJECT_ACCESS_EXPRESSION = new IJavaElementType("CLASS_OBJECT_ACCESS_EXPRESSION");
|
||||
IElementType EMPTY_EXPRESSION = new IJavaElementType("EMPTY_EXPRESSION");
|
||||
|
||||
IElementType EXPRESSION_LIST = new IJavaElementType("EXPRESSION_LIST");
|
||||
IElementType EXPRESSION_LIST = new IJavaElementType("EXPRESSION_LIST", true);
|
||||
|
||||
IElementType EMPTY_STATEMENT = new IJavaElementType("EMPTY_STATEMENT");
|
||||
IElementType BLOCK_STATEMENT = new IJavaElementType("BLOCK_STATEMENT");
|
||||
|
||||
+10
@@ -32,6 +32,7 @@ import com.intellij.refactoring.HelpID;
|
||||
import com.intellij.refactoring.RefactoringBundle;
|
||||
import com.intellij.refactoring.ui.TypeSelectorManagerImpl;
|
||||
import com.intellij.refactoring.util.CommonRefactoringUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.intellij.refactoring.util.classMembers.ClassMemberReferencesVisitor;
|
||||
import com.intellij.refactoring.util.occurences.ExpressionOccurenceManager;
|
||||
import com.intellij.refactoring.util.occurences.OccurenceManager;
|
||||
@@ -85,6 +86,15 @@ public class IntroduceConstantHandler extends BaseExpressionToFieldHandler {
|
||||
PsiExpression[] occurences,
|
||||
PsiElement anchorElement,
|
||||
PsiElement anchorElementIfAll) {
|
||||
for (PsiExpression occurrence : occurences) {
|
||||
if (RefactoringUtil.isAssignmentLHS(occurrence)) {
|
||||
String message =
|
||||
RefactoringBundle.getCannotRefactorMessage("Selected expression is used for write");
|
||||
CommonRefactoringUtil.showErrorHint(project, editor, message, REFACTORING_NAME, getHelpID());
|
||||
highlightError(project, editor, occurrence);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
PsiLocalVariable localVariable = null;
|
||||
if (expr instanceof PsiReferenceExpression) {
|
||||
PsiElement ref = ((PsiReferenceExpression)expr).resolve();
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
PsiJavaFile:CompletionHack0.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:s
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:X
|
||||
PsiIdentifier:X('X')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected identifier
|
||||
PsiIdentifier:IntelliJIdeaRulezz('IntelliJIdeaRulezz')
|
||||
PsiJavaToken:GT('>')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:s('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:""
|
||||
PsiJavaToken:STRING_LITERAL('""')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,31 @@
|
||||
PsiJavaFile:CompletionHack1.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:s
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:X
|
||||
PsiIdentifier:X('X')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiErrorElement:'>' expected.
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:s('s')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:""
|
||||
PsiJavaToken:STRING_LITERAL('""')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,4 @@
|
||||
PsiJavaFile:EmptyBody0.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,5 @@
|
||||
PsiJavaFile:EmptyBody1.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiErrorElement:'}' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
@@ -0,0 +1,6 @@
|
||||
PsiJavaFile:EnumBody0.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,28 @@
|
||||
PsiJavaFile:EnumBody1.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:RED
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:RED('RED')
|
||||
PsiExpressionList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:GREEN
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:GREEN('GREEN')
|
||||
PsiExpressionList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:BLUE
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:BLUE('BLUE')
|
||||
PsiExpressionList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,27 @@
|
||||
PsiJavaFile:EnumBody2.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:RED
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:RED('RED')
|
||||
PsiExpressionList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:GREEN
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:GREEN('GREEN')
|
||||
PsiExpressionList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:BLUE
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:BLUE('BLUE')
|
||||
PsiExpressionList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,28 @@
|
||||
PsiJavaFile:EnumBody3.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:RED
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:RED('RED')
|
||||
PsiExpressionList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:GREEN
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:GREEN('GREEN')
|
||||
PsiExpressionList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:BLUE
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:BLUE('BLUE')
|
||||
PsiExpressionList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,37 @@
|
||||
PsiJavaFile:EnumBody4.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:RED
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:RED('RED')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:0
|
||||
PsiJavaToken:INTEGER_LITERAL('0')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:GREEN
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:GREEN('GREEN')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:1
|
||||
PsiJavaToken:INTEGER_LITERAL('1')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:BLUE
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:BLUE('BLUE')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:2
|
||||
PsiJavaToken:INTEGER_LITERAL('2')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,22 @@
|
||||
PsiJavaFile:EnumBody5.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiEnumConstant:A
|
||||
PsiModifierList:@ANNOTATION
|
||||
PsiAnnotation
|
||||
PsiJavaToken:AT('@')
|
||||
PsiJavaCodeReferenceElement:ANNOTATION
|
||||
PsiIdentifier:ANNOTATION('ANNOTATION')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiAnnotationParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:A('A')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiLiteralExpression:10
|
||||
PsiJavaToken:INTEGER_LITERAL('10')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,45 @@
|
||||
PsiJavaFile:Errors.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiModifierList:public static
|
||||
PsiKeyword:public('public')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:static('static')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:error
|
||||
PsiIdentifier:error('error')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiErrorElement:'>' expected.
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeElement:descr
|
||||
PsiJavaCodeReferenceElement:descr
|
||||
PsiIdentifier:descr('descr')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiJavaToken:STRING_LITERAL('"2"')
|
||||
PsiJavaToken:GT('>')
|
||||
PsiField:f1
|
||||
PsiModifierList:protected
|
||||
PsiKeyword:protected('protected')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f1('f1')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:0
|
||||
PsiJavaToken:INTEGER_LITERAL('0')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,22 @@
|
||||
PsiJavaFile:FieldMulti.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:field1
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:field1('field1')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:0
|
||||
PsiJavaToken:INTEGER_LITERAL('0')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:field2
|
||||
PsiIdentifier:field2('field2')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,18 @@
|
||||
PsiJavaFile:FieldSimple.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:field
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:field('field')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLiteralExpression:0
|
||||
PsiJavaToken:INTEGER_LITERAL('0')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,91 @@
|
||||
PsiJavaFile:GenericMethod.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:test
|
||||
PsiModifierList:public static
|
||||
PsiKeyword:public('public')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:static('static')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:E
|
||||
PsiIdentifier:E('E')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:test('test')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiMethod:test1
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:E
|
||||
PsiIdentifier:E('E')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:test1('test1')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiMethod:test2
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:E1
|
||||
PsiIdentifier:E1('E1')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
PsiKeyword:extends('extends')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:Integer
|
||||
PsiIdentifier:Integer('Integer')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeParameter:E2
|
||||
PsiIdentifier:E2('E2')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
PsiKeyword:extends('extends')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:Runnable
|
||||
PsiIdentifier:Runnable('Runnable')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:test2('test2')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,43 @@
|
||||
PsiJavaFile:GenericMethodErrors.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:Error
|
||||
PsiIdentifier:Error('Error')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiErrorElement:'>' expected.
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeElement:sss
|
||||
PsiJavaCodeReferenceElement:sss
|
||||
PsiIdentifier:sss('sss')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiJavaToken:DIV('/')
|
||||
PsiJavaToken:GT('>')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:test <error>
|
||||
PsiIdentifier:test('test')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:error
|
||||
PsiJavaCodeReferenceElement:error
|
||||
PsiIdentifier:error('error')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,24 @@
|
||||
PsiJavaFile:MethodNormal0.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:f
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f('f')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiCodeBlock
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,20 @@
|
||||
PsiJavaFile:MethodNormal1.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:f
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f('f')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,16 @@
|
||||
PsiJavaFile:MissingInitializer.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:field
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:field('field')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
PsiJavaFile:MissingInitializerExpression.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:field
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:field('field')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,23 @@
|
||||
PsiJavaFile:MultiLineUnclosed.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' \n ')
|
||||
PsiField:o
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:Object
|
||||
PsiJavaCodeReferenceElement:Object
|
||||
PsiIdentifier:Object('Object')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:o('o')
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,21 @@
|
||||
PsiJavaFile:Unclosed0.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:f
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f('f')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiErrorElement:'{' or ';' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,22 @@
|
||||
PsiJavaFile:Unclosed1.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:f
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f('f')
|
||||
PsiParameterList:(
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiErrorElement:'{' or ';' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,37 @@
|
||||
PsiJavaFile:Unclosed2.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:f
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f('f')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiErrorElement:'{' or ';' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiMethod:g
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:g('g')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,29 @@
|
||||
PsiJavaFile:Unclosed3.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:f
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f('f')
|
||||
PsiParameterList:(int a
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:a
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:a('a')
|
||||
PsiErrorElement:')' expected
|
||||
<empty list>
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiErrorElement:'{' or ';' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,33 @@
|
||||
PsiJavaFile:Unclosed4.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:f
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f('f')
|
||||
PsiParameterList:(int a,,
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:a
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:a('a')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiErrorElement:Parameter expected
|
||||
<empty list>
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiErrorElement:Identifier or type expected
|
||||
<empty list>
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiErrorElement:'{' or ';' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,30 @@
|
||||
PsiJavaFile:Unclosed5.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:f
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:f('f')
|
||||
PsiParameterList:(int a,)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:a
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:a('a')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiErrorElement:Identifier or type expected
|
||||
<empty list>
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:UnclosedBracket.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:field
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:field('field')
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiErrorElement:']' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,15 @@
|
||||
PsiJavaFile:UnclosedComma.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:field
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:field('field')
|
||||
PsiJavaToken:COMMA(',')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,14 @@
|
||||
PsiJavaFile:UnclosedSemicolon.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiField:field
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:int
|
||||
PsiKeyword:int('int')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:field('field')
|
||||
PsiErrorElement:';' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,55 @@
|
||||
PsiJavaFile:WildcardParsing.java
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethod:x
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:List<? extends B>
|
||||
PsiJavaCodeReferenceElement:List<? extends B>
|
||||
PsiIdentifier:List('List')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:? extends B
|
||||
PsiJavaToken:QUEST('?')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:extends('extends')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeElement:B
|
||||
PsiJavaCodeReferenceElement:B
|
||||
PsiIdentifier:B('B')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:x('x')
|
||||
PsiParameterList:(Collection<? super B> x)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:x
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:Collection<? super B>
|
||||
PsiJavaCodeReferenceElement:Collection<? super B>
|
||||
PsiIdentifier:Collection('Collection')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:? super B
|
||||
PsiJavaToken:QUEST('?')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:super('super')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeElement:B
|
||||
PsiJavaCodeReferenceElement:B
|
||||
PsiIdentifier:B('B')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:x('x')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
@@ -0,0 +1,11 @@
|
||||
PsiJavaFile:Type5.java
|
||||
PsiTypeElement:Object[]...
|
||||
PsiTypeElement:Object[]
|
||||
PsiTypeElement:Object
|
||||
PsiJavaCodeReferenceElement:Object
|
||||
PsiIdentifier:Object('Object')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:LBRACKET('[')
|
||||
PsiJavaToken:RBRACKET(']')
|
||||
PsiJavaToken:ELLIPSIS('...')
|
||||
@@ -4,9 +4,9 @@ PsiJavaFile:TypeParams5.java
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:extends('extends')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
PsiKeyword:extends('extends')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:X
|
||||
PsiIdentifier:X('X')
|
||||
PsiReferenceParameterList
|
||||
|
||||
@@ -4,9 +4,9 @@ PsiJavaFile:TypeParams7.java
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiKeyword:extends('extends')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
PsiKeyword:extends('extends')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:X
|
||||
PsiIdentifier:X('X')
|
||||
PsiReferenceParameterList
|
||||
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.lang.java.parser.partial;
|
||||
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.lang.java.parser.DeclarationParser;
|
||||
import com.intellij.lang.java.parser.JavaParsingTestCase;
|
||||
|
||||
|
||||
public class DeclarationParserTest extends JavaParsingTestCase {
|
||||
public DeclarationParserTest() {
|
||||
super("parser-partial/declarations");
|
||||
}
|
||||
|
||||
public void testEmptyBody0() { doParserTest("{ }", false, false); }
|
||||
public void testEmptyBody1() { doParserTest("{ ", false, false); }
|
||||
|
||||
public void testEnumBody0() { doParserTest("{ ; }", false, true); }
|
||||
public void testEnumBody1() { doParserTest("{ RED, GREEN, BLUE; }", false, true); }
|
||||
public void testEnumBody2() { doParserTest("{ RED, GREEN, BLUE }", false, true); }
|
||||
public void testEnumBody3() { doParserTest("{ RED, GREEN, BLUE, }", false, true); }
|
||||
public void testEnumBody4() { doParserTest("{ RED(0), GREEN(1), BLUE(2); }", false, true); }
|
||||
public void testEnumBody5() { doParserTest("{ @ANNOTATION A(10) }", false, true); }
|
||||
|
||||
public void testFieldSimple() { doParserTest("{ int field = 0; }", false, false); }
|
||||
public void testFieldMulti() { doParserTest("{ int field1 = 0, field2; }", false, false); }
|
||||
public void testUnclosedBracket() { doParserTest("{ int field[ }", false, false); }
|
||||
public void testMissingInitializer() { doParserTest("{ int field = }", false, false); }
|
||||
public void testUnclosedComma() { doParserTest("{ int field, }", false, false); }
|
||||
public void testUnclosedSemicolon() { doParserTest("{ int field }", false, false); }
|
||||
public void testMissingInitializerExpression() { doParserTest("{ int field=; }", false, false); }
|
||||
//public void testMultiLineUnclosed() { doParserTest("{ int \n Object o; }", false, false); } // todo: implement
|
||||
|
||||
//public void testMethodNormal0() { doParserTest("{ void f() { } }", false, false); } // todo: parse code block correctly
|
||||
public void testMethodNormal1() { doParserTest("{ void f(); }", false, false); }
|
||||
public void testUnclosed0() { doParserTest("{ void f() }", false, false); }
|
||||
public void testUnclosed1() { doParserTest("{ void f( }", false, false); }
|
||||
public void testUnclosed2() { doParserTest("{ void f()\n void g(); }", false, false); }
|
||||
public void testUnclosed3() { doParserTest("{ void f(int a }", false, false); }
|
||||
public void testUnclosed4() { doParserTest("{ void f(int a,, }", false, false); }
|
||||
public void testUnclosed5() { doParserTest("{ void f(int a,); }", false, false); }
|
||||
public void testGenericMethod() { doParserTest("{ public static <E> test();\n" +
|
||||
" <E> void test1();\n" +
|
||||
" <E1 extends Integer, E2 extends Runnable> String test2(); }", false, false); }
|
||||
public void testGenericMethodErrors() { doParserTest("{ <Error sss /> test <error>(); }", false, false); }
|
||||
public void testErrors() { doParserTest("{ public static <error descr=\"2\">protected int f1 = 0; }", false, false); }
|
||||
public void testCompletionHack0() { doParserTest("{ <X IntelliJIdeaRulezz>\n String s = \"\"; }", false, false); }
|
||||
public void testCompletionHack1() { doParserTest("{ <X\n String s = \"\"; }", false, false); }
|
||||
public void testWildcardParsing() { doParserTest("{ List<? extends B> x(Collection<? super B> x); }", false, false); }
|
||||
|
||||
private void doParserTest(final String text, final boolean isAnnotation, final boolean isEnum) {
|
||||
doParserTest(text, new Parser() {
|
||||
public void parse(final PsiBuilder builder) {
|
||||
DeclarationParser.parseClassBodyWithBraces(builder, isAnnotation, isEnum);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -34,6 +34,7 @@ public class ReferenceParserTest extends JavaParsingTestCase {
|
||||
public void testType2() { doTypeParserTest("int[]", false); }
|
||||
public void testType3() { doTypeParserTest("int[][", false); }
|
||||
public void testType4() { doTypeParserTest("Map<String,List<String>>", false); }
|
||||
public void testType5() { doTypeParserTest("Object[]...", false); }
|
||||
|
||||
public void testTypeParams0() { doTypeParamsParserTest("<T>"); }
|
||||
public void testTypeParams1() { doTypeParamsParserTest("<T, U>"); }
|
||||
@@ -55,7 +56,7 @@ public class ReferenceParserTest extends JavaParsingTestCase {
|
||||
private void doTypeParserTest(final String text, final boolean incomplete) {
|
||||
doParserTest(text, new Parser() {
|
||||
public void parse(final PsiBuilder builder) {
|
||||
ReferenceParser.parseType(builder, incomplete, false);
|
||||
ReferenceParser.parseTypeWithEllipsis(builder, incomplete, false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.execution;
|
||||
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class ExecutionAdapter implements ExecutionListener {
|
||||
@Override
|
||||
public void processStarting(@NotNull RunProfile runProfile) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processNotStarted(@NotNull RunProfile runProfile) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processStarted(@NotNull RunProfile runProfile, @NotNull ProcessHandler handler) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminating(@NotNull RunProfile runProfile, @NotNull ProcessHandler handler) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminated(@NotNull RunProfile runProfile, @NotNull ProcessHandler handler) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.execution;
|
||||
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.EventListener;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public interface ExecutionListener extends EventListener {
|
||||
|
||||
void processStarting(@NotNull RunProfile runProfile);
|
||||
|
||||
void processNotStarted(@NotNull RunProfile runProfile);
|
||||
|
||||
void processStarted(@NotNull RunProfile runProfile, @NotNull ProcessHandler handler);
|
||||
|
||||
void processTerminating(@NotNull RunProfile runProfile, @NotNull ProcessHandler handler);
|
||||
|
||||
void processTerminated(@NotNull RunProfile runProfile, @NotNull ProcessHandler handler);
|
||||
}
|
||||
@@ -18,10 +18,16 @@ package com.intellij.execution;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.configurations.RunProfileState;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.ui.RunContentManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.messages.Topic;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class ExecutionManager {
|
||||
public static final Topic<ExecutionListener> EXECUTION_TOPIC = new Topic<ExecutionListener>("configuration executed", ExecutionListener.class,
|
||||
Topic.BroadcastDirection.TO_PARENT);
|
||||
|
||||
public static ExecutionManager getInstance(final Project project) {
|
||||
return project.getComponent(ExecutionManager.class);
|
||||
}
|
||||
@@ -32,5 +38,6 @@ public abstract class ExecutionManager {
|
||||
|
||||
public abstract ProcessHandler[] getRunningProcesses();
|
||||
|
||||
|
||||
public abstract void startRunProfile(@NotNull RunProfileStarter starter, @NotNull RunProfileState state,
|
||||
@NotNull Project project, @NotNull Executor executor, @NotNull ExecutionEnvironment env);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.execution;
|
||||
|
||||
import com.intellij.execution.configurations.RunProfileState;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class RunProfileStarter {
|
||||
@Nullable
|
||||
public abstract RunContentDescriptor execute(@NotNull Project project, @NotNull Executor executor, @NotNull RunProfileState state,
|
||||
@Nullable RunContentDescriptor contentToReuse, @NotNull ExecutionEnvironment env) throws ExecutionException;
|
||||
|
||||
}
|
||||
@@ -18,12 +18,9 @@ package com.intellij.execution.runners;
|
||||
|
||||
import com.intellij.execution.*;
|
||||
import com.intellij.execution.configurations.*;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.history.LocalHistory;
|
||||
import com.intellij.openapi.actionSystem.AnAction;
|
||||
import com.intellij.openapi.actionSystem.DataKey;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.options.SettingsEditor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.JDOMExternalizable;
|
||||
@@ -67,51 +64,34 @@ public abstract class GenericProgramRunner<Settings extends JDOMExternalizable>
|
||||
|
||||
public void execute(@NotNull final Executor executor, @NotNull final ExecutionEnvironment env, @Nullable final Callback callback)
|
||||
throws ExecutionException {
|
||||
final RunProfile profile = env.getRunProfile();
|
||||
|
||||
final Project project = env.getProject();
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
final RunContentDescriptor reuseContent =
|
||||
ExecutionManager.getInstance(project).getContentManager().getReuseContent(executor, env.getContentToReuse());
|
||||
|
||||
final RunProfileState state = env.getState(executor);
|
||||
if (state == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Runnable startRunnable = new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
if (project.isDisposed()) return;
|
||||
|
||||
final RunContentDescriptor descriptor =
|
||||
doExecute(project, executor, state, reuseContent, env);
|
||||
|
||||
if (callback != null) callback.processStarted(descriptor);
|
||||
|
||||
if (descriptor != null) {
|
||||
ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, descriptor);
|
||||
final ProcessHandler processHandler = descriptor.getProcessHandler();
|
||||
if (processHandler != null) processHandler.startNotify();
|
||||
}
|
||||
}
|
||||
catch (ExecutionException e) {
|
||||
ExecutionUtil.handleExecutionError(project, executor.getToolWindowId(), profile, e);
|
||||
}
|
||||
ExecutionManager.getInstance(project).startRunProfile(new RunProfileStarter() {
|
||||
@Override
|
||||
public RunContentDescriptor execute(@NotNull Project project,
|
||||
@NotNull Executor executor,
|
||||
@NotNull RunProfileState state,
|
||||
@Nullable RunContentDescriptor contentToReuse,
|
||||
@NotNull ExecutionEnvironment env) throws ExecutionException {
|
||||
final RunContentDescriptor descriptor = doExecute(project, executor, state, contentToReuse, env);
|
||||
if (callback != null) callback.processStarted(descriptor);
|
||||
return descriptor;
|
||||
}
|
||||
};
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
startRunnable.run();
|
||||
}
|
||||
else {
|
||||
ExecutionManager.getInstance(project).compileAndRun(startRunnable, profile, state);
|
||||
}
|
||||
}, state, project, executor, env);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
protected abstract RunContentDescriptor doExecute(final Project project, final Executor executor, final RunProfileState state,
|
||||
final RunContentDescriptor contentToReuse,
|
||||
final ExecutionEnvironment env) throws ExecutionException;
|
||||
|
||||
}
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
|
||||
package com.intellij.execution.impl;
|
||||
|
||||
import com.intellij.execution.BeforeRunTask;
|
||||
import com.intellij.execution.BeforeRunTaskProvider;
|
||||
import com.intellij.execution.ExecutionManager;
|
||||
import com.intellij.execution.*;
|
||||
import com.intellij.execution.configurations.ConfigurationPerRunnerSettings;
|
||||
import com.intellij.execution.configurations.RunConfiguration;
|
||||
import com.intellij.execution.configurations.RunProfile;
|
||||
import com.intellij.execution.configurations.RunProfileState;
|
||||
import com.intellij.execution.process.ProcessAdapter;
|
||||
import com.intellij.execution.process.ProcessEvent;
|
||||
import com.intellij.execution.process.ProcessHandler;
|
||||
import com.intellij.execution.runners.ExecutionEnvironment;
|
||||
import com.intellij.execution.runners.ExecutionUtil;
|
||||
import com.intellij.execution.ui.RunContentDescriptor;
|
||||
import com.intellij.execution.ui.RunContentManager;
|
||||
import com.intellij.execution.ui.RunContentManagerImpl;
|
||||
@@ -64,7 +66,8 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
|
||||
public void projectClosed() {
|
||||
}
|
||||
|
||||
public void initComponent() { }
|
||||
public void initComponent() {
|
||||
}
|
||||
|
||||
public void disposeComponent() {
|
||||
}
|
||||
@@ -94,53 +97,112 @@ public class ExecutionManagerImpl extends ExecutionManager implements ProjectCom
|
||||
public void compileAndRun(final Runnable startRunnable,
|
||||
final RunProfile configuration,
|
||||
final RunProfileState state) {
|
||||
final Runnable antAwareRunnable = new Runnable() {
|
||||
public void run() {
|
||||
if (configuration instanceof RunConfiguration) {
|
||||
final RunConfiguration runConfiguration = (RunConfiguration)configuration;
|
||||
final RunManagerImpl runManager = RunManagerImpl.getInstanceImpl(myProject);
|
||||
if (configuration instanceof RunConfiguration) {
|
||||
final RunConfiguration runConfiguration = (RunConfiguration)configuration;
|
||||
final RunManagerImpl runManager = RunManagerImpl.getInstanceImpl(myProject);
|
||||
|
||||
final Map<BeforeRunTaskProvider<BeforeRunTask>, BeforeRunTask> activeProviders = new LinkedHashMap<BeforeRunTaskProvider<BeforeRunTask>, BeforeRunTask>();
|
||||
for (final BeforeRunTaskProvider<BeforeRunTask> provider : Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, myProject)) {
|
||||
final BeforeRunTask task = runManager.getBeforeRunTask(runConfiguration, provider.getId());
|
||||
if (task != null && task.isEnabled()) {
|
||||
activeProviders.put(provider, task);
|
||||
final Map<BeforeRunTaskProvider<BeforeRunTask>, BeforeRunTask> activeProviders = new LinkedHashMap<BeforeRunTaskProvider<BeforeRunTask>, BeforeRunTask>();
|
||||
for (final BeforeRunTaskProvider<BeforeRunTask> provider : Extensions.getExtensions(BeforeRunTaskProvider.EXTENSION_POINT_NAME, myProject)) {
|
||||
final BeforeRunTask task = runManager.getBeforeRunTask(runConfiguration, provider.getId());
|
||||
if (task != null && task.isEnabled()) {
|
||||
activeProviders.put(provider, task);
|
||||
}
|
||||
}
|
||||
|
||||
if (!activeProviders.isEmpty()) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
ConfigurationPerRunnerSettings configurationSettings = state.getConfigurationSettings();
|
||||
DataContext projectContext = SimpleDataContext.getProjectContext(myProject);
|
||||
|
||||
final DataContext dataContext = configurationSettings != null ? SimpleDataContext
|
||||
.getSimpleContext(BeforeRunTaskProvider.RUNNER_ID, configurationSettings.getRunnerId(), projectContext) : projectContext;
|
||||
for (BeforeRunTaskProvider<BeforeRunTask> provider : activeProviders.keySet()) {
|
||||
if(!provider.executeTask(dataContext, runConfiguration, activeProviders.get(provider))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
DumbService.getInstance(myProject).smartInvokeLater(startRunnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
startRunnable.run();
|
||||
}
|
||||
}
|
||||
else {
|
||||
startRunnable.run();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startRunProfile(@NotNull final RunProfileStarter starter, @NotNull final RunProfileState state,
|
||||
@NotNull final Project project, @NotNull final Executor executor, @NotNull final ExecutionEnvironment env) {
|
||||
final RunContentDescriptor reuseContent = ExecutionManager.getInstance(project).getContentManager().getReuseContent(executor, env.getContentToReuse());
|
||||
final RunProfile profile = env.getRunProfile();
|
||||
|
||||
Runnable startRunnable = new Runnable() {
|
||||
public void run() {
|
||||
boolean started = false;
|
||||
try {
|
||||
if (project.isDisposed()) return;
|
||||
|
||||
project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStarting(profile);
|
||||
|
||||
final RunContentDescriptor descriptor = starter.execute(project, executor, state, reuseContent, env);
|
||||
|
||||
if (descriptor != null) {
|
||||
ExecutionManager.getInstance(project).getContentManager().showRunContent(executor, descriptor);
|
||||
final ProcessHandler processHandler = descriptor.getProcessHandler();
|
||||
if (processHandler != null) {
|
||||
processHandler.startNotify();
|
||||
project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processStarted(profile, processHandler);
|
||||
started = true;
|
||||
processHandler.addProcessListener(new ProcessExecutionListener(project, profile, processHandler));
|
||||
}
|
||||
}
|
||||
|
||||
if (!activeProviders.isEmpty()) {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
ConfigurationPerRunnerSettings configurationSettings = state.getConfigurationSettings();
|
||||
DataContext projectContext = SimpleDataContext.getProjectContext(myProject);
|
||||
|
||||
final DataContext dataContext = configurationSettings != null ? SimpleDataContext
|
||||
.getSimpleContext(BeforeRunTaskProvider.RUNNER_ID, configurationSettings.getRunnerId(), projectContext) : projectContext;
|
||||
for (BeforeRunTaskProvider<BeforeRunTask> provider : activeProviders.keySet()) {
|
||||
if(!provider.executeTask(dataContext, runConfiguration, activeProviders.get(provider))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
DumbService.getInstance(myProject).smartInvokeLater(startRunnable);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
startRunnable.run();
|
||||
}
|
||||
}
|
||||
else {
|
||||
startRunnable.run();
|
||||
catch (ExecutionException e) {
|
||||
ExecutionUtil.handleExecutionError(project, executor.getToolWindowId(), profile, e);
|
||||
}
|
||||
if (!started) {
|
||||
project.getMessageBus().syncPublisher(EXECUTION_TOPIC).processNotStarted(profile);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
antAwareRunnable.run();
|
||||
//ApplicationManager.getApplication().invokeLater(antAwareRunnable);
|
||||
if (ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
startRunnable.run();
|
||||
}
|
||||
else {
|
||||
compileAndRun(startRunnable, profile, state);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getComponentName() {
|
||||
return "ExecutionManager";
|
||||
}
|
||||
|
||||
private static class ProcessExecutionListener extends ProcessAdapter {
|
||||
private final Project myProject;
|
||||
private final RunProfile myProfile;
|
||||
private final ProcessHandler myProcessHandler;
|
||||
|
||||
public ProcessExecutionListener(Project project, RunProfile profile, ProcessHandler processHandler) {
|
||||
myProject = project;
|
||||
myProfile = profile;
|
||||
myProcessHandler = processHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processTerminated(ProcessEvent event) {
|
||||
myProject.getMessageBus().syncPublisher(EXECUTION_TOPIC).processTerminated(myProfile, myProcessHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processWillTerminate(ProcessEvent event, boolean willBeDestroyed) {
|
||||
myProject.getMessageBus().syncPublisher(EXECUTION_TOPIC).processTerminating(myProfile, myProcessHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public class ActionButton extends JComponent implements ActionButtonComponent {
|
||||
}
|
||||
|
||||
protected boolean isButtonEnabled() {
|
||||
return myPresentation.isEnabled();
|
||||
return isEnabled() && myPresentation.isEnabled();
|
||||
}
|
||||
|
||||
private void onMousePresenceChanged(boolean setInfo) {
|
||||
|
||||
@@ -4649,7 +4649,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
|
||||
|
||||
public synchronized void update(int startLine, int newEndLine, int oldEndLine) {
|
||||
final int lineWidthSize = myLineWidths.size();
|
||||
if (lineWidthSize == 0) {
|
||||
if (lineWidthSize == 0 || myDocument.getTextLength() <= 0) {
|
||||
reset();
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -51,6 +51,7 @@ public final class VcsConfiguration implements PersistentStateComponent<Element>
|
||||
|
||||
@NonNls private static final String VALUE_ATTR = "value";
|
||||
@NonNls private static final String CONFIRM_MOVE_TO_FAILED_COMMIT_ELEMENT = "confirmMoveToFailedCommit";
|
||||
@NonNls private static final String CONFIRM_REMOVE_EMPTY_CHANGELIST_ELEMENT = "confirmRemoveEmptyChangelist";
|
||||
private Project myProject;
|
||||
|
||||
public boolean OFFER_MOVE_TO_ANOTHER_CHANGELIST_ON_PARTIAL_COMMIT = true;
|
||||
@@ -164,10 +165,14 @@ public final class VcsConfiguration implements PersistentStateComponent<Element>
|
||||
|
||||
public void readExternal(Element element) throws InvalidDataException {
|
||||
DefaultJDOMExternalizer.readExternal(this, element);
|
||||
final Element child = element.getChild(CONFIRM_MOVE_TO_FAILED_COMMIT_ELEMENT);
|
||||
Element child = element.getChild(CONFIRM_MOVE_TO_FAILED_COMMIT_ELEMENT);
|
||||
if (child != null) {
|
||||
MOVE_TO_FAILED_COMMIT_CHANGELIST = VcsShowConfirmationOption.Value.fromString(child.getAttributeValue(VALUE_ATTR));
|
||||
}
|
||||
child = element.getChild(CONFIRM_REMOVE_EMPTY_CHANGELIST_ELEMENT);
|
||||
if (child != null) {
|
||||
REMOVE_EMPTY_INACTIVE_CHANGELISTS = VcsShowConfirmationOption.Value.fromString(child.getAttributeValue(VALUE_ATTR));
|
||||
}
|
||||
final List messages = element.getChildren(MESSAGE_ELEMENT_NAME);
|
||||
for (final Object message : messages) {
|
||||
saveCommitMessage(((Element)message).getAttributeValue(VALUE_ATTR));
|
||||
@@ -188,6 +193,11 @@ public final class VcsConfiguration implements PersistentStateComponent<Element>
|
||||
confirmChild.setAttribute(VALUE_ATTR, MOVE_TO_FAILED_COMMIT_CHANGELIST.toString());
|
||||
element.addContent(confirmChild);
|
||||
}
|
||||
if (REMOVE_EMPTY_INACTIVE_CHANGELISTS != VcsShowConfirmationOption.Value.SHOW_CONFIRMATION) {
|
||||
Element confirmChild = new Element(CONFIRM_REMOVE_EMPTY_CHANGELIST_ELEMENT);
|
||||
confirmChild.setAttribute(VALUE_ATTR, REMOVE_EMPTY_INACTIVE_CHANGELISTS.toString());
|
||||
element.addContent(confirmChild);
|
||||
}
|
||||
for (String message : myLastCommitMessages) {
|
||||
final Element messageElement = new Element(MESSAGE_ELEMENT_NAME);
|
||||
messageElement.setAttribute(VALUE_ATTR, message);
|
||||
|
||||
@@ -115,6 +115,11 @@ public class IdeaSpecificSettings {
|
||||
replaceModuleRelatedRoots(model.getProject(), modifiableModel, libElement, OrderRootType.CLASSES, RELATIVE_MODULE_CLS);
|
||||
replaceModuleRelatedRoots(model.getProject(), modifiableModel, libElement, JavadocOrderRootType.getInstance(), RELATIVE_MODULE_JAVADOC);
|
||||
modifiableModel.commit();
|
||||
} else {
|
||||
final Library library = EclipseClasspathReader.findLibraryByName(model.getProject(), libName);
|
||||
if (library != null) {
|
||||
appendLibraryScope(model, libElement, library);
|
||||
}
|
||||
}
|
||||
}
|
||||
overrideModulesScopes(root, model);
|
||||
|
||||
@@ -252,6 +252,7 @@
|
||||
<packaging.artifactType implementation="com.intellij.packaging.impl.artifacts.JarArtifactType" order="first"/>
|
||||
<packaging.artifactType implementation="com.intellij.packaging.impl.artifacts.PlainArtifactType" order="last"/>
|
||||
<compiler.additionalCompileScopeProvider implementation="com.intellij.packaging.impl.compiler.ArtifactAdditionalCompileScopeProvider"/>
|
||||
<compiler implementation="com.intellij.packaging.impl.compiler.ArtifactsCompiler" id="artifactsCompiler"/>
|
||||
|
||||
<lookup.charFilter implementation="com.intellij.codeInsight.completion.JavaCharFilter" id="java"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user