Merge remote-tracking branch 'origin/master'
@@ -106,6 +106,7 @@
|
||||
<module fileurl="file://$PROJECT_DIR$/python/main_idea_python_plugin.iml" filepath="$PROJECT_DIR$/python/main_idea_python_plugin.iml" group="python" />
|
||||
<module fileurl="file://$PROJECT_DIR$/python/main_pycharm_ce.iml" filepath="$PROJECT_DIR$/python/main_pycharm_ce.iml" group="python" />
|
||||
<module fileurl="file://$PROJECT_DIR$/java/manifest/manifest.iml" filepath="$PROJECT_DIR$/java/manifest/manifest.iml" group="java" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m31/maven-artifact-resolver-m31.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m31/maven-artifact-resolver-m31.iml" group="plugins/maven" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/maven/maven.iml" filepath="$PROJECT_DIR$/plugins/maven/maven.iml" group="plugins/maven" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m2/maven-artifact-resolver-m2.iml" group="plugins/maven" />
|
||||
<module fileurl="file://$PROJECT_DIR$/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml" filepath="$PROJECT_DIR$/plugins/maven/artifact-resolver-m3/maven-artifact-resolver-m3.iml" group="plugins/maven" />
|
||||
|
||||
@@ -299,6 +299,13 @@ public def layoutCommunityPlugins(String home) {
|
||||
}
|
||||
}
|
||||
|
||||
jar("artifact-resolver-m31.jar") {
|
||||
module("maven-artifact-resolver-m31")
|
||||
module("maven-artifact-resolver-m2") {
|
||||
include(name: 'org/jetbrains/idea/maven/artifactResolver/common/*')
|
||||
}
|
||||
}
|
||||
|
||||
dir("maven3") {
|
||||
fileset(dir: "$home/plugins/maven/maven3-server-impl/lib") {include(name: "*.jar")}
|
||||
fileset(dir: "$home/plugins/maven/maven3-server-impl/lib/maven3/lib") {include(name: "*.jar")}
|
||||
|
||||
@@ -207,6 +207,7 @@ libraryLicense(name: "markdownj", libraryName: "markdownj", version: "0.4.2", li
|
||||
libraryLicense(name: "Maven", version: "2.2.1", license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
|
||||
libraryLicense(name: "plexus-util", version: "2.0.6", license: "Apache 2.0", url: "http://maven.apache.org/", libraryNames:['plexus-utils-2.0.6.jar'], licenseUrl: "http://apache.org/licenses/LICENSE-2.0")
|
||||
libraryLicense(name: "aether-api", version: "1.11", libraryNames: ["aether-api-1.11.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
|
||||
libraryLicense(name: "aether-api-0.9.0.M2.jar", version: "0.9.0.M2", libraryNames: ["aether-api-0.9.0.M2.jar"], license: "Eclipse Public License v1.0", url: "http://nexus.sonatype.org/", licenseUrl: "http://www.eclipse.org/org/documents/epl-v10.html")
|
||||
libraryLicense(name: "maven-2.2.1-uber", version: "2.2.1", libraryNames: ["maven-2.2.1-uber.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
|
||||
libraryLicense(name: "maven-artifact", version: "3.0.3", libraryNames: ["maven-artifact-3.0.3.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
|
||||
libraryLicense(name: "maven-core", version: "3.0.3", libraryNames: ["maven-core-3.0.3.jar"], license: "Apache 2.0", url: "http://maven.apache.org/", licenseUrl: "http://maven.apache.org/license.html")
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<company name="JetBrains s.r.o." url="http://www.jetbrains.com/?fromIDE"/>
|
||||
<build number="__BUILD_NUMBER__" date="__BUILD_DATE__"/>
|
||||
<install-over minbuild="129.1" maxbuild="132.9999" version="12.1"/>
|
||||
<logo url="/idea_community_logo.png" textcolor="ffffff" progressColor="ffaa16" progressY="230" progressTailIcon="/community_progress_tail.png"/>
|
||||
<about url="/idea_community_about.png" foreground="f5f5f5" linkColor="9dc0ff" logoX="300" logoY="265" logoW="75" logoH="30"/>
|
||||
<logo url="/idea_community_logo.png" textcolor="444444" progressColor="ffaa16" progressY="222" progressTailIcon="/community_progress_tail.png"/>
|
||||
<about url="/idea_community_about.png" foreground="444444" linkColor="000099" logoX="300" logoY="265" logoW="75" logoH="30"/>
|
||||
<icon size32="/icon_CE.png" size16="/icon_CEsmall.png" size32opaque="/icon_CEwhite.png" size12="/toolwindows/toolWindowProject.png" size128="/icon_CE_128.png" ico="idea_CE.ico"/>
|
||||
<package code="__PACKAGE_CODE__"/>
|
||||
<names product="IDEA" fullname="IntelliJ IDEA" script="idea"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 72 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 209 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 270 KiB After Width: | Height: | Size: 346 KiB |
@@ -41,7 +41,7 @@ class BuildMessageDispatcher extends SimpleChannelInboundHandler<CmdlineRemotePr
|
||||
|
||||
private static final AttributeKey<SessionData> SESSION_DATA = AttributeKey.valueOf("BuildMessageDispatcher.sessionData");
|
||||
|
||||
private final Map<UUID, SessionData> myMessageHandlers = new ConcurrentHashMap<UUID, SessionData>();
|
||||
private final Map<UUID, SessionData> myMessageHandlers = new ConcurrentHashMap<UUID, SessionData>(16, 0.75f, 1);
|
||||
private final Set<UUID> myCanceledSessions = new ConcurrentHashSet<UUID>();
|
||||
|
||||
public void registerBuildMessageHandler(UUID sessionId,
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.markup.EffectType;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.psi.*;
|
||||
@@ -84,10 +85,16 @@ public class ExceptionExFilterFactory implements ExceptionFilterFactory {
|
||||
worker.execute(text, lineEndOffset);
|
||||
Result result = worker.getResult();
|
||||
if (result == null) continue;
|
||||
OpenFileHyperlinkInfo hyperlinkInfo = ExceptionWorker.getOpenFileHyperlinkInfo(result);
|
||||
int offset = hyperlinkInfo == null? -1 : hyperlinkInfo.getDescriptor().getOffset();
|
||||
HyperlinkInfo hyperlinkInfo = result.hyperlinkInfo;
|
||||
if (!(hyperlinkInfo instanceof FileHyperlinkInfo)) continue;
|
||||
|
||||
OpenFileDescriptor descriptor = ((FileHyperlinkInfo)hyperlinkInfo).getDescriptor();
|
||||
if (descriptor == null) continue;
|
||||
|
||||
int offset = descriptor.getOffset();
|
||||
PsiFile psiFile = worker.getFile();
|
||||
if (offset <= 0 || psiFile == null) continue;
|
||||
|
||||
PsiElement element = psiFile.findElementAt(offset);
|
||||
PsiTryStatement parent = PsiTreeUtil.getParentOfType(element, PsiTryStatement.class, true, PsiClass.class);
|
||||
PsiCodeBlock tryBlock = parent != null? parent.getTryBlock() : null;
|
||||
|
||||
@@ -234,25 +234,25 @@ public abstract class BaseLibrariesConfigurable extends BaseStructureConfigurabl
|
||||
@Override
|
||||
protected void updateSelection(@Nullable NamedConfigurable configurable) {
|
||||
boolean selectionChanged = !Comparing.equal(myCurrentConfigurable, configurable);
|
||||
if (myCurrentConfigurable != null && selectionChanged) {
|
||||
if (myCurrentConfigurable instanceof LibraryConfigurable && selectionChanged) {
|
||||
((LibraryConfigurable)myCurrentConfigurable).onUnselected();
|
||||
}
|
||||
super.updateSelection(configurable);
|
||||
if (myCurrentConfigurable != null && selectionChanged) {
|
||||
if (myCurrentConfigurable instanceof LibraryConfigurable && selectionChanged) {
|
||||
((LibraryConfigurable)myCurrentConfigurable).onSelected();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStructureUnselected() {
|
||||
if (myCurrentConfigurable != null) {
|
||||
if (myCurrentConfigurable instanceof LibraryConfigurable) {
|
||||
((LibraryConfigurable)myCurrentConfigurable).onUnselected();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStructureSelected() {
|
||||
if (myCurrentConfigurable != null) {
|
||||
if (myCurrentConfigurable instanceof LibraryConfigurable) {
|
||||
((LibraryConfigurable)myCurrentConfigurable).onSelected();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,15 +234,14 @@ public class HighlightNamesUtil {
|
||||
DependencyValidationManagerImpl validationManager = (DependencyValidationManagerImpl)DependencyValidationManager.getInstance(file.getProject());
|
||||
List<Pair<NamedScope,NamedScopesHolder>> scopes = validationManager.getScopeBasedHighlightingCachedScopes();
|
||||
for (Pair<NamedScope, NamedScopesHolder> scope : scopes) {
|
||||
NamedScope namedScope = scope.getFirst();
|
||||
NamedScopesHolder scopesHolder = scope.getSecond();
|
||||
PackageSet packageSet = namedScope.getValue();
|
||||
if (packageSet != null && packageSet.contains(file, scopesHolder)) {
|
||||
TextAttributesKey scopeKey = ScopeAttributesUtil.getScopeTextAttributeKey(namedScope.getName());
|
||||
TextAttributes attributes = colorsScheme.getAttributes(scopeKey);
|
||||
if (attributes == null || attributes.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
final NamedScope namedScope = scope.getFirst();
|
||||
final TextAttributesKey scopeKey = ScopeAttributesUtil.getScopeTextAttributeKey(namedScope.getName());
|
||||
final TextAttributes attributes = colorsScheme.getAttributes(scopeKey);
|
||||
if (attributes == null || attributes.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
final PackageSet packageSet = namedScope.getValue();
|
||||
if (packageSet != null && packageSet.contains(file, scope.getSecond())) {
|
||||
result = TextAttributes.merge(attributes, result);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,21 +21,19 @@ import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.controlFlow.*;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -55,6 +53,18 @@ public class LocalCanBeFinal extends BaseJavaBatchLocalInspectionTool {
|
||||
myQuickFix = new AcceptSuggested();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSettings(@NotNull Element node) throws WriteExternalException {
|
||||
node.addContent(new Element("option").setAttribute("name", "REPORT_VARIABLES").setAttribute("value", String.valueOf(REPORT_VARIABLES)));
|
||||
node.addContent(new Element("option").setAttribute("name", "REPORT_PARAMETERS").setAttribute("value", String.valueOf(REPORT_PARAMETERS)));
|
||||
if (!REPORT_CATCH_PARAMETERS) {
|
||||
node.addContent(new Element("option").setAttribute("name", "REPORT_CATCH_PARAMETERS").setAttribute("value", "false"));
|
||||
}
|
||||
if (!REPORT_FOREACH_PARAMETERS) {
|
||||
node.addContent(new Element("option").setAttribute("name", "REPORT_FOREACH_PARAMETERS").setAttribute("value", "false"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProblemDescriptor[] checkMethod(@NotNull PsiMethod method, @NotNull InspectionManager manager, boolean isOnTheFly) {
|
||||
List<ProblemDescriptor> list = checkCodeBlock(method.getBody(), manager, isOnTheFly);
|
||||
|
||||
@@ -46,6 +46,11 @@ public class DummyEntryPointsPresentation extends UnusedDeclarationPresentation
|
||||
return myQuickFixActions;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSeverityDelegateName() {
|
||||
return UnusedDeclarationInspection.SHORT_NAME;
|
||||
}
|
||||
|
||||
private class MoveEntriesToSuspicious extends QuickFixAction {
|
||||
private MoveEntriesToSuspicious(@NotNull InspectionToolWrapper toolWrapper) {
|
||||
super(InspectionsBundle.message("inspection.dead.code.remove.from.entry.point.quickfix"), null, null, toolWrapper);
|
||||
|
||||
@@ -117,7 +117,7 @@ public class UnusedDeclarationPresentation extends DefaultInspectionToolPresenta
|
||||
@NonNls Element problemClassElement = new Element(InspectionsBundle.message("inspection.export.results.problem.element.tag"));
|
||||
|
||||
final RefElement refElement = (RefElement)refEntity;
|
||||
final HighlightSeverity severity = getSeverity(refElement, getContext(), getToolWrapper());
|
||||
final HighlightSeverity severity = getSeverity(refElement);
|
||||
final String attributeKey =
|
||||
getTextAttributeKey(refElement.getRefManager().getProject(), severity, ProblemHighlightType.LIKE_UNUSED_SYMBOL);
|
||||
problemClassElement.setAttribute("severity", severity.myName);
|
||||
|
||||
@@ -455,7 +455,12 @@ public class LambdaUtil {
|
||||
if (!tryToSubstitute) return cachedType;
|
||||
}
|
||||
|
||||
final PsiElement gParent = expressionList.getParent();
|
||||
PsiElement gParent = expressionList.getParent();
|
||||
|
||||
if (gParent instanceof PsiAnonymousClass) {
|
||||
gParent = gParent.getParent();
|
||||
}
|
||||
|
||||
if (gParent instanceof PsiCall) {
|
||||
final PsiCall contextCall = (PsiCall)gParent;
|
||||
final JavaResolveResult resolveResult = contextCall.resolveMethodGenerics();
|
||||
|
||||
@@ -9,10 +9,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.infos.CandidateInfo;
|
||||
import com.intellij.psi.util.MethodSignature;
|
||||
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
|
||||
import com.intellij.psi.util.MethodSignatureUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
@@ -47,12 +44,12 @@ public class OverrideImplementExploreUtil {
|
||||
Map<MethodSignature, PsiMethod> finals = new LinkedHashMap<MethodSignature,PsiMethod>();
|
||||
Map<MethodSignature, PsiMethod> concretes = new LinkedHashMap<MethodSignature,PsiMethod>();
|
||||
|
||||
LOG.assertTrue(aClass.isValid());
|
||||
PsiUtilCore.ensureValid(aClass);
|
||||
Collection<HierarchicalMethodSignature> allMethodSigs = aClass.getVisibleSignatures();
|
||||
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(aClass.getProject()).getResolveHelper();
|
||||
for (HierarchicalMethodSignature signature : allMethodSigs) {
|
||||
PsiMethod method = signature.getMethod();
|
||||
LOG.assertTrue(method.isValid(), aClass);
|
||||
PsiUtilCore.ensureValid(method);
|
||||
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC) || !resolveHelper.isAccessible(method, aClass, aClass)) continue;
|
||||
PsiClass hisClass = method.getContainingClass();
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.JavaConstantExpressionEvaluator;
|
||||
import com.intellij.psi.impl.source.javadoc.PsiInlineDocTagImpl;
|
||||
import com.intellij.psi.impl.source.tree.JavaDocElementType;
|
||||
import com.intellij.psi.javadoc.PsiDocComment;
|
||||
import com.intellij.psi.javadoc.PsiDocTag;
|
||||
@@ -1039,7 +1040,7 @@ public class JavaDocInfoGenerator {
|
||||
generateLinkValue(tag, buffer, false);
|
||||
}
|
||||
else if (tagName.equals(LITERAL_TAG)) {
|
||||
generateLiteralValue(tag, buffer);
|
||||
generateLiteralValue(buffer, ((PsiInlineDocTagImpl)tag).getDataElementsIgnoreWhitespaces());
|
||||
}
|
||||
else if (tagName.equals(CODE_TAG)) {
|
||||
generateCodeValue(tag, buffer);
|
||||
@@ -1073,14 +1074,12 @@ public class JavaDocInfoGenerator {
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
private static void generateCodeValue(PsiInlineDocTag tag, StringBuilder buffer) {
|
||||
buffer.append("<code>");
|
||||
generateLiteralValue(tag, buffer);
|
||||
generateLiteralValue(buffer, tag.getDataElements());
|
||||
buffer.append("</code>");
|
||||
}
|
||||
|
||||
private static void generateLiteralValue(PsiInlineDocTag tag, StringBuilder buffer) {
|
||||
PsiElement[] elements = tag.getDataElements();
|
||||
|
||||
for (PsiElement element : elements) {
|
||||
private static void generateLiteralValue(StringBuilder buffer, final PsiElement[] dataElements) {
|
||||
for (PsiElement element : dataElements) {
|
||||
appendPlainText(element.getText(), buffer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,10 +35,11 @@ import com.intellij.util.IncorrectOperationException;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlineDocTag, Constants {
|
||||
private static final TokenSet TAG_VALUE_BIT_SET = TokenSet.create(
|
||||
DOC_TAG_VALUE_ELEMENT, DOC_METHOD_OR_FIELD_REF);
|
||||
private static final TokenSet VALUE_BIT_SET = TokenSet.orSet(TAG_VALUE_BIT_SET, TokenSet.create(
|
||||
private static final TokenSet TAG_VALUE_BIT_SET = TokenSet.create(DOC_TAG_VALUE_ELEMENT, DOC_METHOD_OR_FIELD_REF);
|
||||
private static final TokenSet VALUE_NO_WHITESPACE_BIT_SET = TokenSet.orSet(TAG_VALUE_BIT_SET, TokenSet.create(
|
||||
JAVA_CODE_REFERENCE, DOC_TAG_VALUE_TOKEN, DOC_COMMENT_DATA, DOC_INLINE_TAG, DOC_REFERENCE_HOLDER, DOC_COMMENT_BAD_CHARACTER));
|
||||
private static final TokenSet VALUE_BIT_SET = TokenSet.orSet(TAG_VALUE_BIT_SET, TokenSet.create(
|
||||
JAVA_CODE_REFERENCE, DOC_TAG_VALUE_TOKEN, WHITE_SPACE, DOC_COMMENT_DATA, DOC_INLINE_TAG, DOC_REFERENCE_HOLDER, DOC_COMMENT_BAD_CHARACTER));
|
||||
|
||||
public PsiInlineDocTagImpl() {
|
||||
super(DOC_INLINE_TAG);
|
||||
@@ -63,6 +64,10 @@ public class PsiInlineDocTagImpl extends CompositePsiElement implements PsiInlin
|
||||
return getChildrenAsPsiElements(VALUE_BIT_SET, PsiElement.ARRAY_FACTORY);
|
||||
}
|
||||
|
||||
public PsiElement[] getDataElementsIgnoreWhitespaces() {
|
||||
return getChildrenAsPsiElements(VALUE_NO_WHITESPACE_BIT_SET, PsiElement.ARRAY_FACTORY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiDocTagValue getValueElement() {
|
||||
return (PsiDocTagValue)findPsiChildByType(TAG_VALUE_BIT_SET);
|
||||
|
||||
@@ -439,9 +439,12 @@ public class PsiMethodReferenceExpressionImpl extends PsiReferenceExpressionBase
|
||||
}
|
||||
} else {
|
||||
if (rightTypes.length != types.length || rightTypes[rightTypes.length - 1].getArrayDimensions() != types[types.length-1].getArrayDimensions()) {
|
||||
types[types.length - 1] = ((PsiArrayType)types[types.length - 1]).getComponentType();
|
||||
boolean expandTypeArray = types.length < rightTypes.length;
|
||||
int min = Math.min(types.length, rightTypes.length);
|
||||
types = Arrays.copyOf(types, min);
|
||||
if (expandTypeArray) {
|
||||
types[types.length - 1] = ((PsiArrayType)types[types.length - 1]).getComponentType();
|
||||
}
|
||||
rightTypes = Arrays.copyOf(rightTypes, min);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ package com.intellij.psi.scope.util;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicatorProvider;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveUtil;
|
||||
@@ -318,7 +319,13 @@ public class PsiScopesUtil {
|
||||
if (initializer instanceof PsiNewExpression) {
|
||||
final PsiAnonymousClass anonymousClass = ((PsiNewExpression)initializer).getAnonymousClass();
|
||||
if (anonymousClass != null && type.equals(anonymousClass.getBaseClassType())) {
|
||||
type = initializer.getType();
|
||||
final PsiMethod[] refMethods = anonymousClass.findMethodsByName(methodCall.getMethodExpression().getReferenceName(), false);
|
||||
if (refMethods.length > 0) {
|
||||
final PsiClass baseClass = PsiUtil.resolveClassInType(type);
|
||||
if (baseClass != null && !hasCovariantOverriding(baseClass, refMethods)) {
|
||||
type = initializer.getType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -381,6 +388,18 @@ public class PsiScopesUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean hasCovariantOverriding(PsiClass baseClass, PsiMethod[] refMethods) {
|
||||
for (PsiMethod method : refMethods) {
|
||||
final PsiType methodReturnType = method.getReturnType();
|
||||
for (PsiMethod superMethod : method.findSuperMethods(baseClass)) {
|
||||
if (!Comparing.equal(methodReturnType, superMethod.getReturnType())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean processQualifierType(@NotNull final PsiType type,
|
||||
final MethodsProcessor processor,
|
||||
PsiManager manager,
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
interface I<T> {
|
||||
void accept(T t);
|
||||
}
|
||||
|
||||
class LamdbaTest<T> {
|
||||
|
||||
public void f() {
|
||||
new A<T>(t -> g(t)) {};
|
||||
}
|
||||
|
||||
private void g(T t) {
|
||||
}
|
||||
|
||||
class A<T2> {
|
||||
public A(I<T> editor) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
<html><head> <style type="text/css"> #error { background-color: #eeeeee; margin-bottom: 10px; } p { margin: 5px 0; } </style></head><body><small><b><a href="psi_element://Foo"><code>Foo</code></a></b></small><PRE>int <b>foo</b></PRE>
|
||||
<pre>
|
||||
<code>
|
||||
class Clazzz {
|
||||
def f[U](u: U) {}
|
||||
|
||||
val a = 1
|
||||
}
|
||||
</code>
|
||||
</pre></body></html>
|
||||
@@ -0,0 +1,14 @@
|
||||
class Foo {
|
||||
/**
|
||||
* <pre>
|
||||
* {@code
|
||||
* class Clazzz {
|
||||
* def f[U](u: U) {}
|
||||
*
|
||||
* val a = 1
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
int foo;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
Compiling files:
|
||||
src/package2/A.java
|
||||
End of files
|
||||
Cleaning output files:
|
||||
out/production/AddClassHidingImportedClass/package2/B.class
|
||||
out/production/AddClassHidingImportedClass/package3/C.class
|
||||
End of files
|
||||
Compiling files:
|
||||
src/package2/B.java
|
||||
src/package3/C.java
|
||||
End of files
|
||||
@@ -0,0 +1,7 @@
|
||||
package package1;
|
||||
|
||||
public class A {
|
||||
public static class D {
|
||||
public final String s = new String("package1");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package package2;
|
||||
|
||||
public class A {
|
||||
public static class D {
|
||||
public final String s = new String("package2");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package package2;
|
||||
import package1.*;
|
||||
|
||||
public class B extends A{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package package3;
|
||||
|
||||
import package2.B;
|
||||
|
||||
public class C {
|
||||
|
||||
public B.D p;
|
||||
|
||||
public String get() {
|
||||
p = new B.D();
|
||||
return p.s;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
interface X {
|
||||
A[] foo();
|
||||
}
|
||||
|
||||
class A {}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
class C {
|
||||
final X x = new X() {
|
||||
@Override
|
||||
public B[] foo() {
|
||||
return new B[0];
|
||||
}
|
||||
};
|
||||
|
||||
B[] bar() {
|
||||
return x.f<ref>oo();
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import com.intellij.openapi.vfs.LocalFileSystem
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.JavaPsiFacade
|
||||
import com.intellij.psi.PsiClass
|
||||
import com.intellij.psi.PsiManager
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import com.intellij.testFramework.PsiTestUtil
|
||||
@@ -141,5 +142,12 @@ public class Test {
|
||||
myFixture.assertPreferredCompletionItems 0, 'getBuilder'
|
||||
}
|
||||
|
||||
public void testNoJavaStructureModificationOnSecondInvocation() {
|
||||
myFixture.configureByText 'a.java', 'class Foo { Xxxxx<caret> }'
|
||||
def oldCount = PsiManager.getInstance(project).modificationTracker.javaStructureModificationCount
|
||||
assert !myFixture.completeBasic()
|
||||
assert !myFixture.completeBasic()
|
||||
assert oldCount == PsiManager.getInstance(project).modificationTracker.javaStructureModificationCount
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -82,6 +82,10 @@ public class NewLambdaHighlightingTest extends LightDaemonAnalyzerTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testArgumentOfAnonymousClass() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(false);
|
||||
}
|
||||
|
||||
@@ -72,6 +72,10 @@ public class JavaDocInfoGeneratorTest extends CodeInsightTestCase {
|
||||
doTestField();
|
||||
}
|
||||
|
||||
public void testCode() throws Exception {
|
||||
doTestField();
|
||||
}
|
||||
|
||||
public void testEnumConstantOrdinal() throws Exception {
|
||||
PsiClass psiClass = getTestClass();
|
||||
PsiField field = psiClass.getFields() [0];
|
||||
|
||||
@@ -313,7 +313,7 @@ public class InspectionProfileTest extends LightIdeaTestCase {
|
||||
assertEquals(0, countInitializedTools(profile));
|
||||
profile.writeExternal(new Element("profile"));
|
||||
List<InspectionToolWrapper> initializedTools = getInitializedTools(profile);
|
||||
if (initializedTools.size() != 1) {
|
||||
if (initializedTools.size() > 0) {
|
||||
for (InspectionToolWrapper initializedTool : initializedTools) {
|
||||
System.out.println(initializedTool.getShortName());
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public void testDirInfos() {
|
||||
public void testDirInfos() throws IOException {
|
||||
checkInfoNull(myRootVFile);
|
||||
|
||||
// beware: files in directory index
|
||||
@@ -215,9 +215,13 @@ public class DirectoryIndexTest extends IdeaTestCase {
|
||||
assertEquals(myModule1Dir, checkInfoNotNull(myLibClsDir).getContentRoot());
|
||||
|
||||
checkInfo(myModule3Dir, myModule3, false, false, null, null);
|
||||
|
||||
VirtualFile cvs = myPack1Dir.createChildDirectory(this, "CVS");
|
||||
checkInfoNull(cvs);
|
||||
assertNull(ProjectRootManager.getInstance(myProject).getFileIndex().getPackageNameByDirectory(cvs));
|
||||
}
|
||||
|
||||
public void testDirsByPackageName() {
|
||||
public void testDirsByPackageName() throws IOException {
|
||||
checkPackage("", true, myFileLibSrc, myFileLibCls, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myLibSrcDir, myLibClsDir, mySrcDir2);
|
||||
checkPackage("", false, myFileLibCls, mySrcDir1, myTestSrc1, myResDir, myTestResDir, myLibClsDir, mySrcDir2);
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import com.intellij.navigation.NavigationItem;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
* @author dsl
|
||||
@@ -129,6 +128,16 @@ public class ResolveMethod15Test extends Resolve15TestCase {
|
||||
assertTrue(containingClass != null ? containingClass.getName() : null, containingClass instanceof PsiAnonymousClass);
|
||||
}
|
||||
|
||||
public void testCovariantReturnTypeAnonymous() throws Exception {
|
||||
final PsiReference ref = configureByFile();
|
||||
assertThat(ref, instanceOf(PsiReferenceExpression.class));
|
||||
final PsiReferenceExpression refExpr = (PsiReferenceExpression)ref;
|
||||
final PsiElement resolve = refExpr.resolve();
|
||||
assertTrue(resolve != null ? resolve.toString() : null, resolve instanceof PsiMethod);
|
||||
final PsiClass containingClass = ((PsiMethod)resolve).getContainingClass();
|
||||
assertTrue(containingClass != null ? containingClass.getName() : null, !(containingClass instanceof PsiAnonymousClass));
|
||||
}
|
||||
|
||||
public void testFilterFixedVsVarargs1() throws Exception {
|
||||
final PsiReference ref = configureByFile();
|
||||
assertThat(ref, instanceOf(PsiReferenceExpression.class));
|
||||
|
||||
@@ -15,26 +15,29 @@
|
||||
*/
|
||||
package com.intellij.execution.filters;
|
||||
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.editor.colors.CodeInsightColors;
|
||||
import com.intellij.openapi.editor.colors.EditorColorsManager;
|
||||
import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.roots.ProjectFileIndex;
|
||||
import com.intellij.openapi.roots.ProjectRootManager;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.PsiShortNamesCache;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* User: Irina.Chernushina
|
||||
@@ -61,8 +64,8 @@ public class ExceptionWorker {
|
||||
private final Project myProject;
|
||||
private final GlobalSearchScope mySearchScope;
|
||||
private Filter.Result myResult;
|
||||
private PsiClass myClass;
|
||||
private PsiFile myFile;
|
||||
private PsiClass[] myClasses = PsiClass.EMPTY_ARRAY;
|
||||
private PsiFile[] myFiles = PsiFile.EMPTY_ARRAY;
|
||||
private String myMethod;
|
||||
private Trinity<TextRange, TextRange, TextRange> myInfo;
|
||||
|
||||
@@ -90,16 +93,17 @@ public class ExceptionWorker {
|
||||
final String lineString = fileAndLine.substring(colonIndex + 1);
|
||||
try {
|
||||
final int lineNumber = Integer.parseInt(lineString);
|
||||
myClass = findPositionClass(line);
|
||||
myFile = myClass == null ? null : (PsiFile)myClass.getContainingFile().getNavigationElement();
|
||||
if (myFile == null) {
|
||||
// try find the file with the required name
|
||||
PsiFile[] files = PsiShortNamesCache.getInstance(myProject).getFilesByName(fileAndLine.substring(0, colonIndex).trim());
|
||||
if (files.length > 0) {
|
||||
myFile = files[0];
|
||||
}
|
||||
myClasses = findPositionClasses(line);
|
||||
myFiles = new PsiFile[myClasses.length];
|
||||
for (int i = 0; i < myClasses.length; i++) {
|
||||
myFiles[i] = (PsiFile)myClasses[i].getContainingFile().getNavigationElement();
|
||||
}
|
||||
if (myFile == null) return;
|
||||
if (myFiles.length == 0) {
|
||||
// try find the file with the required name
|
||||
//todo[nik] it would be better to use FilenameIndex here to honor the scope by it isn't accessible in Open API
|
||||
myFiles = PsiShortNamesCache.getInstance(myProject).getFilesByName(fileAndLine.substring(0, colonIndex).trim());
|
||||
}
|
||||
if (myFiles.length == 0) return;
|
||||
|
||||
/*
|
||||
IDEADEV-4976: Some scramblers put something like SourceFile mock instead of real class name.
|
||||
@@ -113,12 +117,31 @@ public class ExceptionWorker {
|
||||
|
||||
final int highlightStartOffset = textStartOffset + lparenthIndex + 1;
|
||||
final int highlightEndOffset = textStartOffset + rparenthIndex;
|
||||
final VirtualFile virtualFile = myFile.getVirtualFile();
|
||||
|
||||
HyperlinkInfo linkInfo = new MyHyperlinkInfo(myProject, virtualFile, lineNumber);
|
||||
ProjectFileIndex index = ProjectRootManager.getInstance(myProject).getFileIndex();
|
||||
List<VirtualFile> virtualFilesInLibraries = new ArrayList<VirtualFile>();
|
||||
List<VirtualFile> virtualFilesInContent = new ArrayList<VirtualFile>();
|
||||
for (PsiFile file : myFiles) {
|
||||
VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (index.isInContent(virtualFile)) {
|
||||
virtualFilesInContent.add(virtualFile);
|
||||
}
|
||||
else {
|
||||
virtualFilesInLibraries.add(virtualFile);
|
||||
}
|
||||
}
|
||||
|
||||
boolean inContent = ProjectRootManager.getInstance(myProject).getFileIndex().isInContent(virtualFile);
|
||||
TextAttributes attributes = inContent ? HYPERLINK_ATTRIBUTES : LIBRARY_HYPERLINK_ATTRIBUTES;
|
||||
List<VirtualFile> virtualFiles;
|
||||
TextAttributes attributes;
|
||||
if (virtualFilesInContent.isEmpty()) {
|
||||
attributes = LIBRARY_HYPERLINK_ATTRIBUTES;
|
||||
virtualFiles = virtualFilesInLibraries;
|
||||
}
|
||||
else {
|
||||
attributes = HYPERLINK_ATTRIBUTES;
|
||||
virtualFiles = virtualFilesInContent;
|
||||
}
|
||||
HyperlinkInfo linkInfo = HyperlinkInfoFactory.getInstance().createMultipleFilesHyperlinkInfo(virtualFiles, lineNumber - 1, myProject);
|
||||
myResult = new Filter.Result(highlightStartOffset, highlightEndOffset, linkInfo, attributes);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
@@ -126,22 +149,23 @@ public class ExceptionWorker {
|
||||
}
|
||||
}
|
||||
|
||||
private PsiClass findPositionClass(String line) {
|
||||
private PsiClass[] findPositionClasses(String line) {
|
||||
String className = myInfo.first.substring(line).trim();
|
||||
PsiClass result = findClassPreferringMyScope(className);
|
||||
if (result == null) {
|
||||
PsiClass[] result = findClassesPreferringMyScope(className);
|
||||
if (result.length == 0) {
|
||||
final int dollarIndex = className.indexOf('$');
|
||||
if (dollarIndex >= 0) {
|
||||
result = findClassPreferringMyScope(className.substring(0, dollarIndex));
|
||||
result = findClassesPreferringMyScope(className.substring(0, dollarIndex));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private PsiClass findClassPreferringMyScope(String className) {
|
||||
@NotNull
|
||||
private PsiClass[] findClassesPreferringMyScope(String className) {
|
||||
JavaPsiFacade psiFacade = JavaPsiFacade.getInstance(myProject);
|
||||
PsiClass result = psiFacade.findClass(className, mySearchScope);
|
||||
return result != null ? result : psiFacade.findClass(className, GlobalSearchScope.allScope(myProject));
|
||||
PsiClass[] result = psiFacade.findClasses(className, mySearchScope);
|
||||
return result.length != 0 ? result : psiFacade.findClasses(className, GlobalSearchScope.allScope(myProject));
|
||||
}
|
||||
|
||||
public Filter.Result getResult() {
|
||||
@@ -149,7 +173,7 @@ public class ExceptionWorker {
|
||||
}
|
||||
|
||||
public PsiClass getPsiClass() {
|
||||
return myClass;
|
||||
return ArrayUtil.getFirstElement(myClasses);
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
@@ -157,7 +181,7 @@ public class ExceptionWorker {
|
||||
}
|
||||
|
||||
public PsiFile getFile() {
|
||||
return myFile;
|
||||
return ArrayUtil.getFirstElement(myFiles);
|
||||
}
|
||||
|
||||
public Trinity<TextRange, TextRange, TextRange> getInfo() {
|
||||
@@ -205,59 +229,4 @@ public class ExceptionWorker {
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static OpenFileHyperlinkInfo getOpenFileHyperlinkInfo(Filter.Result result) {
|
||||
if (result.hyperlinkInfo instanceof MyHyperlinkInfo) {
|
||||
MyHyperlinkInfo info = (MyHyperlinkInfo)result.hyperlinkInfo;
|
||||
return new OpenFileHyperlinkInfo(info.myProject, info.myVirtualFile, info.myLineNumber);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class MyHyperlinkInfo implements FileHyperlinkInfo {
|
||||
private final VirtualFile myVirtualFile;
|
||||
private final int myLineNumber;
|
||||
private final Project myProject;
|
||||
|
||||
public MyHyperlinkInfo(@NotNull Project project, @NotNull VirtualFile virtualFile, int lineNumber) {
|
||||
myProject = project;
|
||||
myVirtualFile = virtualFile;
|
||||
myLineNumber = lineNumber;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigate(Project project) {
|
||||
VirtualFile currentVirtualFile = null;
|
||||
|
||||
AccessToken accessToken = ReadAction.start();
|
||||
|
||||
try {
|
||||
if (!myVirtualFile.isValid()) return;
|
||||
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(myVirtualFile);
|
||||
if (psiFile != null) {
|
||||
PsiElement navigationElement = psiFile.getNavigationElement(); // Sources may be downloaded.
|
||||
if (navigationElement instanceof PsiFile) {
|
||||
currentVirtualFile = ((PsiFile)navigationElement).getVirtualFile();
|
||||
}
|
||||
}
|
||||
|
||||
if (currentVirtualFile == null) {
|
||||
currentVirtualFile = myVirtualFile;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
accessToken.finish();
|
||||
}
|
||||
|
||||
new OpenFileHyperlinkInfo(myProject, currentVirtualFile, myLineNumber - 1).navigate(project);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public OpenFileDescriptor getDescriptor() {
|
||||
return new OpenFileDescriptor(myProject, myVirtualFile, myLineNumber - 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<orderEntry type="module" module-name="debugger-impl" />
|
||||
<orderEntry type="module" module-name="execution-openapi" />
|
||||
<orderEntry type="module" module-name="lang-impl" />
|
||||
<orderEntry type="module" module-name="remote-servers-impl" scope="RUNTIME" />
|
||||
<orderEntry type="module" module-name="remote-servers-impl" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2000-2013 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.remoteServer.impl.util;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.packaging.artifacts.Artifact;
|
||||
import com.intellij.remoteServer.agent.util.CloudGitApplication;
|
||||
import com.intellij.remoteServer.configuration.deployment.ArtifactDeploymentSource;
|
||||
import com.intellij.remoteServer.configuration.deployment.DeploymentSource;
|
||||
import com.intellij.remoteServer.util.DeploymentSourceHandler;
|
||||
import com.intellij.remoteServer.util.ServerRuntimeException;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author michael.golubev
|
||||
*/
|
||||
public abstract class ArtifactDeploymentSourceHandlerBase implements DeploymentSourceHandler {
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#" + ArtifactDeploymentSourceHandlerBase.class.getName());
|
||||
|
||||
private Artifact myArtifact;
|
||||
private File myRepositoryRootFile;
|
||||
|
||||
protected File getArtifactFile() {
|
||||
return new File(myArtifact.getOutputFilePath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getRepositoryRootFile() {
|
||||
return myRepositoryRootFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean init(DeploymentSource deploymentSource) throws ServerRuntimeException {
|
||||
if (!(deploymentSource instanceof ArtifactDeploymentSource)) {
|
||||
return false;
|
||||
}
|
||||
ArtifactDeploymentSource artifactDeploymentSource = (ArtifactDeploymentSource)deploymentSource;
|
||||
Artifact artifact = artifactDeploymentSource.getArtifact();
|
||||
if (artifact == null) {
|
||||
throw new ServerRuntimeException("Artifact not found " + artifactDeploymentSource.getArtifactPointer().getArtifactName());
|
||||
}
|
||||
|
||||
String outputPath = artifact.getOutputPath();
|
||||
LOG.assertTrue(outputPath != null, "Artifact output path not found");
|
||||
myRepositoryRootFile = new File(outputPath, "/deploy");
|
||||
if (!myRepositoryRootFile.exists()) {
|
||||
if (!myRepositoryRootFile.mkdir()) {
|
||||
throw new ServerRuntimeException("Unable to create deploy folder");
|
||||
}
|
||||
}
|
||||
myArtifact = artifact;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.FileUtilRt;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -37,6 +36,7 @@ import org.jetbrains.jps.service.JpsServiceManager;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
@@ -55,7 +55,7 @@ public class BuildRootIndexImpl implements BuildRootIndex {
|
||||
myIgnoredFileIndex = ignoredFileIndex;
|
||||
myRootsByTarget = new HashMap<BuildTarget<?>, List<? extends BuildRootDescriptor>>();
|
||||
myRootToDescriptors = new THashMap<File, List<BuildRootDescriptor>>(FileUtil.FILE_HASHING_STRATEGY);
|
||||
myFileFilters = new ConcurrentHashMap<BuildRootDescriptor, FileFilter>();
|
||||
myFileFilters = new ConcurrentHashMap<BuildRootDescriptor, FileFilter>(16, 0.75f, 1);
|
||||
final Iterable<AdditionalRootsProviderService> rootsProviders = JpsServiceManager.getInstance().getExtensions(AdditionalRootsProviderService.class);
|
||||
for (BuildTargetType<?> targetType : TargetTypeRegistry.getInstance().getTargetTypes()) {
|
||||
for (BuildTarget<?> target : targetIndex.getAllTargets(targetType)) {
|
||||
|
||||
@@ -321,15 +321,17 @@ public class ClassRepr extends Proto {
|
||||
}
|
||||
|
||||
public String getPackageName() {
|
||||
return getPackageName(name);
|
||||
final String strValue = myContext.getValue(name);
|
||||
return strValue != null? getPackageName(strValue) : null;
|
||||
}
|
||||
|
||||
public String getPackageName(final int s) {
|
||||
return getPackageName(myContext.getValue(s));
|
||||
public String getShortName() {
|
||||
final String strValue = myContext.getValue(name);
|
||||
return strValue != null? getShortName(strValue) : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getPackageName(final String raw) {
|
||||
public static String getPackageName(@NotNull final String raw) {
|
||||
final int index = raw.lastIndexOf('/');
|
||||
|
||||
if (index == -1) {
|
||||
@@ -339,6 +341,17 @@ public class ClassRepr extends Proto {
|
||||
return raw.substring(0, index);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static String getShortName(@NotNull final String fqName) {
|
||||
final int index = fqName.lastIndexOf('/');
|
||||
|
||||
if (index == -1) {
|
||||
return fqName;
|
||||
}
|
||||
|
||||
return fqName.substring(index + 1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FieldRepr findField(final int name) {
|
||||
for (FieldRepr f : myFields) {
|
||||
|
||||
@@ -45,6 +45,7 @@ public class Mappings {
|
||||
|
||||
private final static String CLASS_TO_SUBCLASSES = "classToSubclasses.tab";
|
||||
private final static String CLASS_TO_CLASS = "classToClass.tab";
|
||||
private final static String SHORT_NAMES = "shortNames.tab";
|
||||
private final static String SOURCE_TO_CLASS = "sourceToClass.tab";
|
||||
private final static String CLASS_TO_SOURCE = "classToSource.tab";
|
||||
private static final IntInlineKeyDescriptor INT_KEY_DESCRIPTOR = new IntInlineKeyDescriptor();
|
||||
@@ -65,6 +66,7 @@ public class Mappings {
|
||||
private final TIntHashSet myChangedClasses;
|
||||
private final THashSet<File> myChangedFiles;
|
||||
private final Set<ClassRepr> myDeletedClasses;
|
||||
private final Set<ClassRepr> myAddedClasses;
|
||||
private final Object myLock;
|
||||
private final File myRootDir;
|
||||
|
||||
@@ -83,6 +85,10 @@ public class Mappings {
|
||||
private IntIntMultiMaplet myClassToClassDependency;
|
||||
private ObjectObjectMultiMaplet<File, ClassRepr> mySourceFileToClasses;
|
||||
private IntObjectMaplet<File> myClassToSourceFile;
|
||||
/**
|
||||
* [short className] -> list of FQ names
|
||||
*/
|
||||
private IntIntMultiMaplet myShortClassNameIndex;
|
||||
|
||||
private IntIntTransientMultiMaplet myRemovedSuperClasses;
|
||||
private IntIntTransientMultiMaplet myAddedSuperClasses;
|
||||
@@ -96,6 +102,7 @@ public class Mappings {
|
||||
myChangedClasses = new TIntHashSet(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
|
||||
myChangedFiles = new THashSet(FileUtil.FILE_HASHING_STRATEGY);
|
||||
myDeletedClasses = new HashSet<ClassRepr>(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
|
||||
myAddedClasses = new HashSet<ClassRepr>(DEFAULT_SET_CAPACITY, DEFAULT_SET_LOAD_FACTOR);
|
||||
myDeltaIsTransient = base.myDeltaIsTransient;
|
||||
myRootDir = new File(FileUtil.toSystemIndependentName(base.myRootDir.getAbsolutePath()) + File.separatorChar + "myDelta");
|
||||
myContext = base.myContext;
|
||||
@@ -112,6 +119,7 @@ public class Mappings {
|
||||
myChangedClasses = null;
|
||||
myChangedFiles = null;
|
||||
myDeletedClasses = null;
|
||||
myAddedClasses = null;
|
||||
myDeltaIsTransient = transientDelta;
|
||||
myRootDir = rootDir;
|
||||
createImplementation();
|
||||
@@ -132,6 +140,7 @@ public class Mappings {
|
||||
if (myIsDelta && myDeltaIsTransient) {
|
||||
myClassToSubclasses = new IntIntTransientMultiMaplet();
|
||||
myClassToClassDependency = new IntIntTransientMultiMaplet();
|
||||
myShortClassNameIndex = null;
|
||||
mySourceFileToClasses = new ObjectObjectTransientMultiMaplet<File, ClassRepr>(FileUtil.FILE_HASHING_STRATEGY, ourClassSetConstructor);
|
||||
myClassToSourceFile = new IntObjectTransientMaplet<File>();
|
||||
}
|
||||
@@ -141,6 +150,7 @@ public class Mappings {
|
||||
}
|
||||
myClassToSubclasses = new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, CLASS_TO_SUBCLASSES), INT_KEY_DESCRIPTOR);
|
||||
myClassToClassDependency = new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, CLASS_TO_CLASS), INT_KEY_DESCRIPTOR);
|
||||
myShortClassNameIndex = myIsDelta? null : new IntIntPersistentMultiMaplet(DependencyContext.getTableFile(myRootDir, SHORT_NAMES), INT_KEY_DESCRIPTOR);
|
||||
mySourceFileToClasses = new ObjectObjectPersistentMultiMaplet<File, ClassRepr>(
|
||||
DependencyContext.getTableFile(myRootDir, SOURCE_TO_CLASS), new FileKeyDescriptor(), ClassRepr.externalizer(myContext),
|
||||
ourClassSetConstructor
|
||||
@@ -1788,36 +1798,51 @@ public class Mappings {
|
||||
|
||||
for (final ClassRepr c : addedClasses) {
|
||||
debug("Class name: ", c.name);
|
||||
myDelta.addChangedClass(c.name);
|
||||
myDelta.addAddedClass(c);
|
||||
|
||||
for (final int sup : c.getSupers()) {
|
||||
myDelta.registerAddedSuperClass(c.name, sup);
|
||||
}
|
||||
|
||||
if (!myEasyMode) {
|
||||
final TIntHashSet depClasses = myClassToClassDependency.get(c.name);
|
||||
|
||||
if (depClasses != null) {
|
||||
depClasses.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int depClass) {
|
||||
final File fName = myClassToSourceFile.get(depClass);
|
||||
if (fName != null) {
|
||||
if (myFilter == null || myFilter.accept(fName)) {
|
||||
debug("Adding dependent file ", fName);
|
||||
myAffectedFiles.add(fName);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
if (!myEasyMode && !c.isAnonymous() && !c.isLocal()) {
|
||||
final TIntHashSet toAffect = new TIntHashSet();
|
||||
toAffect.add(c.name);
|
||||
final TIntHashSet classes = myShortClassNameIndex.get(myContext.get(c.getShortName()));
|
||||
if (classes != null) {
|
||||
// affecting dependencies on all other classes with the same short name
|
||||
toAffect.addAll(classes.toArray());
|
||||
}
|
||||
toAffect.forEach(new TIntProcedure() {
|
||||
public boolean execute(int qName) {
|
||||
final TIntHashSet depClasses = myClassToClassDependency.get(qName);
|
||||
if (depClasses != null) {
|
||||
affectCorrespondingSourceFiles(depClasses);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
debug("End of added classes processing.");
|
||||
}
|
||||
|
||||
private void affectCorrespondingSourceFiles(TIntHashSet toAffect) {
|
||||
toAffect.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int depClass) {
|
||||
final File fName = myClassToSourceFile.get(depClass);
|
||||
if (fName != null) {
|
||||
if (myFilter == null || myFilter.accept(fName)) {
|
||||
debug("Adding dependent file ", fName);
|
||||
myAffectedFiles.add(fName);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void calculateAffectedFiles(final DiffState state) {
|
||||
debug("Checking dependent classes:");
|
||||
|
||||
@@ -1979,10 +2004,7 @@ public class Mappings {
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupRemovedClass(final Mappings delta,
|
||||
@NotNull final ClassRepr cr,
|
||||
final Set<UsageRepr.Usage> usages,
|
||||
final IntIntMultiMaplet dependenciesTrashBin) {
|
||||
private void cleanupRemovedClass(final Mappings delta, @NotNull final ClassRepr cr, final Set<UsageRepr.Usage> usages, final IntIntMultiMaplet dependenciesTrashBin) {
|
||||
final int className = cr.name;
|
||||
|
||||
for (final int superSomething : cr.getSupers()) {
|
||||
@@ -1994,6 +2016,9 @@ public class Mappings {
|
||||
myClassToClassDependency.remove(className);
|
||||
myClassToSubclasses.remove(className);
|
||||
myClassToSourceFile.remove(className);
|
||||
if (!cr.isLocal() && !cr.isAnonymous()) {
|
||||
myShortClassNameIndex.removeFrom(myContext.get(cr.getShortName()), className);
|
||||
}
|
||||
}
|
||||
|
||||
public void integrate(final Mappings delta) {
|
||||
@@ -2025,6 +2050,11 @@ public class Mappings {
|
||||
for (final ClassRepr repr : delta.getDeletedClasses()) {
|
||||
cleanupRemovedClass(delta, repr, repr.getUsages(), dependenciesTrashBin);
|
||||
}
|
||||
for (ClassRepr repr : delta.getAddedClasses()) {
|
||||
if (!repr.isAnonymous() && !repr.isLocal()) {
|
||||
myShortClassNameIndex.put(myContext.get(repr.getShortName()), repr.name);
|
||||
}
|
||||
}
|
||||
|
||||
final TIntHashSet superClasses = new TIntHashSet();
|
||||
final IntIntTransientMultiMaplet addedSuperClasses = delta.getAddedSuperClasses();
|
||||
@@ -2090,6 +2120,16 @@ public class Mappings {
|
||||
myClassToSubclasses.putAll(delta.myClassToSubclasses);
|
||||
myClassToSourceFile.putAll(delta.myClassToSourceFile);
|
||||
mySourceFileToClasses.replaceAll(delta.mySourceFileToClasses);
|
||||
delta.mySourceFileToClasses.forEachEntry(new TObjectObjectProcedure<File, Collection<ClassRepr>>() {
|
||||
public boolean execute(File src, Collection<ClassRepr> classes) {
|
||||
for (ClassRepr repr : classes) {
|
||||
if (!repr.isAnonymous() && !repr.isLocal()) {
|
||||
myShortClassNameIndex.put(myContext.get(repr.getShortName()), repr.name);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// updating classToClass dependencies
|
||||
@@ -2224,6 +2264,7 @@ public class Mappings {
|
||||
myClassToSourceFile.close();
|
||||
|
||||
if (!myIsDelta) {
|
||||
myShortClassNameIndex.close();
|
||||
// only close if you own the context
|
||||
final DependencyContext context = myContext;
|
||||
if (context != null) {
|
||||
@@ -2247,6 +2288,7 @@ public class Mappings {
|
||||
myClassToSourceFile.flush(memoryCachesOnly);
|
||||
|
||||
if (!myIsDelta) {
|
||||
myShortClassNameIndex.flush(memoryCachesOnly);
|
||||
// flush if you own the context
|
||||
final DependencyContext context = myContext;
|
||||
if (context != null) {
|
||||
@@ -2312,6 +2354,14 @@ public class Mappings {
|
||||
addChangedClass(cr.name);
|
||||
}
|
||||
|
||||
private void addAddedClass(final ClassRepr cr) {
|
||||
assert (myAddedClasses != null);
|
||||
|
||||
myAddedClasses.add(cr);
|
||||
|
||||
addChangedClass(cr.name);
|
||||
}
|
||||
|
||||
private void addChangedClass(final int it) {
|
||||
assert (myChangedClasses != null && myChangedFiles != null);
|
||||
myChangedClasses.add(it);
|
||||
@@ -2328,6 +2378,11 @@ public class Mappings {
|
||||
return myDeletedClasses == null ? Collections.<ClassRepr>emptySet() : Collections.unmodifiableSet(myDeletedClasses);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Set<ClassRepr> getAddedClasses() {
|
||||
return myAddedClasses == null ? Collections.<ClassRepr>emptySet() : Collections.unmodifiableSet(myAddedClasses);
|
||||
}
|
||||
|
||||
private TIntHashSet getChangedClasses() {
|
||||
return myChangedClasses;
|
||||
}
|
||||
@@ -2390,6 +2445,7 @@ public class Mappings {
|
||||
myClassToClassDependency,
|
||||
mySourceFileToClasses,
|
||||
myClassToSourceFile,
|
||||
myShortClassNameIndex
|
||||
};
|
||||
|
||||
final String[] info = {
|
||||
@@ -2397,6 +2453,7 @@ public class Mappings {
|
||||
"ClassToClassDependency",
|
||||
"SourceFileToClasses",
|
||||
"ClassToSourceFile",
|
||||
"ShortClassNameIndex"
|
||||
};
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.util.concurrent.Executor;
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
final class ProtobufClientMessageHandler<T extends ProtobufResponseHandler> extends SimpleChannelInboundHandler<MessageLite> {
|
||||
private final ConcurrentHashMap<UUID, RequestFuture<T>> myHandlers = new ConcurrentHashMap<UUID, RequestFuture<T>>();
|
||||
private final ConcurrentHashMap<UUID, RequestFuture<T>> myHandlers = new ConcurrentHashMap<UUID, RequestFuture<T>>(16, 0.75f, 1);
|
||||
@NotNull
|
||||
private final UUIDGetter myUuidGetter;
|
||||
private final SimpleProtobufClient myClient;
|
||||
|
||||
@@ -88,6 +88,7 @@ public class IncProjectBuilder {
|
||||
maxThreads = Math.max(2, Integer.parseInt(System.getProperty(GlobalOptions.COMPILE_PARALLEL_MAX_THREADS_OPTION, Integer.toString(maxThreads))));
|
||||
}
|
||||
catch (NumberFormatException ignored) {
|
||||
maxThreads = Math.max(2, maxThreads);
|
||||
}
|
||||
MAX_BUILDER_THREADS = maxThreads;
|
||||
}
|
||||
@@ -632,9 +633,7 @@ public class IncProjectBuilder {
|
||||
}
|
||||
|
||||
private class BuildParallelizer {
|
||||
private final BoundedTaskExecutor myParallelBuildExecutor =
|
||||
new BoundedTaskExecutor(SharedThreadPool.getInstance(),
|
||||
Math.min(MAX_BUILDER_THREADS, Math.max(2, Runtime.getRuntime().availableProcessors())));
|
||||
private final BoundedTaskExecutor myParallelBuildExecutor = new BoundedTaskExecutor(SharedThreadPool.getInstance(), MAX_BUILDER_THREADS);
|
||||
private final CompileContext myContext;
|
||||
private final AtomicReference<Throwable> myException = new AtomicReference<Throwable>();
|
||||
private final Object myQueueLock = new Object();
|
||||
|
||||
@@ -41,7 +41,7 @@ import java.util.concurrent.ConcurrentMap;
|
||||
* Date: 10/7/11
|
||||
*/
|
||||
public class BuildDataManager implements StorageOwner {
|
||||
private static final int VERSION = 20;
|
||||
private static final int VERSION = 21;
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildDataManager");
|
||||
private static final String SRC_TO_FORM_STORAGE = "src-form";
|
||||
private static final String MAPPINGS_STORAGE = "mappings";
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.jetbrains.jps.incremental.storage;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import com.intellij.util.io.IOUtil;
|
||||
import org.jetbrains.jps.builders.BuildTarget;
|
||||
import org.jetbrains.jps.builders.BuildTargetLoader;
|
||||
@@ -26,6 +25,7 @@ import org.jetbrains.jps.builders.BuildTargetType;
|
||||
import java.io.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
/**
|
||||
@@ -43,7 +43,7 @@ public class BuildTargetTypeState {
|
||||
myTargetType = targetType;
|
||||
myTargetsState = state;
|
||||
myTargetsFile = new File(state.getDataPaths().getTargetTypeDataRoot(targetType), "targets.dat");
|
||||
myConfigurations = new ConcurrentHashMap<BuildTarget<?>, BuildTargetConfiguration>();
|
||||
myConfigurations = new ConcurrentHashMap<BuildTarget<?>, BuildTargetConfiguration>(16, 0.75f, 1);
|
||||
myTargetIds = new HashMap<BuildTarget<?>, Integer>();
|
||||
load();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ package org.jetbrains.jps.incremental.storage;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jps.builders.BuildTarget;
|
||||
import org.jetbrains.jps.builders.BuildTargetType;
|
||||
@@ -27,6 +26,7 @@ import org.jetbrains.jps.incremental.TargetTypeRegistry;
|
||||
import org.jetbrains.jps.model.JpsModel;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@@ -37,7 +37,7 @@ public class BuildTargetsState {
|
||||
private static final Logger LOG = Logger.getInstance("#org.jetbrains.jps.incremental.storage.BuildTargetsState");
|
||||
private final BuildDataPaths myDataPaths;
|
||||
private AtomicInteger myMaxTargetId = new AtomicInteger(0);
|
||||
private ConcurrentMap<BuildTargetType<?>, BuildTargetTypeState> myTypeStates = new ConcurrentHashMap<BuildTargetType<?>, BuildTargetTypeState>();
|
||||
private ConcurrentMap<BuildTargetType<?>, BuildTargetTypeState> myTypeStates = new ConcurrentHashMap<BuildTargetType<?>, BuildTargetTypeState>(16, 0.75f, 1);
|
||||
private JpsModel myModel;
|
||||
private final BuildRootIndexImpl myBuildRootIndex;
|
||||
|
||||
@@ -99,9 +99,11 @@ public class BuildTargetsState {
|
||||
private BuildTargetTypeState getTypeState(BuildTargetType<?> type) {
|
||||
BuildTargetTypeState state = myTypeStates.get(type);
|
||||
if (state == null) {
|
||||
state = new BuildTargetTypeState(type, this);
|
||||
myTypeStates.putIfAbsent(type, state);
|
||||
state = myTypeStates.get(type);
|
||||
final BuildTargetTypeState newState = new BuildTargetTypeState(type, this);
|
||||
state = myTypeStates.putIfAbsent(type, newState);
|
||||
if (state == null) {
|
||||
state = newState;
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -542,6 +542,7 @@ class OptimizedFileManager extends DefaultFileManager {
|
||||
myDirectoryCache.clear();
|
||||
myByteBufferCache.clear();
|
||||
myIsFile.clear();
|
||||
Paths.clearPathExistanceCache();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,4 +113,9 @@ public class CommonTest extends IncrementalTestCase {
|
||||
public void testAddDuplicateClass() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testAddClassHidingImportedClass() throws Exception {
|
||||
doTest();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,8 +24,8 @@ import java.util.concurrent.ConcurrentHashMap;
|
||||
* @author nik
|
||||
*/
|
||||
public class JpsServiceManagerImpl extends JpsServiceManager {
|
||||
private final ConcurrentHashMap<Class, Object> myServices = new ConcurrentHashMap<Class, Object>();
|
||||
private final ConcurrentHashMap<Class, List<?>> myExtensions = new ConcurrentHashMap<Class, List<?>>();
|
||||
private final ConcurrentHashMap<Class, Object> myServices = new ConcurrentHashMap<Class, Object>(16, 0.75f, 1);
|
||||
private final ConcurrentHashMap<Class, List<?>> myExtensions = new ConcurrentHashMap<Class, List<?>>(16, 0.75f, 1);
|
||||
|
||||
@Override
|
||||
public <T> T getService(Class<T> serviceClass) {
|
||||
@@ -36,14 +36,16 @@ public class JpsServiceManagerImpl extends JpsServiceManager {
|
||||
if (!iterator.hasNext()) {
|
||||
throw new ServiceConfigurationError("Implementation for " + serviceClass + " not found");
|
||||
}
|
||||
service = iterator.next();
|
||||
final T loadedService = iterator.next();
|
||||
if (iterator.hasNext()) {
|
||||
throw new ServiceConfigurationError(
|
||||
"More than one implementation for " + serviceClass + " found: " + service.getClass() + " and " + iterator.next().getClass());
|
||||
"More than one implementation for " + serviceClass + " found: " + loadedService.getClass() + " and " + iterator.next().getClass());
|
||||
}
|
||||
myServices.putIfAbsent(serviceClass, service);
|
||||
//noinspection unchecked
|
||||
service = (T)myServices.get(serviceClass);
|
||||
service = (T)myServices.putIfAbsent(serviceClass, loadedService);
|
||||
if (service == null) {
|
||||
service = loadedService;
|
||||
}
|
||||
}
|
||||
return service;
|
||||
}
|
||||
@@ -53,12 +55,14 @@ public class JpsServiceManagerImpl extends JpsServiceManager {
|
||||
List<?> cached = myExtensions.get(extensionClass);
|
||||
if (cached == null) {
|
||||
final ServiceLoader<T> loader = ServiceLoader.load(extensionClass, extensionClass.getClassLoader());
|
||||
List<T> extensions = new ArrayList<T>();
|
||||
final List<T> extensions = new ArrayList<T>();
|
||||
for (T t : loader) {
|
||||
extensions.add(t);
|
||||
}
|
||||
myExtensions.putIfAbsent(extensionClass, extensions);
|
||||
cached = myExtensions.get(extensionClass);
|
||||
cached = myExtensions.putIfAbsent(extensionClass, extensions);
|
||||
if (cached == null) {
|
||||
cached = extensions;
|
||||
}
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (List<T>)cached;
|
||||
|
||||
@@ -145,7 +145,9 @@ public class ToolsImpl implements Tools {
|
||||
scopeElement.setAttribute(LEVEL_ATTRIBUTE, state.getLevel().toString());
|
||||
scopeElement.setAttribute(ENABLED_ATTRIBUTE, Boolean.toString(state.isEnabled()));
|
||||
InspectionToolWrapper toolWrapper = state.getTool();
|
||||
toolWrapper.getTool().writeSettings(scopeElement);
|
||||
if (toolWrapper.isInitialized()) {
|
||||
toolWrapper.getTool().writeSettings(scopeElement);
|
||||
}
|
||||
inspectionElement.addContent(scopeElement);
|
||||
}
|
||||
}
|
||||
@@ -153,7 +155,9 @@ public class ToolsImpl implements Tools {
|
||||
inspectionElement.setAttribute(LEVEL_ATTRIBUTE, getLevel().toString());
|
||||
inspectionElement.setAttribute(ENABLED_BY_DEFAULT_ATTRIBUTE, Boolean.toString(myDefaultState.isEnabled()));
|
||||
InspectionToolWrapper toolWrapper = myDefaultState.getTool();
|
||||
toolWrapper.getTool().writeSettings(inspectionElement);
|
||||
if (toolWrapper.isInitialized()) {
|
||||
toolWrapper.getTool().writeSettings(inspectionElement);
|
||||
}
|
||||
}
|
||||
|
||||
void readExternal(@NotNull Element toolElement, @NotNull InspectionProfile profile) throws InvalidDataException {
|
||||
|
||||
@@ -106,7 +106,9 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
if (baseLanguage.isKindOf(reparseable.getLanguage())) {
|
||||
final int start = textRange.getStartOffset();
|
||||
final int end = start + textRange.getLength() + lengthShift;
|
||||
assertFileLength(file, newFileText, node, elementType, start, end);
|
||||
if (!assertFileLength(file, newFileText, node, elementType, start, end)) {
|
||||
break;
|
||||
}
|
||||
|
||||
CharSequence newTextStr = newFileText.subSequence(start, end);
|
||||
|
||||
@@ -134,11 +136,13 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
return makeFullParse(node, newFileText, textLength, fileImpl, indicator);
|
||||
}
|
||||
|
||||
private static void assertFileLength(PsiFile file, CharSequence newFileText, ASTNode node, IElementType elementType, int start, int end) {
|
||||
if (end > newFileText.length() && ApplicationManager.getApplication().isInternal()) {
|
||||
private static boolean assertFileLength(PsiFile file, CharSequence newFileText, ASTNode node, IElementType elementType, int start, int end) {
|
||||
if ((end > newFileText.length() || start > end) && ApplicationManager.getApplication().isInternal()) {
|
||||
String newTextBefore = newFileText.subSequence(0, start).toString();
|
||||
String oldTextBefore = file.getText().subSequence(0, start).toString();
|
||||
String message = "IOOBE: type=" + elementType +
|
||||
"; start=" + start +
|
||||
"; end=" + end +
|
||||
"; oldText=" + node.getText() +
|
||||
"; newText=" + newFileText.subSequence(start, newFileText.length()) +
|
||||
"; length=" + node.getTextLength();
|
||||
@@ -148,8 +152,10 @@ public class BlockSupportImpl extends BlockSupport {
|
||||
message += "; oldTextBefore=" + oldTextBefore +
|
||||
"; newTextBefore=" + newTextBefore;
|
||||
}
|
||||
throw new AssertionError(message);
|
||||
LOG.error(message);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -11,6 +11,7 @@ setting.type.location.explicit.correct={0} location is defined
|
||||
setting.type.location.explicit.incorrect={0} location is incorrect
|
||||
settings.label.select.project={0} project:
|
||||
settings.label.use.auto.import=Use auto-import
|
||||
settings.label.create.empty.content.root.directories=Create directories for empty content roots automatically
|
||||
settings.title.linked.projects=Linked {0} projects
|
||||
settings.title.project.settings=Project-level settings
|
||||
settings.title.system.settings=Global {0} settings
|
||||
@@ -59,6 +60,8 @@ run.configuration.settings.label.project={0} project:
|
||||
run.configuration.settings.label.tasks=Tasks:
|
||||
run.configuration.settings.label.vmoptions=VM options:
|
||||
run.configuration.settings.caption.vmoptions=VM options:
|
||||
run.text.starting.multiple.task=Executing external tasks ''{0}''...\n
|
||||
run.text.starting.single.task=Executing external task ''{0}''...\n
|
||||
run.text.starting.multiple.task={0}: Executing external tasks ''{1}''...\n
|
||||
run.text.starting.single.task={0}: Executing external task ''{1}''...\n
|
||||
run.text.ended.multiple.task={0}: External tasks execution finished ''{1}''.\n
|
||||
run.text.ended.single.task={0}: External task execution finished ''{1}''.\n
|
||||
run.error.undefined.task=No task to execute is specified
|
||||
@@ -77,6 +77,7 @@ public abstract class AbstractDependencyData<T extends AbstractExternalEntityDat
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = super.hashCode();
|
||||
result = 31 * result + myScope.hashCode();
|
||||
result = 31 * result + myOwnerModule.hashCode();
|
||||
result = 31 * result + myTarget.hashCode();
|
||||
return result;
|
||||
@@ -88,7 +89,7 @@ public abstract class AbstractDependencyData<T extends AbstractExternalEntityDat
|
||||
return false;
|
||||
}
|
||||
AbstractDependencyData<?> that = (AbstractDependencyData<?>)o;
|
||||
return myOwnerModule.equals(that.myOwnerModule) && myTarget.equals(that.myTarget);
|
||||
return myScope.equals(that.myScope) && myOwnerModule.equals(that.myOwnerModule) && myTarget.equals(that.myTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -28,6 +28,7 @@ public abstract class ExternalProjectSettings implements Comparable<ExternalProj
|
||||
|
||||
private String myExternalProjectPath;
|
||||
private boolean myUseAutoImport;
|
||||
private boolean myCreateEmptyContentRootDirectories;
|
||||
|
||||
public String getExternalProjectPath() {
|
||||
return myExternalProjectPath;
|
||||
@@ -45,6 +46,14 @@ public abstract class ExternalProjectSettings implements Comparable<ExternalProj
|
||||
myUseAutoImport = useAutoImport;
|
||||
}
|
||||
|
||||
public boolean isCreateEmptyContentRootDirectories() {
|
||||
return myCreateEmptyContentRootDirectories;
|
||||
}
|
||||
|
||||
public void setCreateEmptyContentRootDirectories(boolean createEmptyContentRootDirectories) {
|
||||
myCreateEmptyContentRootDirectories = createEmptyContentRootDirectories;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(@NotNull ExternalProjectSettings that) {
|
||||
return Comparing.compare(myExternalProjectPath, that.myExternalProjectPath);
|
||||
@@ -76,5 +85,6 @@ public abstract class ExternalProjectSettings implements Comparable<ExternalProj
|
||||
protected void copyTo(@NotNull ExternalProjectSettings receiver) {
|
||||
receiver.myExternalProjectPath = myExternalProjectPath;
|
||||
receiver.myUseAutoImport = myUseAutoImport;
|
||||
receiver.myCreateEmptyContentRootDirectories = myCreateEmptyContentRootDirectories;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import com.intellij.openapi.util.WriteExternalException;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.net.NetUtils;
|
||||
import com.intellij.util.text.DateFormatUtil;
|
||||
import com.intellij.util.xmlb.XmlSerializer;
|
||||
import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -166,12 +167,13 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase {
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final String startDateTime = DateFormatUtil.formatTimeWithSeconds(System.currentTimeMillis());
|
||||
final String greeting;
|
||||
if (mySettings.getTaskNames().size() > 1) {
|
||||
greeting = ExternalSystemBundle.message("run.text.starting.multiple.task", StringUtil.join(mySettings.getTaskNames(), " "));
|
||||
greeting = ExternalSystemBundle.message("run.text.starting.multiple.task", startDateTime, StringUtil.join(mySettings.getTaskNames(), " "));
|
||||
}
|
||||
else {
|
||||
greeting = ExternalSystemBundle.message("run.text.starting.single.task", StringUtil.join(mySettings.getTaskNames(), " "));
|
||||
greeting = ExternalSystemBundle.message("run.text.starting.single.task", startDateTime, StringUtil.join(mySettings.getTaskNames(), " "));
|
||||
}
|
||||
processHandler.notifyTextAvailable(greeting, ProcessOutputTypes.SYSTEM);
|
||||
task.execute(new ExternalSystemTaskNotificationListenerAdapter() {
|
||||
@@ -189,6 +191,15 @@ public class ExternalSystemRunConfiguration extends LocatableConfigurationBase {
|
||||
|
||||
@Override
|
||||
public void onEnd(@NotNull ExternalSystemTaskId id) {
|
||||
final String endDateTime = DateFormatUtil.formatTimeWithSeconds(System.currentTimeMillis());
|
||||
final String farewell;
|
||||
if (mySettings.getTaskNames().size() > 1) {
|
||||
farewell = ExternalSystemBundle.message("run.text.ended.multiple.task", endDateTime, StringUtil.join(mySettings.getTaskNames(), " "));
|
||||
}
|
||||
else {
|
||||
farewell = ExternalSystemBundle.message("run.text.ended.single.task", endDateTime, StringUtil.join(mySettings.getTaskNames(), " "));
|
||||
}
|
||||
processHandler.notifyTextAvailable(farewell, ProcessOutputTypes.SYSTEM);
|
||||
processHandler.notifyProcessTerminated(0);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -4,10 +4,13 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.externalSystem.model.DataNode;
|
||||
import com.intellij.openapi.externalSystem.model.Key;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys;
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.model.project.ContentRootData;
|
||||
import com.intellij.openapi.externalSystem.model.project.ExternalSystemSourceType;
|
||||
import com.intellij.openapi.externalSystem.model.project.ModuleData;
|
||||
import com.intellij.openapi.externalSystem.service.project.ProjectStructureHelper;
|
||||
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
|
||||
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
|
||||
import com.intellij.openapi.externalSystem.util.DisposeAwareProjectChange;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
|
||||
@@ -95,30 +98,45 @@ public class ContentRootDataService implements ProjectDataService<ContentRootDat
|
||||
for(ContentEntry contentEntry : contentEntries) {
|
||||
contentEntriesMap.put(contentEntry.getUrl(), contentEntry);
|
||||
}
|
||||
|
||||
boolean createEmptyContentRootDirectories = false;
|
||||
if (!datas.isEmpty()) {
|
||||
ProjectSystemId projectSystemId = datas.iterator().next().getData().getOwner();
|
||||
AbstractExternalSystemSettings externalSystemSettings =
|
||||
ExternalSystemApiUtil.getSettings(module.getProject(), projectSystemId);
|
||||
|
||||
String path = module.getOptionValue(ExternalSystemConstants.ROOT_PROJECT_PATH_KEY);
|
||||
if (path != null) {
|
||||
ExternalProjectSettings projectSettings = externalSystemSettings.getLinkedProjectSettings(path);
|
||||
createEmptyContentRootDirectories = projectSettings != null && projectSettings.isCreateEmptyContentRootDirectories();
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
for (final DataNode<ContentRootData> data : datas) {
|
||||
final ContentRootData contentRoot = data.getData();
|
||||
|
||||
final ContentEntry contentEntry = findOrCreateContentRoot(model, contentRoot.getRootPath());
|
||||
contentEntry.clearExcludeFolders();
|
||||
contentEntry.clearSourceFolders();
|
||||
LOG.info(String.format("Importing content root '%s' for module '%s'", contentRoot.getRootPath(), module.getName()));
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.SOURCE)) {
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.SOURCE, false);
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.SOURCE, false, createEmptyContentRootDirectories);
|
||||
}
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.TEST)) {
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.TEST_SOURCE, false);
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.TEST_SOURCE, false, createEmptyContentRootDirectories);
|
||||
}
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.RESOURCE)) {
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaResourceRootType.RESOURCE, false);
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaResourceRootType.RESOURCE, false, createEmptyContentRootDirectories);
|
||||
}
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.TEST_RESOURCE)) {
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaResourceRootType.TEST_RESOURCE, false);
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaResourceRootType.TEST_RESOURCE, false, createEmptyContentRootDirectories);
|
||||
}
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.SOURCE_GENERATED)) {
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.SOURCE, true);
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.SOURCE, true, createEmptyContentRootDirectories);
|
||||
}
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.TEST_GENERATED)) {
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.TEST_SOURCE, true);
|
||||
createSourceRootIfAbsent(contentEntry, path, module.getName(), JavaSourceRootType.TEST_SOURCE, true, createEmptyContentRootDirectories);
|
||||
}
|
||||
for (String path : contentRoot.getPaths(ExternalSystemSourceType.EXCLUDED)) {
|
||||
createExcludedRootIfAbsent(contentEntry, path, module.getName());
|
||||
@@ -154,7 +172,7 @@ public class ContentRootDataService implements ProjectDataService<ContentRootDat
|
||||
|
||||
private static void createSourceRootIfAbsent(
|
||||
@NotNull ContentEntry entry, @NotNull String path, @NotNull String moduleName,
|
||||
@NotNull JpsModuleSourceRootType sourceRootType, boolean generated) {
|
||||
@NotNull JpsModuleSourceRootType sourceRootType, boolean generated, boolean createEmptyContentRootDirectories) {
|
||||
List<SourceFolder> folders = entry.getSourceFolders(sourceRootType);
|
||||
for (SourceFolder folder : folders) {
|
||||
VirtualFile file = folder.getFile();
|
||||
@@ -173,11 +191,13 @@ public class ContentRootDataService implements ProjectDataService<ContentRootDat
|
||||
properties.setForGeneratedSources(true);
|
||||
}
|
||||
}
|
||||
try {
|
||||
VfsUtil.createDirectoryIfMissing(path);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn(String.format("Unable to create directory for the path: %s", path), e);
|
||||
if(createEmptyContentRootDirectories) {
|
||||
try {
|
||||
VfsUtil.createDirectoryIfMissing(path);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn(String.format("Unable to create directory for the path: %s", path), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
|
||||
// The trick is that we should perform module settings modification inside try/finally block against target root model.
|
||||
// That means that we need to prepare all necessary data, obtain a model and modify it as necessary.
|
||||
Map<Set<String>/* library paths */, LibraryDependencyData> moduleLibrariesToImport = ContainerUtilRt.newHashMap();
|
||||
Map<String/* library name */, LibraryDependencyData> projectLibrariesToImport = ContainerUtilRt.newHashMap();
|
||||
Map<String/* library name + scope */, LibraryDependencyData> projectLibrariesToImport = ContainerUtilRt.newHashMap();
|
||||
Set<LibraryDependencyData> toImport = ContainerUtilRt.newLinkedHashSet();
|
||||
|
||||
boolean hasUnresolved = false;
|
||||
@@ -132,7 +132,7 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
|
||||
}
|
||||
break;
|
||||
case PROJECT:
|
||||
projectLibrariesToImport.put(ExternalSystemApiUtil.getLibraryName(libraryData), dependencyData);
|
||||
projectLibrariesToImport.put(ExternalSystemApiUtil.getLibraryName(libraryData) + dependencyData.getScope().name(), dependencyData);
|
||||
toImport.add(dependencyData);
|
||||
}
|
||||
}
|
||||
@@ -224,8 +224,8 @@ public class LibraryDependencyDataService extends AbstractDependencyDataService<
|
||||
else if (entry instanceof LibraryOrderEntry) {
|
||||
final LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry)entry;
|
||||
final String libraryName = libraryOrderEntry.getLibraryName();
|
||||
final LibraryDependencyData existing = projectLibrariesToImport.remove(libraryName);
|
||||
if (existing != null && libraryOrderEntry.getScope() == existing.getScope()) {
|
||||
final LibraryDependencyData existing = projectLibrariesToImport.remove(libraryName + libraryOrderEntry.getScope().name());
|
||||
if (existing != null) {
|
||||
toImport.remove(existing);
|
||||
}
|
||||
else if (!hasUnresolvedLibraries) {
|
||||
|
||||
@@ -37,6 +37,7 @@ public abstract class AbstractExternalProjectSettingsControl<S extends ExternalP
|
||||
@NotNull private S myInitialSettings;
|
||||
|
||||
private JBCheckBox myUseAutoImportBox;
|
||||
private JBCheckBox myCreateEmptyContentRootDirectoriesBox;
|
||||
private boolean myHideUseAutoImportBox;
|
||||
|
||||
protected AbstractExternalProjectSettingsControl(@NotNull S initialSettings) {
|
||||
@@ -57,13 +58,18 @@ public abstract class AbstractExternalProjectSettingsControl<S extends ExternalP
|
||||
myUseAutoImportBox = new JBCheckBox(ExternalSystemBundle.message("settings.label.use.auto.import"));
|
||||
myUseAutoImportBox.setVisible(!myHideUseAutoImportBox);
|
||||
canvas.add(myUseAutoImportBox, ExternalSystemUiUtil.getFillLineConstraints(indentLevel));
|
||||
myCreateEmptyContentRootDirectoriesBox =
|
||||
new JBCheckBox(ExternalSystemBundle.message("settings.label.create.empty.content.root.directories"));
|
||||
canvas.add(myCreateEmptyContentRootDirectoriesBox, ExternalSystemUiUtil.getFillLineConstraints(indentLevel));
|
||||
fillExtraControls(canvas, indentLevel);
|
||||
}
|
||||
|
||||
protected abstract void fillExtraControls(@NotNull PaintAwarePanel content, int indentLevel);
|
||||
|
||||
public boolean isModified() {
|
||||
return myUseAutoImportBox.isSelected() != getInitialSettings().isUseAutoImport() || isExtraSettingModified();
|
||||
return myUseAutoImportBox.isSelected() != getInitialSettings().isUseAutoImport()
|
||||
|| myCreateEmptyContentRootDirectoriesBox.isSelected() != getInitialSettings().isCreateEmptyContentRootDirectories()
|
||||
|| isExtraSettingModified();
|
||||
}
|
||||
|
||||
protected abstract boolean isExtraSettingModified();
|
||||
@@ -74,6 +80,7 @@ public abstract class AbstractExternalProjectSettingsControl<S extends ExternalP
|
||||
|
||||
public void reset(boolean isDefaultModuleCreation) {
|
||||
myUseAutoImportBox.setSelected(getInitialSettings().isUseAutoImport());
|
||||
myCreateEmptyContentRootDirectoriesBox.setSelected(getInitialSettings().isCreateEmptyContentRootDirectories());
|
||||
resetExtraSettings(isDefaultModuleCreation);
|
||||
}
|
||||
|
||||
@@ -83,6 +90,8 @@ public abstract class AbstractExternalProjectSettingsControl<S extends ExternalP
|
||||
public void apply(@NotNull S settings) {
|
||||
settings.setUseAutoImport(myUseAutoImportBox.isSelected());
|
||||
myInitialSettings.setUseAutoImport(myUseAutoImportBox.isSelected());
|
||||
settings.setCreateEmptyContentRootDirectories(myCreateEmptyContentRootDirectoriesBox.isSelected());
|
||||
myInitialSettings.setCreateEmptyContentRootDirectories(myCreateEmptyContentRootDirectoriesBox.isSelected());
|
||||
if (myInitialSettings.getExternalProjectPath() != null) {
|
||||
settings.setExternalProjectPath(myInitialSettings.getExternalProjectPath());
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package com.intellij.openapi.externalSystem.service.task.ui;
|
||||
|
||||
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
|
||||
import com.intellij.openapi.externalSystem.model.execution.ExternalSystemTaskExecutionSettings;
|
||||
import com.intellij.openapi.externalSystem.model.execution.ExternalTaskExecutionInfo;
|
||||
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
@@ -23,6 +24,7 @@ import com.intellij.ui.TreeSpeedSearch;
|
||||
import com.intellij.ui.treeStructure.Tree;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Producer;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.ContainerUtilRt;
|
||||
import com.intellij.util.ui.tree.TreeModelAdapter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -52,12 +54,12 @@ public class ExternalSystemTasksTree extends Tree implements Producer<ExternalTa
|
||||
return o2.getPathCount() - o1.getPathCount();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@NotNull private final Alarm myCollapseStateAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD);
|
||||
|
||||
/** Holds list of paths which 'expand/collapse' state should be restored. */
|
||||
@NotNull private final Set<TreePath> myPathsToProcessCollapseState = ContainerUtilRt.newHashSet();
|
||||
|
||||
|
||||
@NotNull private final Map<String/*tree path*/, Boolean/*expanded*/> myExpandedStateHolder;
|
||||
|
||||
private boolean mySuppressCollapseTracking;
|
||||
@@ -86,7 +88,7 @@ public class ExternalSystemTasksTree extends Tree implements Producer<ExternalTa
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
model.addTreeModelListener(new TreeModelAdapter() {
|
||||
@Override
|
||||
public void treeStructureChanged(TreeModelEvent e) {
|
||||
@@ -183,16 +185,39 @@ public class ExternalSystemTasksTree extends Tree implements Producer<ExternalTa
|
||||
@Nullable
|
||||
@Override
|
||||
public ExternalTaskExecutionInfo produce() {
|
||||
TreePath selectionPath = getLeadSelectionPath();
|
||||
if (selectionPath == null) {
|
||||
return null;
|
||||
}
|
||||
Object component = selectionPath.getLastPathComponent();
|
||||
if (!(component instanceof ExternalSystemNode)) {
|
||||
TreePath[] selectionPaths = getSelectionPaths();
|
||||
if (selectionPaths == null || selectionPaths.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Object element = ((ExternalSystemNode)component).getDescriptor().getElement();
|
||||
return element instanceof ExternalTaskExecutionInfo ? ((ExternalTaskExecutionInfo)element) : null;
|
||||
Map<String, ExternalTaskExecutionInfo> map = ContainerUtil.newHashMap();
|
||||
for (TreePath selectionPath : selectionPaths) {
|
||||
Object component = selectionPath.getLastPathComponent();
|
||||
if (!(component instanceof ExternalSystemNode)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Object element = ((ExternalSystemNode)component).getDescriptor().getElement();
|
||||
if (element instanceof ExternalTaskExecutionInfo) {
|
||||
ExternalTaskExecutionInfo taskExecutionInfo = (ExternalTaskExecutionInfo)element;
|
||||
ExternalSystemTaskExecutionSettings executionSettings = taskExecutionInfo.getSettings();
|
||||
String key = executionSettings.getExternalSystemIdString() + executionSettings.getExternalProjectPath() + executionSettings.getVmOptions();
|
||||
ExternalTaskExecutionInfo executionInfo = map.get(key);
|
||||
if(executionInfo == null) {
|
||||
ExternalSystemTaskExecutionSettings taskExecutionSettings = new ExternalSystemTaskExecutionSettings();
|
||||
taskExecutionSettings.setExternalProjectPath(executionSettings.getExternalProjectPath());
|
||||
taskExecutionSettings.setExternalSystemIdString(executionSettings.getExternalSystemIdString());
|
||||
taskExecutionSettings.setVmOptions(executionSettings.getVmOptions());
|
||||
executionInfo = new ExternalTaskExecutionInfo(taskExecutionSettings, taskExecutionInfo.getExecutorId());
|
||||
map.put(key, executionInfo);
|
||||
}
|
||||
executionInfo.getSettings().getTaskNames().addAll(executionSettings.getTaskNames());
|
||||
executionInfo.getSettings().getTaskDescriptions().addAll(executionSettings.getTaskDescriptions());
|
||||
}
|
||||
}
|
||||
|
||||
// Disable tasks execution if it comes from different projects
|
||||
if(map.values().size() > 1) return null;
|
||||
return map.values().iterator().next();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public class ExternalProjectServiceTest extends AbstractExternalSystemTest {
|
||||
dependencies[name]++
|
||||
}
|
||||
}
|
||||
ExternalSystemTestUtil.assertMapsEqual(['lib1': 1, 'lib2': 1], dependencies)
|
||||
ExternalSystemTestUtil.assertMapsEqual(['Test_external_system_id: lib1': 1, 'Test_external_system_id: lib2': 1], dependencies)
|
||||
}
|
||||
|
||||
void 'test changes in a project layout (content roots) could be detected on Refresh'() {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.filters;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class HyperlinkInfoFactory {
|
||||
@NotNull
|
||||
public static HyperlinkInfoFactory getInstance() {
|
||||
return ServiceManager.getService(HyperlinkInfoFactory.class);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public abstract HyperlinkInfo createMultipleFilesHyperlinkInfo(@NotNull List<VirtualFile> files,
|
||||
int line, @NotNull Project project);
|
||||
}
|
||||
@@ -75,7 +75,10 @@ public class CodeStyleSchemesUIConfiguration implements PersistentStateComponent
|
||||
public static void setRecentImportFile(@NotNull VirtualFile recentFile) {
|
||||
CodeStyleSchemesUIConfiguration configuration = getInstance();
|
||||
if (configuration != null) {
|
||||
configuration.RECENT_IMPORT_FILE_LOCATION = recentFile.getUrl();
|
||||
URL url = VfsUtil.convertToURL(recentFile.getUrl());
|
||||
if (url != null) {
|
||||
configuration.RECENT_IMPORT_FILE_LOCATION = url.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ import com.intellij.openapi.project.IndexNotReadyException;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.Trinity;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.PsiDocumentManager;
|
||||
@@ -457,7 +457,7 @@ public class CodeCompletionHandlerBase {
|
||||
public void run() {
|
||||
AccessToken token = WriteAction.start();
|
||||
try {
|
||||
hostCopy[0] = createFileCopy(hostFile);
|
||||
hostCopy[0] = createFileCopy(hostFile, initContext.getStartOffset(), initContext.getSelectionEndOffset());
|
||||
}
|
||||
finally {
|
||||
token.finish();
|
||||
@@ -748,7 +748,7 @@ public class CodeCompletionHandlerBase {
|
||||
}
|
||||
}
|
||||
|
||||
public static final Key<SoftReference<Pair<PsiFile, Document>>> FILE_COPY_KEY = Key.create("CompletionFileCopy");
|
||||
private static final Key<SoftReference<Trinity<PsiFile, Document, Long>>> FILE_COPY_KEY = Key.create("CompletionFileCopy");
|
||||
|
||||
private static boolean isCopyUpToDate(Document document, @NotNull PsiFile file) {
|
||||
if (!file.isValid()) {
|
||||
@@ -760,31 +760,37 @@ public class CodeCompletionHandlerBase {
|
||||
return current != null && current.getViewProvider().getPsi(file.getLanguage()) == file;
|
||||
}
|
||||
|
||||
private static PsiFile createFileCopy(PsiFile file) {
|
||||
private static PsiFile createFileCopy(PsiFile file, long caret, long selEnd) {
|
||||
final VirtualFile virtualFile = file.getVirtualFile();
|
||||
if (file.isPhysical() && virtualFile != null && virtualFile.isInLocalFileSystem()
|
||||
// must not cache injected file copy, since it does not reflect changes in host document
|
||||
&& !InjectedLanguageManager.getInstance(file.getProject()).isInjectedFragment(file)) {
|
||||
final SoftReference<Pair<PsiFile, Document>> reference = file.getUserData(FILE_COPY_KEY);
|
||||
if (reference != null) {
|
||||
final Pair<PsiFile, Document> pair = reference.get();
|
||||
if (pair != null && pair.first.getClass().equals(file.getClass()) && isCopyUpToDate(pair.second, pair.first)) {
|
||||
final PsiFile copy = pair.first;
|
||||
if (copy.getViewProvider().getModificationStamp() > file.getViewProvider().getModificationStamp()) {
|
||||
((PsiModificationTrackerImpl) file.getManager().getModificationTracker()).incCounter();
|
||||
}
|
||||
final Document document = pair.second;
|
||||
assert document != null;
|
||||
document.setText(file.getText());
|
||||
return copy;
|
||||
boolean mayCacheCopy = file.isPhysical() &&
|
||||
// we don't want to cache code fragment copies even if they appear to be physical
|
||||
virtualFile != null && virtualFile.isInLocalFileSystem();
|
||||
long combinedOffsets = caret + (selEnd << 32);
|
||||
if (mayCacheCopy) {
|
||||
final Trinity<PsiFile, Document, Long> cached = SoftReference.dereference(file.getUserData(FILE_COPY_KEY));
|
||||
if (cached != null && cached.first.getClass().equals(file.getClass()) && isCopyUpToDate(cached.second, cached.first)) {
|
||||
final PsiFile copy = cached.first;
|
||||
if (copy.getViewProvider().getModificationStamp() > file.getViewProvider().getModificationStamp() &&
|
||||
cached.third.longValue() != combinedOffsets) {
|
||||
// the copy PSI might have some caches that are not cleared on its modification because there are no events in the copy
|
||||
// so, clear all the caches
|
||||
// hopefully it's a rare situation that the user invokes completion in different parts of the file
|
||||
// without modifying anything physical in between
|
||||
((PsiModificationTrackerImpl) file.getManager().getModificationTracker()).incCounter();
|
||||
}
|
||||
final Document document = cached.second;
|
||||
assert document != null;
|
||||
document.setText(file.getText());
|
||||
return copy;
|
||||
}
|
||||
}
|
||||
|
||||
final PsiFile copy = (PsiFile)file.copy();
|
||||
final Document document = copy.getViewProvider().getDocument();
|
||||
assert document != null;
|
||||
file.putUserData(FILE_COPY_KEY, new SoftReference<Pair<PsiFile,Document>>(Pair.create(copy, document)));
|
||||
if (mayCacheCopy) {
|
||||
final Document document = copy.getViewProvider().getDocument();
|
||||
assert document != null;
|
||||
file.putUserData(FILE_COPY_KEY, new SoftReference<Trinity<PsiFile,Document, Long>>(Trinity.create(copy, document, combinedOffsets)));
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,17 +91,16 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
|
||||
return FileStatus.NOT_CHANGED;
|
||||
}
|
||||
|
||||
protected static HighlightSeverity getSeverity(@NotNull RefElement element,
|
||||
@NotNull GlobalInspectionContextImpl context,
|
||||
@NotNull InspectionToolWrapper thisToolWrapper) {
|
||||
protected HighlightSeverity getSeverity(@NotNull RefElement element) {
|
||||
final PsiElement psiElement = element.getPointer().getContainingFile();
|
||||
if (psiElement != null) {
|
||||
String shortName = thisToolWrapper.getShortName();
|
||||
final GlobalInspectionContextImpl context = getContext();
|
||||
final String shortName = getSeverityDelegateName();
|
||||
final Tools tools = context.getTools().get(shortName);
|
||||
if (tools != null) {
|
||||
for (ScopeToolState state : tools.getTools()) {
|
||||
InspectionToolWrapper toolWrapper = state.getTool();
|
||||
if (toolWrapper == thisToolWrapper) {
|
||||
if (toolWrapper == getToolWrapper()) {
|
||||
return context.getCurrentProfile().getErrorLevel(HighlightDisplayKey.find(shortName), psiElement).getSeverity();
|
||||
}
|
||||
}
|
||||
@@ -114,6 +113,10 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String getSeverityDelegateName() {
|
||||
return getToolWrapper().getShortName();
|
||||
}
|
||||
|
||||
protected static String getTextAttributeKey(@NotNull Project project,
|
||||
@NotNull HighlightSeverity severity,
|
||||
@NotNull ProblemHighlightType highlightType) {
|
||||
@@ -203,7 +206,7 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
|
||||
}
|
||||
InspectionNode toolNode = myToolNode;
|
||||
if (toolNode == null) {
|
||||
final HighlightSeverity currentSeverity = getSeverity((RefElement)refElement, context, myToolWrapper);
|
||||
final HighlightSeverity currentSeverity = getSeverity((RefElement)refElement);
|
||||
view.addTool(myToolWrapper, HighlightDisplayLevel.find(currentSeverity), context.getUIOptions().GROUP_BY_SEVERITY);
|
||||
}
|
||||
else if (toolNode.isTooBigForOnlineRefresh()) {
|
||||
@@ -437,7 +440,7 @@ public class DefaultInspectionToolPresentation implements ProblemDescriptionsPro
|
||||
problemClassElement.addContent(myToolWrapper.getDisplayName());
|
||||
if (refEntity instanceof RefElement){
|
||||
final RefElement refElement = (RefElement)refEntity;
|
||||
final HighlightSeverity severity = getSeverity(refElement, getContext(), getToolWrapper());
|
||||
final HighlightSeverity severity = getSeverity(refElement);
|
||||
ProblemHighlightType problemHighlightType = descriptor instanceof ProblemDescriptor
|
||||
? ((ProblemDescriptor)descriptor).getHighlightType()
|
||||
: ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.filters.impl;
|
||||
|
||||
import com.intellij.execution.filters.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public class HyperlinkInfoFactoryImpl extends HyperlinkInfoFactory {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public HyperlinkInfo createMultipleFilesHyperlinkInfo(@NotNull List<VirtualFile> files,
|
||||
int line, @NotNull Project project) {
|
||||
return new MultipleFilesHyperlinkInfo(files, line, project);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.filters.impl;
|
||||
|
||||
import com.intellij.execution.filters.FileHyperlinkInfo;
|
||||
import com.intellij.execution.filters.HyperlinkInfoBase;
|
||||
import com.intellij.execution.filters.OpenFileHyperlinkInfo;
|
||||
import com.intellij.ide.util.gotoByName.GotoFileCellRenderer;
|
||||
import com.intellij.openapi.application.AccessToken;
|
||||
import com.intellij.openapi.application.ReadAction;
|
||||
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.popup.JBPopup;
|
||||
import com.intellij.openapi.ui.popup.JBPopupFactory;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.wm.WindowManager;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.ui.components.JBList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class MultipleFilesHyperlinkInfo extends HyperlinkInfoBase implements FileHyperlinkInfo {
|
||||
private final List<VirtualFile> myVirtualFiles;
|
||||
private final int myLineNumber;
|
||||
private final Project myProject;
|
||||
|
||||
public MultipleFilesHyperlinkInfo(@NotNull List<VirtualFile> virtualFiles, int lineNumber, @NotNull Project project) {
|
||||
myVirtualFiles = virtualFiles;
|
||||
myLineNumber = lineNumber;
|
||||
myProject = project;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void navigate(@NotNull final Project project, @Nullable RelativePoint hyperlinkLocationPoint) {
|
||||
List<PsiFile> currentFiles = new ArrayList<PsiFile>();
|
||||
|
||||
AccessToken accessToken = ReadAction.start();
|
||||
try {
|
||||
for (VirtualFile file : myVirtualFiles) {
|
||||
if (!file.isValid()) continue;
|
||||
|
||||
PsiFile psiFile = PsiManager.getInstance(project).findFile(file);
|
||||
if (psiFile != null) {
|
||||
PsiElement navigationElement = psiFile.getNavigationElement(); // Sources may be downloaded.
|
||||
if (navigationElement instanceof PsiFile) {
|
||||
currentFiles.add((PsiFile)navigationElement);
|
||||
continue;
|
||||
}
|
||||
currentFiles.add(psiFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
accessToken.finish();
|
||||
}
|
||||
|
||||
if (currentFiles.isEmpty()) return;
|
||||
|
||||
if (currentFiles.size() == 1) {
|
||||
new OpenFileHyperlinkInfo(myProject, currentFiles.get(0).getVirtualFile(), myLineNumber).navigate(project);
|
||||
}
|
||||
else {
|
||||
final JBList list = new JBList(currentFiles);
|
||||
int width = WindowManager.getInstance().getFrame(project).getSize().width;
|
||||
list.setCellRenderer(new GotoFileCellRenderer(width));
|
||||
JBPopup popup = JBPopupFactory.getInstance().createListPopupBuilder(list)
|
||||
.setTitle("Choose Target File")
|
||||
.setItemChoosenCallback(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
VirtualFile file = ((PsiFile)list.getSelectedValue()).getVirtualFile();
|
||||
new OpenFileHyperlinkInfo(myProject, file, myLineNumber).navigate(project);
|
||||
}
|
||||
})
|
||||
.createPopup();
|
||||
if (hyperlinkLocationPoint != null) {
|
||||
popup.show(hyperlinkLocationPoint);
|
||||
}
|
||||
else {
|
||||
popup.showInFocusCenter();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public OpenFileDescriptor getDescriptor() {
|
||||
VirtualFile file = getPreferredFile();
|
||||
return file != null ? new OpenFileDescriptor(myProject, file, myLineNumber, 0) : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private VirtualFile getPreferredFile() {
|
||||
return ContainerUtil.getFirstItem(myVirtualFiles);
|
||||
}
|
||||
}
|
||||
@@ -65,6 +65,7 @@ import com.intellij.psi.PsiDocumentManager;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.intellij.ui.EditorNotificationPanel;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.Alarm;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.EditorPopupHandler;
|
||||
@@ -1384,10 +1385,18 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo
|
||||
return EditorHyperlinkSupport.getNextOccurrence(myEditor, hyperlinks.getHyperlinks().keySet(), delta, new Consumer<RangeHighlighter>() {
|
||||
@Override
|
||||
public void consume(RangeHighlighter next) {
|
||||
scrollTo(next.getStartOffset());
|
||||
int offset = next.getStartOffset();
|
||||
scrollTo(offset);
|
||||
final HyperlinkInfo hyperlinkInfo = hyperlinks.getHyperlinks().get(next);
|
||||
if (hyperlinkInfo != null) {
|
||||
hyperlinkInfo.navigate(myProject);
|
||||
if (hyperlinkInfo instanceof HyperlinkInfoBase) {
|
||||
VisualPosition position = myEditor.offsetToVisualPosition(offset);
|
||||
Point point = myEditor.visualPositionToXY(new VisualPosition(position.getLine() + 1, position.getColumn()));
|
||||
((HyperlinkInfoBase)hyperlinkInfo).navigate(myProject, new RelativePoint(myEditor.getContentComponent(), point));
|
||||
}
|
||||
else {
|
||||
hyperlinkInfo.navigate(myProject);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ public class RerunTestsNotification {
|
||||
return;
|
||||
}
|
||||
|
||||
GotItMessage message = GotItMessage.createMessage("Press " + shortcutText + " to rerun tests", "");
|
||||
GotItMessage message = GotItMessage.createMessage("Rerun tests with " + shortcutText, "");
|
||||
message.setDisposable(executionConsole);
|
||||
message.setCallback(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -31,6 +31,10 @@ import com.intellij.psi.PsiElement;
|
||||
public class FindInPathAction extends AnAction implements DumbAware {
|
||||
static final NotificationGroup NOTIFICATION_GROUP = NotificationGroup.toolWindowGroup("FindInPath", ToolWindowId.FIND, false);
|
||||
|
||||
{ // enabled in modal content for find in path <-> replace in path modal dialog transition
|
||||
setEnabledInModalContext(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
DataContext dataContext = e.getDataContext();
|
||||
|
||||
@@ -22,6 +22,10 @@ import com.intellij.openapi.actionSystem.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
|
||||
public class ReplaceInPathAction extends AnAction {
|
||||
{ // enabled in modal content for find in path <-> replace in path modal dialog transition
|
||||
setEnabledInModalContext(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
DataContext dataContext = e.getDataContext();
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.openapi.actionSystem.CommonDataKeys;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import com.intellij.openapi.actionSystem.LangDataKeys;
|
||||
import com.intellij.openapi.actionSystem.PlatformDataKeys;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ApplicationNamesInfo;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
@@ -114,6 +113,13 @@ public class FindInProjectUtil {
|
||||
if (model.getModuleName() == null || editor == null) {
|
||||
model.setDirectoryName(directoryName);
|
||||
model.setProjectScope(directoryName == null && module == null && !model.isCustomScope() || editor != null);
|
||||
|
||||
// for convenience set directory name to directory of current file, note that we doesn't change default projectScope
|
||||
if (directoryName == null) {
|
||||
VirtualFile virtualFile = CommonDataKeys.VIRTUAL_FILE.getData(dataContext);
|
||||
if (virtualFile != null && !virtualFile.isDirectory()) virtualFile = virtualFile.getParent();
|
||||
if (virtualFile != null) model.setDirectoryName(virtualFile.getPresentableUrl());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -454,7 +454,7 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
|
||||
SyntaxHighlighter highlighter = getHighlighter(file, lang);
|
||||
|
||||
if (highlighter == null) {
|
||||
LOG.error("Syntax highlighter is null:"+file);
|
||||
// no syntax highlighter -> no search
|
||||
return NOT_FOUND_RESULT;
|
||||
}
|
||||
|
||||
@@ -467,12 +467,9 @@ public class FindManagerImpl extends FindManager implements PersistentStateCompo
|
||||
public Set<Language> compute() {
|
||||
THashSet<Language> result = new THashSet<Language>();
|
||||
|
||||
for(Project project: ProjectManager.getInstance().getOpenProjects()) {
|
||||
FileViewProvider viewProvider = PsiManager.getInstance(project).findViewProvider(file);
|
||||
if (viewProvider != null) {
|
||||
result.addAll(viewProvider.getLanguages());
|
||||
break;
|
||||
}
|
||||
FileViewProvider viewProvider = PsiManager.getInstance(myProject).findViewProvider(file);
|
||||
if (viewProvider != null) {
|
||||
result.addAll(viewProvider.getLanguages());
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.intellij.ide.ui.search.BooleanOptionDescription;
|
||||
import com.intellij.ide.ui.search.OptionDescription;
|
||||
import com.intellij.ide.ui.search.SearchableOptionsRegistrarImpl;
|
||||
import com.intellij.ide.util.DefaultPsiElementCellRenderer;
|
||||
import com.intellij.ide.util.PropertiesComponent;
|
||||
import com.intellij.ide.util.gotoByName.*;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.actionSystem.*;
|
||||
@@ -92,6 +93,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import java.awt.*;
|
||||
import java.awt.event.*;
|
||||
@@ -105,6 +107,7 @@ import java.util.concurrent.atomic.AtomicLong;
|
||||
* @author Konstantin Bulenkov
|
||||
*/
|
||||
public class SearchEverywhereAction extends AnAction implements CustomComponentAction, DumbAware{
|
||||
public static final String SE_HISTORY_KEY = "SearchEverywhereHistory";
|
||||
public static final int SEARCH_FIELD_COLUMNS = 25;
|
||||
private static final int MAX_CLASSES = 6;
|
||||
private static final int MAX_FILES = 6;
|
||||
@@ -149,6 +152,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
private static AtomicLong ourLastTimePressed = new AtomicLong(0);
|
||||
private static AtomicBoolean showAll = new AtomicBoolean(false);
|
||||
private ArrayList<VirtualFile> myAlreadyAddedFiles = new ArrayList<VirtualFile>();
|
||||
private int myHistoryIndex = 0;
|
||||
|
||||
static {
|
||||
IdeEventQueue.getInstance().addPostprocessor(new IdeEventQueue.EventDispatcher() {
|
||||
@@ -250,8 +254,8 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
if (myBalloon != null && !myBalloon.isDisposed() && myActionEvent != null && myActionEvent.getInputEvent() instanceof MouseEvent) {
|
||||
((Graphics2D)g).setPaint(new GradientPaint(0,0, new JBColor(new Color(147, 162, 174), new Color(64, 80, 94)), 0, getHeight(),
|
||||
new JBColor(new Color(116, 128, 143), new Color(53, 65, 87))));
|
||||
final Gradient gradient = getGradientColors();
|
||||
((Graphics2D)g).setPaint(new GradientPaint(0, 0, gradient.getStartColor(), 0, getHeight(), gradient.getEndColor()));
|
||||
g.fillRect(0,0,getWidth(), getHeight());
|
||||
} else {
|
||||
super.paintComponent(g);
|
||||
@@ -299,6 +303,11 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
return panel;
|
||||
}
|
||||
|
||||
private static Gradient getGradientColors() {
|
||||
return new Gradient(
|
||||
new JBColor(new Color(101, 147, 242), new Color(64, 80, 94)),
|
||||
new JBColor(new Color(46, 111, 205), new Color(53, 65, 87)));
|
||||
}
|
||||
|
||||
public SearchEverywhereAction() {
|
||||
myRenderer = new MyListRenderer();
|
||||
@@ -511,6 +520,15 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
if (myPopup != null && myPopup.isVisible()) {
|
||||
myPopup.cancel();
|
||||
}
|
||||
|
||||
if (value instanceof BooleanOptionDescription) {
|
||||
final BooleanOptionDescription option = (BooleanOptionDescription)value;
|
||||
option.setOptionState(!option.isOptionEnabled());
|
||||
myList.revalidate();
|
||||
myList.repaint();
|
||||
return;
|
||||
}
|
||||
|
||||
AccessToken token = ApplicationManager.getApplication().acquireReadActionLock();
|
||||
try {
|
||||
if (value instanceof PsiElement) {
|
||||
@@ -531,17 +549,11 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
IdeFocusManager.getInstance(project).doWhenFocusSettlesDown(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (value instanceof BooleanOptionDescription) {
|
||||
final BooleanOptionDescription option = (BooleanOptionDescription)value;
|
||||
option.setOptionState(!option.isOptionEnabled());
|
||||
}
|
||||
else {
|
||||
Component c = comp;
|
||||
if (c == null) {
|
||||
c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
}
|
||||
GotoActionAction.openOptionOrPerformAction(value, pattern, project, c, event);
|
||||
Component c = comp;
|
||||
if (c == null) {
|
||||
c = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
|
||||
}
|
||||
GotoActionAction.openOptionOrPerformAction(value, pattern, project, c, event);
|
||||
}
|
||||
});
|
||||
return;
|
||||
@@ -588,6 +600,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
if (e == null) return;
|
||||
myContextComponent = PlatformDataKeys.CONTEXT_COMPONENT.getData(e.getDataContext());
|
||||
final Project project = e.getProject();
|
||||
Window wnd = myContextComponent != null ? SwingUtilities.windowForComponent(myContextComponent)
|
||||
: KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow();
|
||||
if (wnd == null && myContextComponent instanceof Window) {
|
||||
@@ -601,35 +614,53 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
myPopupField = new MySearchTextField();
|
||||
initSearchField(myPopupField);
|
||||
myPopupField.setOpaque(false);
|
||||
myPopupField.getTextEditor().setColumns(SEARCH_FIELD_COLUMNS);
|
||||
final JTextField editor = myPopupField.getTextEditor();
|
||||
editor.setColumns(SEARCH_FIELD_COLUMNS);
|
||||
final JPanel panel = new JPanel(new BorderLayout()) {
|
||||
@Override
|
||||
protected void paintComponent(Graphics g) {
|
||||
((Graphics2D)g).setPaint(new GradientPaint(0,0, new JBColor(new Color(147, 162, 174), new Color(64, 80, 94)), 0, getHeight(),
|
||||
new JBColor(new Color(116, 128, 143), new Color(53, 65, 87))));
|
||||
final Gradient gradient = getGradientColors();
|
||||
((Graphics2D)g).setPaint(new GradientPaint(0, 0, gradient.getStartColor(), 0, getHeight(), gradient.getEndColor()));
|
||||
g.fillRect(0, 0, getWidth(), getHeight());
|
||||
}
|
||||
};
|
||||
final JLabel title = new JLabel(" Search Everywhere: ");
|
||||
final JPanel topPanel = new NonOpaquePanel(new BorderLayout());
|
||||
title.setForeground(new JBColor(Gray._50, Gray._180));
|
||||
title.setForeground(new JBColor(Gray._240, Gray._200));
|
||||
if (SystemInfo.isMac) {
|
||||
title.setFont(title.getFont().deriveFont(Font.BOLD, title.getFont().getSize() - 1f));
|
||||
} else {
|
||||
title.setFont(title.getFont().deriveFont(Font.BOLD));
|
||||
}
|
||||
topPanel.add(title, BorderLayout.WEST);
|
||||
myNonProjectCheckBox.setForeground(new JBColor(Gray._240, Gray._200));
|
||||
myNonProjectCheckBox.setText("Include non-project items (" + getShortcut() + ")");
|
||||
topPanel.add(myNonProjectCheckBox, BorderLayout.EAST);
|
||||
panel.add(myPopupField, BorderLayout.CENTER);
|
||||
panel.add(topPanel, BorderLayout.NORTH);
|
||||
panel.setBorder(IdeBorderFactory.createEmptyBorder(3, 5, 4, 5));
|
||||
final ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, myPopupField.getTextEditor());
|
||||
final ComponentPopupBuilder builder = JBPopupFactory.getInstance().createComponentPopupBuilder(panel, editor);
|
||||
myBalloon = builder
|
||||
.setCancelOnClickOutside(true)
|
||||
.setModalContext(false)
|
||||
.setCancelCallback(new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
final String last = editor.getText().trim();
|
||||
final PropertiesComponent storage = PropertiesComponent.getInstance(project);
|
||||
final String historyString = storage.getValue(SE_HISTORY_KEY);
|
||||
List<String> history = StringUtil.isEmpty(historyString) ? new ArrayList<String>() : StringUtil.split(historyString, "\n");
|
||||
history.remove(last);
|
||||
history.add(last);
|
||||
if (history.size() > 10) {
|
||||
history = history.subList(0, 10);
|
||||
}
|
||||
storage.setValue(SE_HISTORY_KEY, StringUtil.join(history, "\n"));
|
||||
return true;
|
||||
}
|
||||
})
|
||||
.createPopup();
|
||||
|
||||
myBalloon.getContent().setBorder(new EmptyBorder(0,0,0,0));
|
||||
final Window window = WindowManager.getInstance().suggestParentWindow(e.getProject());
|
||||
|
||||
Component parent = UIUtil.findUltimateParent(window);
|
||||
@@ -656,7 +687,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
myBalloon.show(showPoint);
|
||||
initSearchActions(myBalloon, myPopupField);
|
||||
IdeFocusManager focusManager = IdeFocusManager.getInstance(e.getProject());
|
||||
focusManager.requestFocus(myPopupField.getTextEditor(), true);
|
||||
focusManager.requestFocus(editor, true);
|
||||
FeatureUsageTracker.getInstance().triggerFeatureUsed(IdeActions.ACTION_SEARCH_EVERYWHERE);
|
||||
}
|
||||
|
||||
@@ -710,6 +741,28 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
}
|
||||
}.registerCustomShortcutSet(CustomShortcutSet.fromString("ENTER"), editor, balloon);
|
||||
new DumbAwareAction(){
|
||||
@Override
|
||||
public void actionPerformed(AnActionEvent e) {
|
||||
final PropertiesComponent storage = PropertiesComponent.getInstance(e.getProject());
|
||||
final String historyString = storage.getValue(SE_HISTORY_KEY);
|
||||
if (historyString != null) {
|
||||
final List<String> history = StringUtil.split(historyString, "\n");
|
||||
if (history.size() > myHistoryIndex) {
|
||||
final String text = history.get(myHistoryIndex);
|
||||
editor.setText(text);
|
||||
editor.setCaretPosition(text.length());
|
||||
editor.moveCaretPosition(0);
|
||||
myHistoryIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(AnActionEvent e) {
|
||||
e.getPresentation().setEnabled(editor.getCaretPosition() == 0);
|
||||
}
|
||||
}.registerCustomShortcutSet(CustomShortcutSet.fromString("LEFT"), editor, balloon);
|
||||
}
|
||||
|
||||
private static class MySearchTextField extends SearchTextField implements DataProvider, Disposable {
|
||||
@@ -1460,6 +1513,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
}
|
||||
})
|
||||
.createPopup();
|
||||
myPopup.getContent().setBorder(new EmptyBorder(0,0,0,0));
|
||||
Disposer.register(myPopup, new Disposable() {
|
||||
@Override
|
||||
public void dispose() {
|
||||
@@ -1487,6 +1541,7 @@ public class SearchEverywhereAction extends AnAction implements CustomComponentA
|
||||
myRenderer.myProject = null;
|
||||
myCalcThread = null;
|
||||
myPopup = null;
|
||||
myHistoryIndex = 0;
|
||||
showAll.set(false);
|
||||
myNonProjectCheckBox.setSelected(false);
|
||||
ActionToolbarImpl.updateAllToolbarsImmediately();
|
||||
|
||||
@@ -82,6 +82,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.border.Border;
|
||||
import javax.swing.border.CompoundBorder;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
@@ -1247,6 +1248,18 @@ public abstract class ChooseByNameBase {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension size = super.getPreferredSize();
|
||||
Border border = super.getBorder();
|
||||
if (border != null && UIUtil.isUnderAquaLookAndFeel()) {
|
||||
Insets insets = border.getBorderInsets(this);
|
||||
size.height += insets.top + insets.bottom;
|
||||
size.width += insets.left + insets.right;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private KeyStroke getShortcut(String actionCodeCompletion) {
|
||||
final Shortcut[] shortcuts = KeymapManager.getInstance().getActiveKeymap().getShortcuts(actionCodeCompletion);
|
||||
|
||||
@@ -64,7 +64,7 @@ public abstract class AbstractGithubTagDownloadedProjectGenerator extends WebPro
|
||||
unpackToDir(project, new File(baseDir.getPath()), tag);
|
||||
}
|
||||
catch (GeneratorException e) {
|
||||
showErrorMessage(e.getMessage());
|
||||
showErrorMessage(project, e.getMessage());
|
||||
}
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
@Override
|
||||
@@ -149,10 +149,9 @@ public abstract class AbstractGithubTagDownloadedProjectGenerator extends WebPro
|
||||
return GithubDownloadUtil.findCacheFile(getGithubUserName(), getGithubRepositoryName(), fileName);
|
||||
}
|
||||
|
||||
private void showErrorMessage(@NotNull String message) {
|
||||
private void showErrorMessage(@NotNull Project project, @NotNull String message) {
|
||||
String fullMessage = "Error creating " + getDisplayName() + " project. " + message;
|
||||
String title = "Create " + getDisplayName() + " Project";
|
||||
Project project = null;
|
||||
Messages.showErrorDialog(project, fullMessage, title);
|
||||
}
|
||||
|
||||
|
||||
@@ -420,6 +420,10 @@ class RootIndex {
|
||||
@Nullable
|
||||
public String getPackageName(@NotNull final VirtualFile dir) {
|
||||
if (dir.isDirectory()) {
|
||||
if (FileTypeManager.getInstance().isFileIgnored(dir)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (final Map.Entry<String, HashSet<VirtualFile>> entry : myPackagePrefixRoots.entrySet()) {
|
||||
if (entry.getValue().contains(dir)) {
|
||||
return entry.getKey();
|
||||
|
||||
@@ -12,11 +12,13 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
/**
|
||||
@@ -45,13 +47,7 @@ public class ZipUtil {
|
||||
@Override
|
||||
public Boolean call() throws IOException {
|
||||
ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator();
|
||||
ZipInputStream stream = new ZipInputStream(new FileInputStream(zipArchive));
|
||||
try {
|
||||
unzip(progress, extractToDir, stream, null, null, unwrapSingleTopLevelFolder);
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
}
|
||||
unzip(progress, extractToDir, zipArchive, null, null, unwrapSingleTopLevelFolder);
|
||||
return true;
|
||||
}
|
||||
},
|
||||
@@ -73,25 +69,59 @@ public class ZipUtil {
|
||||
}
|
||||
}
|
||||
|
||||
private static File getUnzipToDir(@Nullable ProgressIndicator progress,
|
||||
@NotNull File targetDir,
|
||||
boolean unwrapSingleTopLevelFolder) throws IOException {
|
||||
if (progress != null) {
|
||||
progress.setText("Extracting...");
|
||||
}
|
||||
if (unwrapSingleTopLevelFolder) {
|
||||
return FileUtil.createTempDirectory("unzip-dir-", null);
|
||||
}
|
||||
return targetDir;
|
||||
}
|
||||
|
||||
// This method will throw IOException, if a zipArchive file isn't a valid zip archive.
|
||||
public static void unzip(@Nullable ProgressIndicator progress,
|
||||
@NotNull File targetDir,
|
||||
@NotNull File zipArchive,
|
||||
@Nullable NullableFunction<String, String> pathConvertor,
|
||||
@Nullable ContentProcessor contentProcessor,
|
||||
boolean unwrapSingleTopLevelFolder) throws IOException {
|
||||
File unzipToDir = getUnzipToDir(progress, targetDir, unwrapSingleTopLevelFolder);
|
||||
ZipFile zipFile = new ZipFile(zipArchive, ZipFile.OPEN_READ);
|
||||
try {
|
||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
ZipEntry entry = entries.nextElement();
|
||||
InputStream entryContentStream = zipFile.getInputStream(entry);
|
||||
unzipEntryToDir(progress, entry, entryContentStream, unzipToDir, pathConvertor, contentProcessor);
|
||||
entryContentStream.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
zipFile.close();
|
||||
}
|
||||
doUnwrapSingleTopLevelFolder(unwrapSingleTopLevelFolder, unzipToDir, targetDir);
|
||||
}
|
||||
|
||||
public static void unzip(@Nullable ProgressIndicator progress,
|
||||
@NotNull File targetDir,
|
||||
@NotNull ZipInputStream stream,
|
||||
@Nullable NullableFunction<String, String> pathConvertor,
|
||||
@Nullable ContentProcessor contentProcessor,
|
||||
boolean unwrapSingleTopLevelFolder) throws IOException {
|
||||
if (progress != null) {
|
||||
progress.setText("Extracting...");
|
||||
}
|
||||
File unzipToDir = targetDir;
|
||||
if (unwrapSingleTopLevelFolder) {
|
||||
unzipToDir = FileUtil.createTempDirectory("unzip-dir-", null);
|
||||
}
|
||||
|
||||
File unzipToDir = getUnzipToDir(progress, targetDir, unwrapSingleTopLevelFolder);
|
||||
ZipEntry entry;
|
||||
while ((entry = stream.getNextEntry()) != null) {
|
||||
unzipEntryToDir(progress, entry, unzipToDir, stream, pathConvertor, contentProcessor);
|
||||
unzipEntryToDir(progress, entry, stream, unzipToDir, pathConvertor, contentProcessor);
|
||||
}
|
||||
doUnwrapSingleTopLevelFolder(unwrapSingleTopLevelFolder, unzipToDir, targetDir);
|
||||
}
|
||||
|
||||
private static void doUnwrapSingleTopLevelFolder(boolean unwrapSingleTopLevelFolder,
|
||||
@NotNull File unzipToDir,
|
||||
@NotNull File targetDir) throws IOException {
|
||||
if (unwrapSingleTopLevelFolder) {
|
||||
File[] topLevelFiles = unzipToDir.listFiles();
|
||||
File dirToMove;
|
||||
@@ -110,8 +140,8 @@ public class ZipUtil {
|
||||
|
||||
private static void unzipEntryToDir(@Nullable ProgressIndicator progress,
|
||||
@NotNull final ZipEntry zipEntry,
|
||||
@NotNull final InputStream entryContentStream,
|
||||
@NotNull final File extractToDir,
|
||||
ZipInputStream stream,
|
||||
@Nullable NullableFunction<String, String> pathConvertor,
|
||||
@Nullable ContentProcessor contentProcessor) throws IOException {
|
||||
String relativeExtractPath = createRelativeExtractPath(zipEntry);
|
||||
@@ -136,14 +166,14 @@ public class ZipUtil {
|
||||
if (contentProcessor == null) {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(child);
|
||||
try {
|
||||
FileUtil.copy(stream, fileOutputStream);
|
||||
FileUtil.copy(entryContentStream, fileOutputStream);
|
||||
}
|
||||
finally {
|
||||
fileOutputStream.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
byte[] content = contentProcessor.processContent(FileUtil.loadBytes(stream), child);
|
||||
byte[] content = contentProcessor.processContent(FileUtil.loadBytes(entryContentStream), child);
|
||||
if (content != null) {
|
||||
FileOutputStream fileOutputStream = new FileOutputStream(child);
|
||||
try {
|
||||
|
||||
@@ -315,7 +315,7 @@ public class StubIndexImpl extends StubIndex implements ApplicationComponent, Pe
|
||||
|
||||
final MyIndex<K> index = (MyIndex<K>)myIndices.get(indexKey);
|
||||
try {
|
||||
return index.processAllKeys(processor, idFilter);
|
||||
return index.processAllKeys(processor, scope, idFilter);
|
||||
}
|
||||
catch (StorageException e) {
|
||||
forceRebuild(e);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -28,5 +29,5 @@ public interface AbstractIndex<Key, Value> {
|
||||
@NotNull
|
||||
ValueContainer<Value> getData(Key key) throws StorageException;
|
||||
|
||||
boolean processAllKeys(Processor<Key> processor, @Nullable IdFilter idFilter) throws StorageException;
|
||||
boolean processAllKeys(Processor<Key> processor, GlobalSearchScope scope, @Nullable IdFilter idFilter) throws StorageException;
|
||||
}
|
||||
|
||||
@@ -736,7 +736,7 @@ public class FileBasedIndexImpl extends FileBasedIndex {
|
||||
return true;
|
||||
}
|
||||
ensureUpToDate(indexId, scope.getProject(), scope);
|
||||
return index.processAllKeys(processor, idFilter);
|
||||
return index.processAllKeys(processor, scope, idFilter);
|
||||
}
|
||||
catch (StorageException e) {
|
||||
scheduleRebuild(indexId, e);
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.Processor;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -39,7 +40,7 @@ public interface IndexStorage<Key, Value> extends Flushable {
|
||||
@NotNull
|
||||
ValueContainer<Value> read(Key key) throws StorageException;
|
||||
|
||||
boolean processKeys(Processor<Key> processor, @Nullable IdFilter idFilter) throws StorageException;
|
||||
boolean processKeys(Processor<Key> processor, GlobalSearchScope scope, @Nullable IdFilter idFilter) throws StorageException;
|
||||
|
||||
Collection<Key> getKeys() throws StorageException;
|
||||
|
||||
|
||||
@@ -18,20 +18,24 @@ package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.LowMemoryWatcher;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.search.ProjectAndLibrariesScope;
|
||||
import com.intellij.psi.search.ProjectScopeImpl;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SystemProperties;
|
||||
import com.intellij.util.containers.SLRUCache;
|
||||
import com.intellij.util.io.*;
|
||||
import com.intellij.util.io.DataOutputStream;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import gnu.trove.TIntProcedure;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -44,10 +48,12 @@ import java.util.concurrent.locks.ReentrantLock;
|
||||
*/
|
||||
public final class MapIndexStorage<Key, Value> implements IndexStorage<Key, Value>{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.util.indexing.MapIndexStorage");
|
||||
private static final boolean ENABLE_CACHED_HASH_IDS = SystemProperties.getBooleanProperty("idea.index.no.cashed.hashids", true);
|
||||
private final boolean myBuildKeyHashToVirtualFileMapping;
|
||||
private PersistentMap<Key, ValueContainer<Value>> myMap;
|
||||
private PersistentBTreeEnumerator<int[]> myKeyHashToVirtualFileMapping;
|
||||
private SLRUCache<Key, ChangeTrackingValueContainer<Value>> myCache;
|
||||
private volatile int myLastScannedId;
|
||||
private final File myStorageFile;
|
||||
private final KeyDescriptor<Key> myKeyDescriptor;
|
||||
private final int myCacheSize;
|
||||
@@ -216,29 +222,58 @@ public final class MapIndexStorage<Key, Value> implements IndexStorage<Key, Valu
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processKeys(final Processor<Key> processor, final IdFilter idFilter) throws StorageException {
|
||||
public boolean processKeys(final Processor<Key> processor, GlobalSearchScope scope, final IdFilter idFilter) throws StorageException {
|
||||
l.lock();
|
||||
try {
|
||||
myCache.clear(); // this will ensure that all new keys are made into the map
|
||||
if (myBuildKeyHashToVirtualFileMapping && idFilter != null) {
|
||||
final TIntHashSet hashMaskSet = new TIntHashSet(1000);
|
||||
TIntHashSet hashMaskSet = null;
|
||||
long l = System.currentTimeMillis();
|
||||
myKeyHashToVirtualFileMapping.iterateData(new Processor<int[]>() {
|
||||
@Override
|
||||
public boolean process(int[] key) {
|
||||
if (!idFilter.containsFileId(key[1])) return true;
|
||||
hashMaskSet.add(key[0]);
|
||||
ProgressManager.checkCanceled();
|
||||
return true;
|
||||
|
||||
File fileWithCaches = getSavedProjectFileValueIds(myLastScannedId, scope);
|
||||
final boolean useCachedHashIds = ENABLE_CACHED_HASH_IDS &&
|
||||
(scope instanceof ProjectScopeImpl || scope instanceof ProjectAndLibrariesScope) &&
|
||||
fileWithCaches != null;
|
||||
int id = myKeyHashToVirtualFileMapping.getLargestId();
|
||||
|
||||
if (useCachedHashIds && id == myLastScannedId) {
|
||||
try {
|
||||
hashMaskSet = loadHashedIds(fileWithCaches);
|
||||
} catch (IOException ex) {
|
||||
LOG.info(ex);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (hashMaskSet == null) {
|
||||
if (useCachedHashIds && myLastScannedId != 0) {
|
||||
FileUtil.asyncDelete(fileWithCaches);
|
||||
}
|
||||
|
||||
hashMaskSet = new TIntHashSet(1000);
|
||||
final TIntHashSet finalHashMaskSet = hashMaskSet;
|
||||
myKeyHashToVirtualFileMapping.iterateData(new Processor<int[]>() {
|
||||
@Override
|
||||
public boolean process(int[] key) {
|
||||
if (!idFilter.containsFileId(key[1])) return true;
|
||||
finalHashMaskSet.add(key[0]);
|
||||
ProgressManager.checkCanceled();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
if (useCachedHashIds) {
|
||||
saveHashedIds(hashMaskSet, id, scope);
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Scanned keyHashToVirtualFileMapping of " + myStorageFile + " for " + (System.currentTimeMillis() - l));
|
||||
}
|
||||
final TIntHashSet finalHashMaskSet = hashMaskSet;
|
||||
return myMap.processKeys(new Processor<Key>() {
|
||||
@Override
|
||||
public boolean process(Key key) {
|
||||
if (!hashMaskSet.contains(myKeyDescriptor.getHashCode(key))) return true;
|
||||
if (!finalHashMaskSet.contains(myKeyDescriptor.getHashCode(key))) return true;
|
||||
return processor.process(key);
|
||||
}
|
||||
});
|
||||
@@ -263,11 +298,70 @@ public final class MapIndexStorage<Key, Value> implements IndexStorage<Key, Valu
|
||||
}
|
||||
}
|
||||
|
||||
private static TIntHashSet loadHashedIds(File fileWithCaches) throws IOException {
|
||||
DataInputStream inputStream = null;
|
||||
try {
|
||||
inputStream = new DataInputStream(new BufferedInputStream(new FileInputStream(fileWithCaches)));
|
||||
int capacity = DataInputOutputUtil.readINT(inputStream);
|
||||
TIntHashSet hashMaskSet = new TIntHashSet(capacity);
|
||||
while(capacity > 0) {
|
||||
hashMaskSet.add(DataInputOutputUtil.readINT(inputStream));
|
||||
--capacity;
|
||||
}
|
||||
inputStream.close();
|
||||
return hashMaskSet;
|
||||
}
|
||||
finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException ex) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void saveHashedIds(TIntHashSet hashMaskSet, int largestId, GlobalSearchScope scope) {
|
||||
File newFileWithCaches = getSavedProjectFileValueIds(largestId, scope);
|
||||
assert newFileWithCaches != null;
|
||||
DataOutputStream stream = null;
|
||||
|
||||
try {
|
||||
stream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(newFileWithCaches)));
|
||||
DataInputOutputUtil.writeINT(stream, hashMaskSet.size());
|
||||
final DataOutputStream finalStream = stream;
|
||||
boolean result = hashMaskSet.forEach(new TIntProcedure() {
|
||||
@Override
|
||||
public boolean execute(int value) {
|
||||
try {
|
||||
DataInputOutputUtil.writeINT(finalStream, value);
|
||||
return true;
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (result) myLastScannedId = largestId;
|
||||
} catch (IOException ex) {}
|
||||
finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException ex) {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable File getSavedProjectFileValueIds(int id, GlobalSearchScope scope) {
|
||||
Project project = scope.getProject();
|
||||
if (project == null) return null;
|
||||
return new File(myStorageFile.getPath() + ".project."+project.hashCode() + "."+id + "." + scope.isSearchInLibraries());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Collection<Key> getKeys() throws StorageException {
|
||||
List<Key> keys = new ArrayList<Key>();
|
||||
processKeys(new CommonProcessors.CollectProcessor<Key>(keys), null);
|
||||
processKeys(new CommonProcessors.CollectProcessor<Key>(keys), null, null);
|
||||
return keys;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Factory;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.io.PersistentHashMap;
|
||||
import gnu.trove.THashMap;
|
||||
@@ -155,11 +156,11 @@ public class MapReduceIndex<Key, Value, Input> implements UpdatableIndex<Key,Val
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processAllKeys(Processor<Key> processor, IdFilter idFilter) throws StorageException {
|
||||
public boolean processAllKeys(Processor<Key> processor, GlobalSearchScope scope, IdFilter idFilter) throws StorageException {
|
||||
final Lock lock = getReadLock();
|
||||
try {
|
||||
lock.lock();
|
||||
return myStorage.processKeys(processor, idFilter);
|
||||
return myStorage.processKeys(processor, scope, idFilter);
|
||||
}
|
||||
finally {
|
||||
lock.unlock();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.intellij.util.indexing;
|
||||
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.util.CommonProcessors;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -101,12 +102,12 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
@Override
|
||||
public Collection<Key> getKeys() throws StorageException {
|
||||
final Set<Key> keys = new HashSet<Key>();
|
||||
processKeys(new CommonProcessors.CollectProcessor<Key>(keys), null);
|
||||
processKeys(new CommonProcessors.CollectProcessor<Key>(keys), null, null);
|
||||
return keys;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean processKeys(final Processor<Key> processor, IdFilter idFilter) throws StorageException {
|
||||
public boolean processKeys(final Processor<Key> processor, GlobalSearchScope scope, IdFilter idFilter) throws StorageException {
|
||||
final Set<Key> stopList = new HashSet<Key>();
|
||||
|
||||
Processor<Key> decoratingProcessor = new Processor<Key>() {
|
||||
@@ -128,7 +129,7 @@ public class MemoryIndexStorage<Key, Value> implements IndexStorage<Key, Value>
|
||||
}
|
||||
stopList.add(key);
|
||||
}
|
||||
return myBackendStorage.processKeys(stopList.size() == 0 && myMap.size() == 0 ? processor : decoratingProcessor, idFilter);
|
||||
return myBackendStorage.processKeys(stopList.size() == 0 && myMap.size() == 0 ? processor : decoratingProcessor, scope, idFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -3,11 +3,13 @@ package com.intellij.platform.templates.github;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import com.intellij.util.io.TestFileSystemBuilder;
|
||||
import junit.framework.Assert;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import static com.intellij.util.io.TestFileSystemBuilder.fs;
|
||||
@@ -51,6 +53,41 @@ public class ZipUtilTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleUnzipUsingFile() throws Exception {
|
||||
File tempDir = FileUtil.createTempDirectory("unzip-test-", null);
|
||||
File simpleZipFile = new File(getZipParentDir(), "simple.zip");
|
||||
ZipUtil.unzip(null, tempDir, simpleZipFile, null, null, true);
|
||||
checkFileStructure(tempDir,
|
||||
fs()
|
||||
.file("a.txt")
|
||||
.dir("dir").file("b.txt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSingleRootDirUnzipUsingFile() throws Exception {
|
||||
File tempDir = FileUtil.createTempDirectory("unzip-test-", null);
|
||||
File simpleZipFile = new File(getZipParentDir(), "single-root-dir-archive.zip");
|
||||
ZipUtil.unzip(null, tempDir, simpleZipFile, null, null, true);
|
||||
checkFileStructure(tempDir,
|
||||
fs()
|
||||
.file("a.txt")
|
||||
.dir("dir").file("b.txt"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpectedFailureOnBrokenZipArchive() throws Exception {
|
||||
File tempDir = FileUtil.createTempDirectory("unzip-test-", null);
|
||||
File file = new File(getZipParentDir(), "invalid-archive.zip");
|
||||
try {
|
||||
ZipUtil.unzip(null, tempDir, file, null, null, true);
|
||||
Assert.fail("Zip archive is broken, but it was unzipped without exceptions.");
|
||||
}
|
||||
catch (IOException e) {
|
||||
// expected exception
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkFileStructure(@NotNull File parentDir, @NotNull TestFileSystemBuilder expected) {
|
||||
expected.build().assertDirectoryEqual(parentDir);
|
||||
}
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
<orderEntry type="library" name="proxy-vole" level="project" />
|
||||
<orderEntry type="module" module-name="analysis-api" exported="" />
|
||||
<orderEntry type="module" module-name="editor-ui-api" exported="" />
|
||||
<orderEntry type="library" name="pty4j" level="project" />
|
||||
<orderEntry type="library" name="Guava" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.execution.configurations;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.execution.CommandLineUtil;
|
||||
import com.intellij.execution.ExecutionException;
|
||||
import com.intellij.execution.Platform;
|
||||
@@ -26,10 +27,12 @@ import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.UserDataHolder;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.EnvironmentUtil;
|
||||
import com.intellij.util.PlatformUtils;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.CaseInsensitiveStringHashingStrategy;
|
||||
import com.pty4j.PtyProcess;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -62,8 +65,10 @@ public class GeneralCommandLine implements UserDataHolder {
|
||||
private Charset myCharset = CharsetToolkit.getDefaultSystemCharset();
|
||||
private boolean myRedirectErrorStream = false;
|
||||
private Map<Object, Object> myUserData = null;
|
||||
private boolean myStartProcessWithPty = false;
|
||||
|
||||
public GeneralCommandLine() { }
|
||||
public GeneralCommandLine() {
|
||||
}
|
||||
|
||||
public GeneralCommandLine(@NotNull String... command) {
|
||||
this(Arrays.asList(command));
|
||||
@@ -107,13 +112,17 @@ public class GeneralCommandLine implements UserDataHolder {
|
||||
return myEnvParams;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #getEnvironment()} (to remove in IDEA 14) */
|
||||
/**
|
||||
* @deprecated use {@link #getEnvironment()} (to remove in IDEA 14)
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public Map<String, String> getEnvParams() {
|
||||
return getEnvironment();
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #getEnvironment()} (to remove in IDEA 14) */
|
||||
/**
|
||||
* @deprecated use {@link #getEnvironment()} (to remove in IDEA 14)
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public void setEnvParams(@Nullable Map<String, String> envParams) {
|
||||
myEnvParams.clear();
|
||||
@@ -126,7 +135,9 @@ public class GeneralCommandLine implements UserDataHolder {
|
||||
myPassParentEnvironment = passParentEnvironment;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #setPassParentEnvironment(boolean)} (to remove in IDEA 14) */
|
||||
/**
|
||||
* @deprecated use {@link #setPassParentEnvironment(boolean)} (to remove in IDEA 14)
|
||||
*/
|
||||
@SuppressWarnings({"unused", "SpellCheckingInspection"})
|
||||
public void setPassParentEnvs(boolean passParentEnvironment) {
|
||||
setPassParentEnvironment(passParentEnvironment);
|
||||
@@ -136,6 +147,15 @@ public class GeneralCommandLine implements UserDataHolder {
|
||||
return myPassParentEnvironment;
|
||||
}
|
||||
|
||||
/**
|
||||
* If argument is true the process created with Pseudo-Terminal (PTY).
|
||||
* This works only on Unix. On Windows the option is ignored.
|
||||
*/
|
||||
public GeneralCommandLine withPty(boolean startProcessWithPty) {
|
||||
myStartProcessWithPty = startProcessWithPty;
|
||||
return this;
|
||||
}
|
||||
|
||||
public void addParameters(final String... parameters) {
|
||||
for (String parameter : parameters) {
|
||||
addParameter(parameter);
|
||||
@@ -235,11 +255,16 @@ public class GeneralCommandLine implements UserDataHolder {
|
||||
}
|
||||
|
||||
try {
|
||||
ProcessBuilder builder = new ProcessBuilder(commands);
|
||||
setupEnvironment(builder.environment());
|
||||
builder.directory(myWorkDirectory);
|
||||
builder.redirectErrorStream(myRedirectErrorStream);
|
||||
return builder.start();
|
||||
if (myStartProcessWithPty && SystemInfo.isUnix) {
|
||||
try {
|
||||
return startProcessWithPty(commands);
|
||||
}
|
||||
catch (Exception e) {
|
||||
LOG.error("Couldn't run process with PTY", e);
|
||||
}
|
||||
}
|
||||
|
||||
return startProcess(commands);
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.warn(e);
|
||||
@@ -247,6 +272,23 @@ public class GeneralCommandLine implements UserDataHolder {
|
||||
}
|
||||
}
|
||||
|
||||
private Process startProcessWithPty(List<String> commands) throws IOException {
|
||||
Map<String, String> env = Maps.newHashMap();
|
||||
setupEnvironment(env);
|
||||
if (myRedirectErrorStream) {
|
||||
LOG.error("Launching process with PTY and redirected error stream is unsupported yet");
|
||||
}
|
||||
return PtyProcess.exec(ArrayUtil.toStringArray(commands), env, myWorkDirectory.getPath(), true);
|
||||
}
|
||||
|
||||
private Process startProcess(List<String> commands) throws IOException {
|
||||
ProcessBuilder builder = new ProcessBuilder(commands);
|
||||
setupEnvironment(builder.environment());
|
||||
builder.directory(myWorkDirectory);
|
||||
builder.redirectErrorStream(myRedirectErrorStream);
|
||||
return builder.start();
|
||||
}
|
||||
|
||||
private void checkWorkingDirectory() throws ExecutionException {
|
||||
if (myWorkDirectory == null) {
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.filters;
|
||||
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
public abstract class HyperlinkInfoBase implements HyperlinkInfo {
|
||||
public abstract void navigate(@NotNull Project project, @Nullable RelativePoint hyperlinkLocationPoint);
|
||||
|
||||
@Override
|
||||
public void navigate(Project project) {
|
||||
navigate(project, null);
|
||||
}
|
||||
}
|
||||
@@ -375,6 +375,18 @@ public class SearchTextField extends JPanel {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dimension getPreferredSize() {
|
||||
Dimension size = super.getPreferredSize();
|
||||
Border border = super.getBorder();
|
||||
if (border != null && UIUtil.isUnderAquaLookAndFeel()) {
|
||||
Insets insets = border.getBorderInsets(this);
|
||||
size.height += insets.top + insets.bottom;
|
||||
size.width += insets.left + insets.right;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
protected Runnable createItemChosenCallback(final JList list) {
|
||||
return new Runnable() {
|
||||
public void run() {
|
||||
|
||||
@@ -17,7 +17,6 @@ package com.intellij.ui.components;
|
||||
|
||||
import com.intellij.ui.Gray;
|
||||
import com.intellij.ui.JBColor;
|
||||
import com.intellij.util.ui.GraphicsUtil;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
|
||||
import javax.swing.*;
|
||||
@@ -67,6 +66,8 @@ public class OnOffButton extends JToggleButton {
|
||||
|
||||
@SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass", "UnusedDeclaration"})
|
||||
public static ComponentUI createUI(JComponent c) {
|
||||
c.setOpaque(false);
|
||||
c.setAlignmentY(0.5f);
|
||||
return new OnOffButtonUI((OnOffButton)c);
|
||||
}
|
||||
|
||||
@@ -92,31 +93,33 @@ public class OnOffButton extends JToggleButton {
|
||||
h--;
|
||||
}
|
||||
Graphics2D g = ((Graphics2D)gr);
|
||||
GraphicsUtil.setupAAPainting(g);
|
||||
g.translate(1,1);
|
||||
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||
int xOff = (myButton.getWidth() - w) / 2;
|
||||
int yOff = (myButton.getHeight() - h) / 2;
|
||||
g.translate(xOff, yOff);
|
||||
if (button.isSelected()) {
|
||||
g.setColor(new JBColor(new Color(57, 113, 238), new Color(13, 41, 62)));
|
||||
g.fillRoundRect(0, 0, w, h, h, h);
|
||||
g.setColor(UIUtil.getBorderColor());
|
||||
g.drawRoundRect(0, 0, w, h, h, h);
|
||||
g.setColor(new JBColor(Gray._220, Gray._128));
|
||||
g.fillOval(w - h + 1, 1, h - 1, h - 1);
|
||||
g.setColor(new JBColor(new Color(74, 146, 73), new Color(77, 105, 76)));
|
||||
g.fillRoundRect(0, 0, w, h, 5, 5);
|
||||
g.setColor(new JBColor(Gray._192, Gray._80));
|
||||
g.drawRoundRect(0, 0, w, h, 5, 5);
|
||||
g.setColor(new JBColor(Gray._200, Gray._100));
|
||||
g.fillRoundRect(w - h, 1, h, h-1, 3, 3);
|
||||
g.setColor(UIUtil.getListForeground(true));
|
||||
g.drawString(button.getOnText(), h/2, h - 4);
|
||||
} else {
|
||||
g.setColor(UIUtil.getPanelBackground());
|
||||
g.fillRoundRect(0, 0, w, h, h, h);
|
||||
g.setColor(UIUtil.getBorderColor());
|
||||
g.drawRoundRect(0, 0, w, h, h, h);
|
||||
g.fillRoundRect(0, 0, w, h, 5, 5);
|
||||
g.setColor(new JBColor(Gray._192, Gray._100));
|
||||
g.drawRoundRect(0, 0, w, h, 5, 5);
|
||||
g.setColor(UIUtil.getLabelDisabledForeground());
|
||||
g.drawString(button.getOffText(), h + 4 , h - 4);
|
||||
g.setColor(UIUtil.getBorderColor());
|
||||
g.setPaint(new GradientPaint(h,0, Gray._178, 0,h, Gray._240));
|
||||
g.fillOval(0, 0, h, h);
|
||||
g.setColor(UIUtil.getBorderColor());
|
||||
g.drawOval(0, 0, h, h);
|
||||
g.setPaint(new GradientPaint(h, 0, new JBColor(Gray._158, Gray._100), 0, h, new JBColor(Gray._210, Gray._100)));
|
||||
g.fillRoundRect(0, 0, h, h, 3, 3);
|
||||
// g.setColor(UIUtil.getBorderColor());
|
||||
// g.drawOval(0, 0, h, h);
|
||||
}
|
||||
g.translate(-1, -1);
|
||||
g.translate(-xOff, -yOff);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -129,6 +129,19 @@ public class NetUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static int tryToFindAvailableSocketPort(int defaultPort) {
|
||||
try {
|
||||
return findAvailableSocketPort();
|
||||
}
|
||||
catch (IOException ignored) {
|
||||
return defaultPort;
|
||||
}
|
||||
}
|
||||
|
||||
public static int tryToFindAvailableSocketPort() {
|
||||
return tryToFindAvailableSocketPort(-1);
|
||||
}
|
||||
|
||||
public static int[] findAvailableSocketPorts(int capacity) throws IOException {
|
||||
final int[] ports = new int[capacity];
|
||||
final ServerSocket[] sockets = new ServerSocket[capacity];
|
||||
|
||||
@@ -4,9 +4,11 @@ import com.intellij.openapi.diagnostic.Attachment;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileEditor.impl.LoadTextUtil;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
|
||||
@@ -26,6 +28,20 @@ public class AttachmentFactory {
|
||||
file.getFileType().isBinary() ? "File is binary" : LoadTextUtil.loadText(file).toString());
|
||||
}
|
||||
|
||||
public static Attachment createAttachment(@NotNull File file, boolean isBinary) {
|
||||
byte[] bytes = getBytes(file);
|
||||
return new Attachment(file.getPath(), bytes, isBinary ? "File is binary" : new String(bytes));
|
||||
}
|
||||
|
||||
private static byte[] getBytes(File file) {
|
||||
try {
|
||||
return FileUtil.loadFileBytes(file);
|
||||
}
|
||||
catch (IOException e) {
|
||||
return Attachment.getBytes(MessageFormat.format(ERROR_MESSAGE_PATTERN, e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] getBytes(VirtualFile file) {
|
||||
try {
|
||||
return file.contentsToByteArray();
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.intellij.execution.impl;
|
||||
import com.intellij.execution.filters.Filter;
|
||||
import com.intellij.execution.filters.FilterMixin;
|
||||
import com.intellij.execution.filters.HyperlinkInfo;
|
||||
import com.intellij.execution.filters.HyperlinkInfoBase;
|
||||
import com.intellij.ide.OccurenceNavigator;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
@@ -36,6 +37,7 @@ import com.intellij.openapi.editor.markup.TextAttributes;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.pom.NavigatableAdapter;
|
||||
import com.intellij.ui.awt.RelativePoint;
|
||||
import com.intellij.util.BeforeAfter;
|
||||
import com.intellij.util.Consumer;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -87,7 +89,12 @@ public class EditorHyperlinkSupport {
|
||||
if (range != null) {
|
||||
final HyperlinkInfo info = myHighlighterToMessageInfoMap.get(range);
|
||||
if (info != null) {
|
||||
info.navigate(project);
|
||||
if (info instanceof HyperlinkInfoBase) {
|
||||
((HyperlinkInfoBase)info).navigate(project, new RelativePoint(mouseEvent));
|
||||
}
|
||||
else {
|
||||
info.navigate(project);
|
||||
}
|
||||
linkFollowed(editor, getHyperlinks().keySet(), range);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,9 +490,9 @@ public class Switcher extends AnAction implements DumbAware {
|
||||
this.add(toolWindows, BorderLayout.WEST);
|
||||
if (filesModel.size() > 0) {
|
||||
files.setAlignmentY(1f);
|
||||
if (files.getModel().getSize() > 30) {
|
||||
if (files.getModel().getSize() > 20) {
|
||||
final JScrollPane pane = ScrollPaneFactory.createScrollPane(files, true);
|
||||
pane.setPreferredSize(new Dimension(files.getPreferredSize().width + 10, 30 * 20));
|
||||
pane.setPreferredSize(new Dimension(files.getPreferredSize().width + 10, 20 * 20));
|
||||
pane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
|
||||
this.add(pane, BorderLayout.EAST);
|
||||
} else {
|
||||
@@ -556,16 +556,9 @@ public class Switcher extends AnAction implements DumbAware {
|
||||
}.registerCustomShortcutSet(CustomShortcutSet.fromString("ESCAPE"), this, myPopup);
|
||||
}
|
||||
|
||||
Component comp = null;
|
||||
final EditorWindow result = FileEditorManagerEx.getInstanceEx(project).getActiveWindow().getResult();
|
||||
if (result != null) {
|
||||
comp = result.getOwner();
|
||||
}
|
||||
if (comp == null) {
|
||||
comp = ideFrame.getContentPane();
|
||||
}
|
||||
final Window window = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusedWindow();
|
||||
myAlarm = new Alarm(Alarm.ThreadToUse.SWING_THREAD, myPopup);
|
||||
myPopup.showInCenterOf(comp);
|
||||
myPopup.showInCenterOf(window);
|
||||
}
|
||||
|
||||
|
||||
@@ -668,48 +661,67 @@ public class Switcher extends AnAction implements DumbAware {
|
||||
}
|
||||
|
||||
private void closeTabOrToolWindow() {
|
||||
final Object value = getSelectedList().getSelectedValue();
|
||||
if (value instanceof FileInfo) {
|
||||
final FileInfo info = (FileInfo)value;
|
||||
final VirtualFile virtualFile = info.first;
|
||||
final FileEditorManagerImpl editorManager = ((FileEditorManagerImpl)FileEditorManager.getInstance(project));
|
||||
final JList jList = getSelectedList();
|
||||
final EditorWindow wnd = findAppropriateWindow(info);
|
||||
if (wnd == null) {
|
||||
editorManager.closeFile(virtualFile, false, false);
|
||||
} else {
|
||||
editorManager.closeFile(virtualFile, wnd, false);
|
||||
}
|
||||
final int selectedIndex = jList.getSelectedIndex();
|
||||
final IdeFocusManager focusManager = IdeFocusManager.getInstance(project);
|
||||
myAlarm.addRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
focusManager.requestFocus(SwitcherPanel.this, true);
|
||||
final int[] selected = getSelectedList().getSelectedIndices();
|
||||
Arrays.sort(selected);
|
||||
int selectedIndex = 0;
|
||||
for (int i = selected.length - 1; i>=0; i--) {
|
||||
selectedIndex = selected[i];
|
||||
Object value = getSelectedList().getModel().getElementAt(selectedIndex);
|
||||
if (value instanceof FileInfo) {
|
||||
final FileInfo info = (FileInfo)value;
|
||||
final VirtualFile virtualFile = info.first;
|
||||
final FileEditorManagerImpl editorManager = ((FileEditorManagerImpl)FileEditorManager.getInstance(project));
|
||||
final JList jList = getSelectedList();
|
||||
final EditorWindow wnd = findAppropriateWindow(info);
|
||||
if (wnd == null) {
|
||||
editorManager.closeFile(virtualFile, false, false);
|
||||
}
|
||||
else {
|
||||
editorManager.closeFile(virtualFile, wnd, false);
|
||||
}
|
||||
|
||||
final IdeFocusManager focusManager = IdeFocusManager.getInstance(project);
|
||||
myAlarm.cancelAllRequests();
|
||||
myAlarm.addRequest(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
focusManager.requestFocus(SwitcherPanel.this, true);
|
||||
}
|
||||
}, 300);
|
||||
if (jList.getModel().getSize() == 1) {
|
||||
goLeft();
|
||||
removeElementAt(jList, selectedIndex);
|
||||
this.remove(jList);
|
||||
this.remove(separator);
|
||||
final Dimension size = toolWindows.getSize();
|
||||
myPopup.setSize(new Dimension(size.width, myPopup.getSize().height));
|
||||
}
|
||||
else {
|
||||
removeElementAt(jList, selectedIndex);
|
||||
jList.setSize(jList.getPreferredSize());
|
||||
}
|
||||
if (isPinnedMode()) {
|
||||
EditorHistoryManager.getInstance(project).removeFile(virtualFile);
|
||||
}
|
||||
}, 300);
|
||||
if (jList.getModel().getSize() == 1) {
|
||||
goLeft();
|
||||
removeElementAt(jList, selectedIndex);
|
||||
this.remove(jList);
|
||||
this.remove(separator);
|
||||
final Dimension size = toolWindows.getSize();
|
||||
myPopup.setSize(new Dimension(size.width, myPopup.getSize().height));
|
||||
} else {
|
||||
goForward();
|
||||
removeElementAt(jList, selectedIndex);
|
||||
jList.setSize(jList.getPreferredSize());
|
||||
}
|
||||
pack();
|
||||
} else if (value instanceof ToolWindow) {
|
||||
final ToolWindow toolWindow = (ToolWindow)value;
|
||||
if (twManager instanceof ToolWindowManagerImpl) {
|
||||
ToolWindowManagerImpl manager = (ToolWindowManagerImpl)twManager;
|
||||
manager.hideToolWindow(ids.get(toolWindow), false, false);
|
||||
} else {
|
||||
toolWindow.hide(null);
|
||||
else if (value instanceof ToolWindow) {
|
||||
final ToolWindow toolWindow = (ToolWindow)value;
|
||||
if (twManager instanceof ToolWindowManagerImpl) {
|
||||
ToolWindowManagerImpl manager = (ToolWindowManagerImpl)twManager;
|
||||
manager.hideToolWindow(ids.get(toolWindow), false, false);
|
||||
}
|
||||
else {
|
||||
toolWindow.hide(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
pack();
|
||||
myPopup.getContent().revalidate();
|
||||
myPopup.getContent().repaint();
|
||||
if (getSelectedList().getModel().getSize() > selectedIndex) {
|
||||
getSelectedList().setSelectedIndex(selectedIndex);
|
||||
getSelectedList().ensureIndexIsVisible(selectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
private static void removeElementAt(JList jList, int index) {
|
||||
|
||||
@@ -34,7 +34,7 @@ public class DarculaTextBorder implements Border, UIResource {
|
||||
public Insets getBorderInsets(Component c) {
|
||||
int vOffset = c instanceof JPasswordField ? 3 : 4;
|
||||
if (DarculaTextFieldUI.isSearchField(c)) {
|
||||
vOffset++;
|
||||
vOffset += 2;
|
||||
}
|
||||
if (DarculaTextFieldUI.isSearchFieldWithHistoryPopup(c)) {
|
||||
return new InsetsUIResource(vOffset, 7 + 16 + 3, vOffset, 7 + 16);
|
||||
|
||||
@@ -17,33 +17,30 @@ package com.intellij.openapi.components.impl.stores;
|
||||
|
||||
import com.intellij.openapi.components.StateStorage;
|
||||
import com.intellij.openapi.components.StateStorageException;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.io.fs.IFile;
|
||||
import gnu.trove.THashMap;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mike
|
||||
*/
|
||||
public class CompoundSaveSession {
|
||||
private final Map<StateStorage, StateStorage.SaveSession> mySaveSessions = new HashMap<StateStorage, StateStorage.SaveSession>();
|
||||
private final Map<StateStorage, StateStorage.SaveSession> mySaveSessions = new THashMap<StateStorage, StateStorage.SaveSession>();
|
||||
|
||||
public CompoundSaveSession(final CompoundExternalizationSession compoundExternalizationSession) {
|
||||
final Collection<StateStorage> stateStorages = compoundExternalizationSession.getStateStorages();
|
||||
|
||||
for (StateStorage stateStorage : stateStorages) {
|
||||
for (StateStorage stateStorage : compoundExternalizationSession.getStateStorages()) {
|
||||
mySaveSessions.put(stateStorage, stateStorage.startSave(compoundExternalizationSession.getExternalizationSession(stateStorage)));
|
||||
}
|
||||
}
|
||||
|
||||
public List<IFile> getAllStorageFilesToSave() throws StateStorageException {
|
||||
List<IFile> result = new ArrayList<IFile>();
|
||||
|
||||
for (StateStorage stateStorage : mySaveSessions.keySet()) {
|
||||
final StateStorage.SaveSession saveSession = mySaveSessions.get(stateStorage);
|
||||
|
||||
List<IFile> result = new SmartList<IFile>();
|
||||
for (StateStorage.SaveSession saveSession : mySaveSessions.values()) {
|
||||
result.addAll(saveSession.getStorageFilesToSave());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -56,11 +53,11 @@ public class CompoundSaveSession {
|
||||
public void finishSave() {
|
||||
RuntimeException re = null;
|
||||
for (StateStorage stateStorage : mySaveSessions.keySet()) {
|
||||
final StateStorage.SaveSession saveSession = mySaveSessions.get(stateStorage);
|
||||
try {
|
||||
stateStorage.finishSave(saveSession);
|
||||
} catch(RuntimeException t) {
|
||||
re = t;
|
||||
stateStorage.finishSave(mySaveSessions.get(stateStorage));
|
||||
}
|
||||
catch (RuntimeException e) {
|
||||
re = e;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,11 +71,10 @@ public class CompoundSaveSession {
|
||||
}
|
||||
|
||||
public List<IFile> getAllStorageFiles() {
|
||||
List<IFile> result = new ArrayList<IFile>();
|
||||
List<IFile> result = new SmartList<IFile>();
|
||||
for (StateStorage.SaveSession saveSession : mySaveSessions.values()) {
|
||||
result.addAll(saveSession.getAllStorageFiles());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||