Merge branch 'master' of git@git.labs.intellij.net:idea/community

This commit is contained in:
Kirill Kalishev
2010-07-28 21:49:55 +04:00
14 changed files with 279 additions and 138 deletions
@@ -0,0 +1,27 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.lang.documentation;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
/**
* User: spLeaner
*/
public interface ExternalDocumentationHandler {
boolean handleExternal(PsiElement element, PsiElement originalElement);
boolean handleExternalLink(PsiManager psiManager, String link, PsiElement context);
}
@@ -21,6 +21,7 @@ import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Consumer;
import com.intellij.util.Function;
import com.intellij.util.Processor;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
@@ -28,16 +29,16 @@ import java.util.Arrays;
* @author oleg
*/
public class ControlFlowUtil {
private static final Logger LOG = Logger.getInstance(ControlFlowUtil.class.getName());
private static final Logger LOG = Logger.getInstance(ControlFlowUtil.class.getName());
private ControlFlowUtil() {
}
public static class Stack {
private final int myCapacity;
private final int[] myValues;
private int myIndex;
public Stack(final int capacity) {
myCapacity = capacity;
myValues = new int[myCapacity];
@@ -65,8 +66,8 @@ public class ControlFlowUtil {
public String toString() {
return "Stack(" + (myIndex + 1) + ") elements";
}
}
}
public static int[] postOrder(Instruction[] flow) {
final int length = flow.length;
int[] result = new int[length];
@@ -108,6 +109,7 @@ public class ControlFlowUtil {
}
// Process control flow in depth first order
public static boolean process(final Instruction[] flow, final int start, final Processor<Instruction> processor){
final int length = flow.length;
boolean[] visited = new boolean[length];
@@ -135,4 +137,35 @@ public class ControlFlowUtil {
}
return true;
}
public static void iteratePrev(final int startInstruction,
@NotNull final Instruction[] instructions,
@NotNull final Function<Instruction, Operation> closure) {
final Stack stack = new Stack(instructions.length);
final boolean[] visited = new boolean[instructions.length];
stack.push(startInstruction);
while (!stack.isEmpty()) {
final int num = stack.pop();
if (visited[num]){
continue;
}
visited[num] = true;
final Instruction instr = instructions[num];
final Operation nextOperation = closure.fun(instr);
if (nextOperation == Operation.CONTINUE) {
continue;
} else if (nextOperation == Operation.BREAK) {
break;
}
for (Instruction pred : instr.allPred()) {
stack.push(pred.num());
}
}
}
public static enum Operation {
CONTINUE, BREAK, NEXT;
}
}
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.hint.HintManagerImpl;
import com.intellij.codeInsight.hint.HintUtil;
import com.intellij.ide.actions.ExternalJavaDocAction;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.lang.documentation.ExternalDocumentationHandler;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.ui.popup.JBPopup;
@@ -405,10 +406,13 @@ public class DocumentationComponent extends JPanel implements Disposable {
if (myElement != null) {
final PsiElement element = myElement.getElement();
final DocumentationProvider provider = DocumentationManager.getProviderFromElement(element);
final List<String> urls = provider.getUrlFor(element, DocumentationManager.getOriginalElement(element));
assert urls != null;
assert !urls.isEmpty();
ExternalJavaDocAction.showExternalJavadoc(urls);
final PsiElement originalElement = DocumentationManager.getOriginalElement(element);
if (!(provider instanceof ExternalDocumentationHandler) || !((ExternalDocumentationHandler)provider).handleExternal(element, originalElement)) {
final List<String> urls = provider.getUrlFor(element, originalElement);
assert urls != null;
assert !urls.isEmpty();
ExternalJavaDocAction.showExternalJavadoc(urls);
}
}
}
@@ -33,6 +33,7 @@ import com.intellij.lang.Language;
import com.intellij.lang.LanguageDocumentation;
import com.intellij.lang.documentation.CompositeDocumentationProvider;
import com.intellij.lang.documentation.DocumentationProvider;
import com.intellij.lang.documentation.ExternalDocumentationHandler;
import com.intellij.lang.documentation.ExternalDocumentationProvider;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
@@ -816,38 +817,43 @@ public class DocumentationManager {
}
}
else {
final DocumentationProvider provider = getProviderFromElement(psiElement);
if (!(provider instanceof ExternalDocumentationHandler) ||
!((ExternalDocumentationHandler)provider).handleExternalLink(manager, url, psiElement)) {
final String docUrl = url;
fetchDocInfo
(new DocumentationCollector() {
public String getDocumentation() throws Exception {
if (docUrl.startsWith(DOC_ELEMENT_PROTOCOL)) {
final List<String> urls = ApplicationManager.getApplication().runReadAction(
fetchDocInfo
(new DocumentationCollector() {
public String getDocumentation() throws Exception {
if (docUrl.startsWith(DOC_ELEMENT_PROTOCOL)) {
final List<String> urls = ApplicationManager.getApplication().runReadAction(
new Computable<List<String>>() {
public List<String> compute() {
final DocumentationProvider provider = getProviderFromElement(psiElement);
return provider.getUrlFor(psiElement, getOriginalElement(psiElement));
}
}
);
BrowserUtil.launchBrowser(urls != null && !urls.isEmpty() ? urls.get(0) : docUrl);
} else {
BrowserUtil.launchBrowser(docUrl);
);
BrowserUtil.launchBrowser(urls != null && !urls.isEmpty() ? urls.get(0) : docUrl);
}
else {
BrowserUtil.launchBrowser(docUrl);
}
return "";
}
return "";
}
public PsiElement getElement() {
//String loc = getElementLocator(docUrl);
//
//if (loc != null) {
// PsiElement context = component.getElement();
// return JavaDocUtil.findReferenceTarget(context.getManager(), loc, context);
//}
public PsiElement getElement() {
//String loc = getElementLocator(docUrl);
//
//if (loc != null) {
// PsiElement context = component.getElement();
// return JavaDocUtil.findReferenceTarget(context.getManager(), loc, context);
//}
return psiElement;
}
}, component);
return psiElement;
}
}, component);
}
}
component.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
@@ -5,6 +5,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
@@ -15,13 +16,16 @@ public class IndentationAnnotatorVisitor extends PsiElementVisitor {
protected final AnnotationHolder myHolder;
private final IElementType myIndentTokenType;
private final IElementType myEolTokenType;
private final TokenSet myCommentTypes;
public IndentationAnnotatorVisitor(@NotNull final AnnotationHolder holder,
final IElementType indentTokenType,
final IElementType eolTokenType) {
final IElementType eolTokenType,
final TokenSet commentTypes) {
myHolder = holder;
myIndentTokenType = indentTokenType;
myEolTokenType = eolTokenType;
myCommentTypes = commentTypes;
}
@SuppressWarnings({"ConstantConditions"})
@@ -45,43 +49,46 @@ public class IndentationAnnotatorVisitor extends PsiElementVisitor {
// Iterating over leafs
while (leaf != null) {
final IElementType leafType = leaf.getNode().getElementType();
if (leafType == myIndentTokenType && nextLeaf!=null && nextLeaf.getNode().getElementType() != myEolTokenType){
final String currentIndentText = leaf.getText();
final IndentInfo currentIndent = getIndent(currentIndentText);
final int currentIndentLength = currentIndent.length;
// Check if spaces and tabs are mixed
if (currentIndentLength == -1){
myHolder.createErrorAnnotation(leaf, "Indentation can't use both tabs and spaces");
}
else
if (currentIndentLength > 0) {
// If we don't have indent info registered
if (indentInfo == null){
indentInfo = currentIndent;
lastIndent = currentIndentLength;
} else {
final Boolean useTab = indentInfo.useTab;
final int indentInfoLength = indentInfo.length;
// If indent and current indent use different space and tabs
if (useTab && currentIndentText.contains(" ") || !useTab && currentIndentText.contains("\t")) {
final String message = useTab
? "Inconsistent indentation: " + currentIndentLength +
" spaces were used for indentation, but the rest of the document was indented using " +
indentInfoLength + " tabs"
: "Inconsistent indentation: " + currentIndentLength +
" tabs were used for indentation, but the rest of the document was indented using " +
indentInfoLength + " spaces";
myHolder.createErrorAnnotation(leaf, message);
if (leafType == myIndentTokenType && nextLeaf != null) {
final IElementType nextLeafType = nextLeaf.getNode().getElementType();
if (nextLeafType != myEolTokenType && !myCommentTypes.contains(nextLeafType)){
final String currentIndentText = leaf.getText();
final IndentInfo currentIndent = getIndent(currentIndentText);
final int currentIndentLength = currentIndent.length;
// Check if spaces and tabs are mixed
if (currentIndentLength == -1){
myHolder.createErrorAnnotation(leaf, "Indentation can't use both tabs and spaces");
}
else
if (currentIndentLength > 0) {
// If we don't have indent info registered
if (indentInfo == null){
indentInfo = currentIndent;
lastIndent = currentIndentLength;
} else {
// Check indent length
final int delta = currentIndentLength - lastIndent;
if (currentIndentLength % indentInfoLength != 0 || delta > indentInfoLength) {
final String message = useTab
? currentIndentLength + " tabs were used for indentation. Must be indented using " + indentInfoLength + " tabs"
: currentIndentLength + " spaces were used for indentation. Must be indented using " + indentInfoLength + " spaces";
final Boolean useTab = indentInfo.useTab;
final int indentInfoLength = indentInfo.length;
// If indent and current indent use different space and tabs
if (useTab && currentIndentText.contains(" ") || !useTab && currentIndentText.contains("\t")) {
final String message = useTab
? "Inconsistent indentation: " + currentIndentLength +
" spaces were used for indentation, but the rest of the document was indented using " +
indentInfoLength + " tabs"
: "Inconsistent indentation: " + currentIndentLength +
" tabs were used for indentation, but the rest of the document was indented using " +
indentInfoLength + " spaces";
myHolder.createErrorAnnotation(leaf, message);
} else {
// Check indent length
final int delta = currentIndentLength - lastIndent;
if (currentIndentLength % indentInfoLength != 0 || delta > indentInfoLength) {
final String message = useTab
? currentIndentLength + " tabs were used for indentation. Must be indented using " + indentInfoLength + " tabs"
: currentIndentLength + " spaces were used for indentation. Must be indented using " + indentInfoLength + " spaces";
myHolder.createErrorAnnotation(leaf, message);
}
lastIndent = currentIndentLength / indentInfoLength * indentInfoLength;
}
lastIndent = currentIndentLength / indentInfoLength * indentInfoLength;
}
}
}
@@ -0,0 +1,48 @@
/*
* Copyright 2000-2010 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.util.proximity;
import com.intellij.openapi.util.NullableLazyKey;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.ProximityLocation;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.NullableFunction;
import org.jetbrains.annotations.NotNull;
/**
* NOTE: This class is only registered in platform-based IDEs. In IDEA, SamePackageWeigher is used instead.
*
* @author yole
*/
public class SameDirectoryWeigher extends ProximityWeigher {
private static final NullableLazyKey<PsiDirectory, ProximityLocation>
PLACE_DIRECTORY = NullableLazyKey.create("placeDirectory", new NullableFunction<ProximityLocation, PsiDirectory>() {
@Override
public PsiDirectory fun(ProximityLocation location) {
return PsiTreeUtil.getParentOfType(location.getPosition(), PsiDirectory.class, false);
}
});
public Comparable weigh(@NotNull final PsiElement element, final ProximityLocation location) {
final PsiDirectory placeDirectory = PLACE_DIRECTORY.getValue(location);
if (placeDirectory == null) {
return false;
}
return placeDirectory.equals(PsiTreeUtil.getParentOfType(element, PsiDirectory.class, false));
}
}
@@ -102,8 +102,8 @@ public class ChangeListStorageImpl implements ChangeListStorage {
}
private ChangeSetBlock doReadBlock(int id) {
DataInputStream in = myStorage.readStream(id);
try {
DataInputStream in = myStorage.readStream(id);
try {
int size = in.readInt();
List<ChangeSet> changes = new ArrayList<ChangeSet>(size);
@@ -58,16 +58,19 @@ public class JBScrollPane extends JScrollPane {
@Override
public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
JViewport vp = getViewport();
if (vp != null) {
Color bg = vp.getView().getBackground();
if (bg != null) {
g.setColor(bg);
g.drawLine(0, 0, width - 1, 0);
g.drawLine(0, height - 1, width - 1, height - 1);
g.drawLine(0, 0, 0, height - 1);
g.drawLine(width - 1, 0, width - 1, height - 1);
}
}
if (vp == null) return;
Component view = vp.getView();
if (view == null) return;
Color bg = view.getBackground();
if (bg == null) return;
g.setColor(bg);
g.drawLine(0, 0, width - 1, 0);
g.drawLine(0, height - 1, width - 1, height - 1);
g.drawLine(0, 0, 0, height - 1);
g.drawLine(width - 1, 0, width - 1, height - 1);
}
@Override
@@ -80,6 +80,8 @@
<checkoutCompletedListener implementation="com.intellij.openapi.vcs.checkout.PlatformProjectCheckoutListener"/>
<weigher key="proximity" implementationClass="com.intellij.psi.util.proximity.SameDirectoryWeigher" id="sameDirectory"
order="after openedInEditor"/>
</extensions>
<xi:include href="xdebugger.xml" xpointer="xpointer(/root/*)"/>
@@ -200,7 +200,47 @@ public abstract class AbstractStorage implements Disposable, Forceable {
}
}
private void appendBytes(int record, byte[] bytes) {
private static int calcCapacity(int requiredLength) {
return Math.max(64, nearestPowerOfTwo(requiredLength * 3 / 2));
}
private static int nearestPowerOfTwo(int n) {
int power = 1;
while (n != 0) {
power *= 2;
n /= 2;
}
return power;
}
public StorageDataOutput writeStream(final int record) {
return new StorageDataOutput(this, record);
}
public AppenderStream appendStream(int record) {
return new AppenderStream(record);
}
public DataInputStream readStream(int record) throws IOException {
final byte[] bytes = readBytes(record);
return new DataInputStream(new ByteArrayInputStream(bytes));
}
protected byte[] readBytes(int record) throws IOException {
synchronized (myLock) {
final int length = myRecordsTable.getSize(record);
if (length == 0) return ArrayUtil.EMPTY_BYTE_ARRAY;
assert length > 0;
final long address = myRecordsTable.getAddress(record);
byte[] result = new byte[length];
myDataTable.readBytes(address, result);
return result;
}
}
protected void appendBytes(int record, byte[] bytes) throws IOException {
int delta = bytes.length;
if (delta == 0) return;
@@ -227,7 +267,7 @@ public abstract class AbstractStorage implements Disposable, Forceable {
}
}
public void writeBytes(int record, byte[] bytes) {
protected void writeBytes(int record, byte[] bytes) throws IOException {
synchronized (myLock) {
final int requiredLength = bytes.length;
final int currentCapacity = myRecordsTable.getCapacity(record);
@@ -257,46 +297,6 @@ public abstract class AbstractStorage implements Disposable, Forceable {
}
}
private static int calcCapacity(int requiredLength) {
return Math.max(64, nearestPowerOfTwo(requiredLength * 3 / 2));
}
private static int nearestPowerOfTwo(int n) {
int power = 1;
while (n != 0) {
power *= 2;
n /= 2;
}
return power;
}
public StorageDataOutput writeStream(final int record) {
return new StorageDataOutput(this, record);
}
public AppenderStream appendStream(int record) {
return new AppenderStream(record);
}
public DataInputStream readStream(int record) {
final byte[] bytes = readBytes(record);
return new DataInputStream(new ByteArrayInputStream(bytes));
}
byte[] readBytes(int record) {
synchronized (myLock) {
final int length = myRecordsTable.getSize(record);
if (length == 0) return ArrayUtil.EMPTY_BYTE_ARRAY;
assert length > 0;
final long address = myRecordsTable.getAddress(record);
byte[] result = new byte[length];
myDataTable.readBytes(address, result);
return result;
}
}
protected void doDeleteRecord(int record) throws IOException {
myDataTable.reclaimSpace(myRecordsTable.getSize(record));
myRecordsTable.deleteRecord(record);
@@ -19,10 +19,14 @@
*/
package com.intellij.util.io.storage;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.io.PagePool;
import java.io.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.zip.DeflaterOutputStream;
import java.util.zip.InflaterInputStream;
@@ -31,32 +35,36 @@ public class RefCountingStorage extends AbstractStorage {
super(path);
}
public RefCountingStorage(String path, PagePool pool) throws IOException {
super(path, pool);
@Override
protected byte[] readBytes(int record) throws IOException {
byte[] result = super.readBytes(record);
InflaterInputStream in = new InflaterInputStream(new ByteArrayInputStream(result));
try {
return StreamUtil.loadFromStream(in);
}
finally {
in.close();
}
}
@Override
public StorageDataOutput writeStream(int record) {
final ByteArrayOutputStream stream = new ByteArrayOutputStream();
return new StorageDataOutput(this, record, new DeflaterOutputStream(stream)) {
@Override
protected ByteArrayOutputStream getByteStream() {
return stream;
}
};
}
@Override
public DataInputStream readStream(int record) {
final byte[] bytes = readBytes(record);
return new DataInputStream(new InflaterInputStream(new ByteArrayInputStream(bytes)));
}
@Override
public AppenderStream appendStream(int record) {
protected void appendBytes(int record, byte[] bytes) throws IOException {
throw new IncorrectOperationException("Appending is not supported");
}
@Override
protected void writeBytes(int record, byte[] bytes) throws IOException {
ByteArrayOutputStream s = new ByteArrayOutputStream();
DeflaterOutputStream out = new DeflaterOutputStream(s);
try {
out.write(bytes);
}
finally {
out.close();
}
super.writeBytes(record, s.toByteArray());
}
@Override
protected AbstractRecordsTable createRecordsTable(PagePool pool, File recordsFile) throws IOException {
return new RefCountingRecordsTable(recordsFile, pool);
@@ -182,6 +182,7 @@ public class MavenPropertyPsiReference extends MavenPsiReference {
result = new MavenDomProjectProcessorUtils.DomParentProjectFileProcessor<PsiElement>(myProjectsManager) {
protected PsiElement doProcessParent(VirtualFile parentFile) {
MavenDomProjectModel parentProjectDom = MavenDomUtil.getMavenDomProjectModel(myProject, parentFile);
if (parentProjectDom == null) return null;
return resolveModelProperty(parentProjectDom, path, recursionGuard);
}
}.process(projectDom);
@@ -224,7 +224,7 @@ public class MavenProjectsManager extends SimpleProjectComponent
myProjectsTree.save(getProjectsTreeFile());
}
catch (IOException e) {
MavenLog.LOG.error(e);
MavenLog.LOG.warn(e);
}
}
}
@@ -125,6 +125,8 @@ public class MavenModuleBuilderHelper {
// execute when current dialog is closed (e.g. Project Structure)
MavenUtil.invokeLater(project, ModalityState.NON_MODAL, new Runnable() {
public void run() {
if (!pom.isValid()) return;
EditorHelper.openInEditor(getPsiFile(project, pom));
if (myArchetype != null) generateFromArchetype(project, pom);
}