mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -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);
|
||||
|
||||
+7
-2
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+24
-1
@@ -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() {
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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;
|
||||
}
|
||||
|
||||
+1
-1
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user