Merge remote-tracking branch 'origin/master'

This commit is contained in:
Alexander Lobas
2012-04-04 12:34:00 +04:00
29 changed files with 236 additions and 3038 deletions
@@ -175,7 +175,7 @@ public class GenericCompilerRunner {
boolean processTarget(T target, final int targetId, final GenericCompiler<Key, SourceState, OutputState> compiler, final GenericCompilerInstance<T, Item, Key, SourceState, OutputState> instance,
final GenericCompilerCache<Key, SourceState, OutputState> cache) throws IOException, ExitException {
if (LOG.isDebugEnabled()) {
LOG.debug("Processing target '" + target + "' (id=" + targetId + ")");
LOG.debug("Processing target '" + target + "' (id=" + targetId + ") by " + compiler);
}
final List<Item> items = instance.getItems(target);
checkForErrorsOrCanceled();
@@ -226,6 +226,12 @@ public class GenericCompilerRunner {
if (LOG.isDebugEnabled()) {
LOG.debug(toProcess.size() + " items will be processed, " + toRemove.size() + " items will be removed");
for (int i = 0; i < Math.min(100, toProcess.size()); i++) {
LOG.debug("to process:" + toProcess.get(i).getItem().getKey());
}
for (int i = 0; i < Math.min(100, toRemove.size()); i++) {
LOG.debug("to delete:" + toRemove.get(i));
}
}
if (toProcess.isEmpty() && toRemove.isEmpty()) {
@@ -271,6 +277,15 @@ public class GenericCompilerRunner {
}
CompilerUtil.refreshIOFiles(filesToRefresh);
CompilerUtil.refreshIODirectories(dirsToRefresh);
if (LOG.isDebugEnabled()) {
LOG.debug("refreshed " + filesToRefresh.size() + " files and " + dirsToRefresh.size() + " dirs");
for (int i = 0; i < Math.min(100, filesToRefresh.size()); i++) {
LOG.debug("file: " + filesToRefresh.get(i));
}
for (int i = 0; i < Math.min(100, dirsToRefresh.size()); i++) {
LOG.debug("dir: " + dirsToRefresh.get(i));
}
}
final RunResult runResult = new ReadAction() {
protected void run(final Result result) throws Throwable {
@@ -142,7 +142,7 @@ public class PostHighlightingPass extends TextEditorHighlightingPass {
VirtualFile virtualFile = viewProvider.getVirtualFile();
myInLibrary = fileIndex.isInLibraryClasses(virtualFile) || fileIndex.isInLibrarySource(virtualFile);
myRefCountHolder = RefCountHolder.getInstance(myFile);
myRefCountHolder = RefCountHolder.endUsing(myFile);
if (!myRefCountHolder.retrieveUnusedReferencesInfo(new Runnable() {
@Override
public void run() {
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.daemon.impl;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.UserDataHolderEx;
import com.intellij.psi.*;
@@ -29,7 +30,6 @@ import com.intellij.util.containers.BidirectionalMap;
import com.intellij.util.containers.ConcurrentHashMap;
import org.jetbrains.annotations.NotNull;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.util.Iterator;
import java.util.List;
@@ -54,16 +54,36 @@ public class RefCountHolder {
BEING_USED_BY_PHP, // post highlighting pass is retrieving info
}
private static final Key<Reference<RefCountHolder>> REF_COUNT_HOLDER_IN_FILE_KEY = Key.create("REF_COUNT_HOLDER_IN_FILE_KEY");
private static class HolderReference extends SoftReference<RefCountHolder> {
@SuppressWarnings("UnusedDeclaration")
private volatile RefCountHolder myHardRef; // to prevent gc
public HolderReference(@NotNull RefCountHolder holder) {
super(holder);
myHardRef = holder;
}
private void makeHardReachable(boolean isHard) {
RefCountHolder holder = get();
assert holder != null;
myHardRef = isHard ? holder : null;
}
}
private static final Key<HolderReference> REF_COUNT_HOLDER_IN_FILE_KEY = Key.create("REF_COUNT_HOLDER_IN_FILE_KEY");
@NotNull
public static RefCountHolder getInstance(@NotNull PsiFile file) {
Reference<RefCountHolder> ref = file.getUserData(REF_COUNT_HOLDER_IN_FILE_KEY);
private static Pair<RefCountHolder, HolderReference> getInstance(@NotNull PsiFile file) {
HolderReference ref = file.getUserData(REF_COUNT_HOLDER_IN_FILE_KEY);
RefCountHolder holder = ref == null ? null : ref.get();
if (holder == null) {
holder = new RefCountHolder(file);
HolderReference newRef = new HolderReference(holder);
while (true) {
boolean replaced = ((UserDataHolderEx)file).replace(REF_COUNT_HOLDER_IN_FILE_KEY, ref, new SoftReference<RefCountHolder>(holder));
if (replaced) break;
boolean replaced = ((UserDataHolderEx)file).replace(REF_COUNT_HOLDER_IN_FILE_KEY, ref, newRef);
if (replaced) {
ref = newRef;
break;
}
ref = file.getUserData(REF_COUNT_HOLDER_IN_FILE_KEY);
RefCountHolder newHolder = ref == null ? null : ref.get();
if (newHolder != null) {
@@ -72,9 +92,24 @@ public class RefCountHolder {
}
}
}
return holder;
return Pair.create(holder, ref);
}
@NotNull
public static RefCountHolder startUsing(@NotNull PsiFile file) {
Pair<RefCountHolder, HolderReference> pair = getInstance(file);
HolderReference reference = pair.second;
reference.makeHardReachable(true);
return pair.first;
}
@NotNull
public static RefCountHolder endUsing(@NotNull PsiFile file) {
Pair<RefCountHolder, HolderReference> pair = getInstance(file);
HolderReference reference = pair.second;
reference.makeHardReachable(false); // no longer needed, can be cleared
return pair.first;
}
private RefCountHolder(@NotNull PsiFile file) {
myFile = file;
}
@@ -276,4 +311,5 @@ public class RefCountHolder {
private void assertIsRetrieving() {
assert myState.get() == State.BEING_USED_BY_PHP : myState.get();
}
}
@@ -128,7 +128,7 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
Project project = file.getProject();
DaemonCodeAnalyzer daemonCodeAnalyzer = DaemonCodeAnalyzer.getInstance(project);
FileStatusMap fileStatusMap = ((DaemonCodeAnalyzerImpl)daemonCodeAnalyzer).getFileStatusMap();
RefCountHolder refCountHolder = RefCountHolder.getInstance(file);
RefCountHolder refCountHolder = RefCountHolder.startUsing(file);
myRefCountHolder = refCountHolder;
Document document = PsiDocumentManager.getInstance(project).getDocument(file);
TextRange dirtyScope = document == null ? file.getTextRange() : fileStatusMap.getFileDirtyScope(document, Pass.UPDATE_ALL);
@@ -755,8 +755,13 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase
if (parent instanceof PsiClass) break;
endElement = parent;
}
myElement.getParent().deleteChildRange(myElement, PsiTreeUtil.skipSiblingsBackward(endElement, PsiWhiteSpace.class));
} else if (myDeleteSelf) {
PsiElement last = PsiTreeUtil.skipSiblingsBackward(endElement, PsiWhiteSpace.class);
if (last.getTextRange().getStartOffset() < myElement.getTextRange().getStartOffset()) {
last = myElement;
}
myElement.getParent().deleteChildRange(myElement, last);
}
else if (myDeleteSelf) {
myElement.getParent().delete();
}
@@ -1,174 +0,0 @@
package org.jetbrains.ether;
import java.io.File;
import java.io.FileFilter;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 19.11.10
* Time: 2:01
* To change this template use File | Settings | File Templates.
*/
public class DirectoryScanner {
public static class Result {
final Set<ProjectWrapper.FileWrapper> myFiles;
long myLatest;
long myEarliest;
public Result() {
myFiles = new HashSet<ProjectWrapper.FileWrapper>();
myLatest = 0;
myEarliest = Long.MAX_VALUE;
}
public void update(final ProjectWrapper.FileWrapper w) {
final long t = w.getStamp();
if (t > myLatest) myLatest = t;
if (t < myEarliest) myEarliest = t;
myFiles.add(w);
}
public long getEarliest() {
return myEarliest;
}
public long getLatest() {
return myLatest;
}
public Set<ProjectWrapper.FileWrapper> getFiles() {
return myFiles;
}
}
private static class Crawler {
final Result myResult;
final FileFilter myFilter;
final ProjectWrapper myProjectWrapper;
public Crawler(final FileFilter ff, final ProjectWrapper pw) {
myResult = new Result();
myFilter = ff;
myProjectWrapper = pw;
}
public Result getResult() {
return myResult;
}
public void run(File root) {
if (root.exists()) {
final File[] files = root.listFiles(myFilter);
for (int i = 0; i < files.length; i++) {
myResult.update(myProjectWrapper.new FileWrapper(files[i]));
}
final File[] subdirs = root.listFiles(myDirectoryFilter);
for (int i = 0; i < subdirs.length; i++) {
run(subdirs[i]);
}
}
}
}
private static FileFilter myDirectoryFilter = new FileFilter() {
public boolean accept(File f) {
final String name = f.getName();
return f.isDirectory() && !name.equals(".") && !name.equals("..");
}
};
private static FileFilter myTrueFilter = new FileFilter() {
public boolean accept(File s) {
return s.isFile();
}
};
private static FileFilter createFilter(final Collection<String> excludes) {
if (excludes == null) {
return myTrueFilter;
}
StringBuilder buf = new StringBuilder();
for (String exclude : excludes) {
StringBuilder alternative = new StringBuilder();
if (exclude != null) {
for (int i = 0; i < exclude.length(); i++) {
final char c = exclude.charAt(i);
switch (c) {
case '.':
case '\\':
case '*':
case '^':
case '$':
case '[':
case '(':
case '|':
alternative.append("\\");
alternative.append(c);
break;
case '?':
alternative.append(".");
break;
default:
alternative.append(c);
}
}
}
if (alternative.length() > 0) {
alternative.append(".*");
if (buf.length() > 0) buf.append("|");
buf.append("(");
buf.append(alternative);
buf.append(')');
}
}
if (buf.length() > 0) {
final Pattern patt = Pattern.compile(buf.toString());
return new FileFilter() {
public boolean accept(File f) {
final Matcher m = patt.matcher(f.getAbsolutePath());
final boolean ok = !m.matches();
return ok && f.isFile();
}
};
}
return myTrueFilter;
}
public static Result getFiles(final Set<String> roots, final Set<String> excludes, final ProjectWrapper pw) {
final Crawler cw = new Crawler(createFilter(excludes), pw);
for (String root : roots) {
cw.run(new File(root));
}
return cw.getResult();
}
}
@@ -1,78 +0,0 @@
package org.jetbrains.ether;
import java.io.PrintStream;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 18.01.11
* Time: 6:33
* To change this template use File | Settings | File Templates.
*/
public class DotPrinter {
private final PrintStream stream;
public DotPrinter(final PrintStream stream) {
this.stream = stream;
}
private static String escape(final String s) {
final StringBuilder b = new StringBuilder();
for (int i = 0; i < s.length(); i++) {
final char c = s.charAt(i);
if (c == '_' || Character.isDigit(c) || Character.isLetter(c)) {
b.append(c);
}
else if (c == '-') {
b.append('_');
}
else {
b.append(Character.getNumericValue(c));
}
}
return b.toString();
}
public static void header(final PrintStream s) {
if (s != null) s.println("digraph X {");
}
public void header() {
header(stream);
}
public static void footer(final PrintStream s) {
if (s != null) s.println("}");
}
public void footer() {
footer(stream);
}
public static void node(final PrintStream s, String n) {
if (s != null) {
n = escape(n);
s.println(" " + n + "[label=\"" + n + "\"];");
}
}
public void node(final String n) {
node(stream, n);
}
public static void edge(final PrintStream s, String b, String e) {
if (s != null) {
b = escape(b);
e = escape(e);
s.println(" " + b + " -> " + e + ";");
}
}
public void edge(final String b, final String e) {
edge(stream, b, e);
}
}
-271
View File
@@ -1,271 +0,0 @@
package org.jetbrains.ether;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.List;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 18.11.10
* Time: 19:42
* To change this template use File | Settings | File Templates.
* <p/>
* The main class to start with
*/
public class Main {
private static final Options myOptions;
private enum Action {
REBUILD,
MAKE,
CLEAN,
NONE
}
static {
final Options.Descriptor[] descrs = {new Options.Descriptor("script", "script", "s", Options.ArgumentSpecifier.MANDATORY,
"specify script for project library/sdk setup; use prefix '@' to specify script file"),
new Options.Descriptor("inspect", "inspect", "i", Options.ArgumentSpecifier.OPTIONAL,
"list relevant information for the whole project or specified module"),
new Options.Descriptor("save", "save", "x", Options.ArgumentSpecifier.NONE, "collect and save project information"),
new Options.Descriptor("clean", "clean", "c", Options.ArgumentSpecifier.NONE, "clean project"),
new Options.Descriptor("rebuild", "rebuild", "r", Options.ArgumentSpecifier.NONE, "rebuild project"),
new Options.Descriptor("make", "make", "m", Options.ArgumentSpecifier.OPTIONAL, "make the whole project or specified module"),
new Options.Descriptor("tests", "tests", "t", Options.ArgumentSpecifier.NONE, "make tests as well"),
new Options.Descriptor("force", "force", "f", Options.ArgumentSpecifier.NONE, "force actions"),
new Options.Descriptor("incremental", "incremental", "u", Options.ArgumentSpecifier.NONE, "perform incremental make"),
new Options.Descriptor("help", "help", "h", Options.ArgumentSpecifier.NONE, "show help on options"),
new Options.Descriptor("log", "log", "l", Options.ArgumentSpecifier.OPTIONAL, "log into file (for development purposes)")};
myOptions = new Options(descrs);
}
private static PrintStream logStream = null;
private static boolean logStreamSet = false;
private static PrintStream getLog() {
if (logStreamSet) {
return logStream;
}
logStreamSet = true;
final Options.Argument arg = myOptions.get("log");
if (arg == null) {
return null;
}
if (arg instanceof Options.Value) {
try {
return logStream = new PrintStream(new FileOutputStream(((Options.Value)arg).get()));
}
catch (IOException e) {
e.printStackTrace();
return null;
}
}
if (arg instanceof Options.Switch) {
return logStream = System.out;
}
return null;
}
private static boolean doSave() {
return myOptions.get("save") instanceof Options.Switch;
}
private static boolean doTests() {
return myOptions.get("tests") instanceof Options.Switch;
}
private static boolean doRebuild() {
return myOptions.get("rebuild") instanceof Options.Switch;
}
private static boolean doForce() {
return myOptions.get("force") instanceof Options.Switch;
}
private static boolean doIncremental() {
return myOptions.get("incremental") instanceof Options.Switch;
}
private static boolean doHelp() {
return myOptions.get("help") instanceof Options.Switch;
}
private static Options.Argument doInspect() {
return myOptions.get("inspect");
}
private static Options.Argument doMake() {
return myOptions.get("make");
}
private static boolean doClean() {
return myOptions.get("clean") instanceof Options.Switch;
}
private static String getScript() {
final Options.Argument arg = myOptions.get("script");
if (arg instanceof Options.Value) return ((Options.Value)arg).get();
return null;
}
private static ProjectWrapper.Flags getFlags() {
return new ProjectWrapper.Flags() {
public boolean tests() {
return doTests();
}
public boolean force() {
return doForce();
}
public boolean incremental() {
return doIncremental();
}
public PrintStream logStream() {
return getLog();
}
};
}
private static void checkConsistency() {
int test = 0;
if (doClean()) test++;
if (doMake() != null) test++;
if (doRebuild()) test++;
if (test > 1) {
System.err.print("WARNING: Conflicting options (should be --make OR --rebuild OR --clean); preferring ");
if (doMake() != null) {
System.err.println("make.");
}
else if (doRebuild()) System.err.println("rebuild.");
}
if (doClean() || doRebuild()) {
if (doTests()) {
System.err.println("WARNING: extra --tests option ignored.");
}
if (doForce()) {
System.err.println("WARNING: extra --force option ignored.");
}
}
}
private static Action getAction() {
if (doMake() != null) {
return Action.MAKE;
}
if (doRebuild()) return Action.REBUILD;
if (doClean()) return Action.CLEAN;
return Action.NONE;
}
public static void main(String[] args) {
System.out.println("JetBrains.com build server. (C) JetBrains.com, 2010-2011.\n");
final List<String> notes = myOptions.parse(args);
for (String note : notes) {
System.err.println("WARNING: " + note);
}
checkConsistency();
if (doHelp()) {
System.out.println("Usage: ??? <options> <project-specifier>\n");
System.out.println("Options are:");
System.out.println(myOptions.memo());
}
final List<String> projects = myOptions.getFree();
if (projects.isEmpty() && !doHelp()) {
System.out.println("Nothing to do; use --help or -h option to see the help.\n");
}
for (String prj : projects) {
boolean saved = false;
ProjectWrapper project = null;
switch (getAction()) {
case CLEAN:
System.out.println("Cleaning project \"" + prj + "\"");
project = ProjectWrapper.load(prj, getScript(), false);
project.clean();
project.save();
saved = true;
break;
case REBUILD:
System.out.println("Rebuilding project \"" + prj + "\"");
project = ProjectWrapper.load(prj, getScript(), false);
project.rebuild();
project.save();
saved = true;
break;
case MAKE:
final Options.Argument make = doMake();
if (make instanceof Options.Value) {
final String module = ((Options.Value)make).get();
System.out.println("Making module \"" + module + "\" in project \"" + prj + "\"");
project = ProjectWrapper.load(prj, getScript(), true);
project.makeModule(module, getFlags());
project.save();
saved = true;
}
else if (make instanceof Options.Switch) {
System.out.println("Making all modules in project \"" + prj + "\"");
project = ProjectWrapper.load(prj, getScript(), true);
project.makeModule(null, getFlags());
project.save();
saved = true;
}
;
break;
}
final Options.Argument inspect = doInspect();
if (inspect instanceof Options.Switch) {
project = ProjectWrapper.load(prj, getScript(), true);
project.report();
if (doSave()) {
project.save();
saved = true;
}
}
else if (inspect instanceof Options.Value) {
project = ProjectWrapper.load(prj, getScript(), true);
project.report(((Options.Value)inspect).get());
if (doSave()) {
project.save();
saved = true;
}
}
if (doSave() && !saved) {
project = ProjectWrapper.load(prj, getScript(), true);
project.save();
}
}
}
}
-127
View File
@@ -1,127 +0,0 @@
package org.jetbrains.ether;
import java.io.FileFilter;
import java.io.FilenameFilter;
import java.util.*;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 27.06.11
* Time: 21:03
* To change this template use File | Settings | File Templates.
*/
public class MockFS {
final Map<java.io.File, File> myFiles = new HashMap<java.io.File, File>();
final File myRoot;
private File getFile(java.io.File f) {
if (f.getAbsolutePath().startsWith(myRoot.getAbsolutePath())) {
File g = myFiles.get(f);
if (g != null) {
return g;
}
g = new File(f, false);
myFiles.put(f, g);
return g;
}
return null;
}
public class File extends java.io.File {
final Set<File> mySubFiles = new HashSet<File>();
final File myParent;
private File(final java.io.File file, final boolean root) {
super(file.getPath());
if (root) {
myParent = null;
return;
}
final java.io.File parent = file.getParentFile();
myParent = parent == null ? null : getFile(parent);
if (myParent != null) {
myParent.mySubFiles.add(this);
}
}
@Override
public String[] list() {
return list(new FilenameFilter() {
public boolean accept(java.io.File dir, String name) {
return true;
}
});
}
@Override
public String[] list(final FilenameFilter filter) {
final List<String> result = new LinkedList<String>();
for (final File f : mySubFiles) {
if (filter.accept(this, f.getName())) {
result.add(f.getName());
}
}
return result.toArray(new String[result.size()]);
}
@Override
public java.io.File[] listFiles() {
return mySubFiles.toArray(new File[mySubFiles.size()]);
}
@Override
public java.io.File[] listFiles(final FilenameFilter filter) {
final List<File> result = new LinkedList<File>();
for (File f : mySubFiles) {
if (filter.accept(this, f.getName())) {
result.add(f);
}
}
return result.toArray(new File[result.size()]);
}
@Override
public java.io.File[] listFiles(final FileFilter filter) {
final List<File> result = new LinkedList<File>();
for (File f : mySubFiles) {
if (filter.accept(f)) {
result.add(f);
}
}
return result.toArray(new File[result.size()]);
}
}
private MockFS(final String root) {
final java.io.File rootFile = new java.io.File(root);
myRoot = new File(rootFile, true);
myFiles.put(rootFile, myRoot);
}
public static File fromFiles(final String root, final Collection<String> files) {
final MockFS fs = new MockFS(root);
for (String f : files) {
fs.getFile(new java.io.File(f));
}
return fs.myRoot;
}
}
-272
View File
@@ -1,272 +0,0 @@
package org.jetbrains.ether;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 21.11.10
* Time: 14:33
* To change this template use File | Settings | File Templates.
*/
public class Options {
public enum ArgumentSpecifier {
MANDATORY,
OPTIONAL,
NONE;
}
public abstract interface Argument {
}
public static class Switch implements Argument {
}
private static Switch SWITCH = new Switch();
public static class Value implements Argument {
private final String myValue;
Value(final String s) {
myValue = s;
}
public String get() {
return myValue;
}
}
private class Cursor {
int myPos;
final int myLength;
final String[] myArgs;
Cursor(final String[] args) {
myArgs = args;
myPos = 0;
myLength = myArgs.length;
}
public String look() {
if (myPos >= myLength) return null;
return myArgs[myPos];
}
public void shift() {
myPos++;
}
public String lookahead() {
final String arg = myArgs[myPos + 1];
myPos += 2;
return arg;
}
public boolean nextIsArg() {
return (myPos < myLength - 1 && !myArgs[myPos + 1].startsWith("-"));
}
public boolean endOf() {
return myPos >= myLength;
}
}
private interface Callback {
void update(String key, Argument value);
void addFree(String value);
void report(String note);
}
public static class Descriptor {
private final ArgumentSpecifier myArgumentSpecifier;
private final String myKey;
private final String myLong;
private final String myShort;
private final String myMemo;
private final Pattern myLongPattern;
Descriptor(final String key, final String longForm, final String shortForm, final ArgumentSpecifier as, final String memo) {
myArgumentSpecifier = as;
myKey = key;
myLong = longForm;
myShort = shortForm;
myMemo = memo;
myLongPattern = myLong == null ? null : Pattern.compile("^--" + myLong + "(=(.*))?$");
}
public String memo() {
final StringBuilder buf = new StringBuilder();
String longArg = "", shortArg = "";
switch (myArgumentSpecifier) {
case OPTIONAL:
longArg = "[=<argument>]";
shortArg = " [<argument>]";
break;
case NONE:
longArg = "";
shortArg = "";
break;
case MANDATORY:
longArg = "=<argument>";
shortArg = " <argument>";
break;
}
buf.append(" --" + myLong + longArg + ", -" + myShort + shortArg + "\n");
buf.append(" " + myMemo + "\n");
return buf.toString();
}
public boolean proceed(final Cursor cursor, final Callback callback) {
if (cursor.endOf()) return false;
final String arg = cursor.look();
if (!arg.startsWith("-")) {
callback.addFree(arg);
cursor.shift();
return true;
}
if (myShort != null && arg.equals("-" + myShort)) {
switch (myArgumentSpecifier) {
case NONE:
callback.update(myKey, SWITCH);
break;
default:
if (cursor.nextIsArg()) {
callback.update(myKey, new Value(cursor.lookahead()));
}
else {
switch (myArgumentSpecifier) {
case OPTIONAL:
callback.update(myKey, SWITCH);
break;
case MANDATORY:
callback.report("option \"" + arg + "\" requires an argument, discarding.");
}
}
}
;
cursor.shift();
return true;
}
final Matcher m = myLongPattern.matcher(arg);
if (myLong != null && m.matches()) {
final String prm = m.group(2);
switch (myArgumentSpecifier) {
case MANDATORY:
if (prm == null) {
callback.report("option \"" + arg + "\" requires an argument, discarding.");
}
else {
callback.update(myKey, new Value(prm));
}
break;
case NONE:
if (prm == null) {
callback.update(myKey, SWITCH);
}
else {
callback.report("option \"" + arg + "\" does not take an argument, omitting.");
}
break;
case OPTIONAL:
callback.update(myKey, prm == null ? SWITCH : new Value(prm));
break;
}
cursor.shift();
return true;
}
return false;
}
}
private Map<String, Argument> myOptions = new HashMap<String, Argument>();
private List<String> myFree;
private final Descriptor[] myDescriptors;
Options(final Descriptor[] descrs) {
myDescriptors = descrs;
}
public List<String> parse(final String[] args) {
myOptions.clear();
myFree = new ArrayList<String>();
final List<String> notes = new ArrayList<String>();
final Callback cb = new Callback() {
public void addFree(final String value) {
myFree.add(value);
}
public void update(final String key, final Argument value) {
myOptions.put(key, value);
}
public void report(final String note) {
notes.add(note);
}
};
final Cursor cursor = new Cursor(args);
while (!cursor.endOf()) {
boolean recognized = false;
for (int i = 0; i < myDescriptors.length; i++) {
recognized |= myDescriptors[i].proceed(cursor, cb);
}
if (!recognized) {
cb.report("unrecognized option \"" + cursor.look() + "\" omitted.");
cursor.shift();
}
}
return notes;
}
public Argument get(final String name) {
return myOptions.get(name);
}
public List<String> getFree() {
return myFree;
}
public String memo() {
final StringBuilder buf = new StringBuilder();
for (final Descriptor descriptor : myDescriptors) {
buf.append(descriptor.memo()).append("\n");
}
return buf.toString();
}
}
File diff suppressed because it is too large Load Diff
-101
View File
@@ -1,101 +0,0 @@
package org.jetbrains.ether;
import org.jetbrains.jps.Module;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 03.12.10
* Time: 19:39
* To change this template use File | Settings | File Templates.
*/
public class Reporter {
public static final String myOkFlag = ".jps.ok";
public static final String myFailFlag = ".jps.fail";
private static String getSafePath(final String path) {
final File f = new File(path);
if (!f.exists()) {
f.mkdir();
}
return path;
}
private static String getOkFlag(final Module m) {
final String outputPath = m.getOutputPath();
if (outputPath == null) return null;
return getSafePath(outputPath) + File.separator + myOkFlag;
}
private static String getFailFlag(final Module m) {
final String outputPath = m.getOutputPath();
if (outputPath == null) return null;
return getSafePath(outputPath) + File.separator + myFailFlag;
}
private static String getOkTestFlag(final Module m) {
final String testOutputPath = m.getTestOutputPath();
if (testOutputPath == null) return null;
return getSafePath(testOutputPath) + File.separator + myOkFlag;
}
private static String getFailTestFlag(final Module m) {
final String testOutputPath = m.getTestOutputPath();
if (testOutputPath == null) {
return null;
}
return getSafePath(testOutputPath) + File.separator + myFailFlag;
}
private static void write(final String name, final String contents) {
if (name == null) return;
try {
final File file = new File(name);
final String path = file.getParent();
new File(path).mkdirs();
final FileWriter writer = new FileWriter(name);
writer.write(contents);
writer.close();
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void reportBuildSuccess(final Module m, final boolean tests) {
if (tests) {
write(getOkTestFlag(m), "dummy");
}
else {
write(getOkFlag(m), "dummy");
}
}
public static void reportBuildFailure(final Module m, final boolean tests, final String reason) {
if (tests) {
write(getFailTestFlag(m), reason);
}
else {
write(getFailFlag(m), reason);
}
}
}
@@ -1,307 +0,0 @@
package org.jetbrains.ether.dependencyView;
import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildListener;
import org.jetbrains.asm4.ClassReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: 01.04.11
* Time: 21:31
* To change this template use File | Settings | File Templates.
*/
public class AntListener implements BuildListener {
private static final Pattern read = Pattern.compile("\\[parsing started (.*)\\]");
private static final Pattern written = Pattern.compile("\\[wrote (.*)\\]");
private final Map<String, List<String>> readFiles = new HashMap<String, List<String>>();
private final Map<String, List<ClassFileInfo>> writtenFiles = new HashMap<String, List<ClassFileInfo>>();
private final String targetFolder;
private final int stripLength;
private final List<String> sourceRoots;
private final Callbacks.Backend callback;
private static String basename(final String name, final String extension) {
return name.substring(0, name.length() - extension.length());
}
private static ClassReader getClassReader(final String fullName) {
try {
final File f = new File(fullName);
final byte[] buffer = new byte[(int)f.length()];
final FileInputStream i = new FileInputStream(f);
final int n = i.read(buffer);
i.close();
assert ((int)f.length() == n);
return new ClassReader(buffer);
}
catch (IOException e) {
e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates.
return null;
}
}
private class ClassFileInfo {
final String packageName;
final String fullName;
List<String> subClasses = null;
public ClassFileInfo(final String fullName, final String packageName) {
this.packageName = packageName;
this.fullName = fullName;
}
public void attachSubClass(final String name) {
if (subClasses == null) {
subClasses = new LinkedList<String>();
}
subClasses.add(name);
}
public String getFullName() {
return fullName;
}
public String getPackageName() {
return packageName;
}
public String toString() {
final StringBuilder builder = new StringBuilder();
builder.append(" Root: ").append(fullName).append(", package ").append(packageName).append("\n");
builder.append(" Subclasses:");
if (subClasses != null) {
for (String s : subClasses) {
builder.append(" ").append(s);
}
}
builder.append(".\n");
return builder.toString();
}
public void associate(final Callbacks.SourceFileNameLookup sourceFileNameLookup) {
if (callback != null) {
callback.associate(fullName, sourceFileNameLookup, getClassReader(fullName));
if (subClasses != null) {
for (String s : subClasses) {
callback.associate(s, sourceFileNameLookup, getClassReader(s));
}
}
}
}
}
public AntListener(final String targetFolder, final List<String> sourceRoots, final Callbacks.Backend callback) {
this.targetFolder = targetFolder;
this.sourceRoots = sourceRoots;
this.callback = callback;
stripLength = targetFolder.length() + 1;
}
public void buildStarted(BuildEvent event) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void buildFinished(BuildEvent event) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void targetStarted(BuildEvent event) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void targetFinished(BuildEvent event) {
//To change body of implemented methods use File | Settings | File Templates.
}
public void taskStarted(BuildEvent event) {
}
public void taskFinished(BuildEvent event) {
if (event.getTask().getTaskName().equals("javac")) {
for (Map.Entry<String, List<ClassFileInfo>> e : writtenFiles.entrySet()) {
final String className = e.getKey();
final List<ClassFileInfo> infos = e.getValue();
final List<String> read = readFiles.get(className);
if (infos.size() == 1 && read != null && read.size() == 1) {
infos.get(0).associate(Callbacks.getDefaultLookup(read.get(0)));
continue;
}
process:
for (ClassFileInfo c : infos) {
final String packageName = c.getPackageName();
final Callbacks.SourceFileNameLookup sourceNameLookup = new Callbacks.SourceFileNameLookup() {
public String get(final String sourceAttribute) {
assert (sourceAttribute != null);
final String className = basename(sourceAttribute, ".java");
final List<String> candidates = readFiles.get(className);
assert (candidates != null);
if (candidates.size() == 1) {
return candidates.get(0);
}
for (String r : candidates) {
if (new PackageNameSelector().get(r).equals(packageName)) {
return r;
}
}
assert (false);
return null;
}
};
c.associate(sourceNameLookup);
}
}
/*
System.out.println("Written files info:");
for (Map.Entry<String, List<ClassFileInfo>> e : writtenFiles.entrySet()) {
final String className = e.getKey();
final List<ClassFileInfo> infos = e.getValue();
System.out.println(" Class name: " + className);
System.out.println(" Class file info(s): ");
for (ClassFileInfo c : infos) {
System.out.println(c.toString());
}
}
System.out.println("End.");
System.out.println("Read files info:");
for (Map.Entry<String, List<String>> e : readFiles.entrySet()) {
final String className = e.getKey();
final List<String> files = e.getValue();
System.out.println(" Class name: " + className);
System.out.print(" Files:");
for (String file : files) {
System.out.print(" " + file);
}
System.out.println(".");
}
System.out.println("End.");
*/
}
}
private String extractPackage(final String s) {
if (s.length() < stripLength) return "";
return s.substring(stripLength);
}
public void messageLogged(BuildEvent event) {
final String m = event.getMessage();
final Matcher writtenMatcher = written.matcher(m);
final Matcher readMatcher = read.matcher(m);
if (writtenMatcher.matches()) {
final String fullName = writtenMatcher.group(1);
final File file = new File(fullName);
final String classFileName = file.getName();
final String packageName = extractPackage(fullName.substring(0, fullName.length() - classFileName.length() - 1));
String className = basename(classFileName, ".class");
boolean subClass = false;
final int i = className.indexOf('$');
if (i >= 0) {
className = className.substring(0, i);
subClass = true;
}
List<ClassFileInfo> info = writtenFiles.get(className);
if (info == null) {
info = new LinkedList<ClassFileInfo>();
writtenFiles.put(className, info);
}
boolean updated = false;
for (ClassFileInfo ci : info) {
if (subClass) {
if (ci.getPackageName().equals(packageName)) {
ci.attachSubClass(fullName);
updated = true;
}
}
else {
if (ci.getFullName().equals(fullName)) {
updated = true;
break;
}
}
}
if (!updated) {
if (subClass) {
final ClassFileInfo c =
new ClassFileInfo(targetFolder + File.separator + packageName + File.separator + className + ".class", packageName);
c.attachSubClass(fullName);
info.add(c);
}
else {
info.add(new ClassFileInfo(fullName, packageName));
}
}
}
if (readMatcher.matches()) {
final String fullName = readMatcher.group(1);
final File file = new File(fullName);
final String sourceFileName = file.getName();
final String className = basename(sourceFileName, ".java");
List<String> files = readFiles.get(className);
if (files == null) {
files = new LinkedList<String>();
readFiles.put(className, files);
}
files.add(fullName);
}
}
}
@@ -2,27 +2,22 @@ package org.jetbrains.jps
import com.intellij.ant.InstrumentationUtil.FormInstrumenter
import com.intellij.compiler.instrumentation.InstrumentationClassFinder
import org.jetbrains.ether.ProjectWrapper
import org.jetbrains.ether.dependencyView.Callbacks.Backend
/**
* @author max
*/
class ModuleBuildState {
boolean iterated
boolean tests
Backend callback
FormInstrumenter formInstrumenter
InstrumentationClassFinder loader
ProjectWrapper projectWrapper
List<File> sourceFiles
List<String> sourceRoots
List<String> excludes
List<String> classpath
List<String> tempRootsToDelete = []
List<String> sourceRootsFromModuleWithDependencies
String targetFolder
boolean incremental = false
def print() {
println "Sources: $sourceRoots"
+16 -70
View File
@@ -2,12 +2,8 @@ package org.jetbrains.jps
import org.apache.tools.ant.BuildException
import org.codehaus.gant.GantBinding
import org.jetbrains.ether.ProjectWrapper
import org.jetbrains.ether.Reporter
import org.jetbrains.ether.dependencyView.Callbacks.Backend
import org.jetbrains.jps.artifacts.ArtifactBuilder
import org.jetbrains.jps.idea.OwnServiceLoader
import org.jetbrains.jps.listeners.BuildInfoPrinter
import org.jetbrains.jps.listeners.BuildStatisticsListener
import org.jetbrains.jps.listeners.DefaultBuildInfoPrinter
@@ -224,7 +220,7 @@ class ProjectBuilder {
private def buildChunks(Collection<Module> modules, boolean tests) {
getChunks(tests).getChunkList().each {
if (!modules.intersect(it.modules).isEmpty()) {
buildChunk(it, tests, null, null, null)
buildChunk(it, tests)
}
}
}
@@ -270,32 +266,16 @@ class ProjectBuilder {
buildModules(dependencies, includeTests)
}
def clearChunk(ModuleChunk chunk, Collection<String> files, ProjectWrapper pw) {
def clearChunk(ModuleChunk chunk) {
if (!dryRun) {
if (files == null) {
stage("Cleaning module ${chunk.name}")
chunk.modules.each {cleanModule it}
}
else {
stage("Cleaning output files for module ${chunk.name}")
files.each {
binding.ant.delete(file: pw.getAbsolutePath(it))
}
chunk.modules.each {
binding.ant.delete(file: it.outputPath + File.separator + Reporter.myOkFlag)
binding.ant.delete(file: it.outputPath + File.separator + Reporter.myFailFlag)
}
}
stage("Cleaning module ${chunk.name}")
chunk.modules.each {cleanModule it}
}
}
def buildChunk(ModuleChunk chunk, boolean tests, Collection<String> files, Backend callback, ProjectWrapper pw) {
def buildChunk(ModuleChunk chunk, boolean tests) {
Set<ModuleChunk> compiledSet = tests ? compiledTestChunks : compiledChunks
if (compiledSet.contains(chunk) && files == null) return
if (compiledSet.contains(chunk)) return
compiledSet.add(chunk)
stage("Making${tests ? ' tests for' : ''} module ${chunk.name}")
@@ -303,39 +283,26 @@ class ProjectBuilder {
warning("Modules $chunk.modules with cyclic dependencies will be compiled to output of ${chunk.modules.toList().first()} module")
}
compile(chunk, tests, files, callback, pw)
compile(chunk, tests)
}
private String getModuleOutputFolder(Module module, boolean tests) {
return getProjectPaths().getModuleOutputDir(module, tests)?.absolutePath
}
private def compile(ModuleChunk chunk, boolean tests, Collection<String> files, Backend callback, ProjectWrapper pw) {
private def compile(ModuleChunk chunk, boolean tests) {
List<String> chunkSources = filterNonExistingFiles(tests ? chunk.testRoots : chunk.sourceRoots, true)
if (chunkSources.isEmpty()) return
List<String> sourceFiles = []
if (files != null) {
files.each {
sourceFiles << pw.getAbsolutePath(it)
}
}
if (!dryRun) {
List<String> chunkClasspath = ProjectPaths.getPathsList(getProjectPaths().getClasspathFiles(chunk, ClasspathKind.compile(tests), files == null))
List<String> chunkClasspath = ProjectPaths.getPathsList(getProjectPaths().getClasspathFiles(chunk, ClasspathKind.compile(tests), true))
List sourceRootsWithDependencies = ProjectPaths.getPathsList(getProjectPaths().getSourcePathsWithDependents(chunk, tests))
Map<ModuleBuildState, ModuleChunk> states = new HashMap<ModuleBuildState, ModuleChunk>()
def chunkState = new ModuleBuildState(
iterated: false,
loader: null,
formInstrumenter: null,
tests: tests,
projectWrapper: pw,
incremental: files != null,
callback: callback,
sourceFiles: sourceFiles,
sourceRoots: chunkSources,
excludes: computeExcludes(chunk.elements, chunkSources),
classpath: chunkClasspath,
@@ -346,14 +313,9 @@ class ProjectBuilder {
List<String> sourceRoots = filterNonExistingFiles(tests ? it.testRoots : it.sourceRoots, false)
if (!sourceRoots.isEmpty()) {
def state = new ModuleBuildState(
iterated: false,
loader: null,
formInstrumenter: null,
tests: tests,
projectWrapper: pw,
incremental: chunkState.incremental,
callback: callback,
sourceFiles: sourceFiles,
sourceRoots: sourceRoots,
excludes: computeExcludes([it], sourceRoots),
classpath: chunkClasspath,
@@ -377,28 +339,15 @@ class ProjectBuilder {
listeners*.onCompilationStarted(chunk)
try {
builders().each {ModuleBuilder builder ->
listeners*.onModuleBuilderStarted(builder, chunk)
if (arrangeModuleCyclesOutputs && chunk.modules.size() > 1 && builder instanceof ModuleCycleBuilder) {
((ModuleCycleBuilder) builder).preprocessModuleCycle(chunkState, chunk, this)
}
states.keySet().each {
builder.processModule(it, states[it], this)
}
listeners*.onModuleBuilderFinished(builder, chunk)
builders().each {ModuleBuilder builder ->
listeners*.onModuleBuilderStarted(builder, chunk)
if (arrangeModuleCyclesOutputs && chunk.modules.size() > 1 && builder instanceof ModuleCycleBuilder) {
((ModuleCycleBuilder) builder).preprocessModuleCycle(chunkState, chunk, this)
}
}
catch (Exception e) {
final String reason = e.toString();
if (pw != null) {
chunk.modules.each {
Reporter.reportBuildFailure(it, tests, reason)
}
states.keySet().each {
builder.processModule(it, states[it], this)
}
throw e;
listeners*.onModuleBuilderFinished(builder, chunk)
}
states.keySet().each {
@@ -413,9 +362,6 @@ class ProjectBuilder {
}
chunk.modules.each {
if (pw != null) {
Reporter.reportBuildSuccess(it, tests)
}
exportProperty("module.${it.name}.output.${tests ? "test" : "main"}", getModuleOutputFolder(it, tests))
}
}
@@ -4,9 +4,6 @@ import com.intellij.ant.InstrumentationUtil
import com.intellij.ant.InstrumentationUtil.FormInstrumenter
import com.intellij.ant.PrefixedPath
import com.intellij.compiler.instrumentation.InstrumentationClassFinder
import org.apache.tools.ant.BuildListener
import org.jetbrains.ether.ProjectWrapper
import org.jetbrains.ether.dependencyView.AntListener
import org.jetbrains.jps.builders.javacApi.Java16ApiCompilerRunner
import org.jetbrains.jps.*
@@ -61,9 +58,6 @@ class JavacBuilder implements ModuleBuilder, ModuleCycleBuilder {
params.debug = String.valueOf(debugInfo);
params.nowarn = String.valueOf(nowarn);
params.deprecation = String.valueOf(deprecation);
if (state.projectWrapper != null) {
params.verbose = "true"
}
def javacExecutable = getJavacExecutable(module)
if (javacExecutable != null) {
@@ -72,33 +66,11 @@ class JavacBuilder implements ModuleBuilder, ModuleCycleBuilder {
def ant = projectBuilder.binding.ant
if (state.projectWrapper != null) {
final BuildListener listener = new AntListener(state.targetFolder, state.sourceRoots, state.callback)
ant.project.addBuildListener(listener)
};
ant.javac(params) {
if (customArgs) {
compilerarg(line: customArgs)
}
if (state.projectWrapper != null && state.sourceFiles != null) {
List patterns = []
state.sourceFiles.each {
for (String root: state.sourceRoots) {
if (it.startsWith(root) && it.endsWith(".java")) {
patterns << it.substring(root.length() + 1)
break;
}
}
patterns.each {
include(name: it)
}
}
}
state.sourceRoots.each {
src(path: it)
}
@@ -117,14 +89,6 @@ class JavacBuilder implements ModuleBuilder, ModuleCycleBuilder {
}
}
}
if (state.projectWrapper != null) {
ant.project.removeBuildListener(listener)
};
if (state.sourceFiles != null) {
projectBuilder.listeners*.onJavaFilesCompiled(module, state.sourceFiles.size())
}
}
private String getJavacExecutable(ModuleChunk module) {
@@ -153,10 +117,6 @@ class ResourceCopier implements ModuleBuilder {
resourcePatternInitialized = true
}
if (state.iterated) return;
state.iterated = true
if (state.sourceRoots.isEmpty()) return;
def ant = projectBuilder.binding.ant
@@ -266,15 +226,6 @@ class GroovyStubGenerator implements ModuleBuilder {
}
}
if (state.incremental) {
Set<File> excluded = state.excludes.collect { new File(it.toString()) }
List<File> filesToCompile = new LinkedList<File>()
JavaFileCollector.collectRecursively(new File(stubsRoot), filesToCompile, excluded)
filesToCompile.each {state.sourceFiles << it.getAbsolutePath()}
}
state.sourceRoots << stubsRoot
state.tempRootsToDelete << stubsRoot
}
@@ -289,12 +240,6 @@ class JetBrainsInstrumentations implements ModuleBuilder {
@Override
void associate(final String formFile, final String classFile) {
if (state.callback != null) {
final String formRelPath = state.projectWrapper.getRelativePath(formFile);
final String classRelPath = state.projectWrapper.getRelativePath(classFile);
state.callback.associateForm(formRelPath, classRelPath);
}
}
@Override
@@ -342,19 +287,6 @@ class JetBrainsInstrumentations implements ModuleBuilder {
state.loader = new InstrumentationClassFinder((URL[])urls.toArray(new URL[urls.size()]))
final List<File> formFiles = new ArrayList<File>();
final ProjectWrapper pw = state.projectWrapper;
if (pw != null) {
for (Module m: moduleChunk.elements) {
final Set<String> names = state.tests ? pw.getModule(m.getName()).getTests() : pw.getModule(m.getName()).getSources();
for (String name: names) {
if (name.endsWith(".form")) {
formFiles.add(new File(pw.getAbsolutePath(name)))
}
}
}
}
final List<PrefixedPath> nestedFormDirs = new ArrayList<PrefixedPath>();
state.sourceRootsFromModuleWithDependencies.each {
@@ -363,49 +295,30 @@ class JetBrainsInstrumentations implements ModuleBuilder {
state.formInstrumenter = new CustomFormInstrumenter(new File(state.targetFolder), nestedFormDirs, formFiles, state);
if (!state.incremental) {
for (File formFile: formFiles) {
state.formInstrumenter.instrumentForm(formFile, state.loader);
}
}
}
if (state.incremental) {
for (String f: state.sourceFiles) {
if (f.endsWith(".form")) {
state.formInstrumenter.instrumentForm(new File(f), state.loader);
}
for (File formFile: formFiles) {
state.formInstrumenter.instrumentForm(formFile, state.loader);
}
}
if (projectBuilder.useInProcessJavac)
return;
if (!state.incremental) {
new Object() {
public void traverse(final File root) {
final File[] files = root.listFiles();
new Object() {
public void traverse(final File root) {
final File[] files = root.listFiles();
for (File f: files) {
final String name = f.getName();
for (File f: files) {
final String name = f.getName();
if (name.endsWith(".class")) {
InstrumentationUtil.instrumentNotNull(f, state.loader)
}
else if (f.isDirectory()) {
traverse(f)
}
if (name.endsWith(".class")) {
InstrumentationUtil.instrumentNotNull(f, state.loader)
}
else if (f.isDirectory()) {
traverse(f)
}
}
}.traverse(new File(state.targetFolder))
}
else {
final Collection<String> classes = state.callback.getClassFiles()
classes.each {
InstrumentationUtil.instrumentNotNull(new File(state.targetFolder + File.separator + it + ".class"), state.loader)
}
}
}.traverse(new File(state.targetFolder))
if (state.loader != null) {
state.loader.releaseResources();
}
@@ -52,18 +52,9 @@ class Java16ApiCompiler {
List<File> filesToCompile = []
if (state.incremental) {
for (String src: state.sourceFiles) {
if (src.endsWith(".java")) {
filesToCompile << new File(src)
}
}
}
else {
Set<File> excluded = state.excludes.collect { new File(it.toString()) }
state.sourceRoots.each {
JavaFileCollector.collectRecursively(new File(it.toString()), filesToCompile, excluded)
}
Set<File> excluded = state.excludes.collect { new File(it.toString()) }
state.sourceRoots.each {
JavaFileCollector.collectRecursively(new File(it.toString()), filesToCompile, excluded)
}
if (filesToCompile.size() > 0) {
@@ -28,7 +28,7 @@ class AntPrePostStepsInArtifactsTest extends JpsBuildTestCase {
public void test_broken_artifact() throws Exception {
Project project = loadProject("testData/artifactWithAntPrePostTasks/.idea", [:])
assertEquals(2, project.artifacts.size());
for (Artifact a: project.artifacts) {
for (Artifact a: project.artifacts.values()) {
assertNull(project.artifacts.properties);
}
}
@@ -154,6 +154,7 @@ public class CodeEditUtil {
if (child == last) break;
child = child.getTreeNext();
}
assert child == last : last + " is not a successor of " + first +" in the .getTreeNext() chain";
final ASTNode prevLeaf = TreeUtil.prevLeaf(first);
final ASTNode nextLeaf = TreeUtil.nextLeaf(first);
@@ -281,7 +281,7 @@ public class CompositeElement extends TreeElement {
}
if (endOffset != len) {
@NonNls String msg = "len=" + len + ";\n endOffset=" + endOffset;
msg += diagnoseTextInconsistency(new String(buffer, 0, endOffset), startStamp);
msg += diagnoseTextInconsistency(new String(buffer, 0, Math.min(len, endOffset)), startStamp);
throw new AssertionError(msg);
}
return buffer;
@@ -354,6 +354,11 @@ public abstract class TreeElement extends ElementBase implements ASTNode, Clonea
assert end == null || end.getTreeParent() == parent : "Trying to remove non-child";
if (end != null) {
TreeElement element;
for (element = this; element != end && element != null; element = element.getTreeNext());
assert element == end : end + " is not successor of " + this +" in the .getTreeNext() chain";
}
if (parent != null){
if (this == parent.getFirstChildNode()) {
parent.setFirstChildNode(end);
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2011 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -426,7 +426,7 @@ public class EditorUtil {
}
public static int charWidth(char c, @JdkConstants.FontStyle int fontType, Editor editor) {
return fontForChar(c, fontType, editor).charWidth(c, editor.getContentComponent());
return fontForChar(c, fontType, editor).charWidth(c);
}
public static int getSpaceWidth(@JdkConstants.FontStyle int fontType, Editor editor) {
@@ -566,7 +566,7 @@ public class EditorUtil {
char c = text.charAt(i);
if (c != '\t') {
FontInfo font = fontForChar(c, fontType, editor);
result += font.charWidth(c, editor.getContentComponent());
result += font.charWidth(c);
continue;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -15,6 +15,8 @@
*/
package com.intellij.openapi.editor.impl;
import com.intellij.ide.ui.UISettings;
import com.intellij.ide.ui.UISettingsListener;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
@@ -38,7 +40,28 @@ public class ComplementaryFontsRegistry {
private static FontKey ourSharedKeyInstance = new FontKey("", 0, 0);
private static FontInfo ourSharedDefaultFont;
private static final TIntHashSet ourUndisplayableChars = new TIntHashSet();
private static boolean ourOldUseAntialiasing;
static {
final UISettings settings = UISettings.getInstance();
ourOldUseAntialiasing = settings.ANTIALIASING_IN_EDITOR;
// Reset font info on 'use antialiasing' setting change.
// Assuming that the listener is notified from the EDT only.
settings.addUISettingsListener(new UISettingsListener() {
@Override
public void uiSettingsChanged(UISettings source) {
if (ourOldUseAntialiasing ^ source.ANTIALIASING_IN_EDITOR) {
ourOldUseAntialiasing = source.ANTIALIASING_IN_EDITOR;
for (FontInfo fontInfo : ourUsedFonts.values()) {
fontInfo.reset();
}
ourUsedFonts.clear();
}
}
}, ApplicationManager.getApplication());
}
private ComplementaryFontsRegistry() {
}
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
* Copyright 2000-2012 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.
@@ -108,7 +108,7 @@ public class DefaultEditorTextRepresentationHelper implements EditorTextRepresen
}
Key key = mySharedKey.clone();
FontInfo font = ComplementaryFontsRegistry.getFontAbleToDisplay(c, key.fontSize, key.fontType, key.fontName);
result = font.charWidth(c, myEditor.getContentComponent());
result = font.charWidth(c);
if (mySymbolWidthCache.size() >= MAX_SYMBOLS_WIDTHS_CACHE_SIZE) {
// Don't expect to be here.
mySymbolWidthCache.clear();
@@ -2635,7 +2635,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
private CachedFontContent(@NotNull FontInfo fontInfo) {
myFontType = fontInfo;
spaceWidth = fontInfo.charWidth(' ', myEditorComponent);
spaceWidth = fontInfo.charWidth(' ');
myHasBreakSymbols = fontInfo.hasGlyphsToBreakDrawingIteration();
}
@@ -2668,8 +2668,8 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
final int lastCount = count - 1;
final Color lastColor = color[lastCount];
if (_data == myLastData && _start == ends[lastCount] && (_color == null || lastColor == null || _color.equals(lastColor))
&& _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */
&& (!myHasBreakSymbols || !myFontType.getSymbolsToBreakDrawingIteration().contains(_data[ends[lastCount] - 1])))
&& _y == y[lastCount] /* there is a possible case that vertical position is adjusted because of soft wrap */
&& (!myHasBreakSymbols || !myFontType.getSymbolsToBreakDrawingIteration().contains(_data[ends[lastCount] - 1])))
{
ends[lastCount] = _end;
if (lastColor == null) color[lastCount] = _color;
@@ -3048,7 +3048,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
// * the fonts mentioned above have different space width;
// So, the problem was when white space followed russian word - the white space width was calculated using the english font
// but drawn using the russian font, so, there was a visual inconsistency at the editor.
final int charWidth = font.charWidth(c, myEditorComponent);
final int charWidth = font.charWidth(c);
if (c == ' '
&& myCommonSpaceWidth > 0
&& myLastCache != null
@@ -6142,7 +6142,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi
}
}
else {
x += ComplementaryFontsRegistry.getFontAbleToDisplay(c, fontSize, fontType, fontName).charWidth(c, myEditorComponent);
x += ComplementaryFontsRegistry.getFontAbleToDisplay(c, fontSize, fontType, fontName).charWidth(c);
offset++;
}
}
@@ -15,11 +15,11 @@
*/
package com.intellij.openapi.editor.impl;
import com.intellij.ide.ui.UISettings;
import gnu.trove.TIntHashSet;
import org.intellij.lang.annotations.JdkConstants;
import org.jetbrains.annotations.NotNull;
import javax.swing.*;
import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
@@ -118,15 +118,20 @@ public class FontInfo {
return myFont;
}
public int charWidth(char c, JComponent anyComponent) {
final FontMetrics metrics = fontMetrics(anyComponent);
public int charWidth(char c) {
final FontMetrics metrics = fontMetrics();
if (c < 128) return charWidth[c];
return metrics.charWidth(c);
}
private FontMetrics fontMetrics(JComponent anyComponent) {
private FontMetrics fontMetrics() {
if (myFontMetrics == null) {
myFontMetrics = anyComponent.getFontMetrics(myFont);
// We need to use antialising-aware font metrics because we've alrady encountered a situation when non-antialiased symbol
// width is not equal to the antialiased one (IDEA-81539).
final Graphics graphics = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB).getGraphics();
UISettings.setupAntialiasing(graphics);
graphics.setFont(myFont);
myFontMetrics = graphics.getFontMetrics();
for (int i = 0; i < 128; i++) {
charWidth[i] = myFontMetrics.charWidth(i);
}
@@ -134,6 +139,10 @@ public class FontInfo {
return myFontMetrics;
}
void reset() {
myFontMetrics = null;
}
public int getSize() {
return mySize;
}
@@ -314,7 +314,7 @@ public class SoftWrapApplianceManager implements SoftWrapFoldingListener, Docume
FontInfo fontInfo = EditorUtil.fontForChar(placeholder.charAt(0), myContext.fontType, myEditor);
int placeholderWidthInPixels = 0;
for (int i = 0; i < placeholder.length(); i++) {
placeholderWidthInPixels += fontInfo.charWidth(placeholder.charAt(i), myContext.contentComponent);
placeholderWidthInPixels += fontInfo.charWidth(placeholder.charAt(i));
}
int newX = myContext.currentPosition.x + placeholderWidthInPixels;
@@ -27,9 +27,9 @@ import java.util.*;
* @author peter
*/
@SuppressWarnings("unchecked")
public class SmartFMap<K,V> extends AbstractMap<K,V> {
public class SmartFMap<K,V> implements Map<K,V> {
private static final SmartFMap EMPTY = new SmartFMap(ArrayUtil.EMPTY_OBJECT_ARRAY);
private static final int ARRAY_THRESHOLD = 5;
private static final int ARRAY_THRESHOLD = 8;
private final Object myMap;
private SmartFMap(Object map) {
@@ -75,12 +75,26 @@ public class SmartFMap<K,V> extends AbstractMap<K,V> {
if (myMap instanceof Map) {
THashMap<K, V> newMap = new THashMap<K, V>((Map<K, V>)myMap);
newMap.remove(key);
if (newMap.size() <= ARRAY_THRESHOLD) {
Object[] newArray = new Object[newMap.size() * 2];
int i = 0;
for (K k : newMap.keySet()) {
newArray[i++] = k;
newArray[i++] = newMap.get(k);
}
return new SmartFMap<K, V>(newArray);
}
return new SmartFMap<K, V>(newMap);
}
Object[] array = (Object[])myMap;
for (int i = 0; i < array.length; i += 2) {
if (key.equals(array[i])) {
if (size() == 1) {
return EMPTY;
}
Object[] newArray = new Object[array.length - 2];
System.arraycopy(array, 0, newArray, 0, i);
System.arraycopy(array, i + 2, newArray, i, array.length - i - 2);
@@ -106,6 +120,16 @@ public class SmartFMap<K,V> extends AbstractMap<K,V> {
return result;
}
@Override
public boolean equals(Object obj) {
return obj instanceof Map && entrySet().equals(((Map)obj).entrySet());
}
@Override
public int hashCode() {
return entrySet().hashCode();
}
@Override
public boolean containsKey(Object key) {
if (key == null) {
@@ -123,6 +147,11 @@ public class SmartFMap<K,V> extends AbstractMap<K,V> {
return false;
}
@Override
public boolean containsValue(Object value) {
return false;
}
@Override
@Nullable
public V get(Object key) {
@@ -159,6 +188,24 @@ public class SmartFMap<K,V> extends AbstractMap<K,V> {
throw new UnsupportedOperationException();
}
@Override
public Set<K> keySet() {
LinkedHashSet<K> result = new LinkedHashSet<K>();
for (Entry<K, V> entry : entrySet()) {
result.add(entry.getKey());
}
return Collections.unmodifiableSet(result);
}
@Override
public Collection<V> values() {
ArrayList<V> result = new ArrayList<V>();
for (Entry<K, V> entry : entrySet()) {
result.add(entry.getValue());
}
return Collections.unmodifiableCollection(result);
}
@Override
@Deprecated
public V remove(Object key) {
@@ -173,20 +220,47 @@ public class SmartFMap<K,V> extends AbstractMap<K,V> {
return ((Object[])myMap).length >> 1;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public Set<Entry<K, V>> entrySet() {
LinkedHashSet<Entry<K, V>> set = new LinkedHashSet<Entry<K, V>>();
if (myMap instanceof Map) {
for (Entry<K, V> entry : ((Map<K, V>)myMap).entrySet()) {
set.add(new SimpleImmutableEntry<K, V>(entry));
set.add(new AbstractMap.SimpleImmutableEntry<K, V>(entry));
}
} else {
Object[] array = (Object[])myMap;
for (int i = 0; i < array.length; i += 2) {
set.add(new SimpleImmutableEntry<K, V>((K)array[i], (V)array[i + 1]));
set.add(new AbstractMap.SimpleImmutableEntry<K, V>((K)array[i], (V)array[i + 1]));
}
}
return Collections.unmodifiableSet(set);
}
// copied from AbstractMap
public String toString() {
Iterator<Entry<K,V>> i = entrySet().iterator();
if (! i.hasNext())
return "{}";
StringBuilder sb = new StringBuilder();
sb.append('{');
while (true) {
Entry<K, V> e = i.next();
K key = e.getKey();
V value = e.getValue();
sb.append(key == this ? "(this Map)" : key);
sb.append('=');
sb.append(value == this ? "(this Map)" : value);
if (!i.hasNext()) {
return sb.append('}').toString();
}
sb.append(", ");
}
}
}
@@ -704,7 +704,7 @@ public abstract class ChangesTreeList<T> extends JPanel {
}
private CheckboxTree.NodeState getNodeStatus(ChangesBrowserNode node) {
private CheckboxTree.NodeState getNodeStatus(ChangesBrowserNode<T> node) {
boolean hasIncluded = false;
boolean hasExcluded = false;