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

This commit is contained in:
Kirill Kalishev
2011-02-07 20:31:07 +03:00
197 changed files with 2788 additions and 1623 deletions
+11
View File
@@ -0,0 +1,11 @@
<component name="libraryTable">
<library name="JPS">
<CLASSES>
<root url="jar://$PROJECT_DIR$/build/lib/gant/lib/jps.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES>
<root url="jar://$PROJECT_DIR$/build/lib/gant/jps-sources.zip!/" />
</SOURCES>
</library>
</component>
+1
View File
@@ -7,6 +7,7 @@
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="Groovy" level="project" />
<orderEntry type="library" name="Ant" level="project" />
<orderEntry type="library" name="JPS" level="project" />
</component>
</module>
+23 -13
View File
@@ -27,7 +27,7 @@ def String getLibraryName(Library lib) {
def name = lib.name
if (name.startsWith("moduleLibrary#")) {
if (lib.classpath.size() != 1) {
project.error("Non-single entry module library $name: $lib.classpath");
project.warning("Non-single entry module library $name: $lib.classpath");
}
String filePath = lib.classpath[0]
return filePath.substring(filePath.lastIndexOf('/')+1)
@@ -72,24 +72,32 @@ binding.setVariable("checkLibLicensesAndGenerateTable", {String filePath ->
})
binding.setVariable("generateLicensesTable", {String filePath ->
Set<Module> modules = project.modules.values().findAll {it["used"] != null}
Set<String> usedLibraries = [] as Set
modules.each {
it.getClasspath(ClasspathKind.PRODUCTION_RUNTIME).each {item ->
Set<Module> usedModules = project.modules.values().findAll {it["used"] != null}
Map<String, String> usedLibraries = [:]
usedModules.each {Module module ->
module.getClasspath(ClasspathKind.PRODUCTION_RUNTIME).each {item ->
if (item instanceof Library) {
usedLibraries << getLibraryName(item)
usedLibraries[getLibraryName(item)] = module
}
}
}
def licenses = licensesList.findAll {usedLibraries.contains(it.libraryName) }
List<String> lines = licenses.collect { LibraryLicense lib ->
def licenses = licensesList.findAll {usedLibraries.containsKey(it.libraryName) }
project.info("Generating licenses table")
project.info("Used libraries:")
List<String> lines = []
licenses.each { LibraryLicense lib ->
def name = lib.url != null ? "[$lib.name|$lib.url]" : lib.name
def license = lib.licenseUrl != null ? "[$lib.license|$lib.licenseUrl]" : lib.license
return "|$name| $lib.version|$license|".toString()
project.info(" $lib.libraryName (in module ${usedLibraries[lib.libraryName]})")
lines << "|$name| $lib.version|$license|".toString()
}
lines.sort(String.CASE_INSENSITIVE_ORDER)
//project.info("Unused libraries:")
//licensesList.findAll {!usedLibraries.containsKey(it.libraryName)}.each {LibraryLicense lib ->
// project.info(" $lib.libraryName")
//}
lines.sort(String.CASE_INSENSITIVE_ORDER)
FileWriter out = new FileWriter(filePath)
out.println("|| Software || Version || License ||")
lines.each {
@@ -108,12 +116,13 @@ libraryLicense(name: "Apache Commons BeanUtils", libraryName: "commons-beanutils
libraryLicense(name: "Apache Commons Codec", libraryName: "commons-codec", version: "1.3", license: "Apache 2.0", url: "http://commons.apache.org/codec/", licenseUrl: "http://commons.apache.org/license.html")
libraryLicense(name: "Apache Commons Collections", libraryName: "commons-collections", version: "3.1", license: "Apache 2.0", url: "http://commons.apache.org/collections/", licenseUrl: "http://commons.apache.org/license.html")
libraryLicense(name: "Apache Commons HTTPClient", libraryName: "http-client-3.1", version: "3.1&nbsp; (with patch by JetBrains)", license: "Apache 2.0", url: "http://hc.apache.org/httpclient-3.x")
libraryLicense(name: "Apache Commons Net", libraryName: "commons-net", version: "2.0", license: "Apache 2.0", url: "http://commons.apache.org/net/")
libraryLicense(name: "Apache Commons Lang", libraryName: "commons-lang", version: "2.4", license: "Apache 2.0", url: "http://commons.apache.org/lang/", licenseUrl: "http://commons.apache.org/lang/license.html")
libraryLicense(name: "Apache Commons Logging", libraryName: "commons-logging", version: "1.1.1", license: "Apache 2.0", url: "http://commons.apache.org/logging/")
libraryLicense(name: "Apache Lucene", libraryName: "lucene-core-2.3.0.jar", version: "2.3.0", license: "Apache 2.0", url: "http://lucene.apache.org/java")
libraryLicense(name: "Automaton", libraryName: "automaton.jar", version: "1.11", license: "BSD", url: "http://www.brics.dk/automaton/", licenseUrl: "http://www.opensource.org/licenses/bsd-license.php")
libraryLicense(name: "DTDParser", version: "1.13", license: "LGPL", url: "http://sourceforge.net/projects/dtdparser/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1")
libraryLicense(name: "Ganymed", version: "bundled with SVNKit", license: "BSD", url: "http://www.ganymed.ethz.ch/ssh2/", licenseUrl: "http://www.ganymed.ethz.ch/ssh2/LICENSE.txt")
libraryLicense(name: "Ganymed", version: "bundled with SVNKit", libraryName: "svnkit.jar", license: "BSD", url: "http://www.ganymed.ethz.ch/ssh2/", licenseUrl: "http://www.ganymed.ethz.ch/ssh2/LICENSE.txt")
libraryLicense(name: "Guava", version: "R6", license: "Apache 2.0", url: "http://code.google.com/p/guava-libraries/", licenseUrl: "http://ant.apache.org/license.html")
libraryLicense(name: "Gradle API", libraryName: "gradle-open-api-0.8.jar", version: "0.8", license: "Apache 2.0", url: "http://www.gradle.org/")
libraryLicense(name: "Groovy", version: "1.7.3", license: "Apache 2.0", url: "http://groovy.codehaus.org/")
@@ -123,7 +132,7 @@ libraryLicense(name: "JavaCVS", version: "no version number available (with patc
libraryLicense(name: "JAXB", libraryName: "JAXB", version: "2.1.10", license: "CDDL 1.1 & GPL 2", url: "http://jaxb.java.net/", licenseUrl: "http://glassfish.java.net/public/CDDL+GPL_1_1.html")
libraryLicense(name: "Jaxen", version: "", license: "modified Apache", url: "http://www.jaxen.org/", licenseUrl: "http://www.jaxen.org/license.html")
libraryLicense(name: "JavaHelp", version: "2.0_02", license: "included as license/javahelp_license.html in IntelliJ IDEA distribution", url: "http://java.sun.com/products/javahelp/")
libraryLicense(name: "JCIP Annotations", libraryName: "jcip-annotations.jar", license: "Creative Commons Attribution License", url: "http://www.jcip.net", licenseUrl: "http://creativecommons.org/licenses/by/2.5")
libraryLicense(name: "JCIP Annotations", libraryName: "jcip", license: "Creative Commons Attribution License", url: "http://www.jcip.net", licenseUrl: "http://creativecommons.org/licenses/by/2.5")
libraryLicense(name: "JDOM", version: "1.1 (with patches by JetBrains)", license: "modified Apache", url: "http://www.jdom.org/", licenseUrl: "http://www.jdom.org/docs/faq.html#a0030")
libraryLicense(name: "JGoodies Forms", libraryName: "jgoodies-forms", version: "CVS snapshot as of 5 May 2006", license: "BSD ", url: "http://www.jgoodies.com/freeware/forms/", licenseUrl: "http://www.jgoodies.com/downloads/libraries.html")
libraryLicense(name: "JNA", libraryName: "jna", version: "3.2.4", license: "LGPL 2.1", url: "https://jna.dev.java.net/", licenseUrl: "http://www.opensource.org/licenses/lgpl-2.1.php")
@@ -141,7 +150,7 @@ libraryLicense(name: "Plexus Utils", libraryName: "plexus-utils-1.5.5.jar", vers
libraryLicense(name: "Relax NG Object Model", libraryName: "rngom-20051226-patched.jar", license: "MIT", url: "http://java.net/projects/rngom/", licenseUrl: "http://www.opensource.org/licenses/mit-license.php")
libraryLicense(name: "SVNKit", libraryName: "svnkit.jar", version: "SVN version, 1.1 branch as of 1 Oct 2007", license: "link (commercial license)", url: "http://www.svnkit.com/", licenseUrl: "http://svnkit.com/license.html")
libraryLicense(name: "TestNG", version: "5.7 snapshot", license: "Apache 2.0", url: "http://testng.org/doc/", licenseUrl: "http://code.google.com/p/testng/")
libraryLicense(name: "Trilead SSH", libraryName: "trilead-ssh2-build213.jar", version: "build 213", license: "BSD style (see LICENSE.txt in trilead-ssh-build213.jar)", url: "http://www.trilead.com/SSH_Library/")
libraryLicense(name: "Trilead SSH", libraryName: "trilead-ssh2", version: "build 213", license: "BSD style (see LICENSE.txt in trilead.jar)", url: "http://www.trilead.com/SSH_Library/")
libraryLicense(name: "Trove4j", version: "1.1 (with patches by JetBrains)", license: "LGPL", url: "http://trove4j.sourceforge.net/", licenseUrl: "http://trove4j.sourceforge.net/html/license.html")
libraryLicense(name: "Velocity", version: "1.3", license: "Apache", url: "http://velocity.apache.org/", licenseUrl: "http://velocity.apache.org/index.html")
libraryLicense(name: "winp", version: "1.14", license: "MIT", url: "http://winp.dev.java.net/", licenseUrl: "https://winp.dev.java.net/license.html")
@@ -151,3 +160,4 @@ libraryLicense(name: "XMLBeans", libraryName: "XmlBeans", version: "2.3.0", lice
libraryLicense(name: "XML-RPC", libraryName: "XmlRPC", version: "2.0", license: "Apache 2.0", url: "http://ws.apache.org/xmlrpc/xmlrpc2/", licenseUrl: "http://ws.apache.org/xmlrpc/xmlrpc2/license.html")
libraryLicense(name: "XStream", version: "1.2.1", license: "BSD", url: "http://xstream.codehaus.org/", licenseUrl: "http://xstream.codehaus.org/license.html")
libraryLicense(name: "YourKit Java Profiler", libraryName: "yjp-controller-api-redist.jar", version: "7.0.2", license: "link (commercial license)", url: "http://yourkit.com/", licenseUrl: "http://www.yourkit.com/purchase/license.html")
jetbrainsLibrary("JPS")
@@ -1680,8 +1680,12 @@ public class CompileDriver {
}
if (LOG.isDebugEnabled() || ourDebugMode) {
if (!toDelete.isEmpty()) {
final String message = "Found items to delete, compiler " + compiler.getDescription();
LOG.debug(message);
final StringBuilder message = new StringBuilder();
message.append("Found items to delete, compiler ").append(compiler.getDescription());
for (Trinity<File, String, Boolean> trinity : toDelete) {
message.append("\n").append(trinity.getFirst());
}
LOG.debug(message.toString());
if (ourDebugMode) {
System.out.println(message);
}
@@ -19,6 +19,7 @@ import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.EnvironmentUtil;
import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.NonNls;
@@ -41,6 +42,18 @@ public abstract class ExternalCompiler implements BackendCompiler {
return COMPILABLE_TYPES;
}
/**
* Checks if the compiler can compile the specified file.
*
* @param file the file to check.
* @param context the context for the current compile operation.
* @return true if can compile the file, false otherwise. If the method returns false, <code>file</code>
* will not be included in the list of files passed to {@link #compile(CompileContext, com.intellij.util.Chunk < com.intellij.openapi.module.Module >,com.intellij.openapi.vfs.VirtualFile[], com.intellij.openapi.compiler.TranslatingCompiler.OutputSink)}.
*/
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
return getCompilableFileTypes().contains(file.getFileType());
}
@NotNull
public Process launchProcess(@NotNull final ModuleChunk chunk, @NotNull final String outputDir, @NotNull final CompileContext compileContext) throws IOException {
final String[] commands = createStartupCommand(chunk, compileContext, outputDir);
@@ -50,7 +50,11 @@ public class JavaCompiler implements TranslatingCompiler {
}
public boolean isCompilableFile(VirtualFile file, CompileContext context) {
return getBackEndCompiler().getCompilableFileTypes().contains(file.getFileType());
final BackendCompiler backEndCompiler = getBackEndCompiler();
if (backEndCompiler instanceof ExternalCompiler) {
return ((ExternalCompiler)backEndCompiler).isCompilableFile(file, context);
}
return backEndCompiler.getCompilableFileTypes().contains(file.getFileType());
}
public void compile(CompileContext context, Chunk<Module> moduleChunk, VirtualFile[] files, OutputSink sink) {
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.*;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiType;
import com.intellij.psi.codeStyle.CodeStyleSettings;
@@ -27,6 +28,8 @@ import org.jetbrains.annotations.Nullable;
* @author peter
*/
public class CastingLookupElementDecorator extends LookupElementDecorator<LookupElement> implements TypedLookupItem {
public static final ClassConditionKey<CastingLookupElementDecorator> CLASS_CONDITION_KEY = ClassConditionKey.create(CastingLookupElementDecorator.class);
private final LookupElement myCastItem;
private final PsiType myCastType;
@@ -78,14 +81,4 @@ public class CastingLookupElementDecorator extends LookupElementDecorator<Lookup
static LookupElement createCastingElement(final LookupElement delegate, PsiType castTo) {
return new CastingLookupElementDecorator(delegate, castTo);
}
public static @Nullable CastingLookupElementDecorator from(LookupElement element) {
if (element instanceof CastingLookupElementDecorator) return (CastingLookupElementDecorator)element;
else if (element instanceof LookupElementDecorator) {
element = ((LookupElementDecorator)element).getDelegate();
if (element instanceof CastingLookupElementDecorator) return (CastingLookupElementDecorator)element;
}
return null;
}
}
@@ -18,6 +18,7 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.*;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
@@ -30,6 +31,7 @@ import java.util.Set;
* @author peter
*/
public class JavaChainLookupElement extends LookupElementDecorator<LookupElement> implements TypedLookupItem {
public static final ClassConditionKey<JavaChainLookupElement> CLASS_CONDITION_KEY = ClassConditionKey.create(JavaChainLookupElement.class);
private final LookupElement myQualifier;
private JavaChainLookupElement(LookupElement qualifier, LookupElement main) {
@@ -72,7 +74,7 @@ public class JavaChainLookupElement extends LookupElementDecorator<LookupElement
final LookupElementPresentation qualifierPresentation = new LookupElementPresentation();
myQualifier.renderElement(qualifierPresentation);
String name = maybeAddParentheses(qualifierPresentation.getItemText());
final String qualifierText = myQualifier.as(CastingLookupElementDecorator.class) != null ? "(" + name + ")" : name;
final String qualifierText = myQualifier.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY) != null ? "(" + name + ")" : name;
presentation.setItemText(qualifierText + "." + presentation.getItemText());
}
@@ -122,7 +124,7 @@ public class JavaChainLookupElement extends LookupElementDecorator<LookupElement
@NotNull
private LookupElement getComparableQualifier() {
final CastingLookupElementDecorator casting = CastingLookupElementDecorator.from(myQualifier);
final CastingLookupElementDecorator casting = myQualifier.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY);
return casting == null ? myQualifier : casting.getDelegate();
}
@@ -242,7 +242,7 @@ public class JavaCompletionContributor extends CompletionContributor {
result.addElement(TailTypeDecorator.withTail(element, TailType.createSimpleTailType(':')));
}
else {
final LookupItem item = element.as(LookupItem.class);
final LookupItem item = element.as(LookupItem.CLASS_CONDITION_KEY);
if (originalFile instanceof PsiJavaCodeReferenceCodeFragment &&
!((PsiJavaCodeReferenceCodeFragment)originalFile).isClassesAccepted() && item != null) {
item.setTailType(TailType.NONE);
@@ -19,7 +19,6 @@ import com.intellij.codeInsight.ExpectedTypeInfo;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupItem;
import com.intellij.openapi.util.Condition;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.statistics.JavaStatisticsManager;
import com.intellij.psi.statistics.StatisticsInfo;
@@ -51,7 +50,7 @@ public class JavaCompletionStatistician extends CompletionStatistician{
}
}
LookupItem item = LookupItem.from(element);
LookupItem item = element.as(LookupItem.CLASS_CONDITION_KEY);
if (item == null) return null;
PsiType qualifierType = JavaCompletionUtil.getQualifierType(item);
@@ -503,13 +503,13 @@ public class JavaCompletionUtil {
@Nullable
public static PsiType getLookupElementType(final LookupElement element) {
TypedLookupItem typed = typedFrom(element);
TypedLookupItem typed = element.as(TypedLookupItem.CLASS_CONDITION_KEY);
if (typed != null) {
return typed.getType();
}
final PsiType qualifierType = getPsiType(element.getObject());
final LookupItem lookupItem = LookupItem.from(element);
final LookupItem lookupItem = element.as(LookupItem.CLASS_CONDITION_KEY);
if (lookupItem != null) {
final Object o = lookupItem.getAttribute(LookupItem.TYPE);
if (o instanceof PsiType) {
@@ -524,16 +524,6 @@ public class JavaCompletionUtil {
return qualifierType;
}
public static @Nullable TypedLookupItem typedFrom(LookupElement element) {
TypedLookupItem typed = null;
if (element instanceof TypedLookupItem) typed = (TypedLookupItem)element;
else if (element instanceof LookupElementDecorator) {
element = ((LookupElementDecorator)element).getDelegate();
if (element instanceof TypedLookupItem) typed = (TypedLookupItem)element;
}
return typed;
}
@Nullable
public static PsiType getQualifiedMemberReferenceType(@Nullable PsiType qualifierType, @NotNull final PsiMember member) {
final ClassCandidateInfo info = TypeConversionUtil.splitType(qualifierType, member);
@@ -605,7 +595,7 @@ public class JavaCompletionUtil {
if (o instanceof PsiMember) {
mentioned.add((PsiMember)o);
}
set.add(mayHighlight ? highlightIfNeeded(qualifierType, item) : item);
set.add(mayHighlight ? highlightIfNeeded(qualifierType, item, o) : item);
}
}
@@ -668,7 +658,8 @@ public class JavaCompletionUtil {
for (CompletionElement completionElement : processor.getResults()) {
final LookupElement item = createLookupElement(completionElement, castTo);
if (item != null) {
set.add(highlightIfNeeded(castTo, castQualifier(project, item, castItem)));
LookupElement item1 = castQualifier(project, item, castItem);
set.add(highlightIfNeeded(castTo, item1, item1.getObject()));
}
}
return castTo;
@@ -706,11 +697,10 @@ public class JavaCompletionUtil {
});
}
private static LookupElement highlightIfNeeded(@NotNull PsiType qualifierType, @NotNull LookupElement item) {
Object o = item.getObject();
public static LookupElement highlightIfNeeded(PsiType qualifierType, LookupElement item, Object object) {
if (qualifierType instanceof PsiArrayType) {
if (o instanceof PsiField || o instanceof PsiMethod) { //length and clone()
PsiElement parent = ((PsiElement)o).getParent();
if (object instanceof PsiField || object instanceof PsiMethod) { //length and clone()
PsiElement parent = ((PsiElement)object).getParent();
if (parent instanceof PsiClass && parent.getContainingFile().getVirtualFile() == null) { //yes, they're a bit dummy
return highlight(item);
}
@@ -718,8 +708,8 @@ public class JavaCompletionUtil {
}
else if (qualifierType instanceof PsiClassType) {
PsiClass qualifierClass = ((PsiClassType)qualifierType).resolve();
if (o instanceof PsiField || o instanceof PsiMethod || o instanceof PsiClass) {
PsiElement parent = ((PsiElement)o).getParent();
if (object instanceof PsiField || object instanceof PsiMethod || object instanceof PsiClass) {
PsiClass parent = ((PsiMember)object).getContainingClass();
if (parent != null && parent.equals(qualifierClass)) {
return highlight(item);
}
@@ -728,14 +718,15 @@ public class JavaCompletionUtil {
return item;
}
private static LookupElementDecorator<LookupElement> highlight(LookupElement decorator) {
return LookupElementDecorator.withRenderer(decorator, new LookupElementRenderer<LookupElementDecorator<LookupElement>>() {
@Override
public void renderElement(LookupElementDecorator<LookupElement> element, LookupElementPresentation presentation) {
element.getDelegate().renderElement(presentation);
presentation.setItemTextBold(true);
}
});
private static LookupElement highlight(LookupElement decorator) {
return PrioritizedLookupElement.withGrouping(
LookupElementDecorator.withRenderer(decorator, new LookupElementRenderer<LookupElementDecorator<LookupElement>>() {
@Override
public void renderElement(LookupElementDecorator<LookupElement> element, LookupElementPresentation presentation) {
element.getDelegate().renderElement(presentation);
presentation.setItemTextBold(true);
}
}), 1);
}
private static LookupItem<?> createLookupElement(CompletionElement completionElement, PsiType qualifierType) {
@@ -974,7 +965,7 @@ public class JavaCompletionUtil {
if (smart || needRightParenth && addCompletionChar) {
TailType toInsert = tailType;
LookupItem lookupItem = item.as(LookupItem.class);
LookupItem lookupItem = item.as(LookupItem.CLASS_CONDITION_KEY);
if (lookupItem == null || lookupItem.getAttribute(LookupItem.TAIL_TYPE_ATTR) != TailType.UNKNOWN) {
if (!hasTail && item.getObject() instanceof PsiMethod && ((PsiMethod)item.getObject()).getReturnType() == PsiType.VOID) {
PsiDocumentManager.getInstance(file.getProject()).commitAllDocuments();
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.lookup.*;
import com.intellij.codeInsight.lookup.impl.JavaElementLookupRenderer;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
@@ -34,6 +35,7 @@ import org.jetbrains.annotations.Nullable;
* @author peter
*/
public class JavaMethodCallElement extends LookupItem<PsiMethod> implements TypedLookupItem, StaticallyImportable {
public static final ClassConditionKey<JavaMethodCallElement> CLASS_CONDITION_KEY = ClassConditionKey.create(JavaMethodCallElement.class);
private static final Key<PsiSubstitutor> INFERENCE_SUBSTITUTOR = Key.create("INFERENCE_SUBSTITUTOR");
@Nullable private final PsiClass myContainingClass;
private final PsiMethod myMethod;
@@ -49,7 +49,7 @@ public class JavaMethodMergingContributor extends CompletionContributor {
}
final PsiMethod method = (PsiMethod)o;
final JavaChainLookupElement chain = item.as(JavaChainLookupElement.class);
final JavaChainLookupElement chain = item.as(JavaChainLookupElement.CLASS_CONDITION_KEY);
final String name = method.getName() + "#" + (chain == null ? "" : chain.getQualifier().getLookupString());
if (commonName != null && !commonName.equals(name)) {
return AutoCompletionDecision.SHOW_LOOKUP;
@@ -200,7 +200,7 @@ public class JavaSmartCompletionContributor extends CompletionContributor {
final CompletionService service = CompletionService.getCompletionService();
new BasicExpressionCompletionContributor().fillCompletionVariants(parameters, service.createResultSet(parameters, new Consumer<LookupElement>() {
public void consume(final LookupElement lookupElement) {
final TypedLookupItem typed = JavaCompletionUtil.typedFrom(lookupElement);
final TypedLookupItem typed = lookupElement.as(TypedLookupItem.CLASS_CONDITION_KEY);
if (typed != null) {
final PsiType psiType = typed.getType();
if (psiType != null && type.isAssignableFrom(psiType)) {
@@ -21,7 +21,6 @@ import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeParameter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
@@ -29,13 +28,10 @@ import org.jetbrains.annotations.Nullable;
public class PreferNonGenericWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
final Object object = item.getObject();
if (object instanceof PsiMethod) {
PsiType type = ((PsiMethod)object).getReturnType();
final JavaMethodCallElement callItem = item.as(JavaMethodCallElement.class);
final JavaMethodCallElement callItem = item.as(JavaMethodCallElement.CLASS_CONDITION_KEY);
if (callItem != null) {
type = callItem.getSubstitutor().substitute(type);
}
@@ -18,7 +18,6 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.PsiTypeLookupItem;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
@@ -26,14 +25,11 @@ import org.jetbrains.annotations.Nullable;
public class PreferSimpleWeigher extends CompletionWeigher {
public Comparable weigh(@NotNull final LookupElement item, @NotNull final CompletionLocation location) {
if (location == null) {
return null;
}
final PsiTypeLookupItem lookupItem = PsiTypeLookupItem.from(item);
final PsiTypeLookupItem lookupItem = item.as(PsiTypeLookupItem.CLASS_CONDITION_KEY);
if (lookupItem != null) {
return -lookupItem.getBracketsCount();
}
if (CastingLookupElementDecorator.from(item) != null) {
if (item.as(CastingLookupElementDecorator.CLASS_CONDITION_KEY) != null) {
return -239;
}
return 0;
@@ -167,7 +167,7 @@ public class ReferenceExpressionCompletionContributor {
}), false, parameters);
for (LookupElement lookupElement : elements) {
if (lookupElement.getObject() instanceof PsiMethod) {
final JavaMethodCallElement item = lookupElement.as(JavaMethodCallElement.class);
final JavaMethodCallElement item = lookupElement.as(JavaMethodCallElement.CLASS_CONDITION_KEY);
assert item != null;
final PsiMethod method = (PsiMethod)lookupElement.getObject();
if (SmartCompletionDecorator.hasUnboundTypeParams(method)) {
@@ -58,8 +58,9 @@ public class SmartCompletionDecorator extends TailTypeDecorator<LookupElement> {
return defType;
}
LookupElement item = getDelegate();
Object object = item.getObject();
LookupElement delegate = getDelegate();
LookupItem item = as(LookupItem.CLASS_CONDITION_KEY);
Object object = delegate.getObject();
if (!CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET && (object instanceof PsiMethod || object instanceof PsiClass)) {
return TailType.NONE;
}
@@ -67,8 +68,8 @@ public class SmartCompletionDecorator extends TailTypeDecorator<LookupElement> {
final PsiExpression enclosing = PsiTreeUtil.getContextOfType(myPosition, PsiExpression.class, true);
if (enclosing != null && object instanceof PsiElement) {
final PsiType type = getItemType(item);
final TailType itemType = item instanceof LookupItem ? ((LookupItem)item).getTailType() : TailType.NONE;
final PsiType type = JavaCompletionUtil.getLookupElementType(delegate);
final TailType itemType = item != null ? item.getTailType() : TailType.NONE;
TailType cached = itemType;
int cachedPrior = 0;
if (type != null && type.isValid()) {
@@ -108,11 +109,6 @@ public class SmartCompletionDecorator extends TailTypeDecorator<LookupElement> {
return null;
}
@Nullable
private PsiType getItemType(LookupElement element) {
return JavaCompletionUtil.getLookupElementType(element);
}
@Override
public void handleInsert(InsertionContext context) {
myPosition = getPosition(context, this);
@@ -15,33 +15,21 @@
*/
package com.intellij.codeInsight.javadoc;
import com.intellij.codeInsight.documentation.AbstractExternalFilter;
import com.intellij.codeInsight.documentation.DocumentationManager;
import com.intellij.codeInsight.documentation.PlatformDocumentationUtil;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.*;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.io.UrlConnectionUtil;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -53,85 +41,19 @@ import java.util.regex.Pattern;
* To change this template use Options | File Templates.
*/
public class JavaDocExternalFilter {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.javadoc.JavaDocExternalFilter");
public class JavaDocExternalFilter extends AbstractExternalFilter {
private final Project myProject;
private final PsiManager myManager;
protected static @NonNls final Pattern ourHTMLsuffix = Pattern.compile("[.][hH][tT][mM][lL]?");
protected static @NonNls final Pattern ourParentFolderprefix = Pattern.compile("^[.][.]/");
protected static @NonNls final Pattern ourAnchorsuffix = Pattern.compile("#(.*)$");
protected static @NonNls final Pattern ourHTMLFilesuffix = Pattern.compile("/([^/]*[.][hH][tT][mM][lL]?)$");
private static @NonNls final Pattern ourHREFselector = Pattern.compile("<A.*?HREF=\"([^>\"]*)\"", Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
private static @NonNls final Pattern ourAnnihilator = Pattern.compile("/[^/^.]*/[.][.]/");
private static @NonNls final Pattern ourIMGselector = Pattern.compile("<IMG[ \\t\\n\\r\\f]+SRC=\"([^>]*)\"", Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
private static @NonNls final Pattern ourMethodHeading = Pattern.compile("<H3>(.+?)</H3>", Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
protected static @NonNls final String DOC_ELEMENT_PROTOCOL = "doc_element://";
protected static @NonNls final String PSI_ELEMENT_PROTOCOL = "psi_element://";
private static @NonNls final String JAR_PROTOCOL = "jar:";
private static @NonNls final String DOC_START_MARKER = "Generated by javadoc";
@NonNls private static final String HR = "<HR>";
@NonNls private static final String P = "<P>";
@NonNls private static final String DL = "<DL>";
@NonNls protected static final String H2 = "</H2>";
@NonNls protected static final String HTML_CLOSE = "</HTML>";
@NonNls protected static final String HTML = "<HTML>";
@NonNls private static final String BR = "<BR>";
@NonNls private static final String DT = "<DT>";
protected static abstract class RefConvertor {
private final Pattern mySelector;
public RefConvertor(Pattern selector) {
mySelector = selector;
}
protected abstract String convertReference(String root, String href);
public String refFilter(final String root, String read) {
String toMatch = read.toUpperCase();
StringBuffer ready = new StringBuffer();
int prev = 0;
Matcher matcher = mySelector.matcher(toMatch);
while (matcher.find()) {
String before = read.substring(prev, matcher.start(1) - 1); // Before reference
final String href = read.substring(matcher.start(1), matcher.end(1)); // The URL
prev = matcher.end(1) + 1;
ready.append(before);
ready.append("\"");
ready.append(ApplicationManager.getApplication().runReadAction(
new Computable<String>() {
public String compute() {
return convertReference(root, href);
}
}
));
ready.append("\"");
}
ready.append(read.substring(prev, read.length()));
return ready.toString();
}
}
protected final RefConvertor myIMGConvertor = new RefConvertor(ourIMGselector) {
protected String convertReference(String root, String href) {
if (StringUtil.startsWithChar(href, '#')) {
return DOC_ELEMENT_PROTOCOL + root + href;
}
if (Comparing.strEqual(VirtualFileManager.extractProtocol(root), LocalFileSystem.PROTOCOL)) {
final String path = VirtualFileManager.extractPath(root);
if (!path.startsWith("/")) {//skip host for local file system files (format - file://host_name/path)
root = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, "/" + path);
}
}
return ourHTMLFilesuffix.matcher(root).replaceAll("/") + href;
}
};
private final RefConvertor[] myReferenceConvertors = new RefConvertor[]{
new RefConvertor(ourHREFselector) {
@@ -155,7 +77,7 @@ public class JavaDocExternalFilter {
final String classRef = ourAnchorsuffix.matcher(elementRef).replaceAll("");
return
(JavaPsiFacade.getInstance(myManager.getProject()).findClass(classRef, GlobalSearchScope.allScope(myProject)) != null)
(JavaPsiFacade.getInstance(myProject).findClass(classRef, GlobalSearchScope.allScope(myProject)) != null)
? PSI_ELEMENT_PROTOCOL + elementRef
: DOC_ELEMENT_PROTOCOL + doAnnihilate(nakedRoot + href);
}
@@ -166,112 +88,9 @@ public class JavaDocExternalFilter {
public JavaDocExternalFilter(Project project) {
myProject = project;
myManager = PsiManager.getInstance(myProject);
}
protected static String doAnnihilate(String path) {
int len = path.length();
do {
path = ourAnnihilator.matcher(path).replaceAll("/");
}
while (len > (len = path.length()));
return path;
}
private interface Waiter{
void sayYes();
boolean runMe();
}
public static boolean isJavaDocURL(final String url) throws Exception {
final Waiter waiter = new Waiter(){
Boolean key = Boolean.FALSE;
final Object LOCK = new Object();
public void sayYes(){
key = Boolean.TRUE;
synchronized (LOCK) {
LOCK.notify();
}
}
public boolean runMe(){
try {
synchronized (LOCK) {
LOCK.wait(600);
}
}
catch (InterruptedException e) {
return false;
}
return key.booleanValue();
}
};
final boolean[] fail = new boolean[1];
final Exception [] ex = new Exception[1];
final HttpConfigurable httpConfigurable = HttpConfigurable.getInstance();
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
public void run() {
Reader stream = null;
try {
stream = getReaderByUrl(url, httpConfigurable, ProgressManager.getInstance().getProgressIndicator());
}
catch (IOException e) {
ex[0] = e;
}
if (stream == null) {
fail[0] = true;
return;
}
try {
BufferedReader reader = null;
try {
reader = new BufferedReader(stream);
int lookUp = 6;
while (lookUp > 0) {
if (reader.readLine().indexOf(DOC_START_MARKER) != -1) {
waiter.sayYes();
}
lookUp--;
}
}
finally {
if (reader != null) {
reader.close();
}
}
}
catch (final Exception e) {
ex[0] = e;
}
}
});
if (ex[0] != null) {
throw ex[0];
}
return !fail[0] && waiter.runMe();
}
private String correctRefs(String root, String read) {
String result = read;
for (RefConvertor myReferenceConvertor : getRefConvertors()) {
result = myReferenceConvertor.refFilter(root, result);
}
return result;
}
@Override
protected RefConvertor[] getRefConvertors() {
return myReferenceConvertors;
}
@@ -281,74 +100,13 @@ public class JavaDocExternalFilter {
if (text == null) {
return null;
}
text = JavaDocUtil.fixupText(text);
text = PlatformDocumentationUtil.fixupText(text);
return text;
}
@Nullable
private static Reader getReaderByUrl(final String surl, final HttpConfigurable httpConfigurable, final ProgressIndicator pi) throws IOException {
if (surl.startsWith(JAR_PROTOCOL)) {
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(BrowserUtil.getDocURL(surl));
if (file == null) {
return null;
}
return new StringReader(VfsUtil.loadText(file));
}
URL url = BrowserUtil.getURL(surl);
if (url == null) {
return null;
}
httpConfigurable.prepareURL(url.toString());
final URLConnection urlConnection = url.openConnection();
final String contentEncoding = urlConnection.getContentEncoding();
final InputStream inputStream =
pi != null ? UrlConnectionUtil.getConnectionInputStreamWithException(urlConnection, pi) : urlConnection.getInputStream();
//noinspection IOResourceOpenedButNotSafelyClosed
return contentEncoding != null ? new InputStreamReader(inputStream, contentEncoding) : new InputStreamReader(inputStream);
}
@Nullable
@SuppressWarnings({"HardCodedStringLiteral"})
public String getExternalDocInfo(final String surl) throws Exception {
if (surl == null) return null;
if (MyJavadocFetcher.isFree()) {
final MyJavadocFetcher fetcher = new MyJavadocFetcher(surl, new MyDocBuilder() {
public void buildFromStream(String surl, Reader input, StringBuffer result) throws IOException {
doBuildFromStream(surl, input, result);
}
});
final Future<?> fetcherFuture = ApplicationManager.getApplication().executeOnPooledThread(fetcher);
try {
fetcherFuture.get();
}
catch (Exception e) {
return null;
}
final Exception exception = fetcher.getException();
if (exception != null) {
fetcher.cleanup();
throw exception;
}
final String docText = correctRefs(ourAnchorsuffix.matcher(surl).replaceAll(""), fetcher.getData());
if (LOG.isDebugEnabled()) {
LOG.debug("Filtered JavaDoc: " + docText + "\n");
}
return JavaDocUtil.fixupText(docText);
}
return null;
}
@Nullable
public String getExternalDocInfoForElement(final String docURL, final PsiElement element) throws Exception {
String externalDoc = getExternalDocInfo(docURL);
String externalDoc = super.getExternalDocInfoForElement(docURL, element);
if (externalDoc != null) {
if (element instanceof PsiMethod) {
final String className = ApplicationManager.getApplication().runReadAction(
@@ -368,154 +126,4 @@ public class JavaDocExternalFilter {
return externalDoc;
}
protected void doBuildFromStream(String surl, Reader input, StringBuffer data) throws IOException {
final BufferedReader buf = new BufferedReader(input);
Matcher anchorMatcher = ourAnchorsuffix.matcher(surl);
@NonNls String startSection = "<!-- ======== START OF CLASS DATA ======== -->";
@NonNls String endSection = "SUMMARY ========";
@NonNls String greatestEndSection = "<!-- ========= END OF CLASS DATA ========= -->";
boolean isClassDoc = true;
if (anchorMatcher.find()) {
isClassDoc = false;
startSection = "<A NAME=\"" + anchorMatcher.group(1).toUpperCase() + "\"";
endSection = "<A NAME=";
}
data.append(HTML);
String read;
do {
read = buf.readLine();
}
while (read != null && read.toUpperCase().indexOf(startSection) == -1);
if (read == null) {
data.delete(0, data.length());
return;
}
appendLine(data, read);
if (isClassDoc) {
boolean skip = false;
while (((read = buf.readLine()) != null) && !read.toUpperCase().trim().equals(DL)) {
if (read.toUpperCase().indexOf(H2) != -1) { // read=class name in <H2>
data.append(H2);
skip = true;
}
else if (!skip) {
appendLine(data, read);
}
}
data.append(DL);
StringBuffer classDetails = new StringBuffer();
while (((read = buf.readLine()) != null) && !read.toUpperCase().equals(HR) && !read.toUpperCase().equals(P)) {
appendLine(classDetails, read);
}
while (((read = buf.readLine()) != null) && !read.toUpperCase().equals(P) && !read.toUpperCase().equals(HR)) {
appendLine(data, read.replaceAll(DT, DT + BR));
}
data.append(classDetails);
data.append(P);
}
while (((read = buf.readLine()) != null) && read.indexOf(endSection) == -1 && read.indexOf(greatestEndSection) == -1) {
if (read.toUpperCase().indexOf(HR) == -1) {
appendLine(data, read);
}
}
data.append(HTML_CLOSE);
}
private static void appendLine(final StringBuffer buffer, final String read) {
buffer.append(read);
buffer.append("\n");
}
private interface MyDocBuilder {
void buildFromStream(String surl, Reader input, StringBuffer result) throws IOException;
}
private static class MyJavadocFetcher implements Runnable {
private static boolean ourFree = true;
private final StringBuffer data = new StringBuffer();
private final String surl;
private final MyDocBuilder myBuilder;
private final Exception [] myExceptions = new Exception[1];
private final HttpConfigurable myHttpConfigurable;
public MyJavadocFetcher(final String surl, MyDocBuilder builder) {
this.surl = surl;
myBuilder = builder;
ourFree = false;
myHttpConfigurable = HttpConfigurable.getInstance();
}
public static boolean isFree() {
return ourFree;
}
public String getData() {
return data.toString();
}
public void run() {
try {
if (surl == null) {
return;
}
Reader stream = null;
try {
stream = getReaderByUrl(surl, myHttpConfigurable, new ProgressIndicatorBase());
}
catch (ProcessCanceledException e) {
return;
}
catch (IOException e) {
myExceptions[0] = e;
}
if (stream == null) {
return;
}
try {
myBuilder.buildFromStream(surl, stream, data);
}
catch (final IOException e) {
myExceptions[0] = e;
}
finally {
try {
stream.close();
}
catch (IOException e) {
myExceptions[0] = e;
}
}
}
finally {
ourFree = true;
}
}
public Exception getException() {
return myExceptions[0];
}
public void cleanup() {
myExceptions[0] = null;
}
}
}
@@ -27,19 +27,14 @@ import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedList;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class JavaDocUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.javadoc.JavaDocUtil");
private static final @NonNls Pattern ourTypePattern = Pattern.compile("[ ]+[^ ^\\[^\\]]");
private static final @NonNls Pattern ourLtFixupPattern = Pattern.compile("<([^/^\\w^!])");
private static final @NonNls Pattern ourToQuote = Pattern.compile("[\\\\\\.\\^\\$\\?\\*\\+\\|\\)\\}\\]\\{\\(\\[]");
private static final @NonNls String LT_ENTITY = "&lt;";
private JavaDocUtil() {
}
@@ -350,41 +345,6 @@ public class JavaDocUtil {
return memberText.substring(0, parenthIndex + 1) + buffer.toString() + ")";
}
private static String quote(String x) {
if (ourToQuote.matcher(x).find()) {
return "\\" + x;
}
return x;
}
public static String fixupText(String docText) {
Matcher fixupMatcher = ourLtFixupPattern.matcher(docText);
LinkedList<String> secondSymbols = new LinkedList<String>();
while (fixupMatcher.find()) {
String s = fixupMatcher.group(1);
//[db] that's workaround to avoid internal bug
if (!s.equals("\\") && !secondSymbols.contains(s)) {
secondSymbols.addFirst(s);
}
}
for (String s : secondSymbols) {
String pattern = "<" + quote(s);
try {
docText = Pattern.compile(pattern).matcher(docText).replaceAll(LT_ENTITY + pattern);
}
catch (PatternSyntaxException e) {
LOG.error("Pattern syntax exception on " + pattern);
}
}
return docText;
}
public static PsiClassType[] getImplementsList(PsiClass aClass) {
if (aClass instanceof PsiAnonymousClass) {
return new PsiClassType[]{((PsiAnonymousClass)aClass).getBaseClassType()};
@@ -405,4 +365,4 @@ public class JavaDocUtil {
return list == null ? PsiClassType.EMPTY_ARRAY : list.getReferencedTypes();
}
}
}
@@ -18,9 +18,9 @@ package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.completion.DefaultInsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.JavaPsiClassReferenceElement;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassReferenceType;
import com.intellij.psi.util.TypeConversionUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -29,6 +29,8 @@ import org.jetbrains.annotations.Nullable;
* @author peter
*/
public class PsiTypeLookupItem extends LookupItem {
public static final ClassConditionKey<PsiTypeLookupItem> CLASS_CONDITION_KEY = ClassConditionKey.create(PsiTypeLookupItem.class);
public PsiTypeLookupItem(Object o, @NotNull @NonNls String lookupString) {
super(o, lookupString);
}
@@ -130,16 +132,6 @@ public class PsiTypeLookupItem extends LookupItem {
}
return new LookupItem(type, type.getPresentableText());
}
public static @Nullable PsiTypeLookupItem from(LookupElement element) {
if (element instanceof PsiTypeLookupItem) return (PsiTypeLookupItem)element;
else if (element instanceof LookupElementDecorator) {
element = ((LookupElementDecorator)element).getDelegate();
if (element instanceof PsiTypeLookupItem) return (PsiTypeLookupItem)element;
}
return null;
}
@Override
public void renderElement(LookupElementPresentation presentation) {
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.lookup;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.Nullable;
@@ -22,6 +23,8 @@ import org.jetbrains.annotations.Nullable;
* @author peter
*/
public interface TypedLookupItem {
ClassConditionKey<TypedLookupItem> CLASS_CONDITION_KEY = ClassConditionKey.create(TypedLookupItem.class);
@Nullable
PsiType getType();
}
@@ -17,6 +17,7 @@
package com.intellij.lang.java;
import com.intellij.codeInsight.CodeInsightBundle;
import com.intellij.codeInsight.documentation.PlatformDocumentationUtil;
import com.intellij.codeInsight.editorActions.CodeDocumentationUtil;
import com.intellij.codeInsight.javadoc.JavaDocExternalFilter;
import com.intellij.codeInsight.javadoc.JavaDocInfoGenerator;
@@ -36,9 +37,7 @@ import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileSystem;
import com.intellij.openapi.vfs.ex.http.HttpFileSystem;
import com.intellij.psi.*;
import com.intellij.psi.impl.beanProperties.BeanPropertyElement;
import com.intellij.psi.impl.source.javadoc.PsiDocParamRef;
@@ -639,7 +638,7 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
}
if (module != null) {
String[] javadocPaths = ModuleRootManager.getInstance(module).getRootUrls(JavadocOrderRootType.getInstance());
final List<String> httpRoots = getHttpRoots(javadocPaths, relPath);
final List<String> httpRoots = PlatformDocumentationUtil.getHttpRoots(javadocPaths, relPath);
// if found nothing and the file is from library classes, fall back to order entries
if (httpRoots != null || !fileIndex.isInLibraryClasses(virtualFile)) {
return httpRoots;
@@ -649,33 +648,12 @@ public class JavaDocumentationProvider implements CodeDocumentationProvider, Ext
final List<OrderEntry> orderEntries = fileIndex.getOrderEntriesForFile(virtualFile);
for (OrderEntry orderEntry : orderEntries) {
final String[] files = orderEntry.getUrls(JavadocOrderRootType.getInstance());
final List<String> httpRoot = getHttpRoots(files, relPath);
final List<String> httpRoot = PlatformDocumentationUtil.getHttpRoots(files, relPath);
if (httpRoot != null) return httpRoot;
}
return null;
}
@Nullable
public static List<String> getHttpRoots(final String[] roots, String relPath) {
final ArrayList<String> result = new ArrayList<String>();
for (String root : roots) {
final VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl(root);
if (virtualFile != null) {
if (virtualFile.getFileSystem() instanceof HttpFileSystem) {
String url = virtualFile.getUrl();
if (!url.endsWith("/")) url += "/";
result.add(url + relPath);
}
else {
VirtualFile file = virtualFile.findFileByRelativePath(relPath);
if (file != null) result.add(file.getUrl());
}
}
}
return result.isEmpty() ? null : result;
}
@Nullable
public static List<String> findUrlForPackage(PsiPackage aPackage) {
String qName = aPackage.getQualifiedName();
@@ -519,7 +519,7 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
AlignmentStrategy.wrap(arrangeChildAlignment(child, alignmentStrategy)), childOffset);
if (childType == JavaElementType.MODIFIER_LIST && containsAnnotations(child)) {
myAnnotationWrap = Wrap.createWrap(getWrapType(getAnnotationWrapType()), true);
myAnnotationWrap = Wrap.createWrap(getWrapType(getAnnotationWrapType(child)), true);
}
if (block instanceof AbstractJavaBlock) {
@@ -789,12 +789,27 @@ public abstract class AbstractJavaBlock extends AbstractBlock implements JavaBlo
return ((PsiModifierList)child.getPsi()).getAnnotations().length > 0;
}
private int getAnnotationWrapType() {
private int getAnnotationWrapType(@NotNull ASTNode child) {
final IElementType nodeType = myNode.getElementType();
if (nodeType == JavaElementType.METHOD) {
return mySettings.METHOD_ANNOTATION_WRAP;
}
if (nodeType == JavaElementType.CLASS) {
// There is a possible case that current document state is invalid from language syntax point of view, e.g. the user starts
// typing field definition and re-formatting is triggered by 'auto insert javadocs' processing. Example:
// class Test {
// @NotNull Object
// }
// Here '@NotNull' has a 'class' node as a parent but we want to use field annotation setting value. Hence, we check if subsequent
// parsed info is valid.
for (ASTNode node = child.getTreeNext(); node != null; node = node.getTreeNext()) {
if (JavaTokenType.WHITE_SPACE == node.getElementType() || node instanceof PsiTypeElement) {
continue;
}
if (node instanceof PsiErrorElement) {
return mySettings.FIELD_ANNOTATION_WRAP;
}
}
return mySettings.CLASS_ANNOTATION_WRAP;
}
if (nodeType == JavaElementType.FIELD) {
@@ -111,7 +111,8 @@ public class PsiClassConverter extends Converter<PsiClass> implements CustomRefe
VirtualFile virtualFile = file.getVirtualFile();
if (virtualFile == null) return null;
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(file.getProject()).getFileIndex();
return GlobalSearchScope.moduleRuntimeScope(module, fileIndex.isInTestSourceContent(virtualFile));
boolean tests = fileIndex.isInTestSourceContent(virtualFile);
return module.getModuleRuntimeScope(tests).union(module.getModuleWithDependenciesAndLibrariesScope(tests));
}
public static class AnnotationType extends PsiClassConverter {
@@ -0,0 +1,15 @@
class Foo {
void fromSuper() {}
void overridden() {}
}
class FooImpl extends Foo {
void overridden() {}
void fromThis() {}
}
class Bar {
{
new FooImpl().<caret>
}
}
@@ -444,4 +444,37 @@ class JavaAutoPopupTest extends CompletionAutoPopupTestCase {
assert !lookup
}
public void testResumeAfterBackspace() {
myFixture.configureByText("a.java", """
class A {
Object foo() { this<caret> }
}
""")
type '.'
assert lookup
type 'a'
assert !lookup
type '\b'
assert !lookup
type 'c'
assert lookup
}
public void testHideOnInvalidSymbolAfterBackspace() {
myFixture.configureByText("a.java", """
class A {
Object foo() { this<caret> }
}
""")
type '.'
assert lookup
type 'c'
assert lookup
type '\b'
assert lookup
type 'x'
assert !lookup
}
}
@@ -170,4 +170,9 @@ public class NormalCompletionOrderingTest extends CompletionSortingTestCase {
assertEquals("foo.Foo", ((JavaPsiClassReferenceElement)getLookup().getCurrentItem()).getQualifiedName());
}
public void testDeclaredMembersGoFirst() throws Exception {
invokeCompletion(getBasePath() + "/" + getTestName(false) + ".java");
assertStringItems("fromThis", "overridden", "fromSuper", "equals", "getClass", "hashCode", "notify", "notifyAll", "toString", "wait", "wait", "wait");
}
}
@@ -256,4 +256,14 @@ public class JavaFormatterWrapTest extends AbstractJavaFormatterTest {
"int j = 2;"
);
}
public void testIncompleteFieldAndAnnotationWrap() throws Exception {
// Inspired by IDEA-64725
getSettings().FIELD_ANNOTATION_WRAP = CommonCodeStyleSettings.DO_NOT_WRAP;
doClassTest(
"@NotNull Comparable<String>",
"@NotNull Comparable<String>"
);
}
}
@@ -50,7 +50,8 @@ public class DomJavaUtil {
}
else {
ProjectFileIndex fileIndex = ProjectRootManager.getInstance(file.getProject()).getFileIndex();
scope = GlobalSearchScope.moduleRuntimeScope(module, fileIndex.isInTestSourceContent(virtualFile));
boolean tests = fileIndex.isInTestSourceContent(virtualFile);
scope = module.getModuleRuntimeScope(tests).union(module.getModuleWithDependenciesAndLibrariesScope(tests));
}
}
else {
@@ -63,6 +63,6 @@ public abstract class ClassValueConverter extends Converter<PsiClass> implements
}
final boolean inTests = ProjectRootManager.getInstance(project).getFileIndex().isInTestSourceContent(file);
return module.getModuleWithDependenciesAndLibrariesScope(inTests);
return module.getModuleRuntimeScope(inTests).union(module.getModuleWithDependenciesAndLibrariesScope(inTests));
}
}
@@ -18,7 +18,7 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementDecorator;
import org.jetbrains.annotations.Nullable;
import com.intellij.openapi.util.ClassConditionKey;
/**
* Use only when you want to control lookup sorting & preference in simple cases when you have control over ALL the items in lookup.
@@ -28,6 +28,7 @@ import org.jetbrains.annotations.Nullable;
* @author peter
*/
public class PrioritizedLookupElement<T extends LookupElement> extends LookupElementDecorator<T> {
public static final ClassConditionKey<PrioritizedLookupElement> CLASS_CONDITION_KEY = ClassConditionKey.create(PrioritizedLookupElement.class);
private final double myPriority;
private final int myGrouping;
@@ -46,18 +47,12 @@ public class PrioritizedLookupElement<T extends LookupElement> extends LookupEle
}
public static LookupElement withPriority(LookupElement element, double priority) {
final PrioritizedLookupElement prioritized = PrioritizedLookupElement.from(element);
final PrioritizedLookupElement prioritized = element.as(CLASS_CONDITION_KEY);
return new PrioritizedLookupElement<LookupElement>(element, priority, prioritized == null ? 0 : prioritized.getGrouping());
}
public static LookupElement withGrouping(LookupElement element, int grouping) {
final PrioritizedLookupElement prioritized = PrioritizedLookupElement.from(element);
final PrioritizedLookupElement prioritized = element.as(CLASS_CONDITION_KEY);
return new PrioritizedLookupElement<LookupElement>(element, prioritized == null ? 0 : prioritized.getPriority(), grouping);
}
public static @Nullable PrioritizedLookupElement from(LookupElement element) {
if (element instanceof PrioritizedLookupElement) return (PrioritizedLookupElement)element;
if (element instanceof LookupElementDecorator) return from (((LookupElementDecorator)element).getDelegate());
return null;
}
}
@@ -15,6 +15,7 @@
*/
package com.intellij.codeInsight.lookup;
import com.intellij.openapi.util.ClassConditionKey;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -56,7 +57,7 @@ public enum AutoCompletionPolicy {
@Nullable
public static AutoCompletionPolicy getPolicy(LookupElement element) {
final PolicyDecorator decorator = element.as(PolicyDecorator.class);
final PolicyDecorator decorator = element.as(PolicyDecorator.CLASS_CONDITION_KEY);
if (decorator != null) {
return decorator.myPolicy;
}
@@ -64,6 +65,7 @@ public enum AutoCompletionPolicy {
}
private static class PolicyDecorator extends LookupElementDecorator<LookupElement> {
public static final ClassConditionKey<PolicyDecorator> CLASS_CONDITION_KEY = ClassConditionKey.create(PolicyDecorator.class);
private final AutoCompletionPolicy myPolicy;
public PolicyDecorator(LookupElement element, AutoCompletionPolicy policy) {
@@ -17,6 +17,7 @@ package com.intellij.codeInsight.lookup;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
@@ -82,10 +83,18 @@ public abstract class LookupElement extends UserDataHolderBase {
presentation.setItemText(getLookupString());
}
/**
* use {@link #as(com.intellij.openapi.util.ClassConditionKey)} instead
*/
@Deprecated
@Nullable
public <T> T as(Class<T> aClass) {
//noinspection unchecked
return aClass.isInstance(this) ? (T) this : null;
public final <T> T as(Class<T> aClass) {
return as(ClassConditionKey.create(aClass));
}
@Nullable
public <T> T as(ClassConditionKey<T> conditionKey) {
return conditionKey.isInstance(this) ? (T) this : null;
}
public boolean isCaseSensitive() {
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.completion.CompletionService;
import com.intellij.codeInsight.completion.InsertHandler;
import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.completion.PrefixMatcher;
import com.intellij.openapi.util.ClassConditionKey;
import org.jetbrains.annotations.NotNull;
import java.util.Set;
@@ -108,9 +109,9 @@ public abstract class LookupElementDecorator<T extends LookupElement> extends Lo
}
@Override
public <T> T as(Class<T> aClass) {
final T t = super.as(aClass);
return t == null ? myDelegate.as(aClass) : t;
public <T> T as(ClassConditionKey<T> conditionKey) {
final T t = super.as(conditionKey);
return t == null ? myDelegate.as(conditionKey) : t;
}
public boolean isCaseSensitive() {
@@ -19,7 +19,7 @@ package com.intellij.psi.impl;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.NativeFileType;
import com.intellij.openapi.fileTypes.INativeFileType;
import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.IndexNotReadyException;
@@ -136,7 +136,7 @@ public abstract class ElementBase extends UserDataHolderBase implements Iconable
}
public static boolean isNativeFileType(FileType fileType) {
return fileType instanceof NativeFileType || fileType instanceof UnknownFileType;
return fileType instanceof INativeFileType || fileType instanceof UnknownFileType;
}
protected Icon getAdjustedBaseIcon(Icon icon, int flags) {
@@ -16,9 +16,7 @@
package com.intellij.codeInsight;
import com.intellij.codeInsight.completion.CodeCompletionHandlerBase;
import com.intellij.codeInsight.completion.CompletionProgressIndicator;
import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler;
import com.intellij.codeInsight.hint.ShowParameterInfoHandler;
@@ -101,7 +99,7 @@ public class AutoPopupController implements Disposable {
if (!file.isValid()) return;
if (condition != null && !condition.value(file)) return;
new CodeCompletionHandlerBase(CompletionType.BASIC, false, true).invoke(myProject, editor, file);
CompletionAutoPopupHandler.invokeAutoPopupCompletion(myProject, editor);
}
};
@@ -452,7 +452,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
return policy;
}
final LookupItem item = element.as(LookupItem.class);
final LookupItem item = element.as(LookupItem.CLASS_CONDITION_KEY);
if (item != null) {
return item.getAutoCompletionPolicy();
}
@@ -505,8 +505,8 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
protected void run(Result result) throws Throwable {
String uniqueText = _uniqueText;
if (item.getObject() instanceof DeferredUserLookupValue && item.as(LookupItem.class) != null) {
if (!((DeferredUserLookupValue)item.getObject()).handleUserSelection(item.as(LookupItem.class), context.getProject())) {
if (item.getObject() instanceof DeferredUserLookupValue && item.as(LookupItem.CLASS_CONDITION_KEY) != null) {
if (!((DeferredUserLookupValue)item.getObject()).handleUserSelection(item.as(LookupItem.CLASS_CONDITION_KEY), context.getProject())) {
return;
}
@@ -18,7 +18,6 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
@@ -26,10 +25,7 @@ import org.jetbrains.annotations.Nullable;
public class GroupingWeigher extends CompletionWeigher {
@Override
public Integer weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) {
if (location == null) {
return null;
}
final PrioritizedLookupElement prioritized = element.as(PrioritizedLookupElement.class);
final PrioritizedLookupElement prioritized = element.as(PrioritizedLookupElement.CLASS_CONDITION_KEY);
if (prioritized != null) {
return -prioritized.getGrouping();
}
@@ -19,7 +19,6 @@ package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupItem;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author peter
@@ -27,15 +26,12 @@ import org.jetbrains.annotations.Nullable;
public class PriorityWeigher extends CompletionWeigher {
@Override
public Double weigh(@NotNull LookupElement element, @NotNull CompletionLocation location) {
if (location == null) {
return null;
}
final PrioritizedLookupElement prioritized = PrioritizedLookupElement.from(element);
final PrioritizedLookupElement prioritized = element.as(PrioritizedLookupElement.CLASS_CONDITION_KEY);
if (prioritized != null) {
return -prioritized.getPriority();
}
final LookupItem item = LookupItem.from(element);
final LookupItem item = element.as(LookupItem.CLASS_CONDITION_KEY);
if (item != null) {
return -item.getPriority();
}
@@ -0,0 +1,359 @@
/*
* Copyright 2000-2011 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.codeInsight.documentation;
import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.util.ProgressIndicatorBase;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.psi.*;
import com.intellij.util.io.UrlConnectionUtil;
import com.intellij.util.net.HttpConfigurable;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by IntelliJ IDEA.
* User: db
* Date: May 2, 2003
* Time: 8:35:34 PM
* To change this template use Options | File Templates.
*/
public abstract class AbstractExternalFilter {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.javadoc.JavaDocExternalFilter");
protected static @NonNls final Pattern ourAnchorsuffix = Pattern.compile("#(.*)$");
protected static @NonNls final Pattern ourHTMLFilesuffix = Pattern.compile("/([^/]*[.][hH][tT][mM][lL]?)$");
private static @NonNls final Pattern ourAnnihilator = Pattern.compile("/[^/^.]*/[.][.]/");
private static @NonNls final Pattern ourIMGselector = Pattern.compile("<IMG[ \\t\\n\\r\\f]+SRC=\"([^>]*)\"", Pattern.CASE_INSENSITIVE|Pattern.DOTALL);
protected static @NonNls final String DOC_ELEMENT_PROTOCOL = "doc_element://";
protected static @NonNls final String PSI_ELEMENT_PROTOCOL = "psi_element://";
private static @NonNls final String JAR_PROTOCOL = "jar:";
@NonNls private static final String HR = "<HR>";
@NonNls private static final String P = "<P>";
@NonNls private static final String DL = "<DL>";
@NonNls protected static final String H2 = "</H2>";
@NonNls protected static final String HTML_CLOSE = "</HTML>";
@NonNls protected static final String HTML = "<HTML>";
@NonNls private static final String BR = "<BR>";
@NonNls private static final String DT = "<DT>";
protected static abstract class RefConvertor {
private final Pattern mySelector;
public RefConvertor(Pattern selector) {
mySelector = selector;
}
protected abstract String convertReference(String root, String href);
public String refFilter(final String root, String read) {
String toMatch = read.toUpperCase();
StringBuffer ready = new StringBuffer();
int prev = 0;
Matcher matcher = mySelector.matcher(toMatch);
while (matcher.find()) {
String before = read.substring(prev, matcher.start(1) - 1); // Before reference
final String href = read.substring(matcher.start(1), matcher.end(1)); // The URL
prev = matcher.end(1) + 1;
ready.append(before);
ready.append("\"");
ready.append(ApplicationManager.getApplication().runReadAction(
new Computable<String>() {
public String compute() {
return convertReference(root, href);
}
}
));
ready.append("\"");
}
ready.append(read.substring(prev, read.length()));
return ready.toString();
}
}
protected final RefConvertor myIMGConvertor = new RefConvertor(ourIMGselector) {
protected String convertReference(String root, String href) {
if (StringUtil.startsWithChar(href, '#')) {
return DOC_ELEMENT_PROTOCOL + root + href;
}
if (Comparing.strEqual(VirtualFileManager.extractProtocol(root), LocalFileSystem.PROTOCOL)) {
final String path = VirtualFileManager.extractPath(root);
if (!path.startsWith("/")) {//skip host for local file system files (format - file://host_name/path)
root = VirtualFileManager.constructUrl(LocalFileSystem.PROTOCOL, "/" + path);
}
}
return ourHTMLFilesuffix.matcher(root).replaceAll("/") + href;
}
};
protected static String doAnnihilate(String path) {
int len = path.length();
do {
path = ourAnnihilator.matcher(path).replaceAll("/");
}
while (len > (len = path.length()));
return path;
}
private String correctRefs(String root, String read) {
String result = read;
for (RefConvertor myReferenceConvertor : getRefConvertors()) {
result = myReferenceConvertor.refFilter(root, result);
}
return result;
}
protected abstract RefConvertor[] getRefConvertors();
@Nullable
private static Reader getReaderByUrl(final String surl, final HttpConfigurable httpConfigurable, final ProgressIndicator pi) throws IOException {
if (surl.startsWith(JAR_PROTOCOL)) {
VirtualFile file = VirtualFileManager.getInstance().findFileByUrl(BrowserUtil.getDocURL(surl));
if (file == null) {
return null;
}
return new StringReader(VfsUtil.loadText(file));
}
URL url = BrowserUtil.getURL(surl);
if (url == null) {
return null;
}
httpConfigurable.prepareURL(url.toString());
final URLConnection urlConnection = url.openConnection();
final String contentEncoding = urlConnection.getContentEncoding();
final InputStream inputStream =
pi != null ? UrlConnectionUtil.getConnectionInputStreamWithException(urlConnection, pi) : urlConnection.getInputStream();
//noinspection IOResourceOpenedButNotSafelyClosed
return contentEncoding != null ? new InputStreamReader(inputStream, contentEncoding) : new InputStreamReader(inputStream);
}
@Nullable
@SuppressWarnings({"HardCodedStringLiteral"})
public String getExternalDocInfo(final String surl) throws Exception {
if (surl == null) return null;
if (MyJavadocFetcher.isFree()) {
final MyJavadocFetcher fetcher = new MyJavadocFetcher(surl, new MyDocBuilder() {
public void buildFromStream(String surl, Reader input, StringBuffer result) throws IOException {
doBuildFromStream(surl, input, result);
}
});
final Future<?> fetcherFuture = ApplicationManager.getApplication().executeOnPooledThread(fetcher);
try {
fetcherFuture.get();
}
catch (Exception e) {
return null;
}
final Exception exception = fetcher.getException();
if (exception != null) {
fetcher.cleanup();
throw exception;
}
final String docText = correctRefs(ourAnchorsuffix.matcher(surl).replaceAll(""), fetcher.getData());
if (LOG.isDebugEnabled()) {
LOG.debug("Filtered JavaDoc: " + docText + "\n");
}
return PlatformDocumentationUtil.fixupText(docText);
}
return null;
}
@Nullable
public String getExternalDocInfoForElement(final String docURL, final PsiElement element) throws Exception {
return getExternalDocInfo(docURL);
}
protected void doBuildFromStream(String surl, Reader input, StringBuffer data) throws IOException {
final BufferedReader buf = new BufferedReader(input);
Matcher anchorMatcher = ourAnchorsuffix.matcher(surl);
@NonNls String startSection = "<!-- ======== START OF CLASS DATA ======== -->";
@NonNls String endSection = "SUMMARY ========";
@NonNls String greatestEndSection = "<!-- ========= END OF CLASS DATA ========= -->";
boolean isClassDoc = true;
if (anchorMatcher.find()) {
isClassDoc = false;
startSection = "<A NAME=\"" + anchorMatcher.group(1).toUpperCase() + "\"";
endSection = "<A NAME=";
}
data.append(HTML);
String read;
do {
read = buf.readLine();
}
while (read != null && read.toUpperCase().indexOf(startSection) == -1);
if (read == null) {
data.delete(0, data.length());
return;
}
appendLine(data, read);
if (isClassDoc) {
boolean skip = false;
while (((read = buf.readLine()) != null) && !read.toUpperCase().trim().equals(DL)) {
if (read.toUpperCase().indexOf(H2) != -1) { // read=class name in <H2>
data.append(H2);
skip = true;
}
else if (!skip) {
appendLine(data, read);
}
}
data.append(DL);
StringBuffer classDetails = new StringBuffer();
while (((read = buf.readLine()) != null) && !read.toUpperCase().equals(HR) && !read.toUpperCase().equals(P)) {
appendLine(classDetails, read);
}
while (((read = buf.readLine()) != null) && !read.toUpperCase().equals(P) && !read.toUpperCase().equals(HR)) {
appendLine(data, read.replaceAll(DT, DT + BR));
}
data.append(classDetails);
data.append(P);
}
while (((read = buf.readLine()) != null) && read.indexOf(endSection) == -1 && read.indexOf(greatestEndSection) == -1) {
if (read.toUpperCase().indexOf(HR) == -1) {
appendLine(data, read);
}
}
data.append(HTML_CLOSE);
}
private static void appendLine(final StringBuffer buffer, final String read) {
buffer.append(read);
buffer.append("\n");
}
private interface MyDocBuilder {
void buildFromStream(String surl, Reader input, StringBuffer result) throws IOException;
}
private static class MyJavadocFetcher implements Runnable {
private static boolean ourFree = true;
private final StringBuffer data = new StringBuffer();
private final String surl;
private final MyDocBuilder myBuilder;
private final Exception [] myExceptions = new Exception[1];
private final HttpConfigurable myHttpConfigurable;
public MyJavadocFetcher(final String surl, MyDocBuilder builder) {
this.surl = surl;
myBuilder = builder;
ourFree = false;
myHttpConfigurable = HttpConfigurable.getInstance();
}
public static boolean isFree() {
return ourFree;
}
public String getData() {
return data.toString();
}
public void run() {
try {
if (surl == null) {
return;
}
Reader stream = null;
try {
stream = getReaderByUrl(surl, myHttpConfigurable, new ProgressIndicatorBase());
}
catch (ProcessCanceledException e) {
return;
}
catch (IOException e) {
myExceptions[0] = e;
}
if (stream == null) {
return;
}
try {
myBuilder.buildFromStream(surl, stream, data);
}
catch (final IOException e) {
myExceptions[0] = e;
}
finally {
try {
stream.close();
}
catch (IOException e) {
myExceptions[0] = e;
}
}
}
finally {
ourFree = true;
}
}
public Exception getException() {
return myExceptions[0];
}
public void cleanup() {
myExceptions[0] = null;
}
}
}
@@ -0,0 +1,95 @@
/*
* Copyright 2000-2011 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.codeInsight.documentation;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.ex.http.HttpFileSystem;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
public class PlatformDocumentationUtil {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.documentation.PlatformDocumentationUtil");
private static final @NonNls Pattern ourLtFixupPattern = Pattern.compile("<([^/^\\w^!])");
private static final @NonNls Pattern ourToQuote = Pattern.compile("[\\\\\\.\\^\\$\\?\\*\\+\\|\\)\\}\\]\\{\\(\\[]");
private static final @NonNls String LT_ENTITY = "&lt;";
@Nullable
public static List<String> getHttpRoots(final String[] roots, String relPath) {
final ArrayList<String> result = new ArrayList<String>();
for (String root : roots) {
final VirtualFile virtualFile = VirtualFileManager.getInstance().findFileByUrl(root);
if (virtualFile != null) {
if (virtualFile.getFileSystem() instanceof HttpFileSystem) {
String url = virtualFile.getUrl();
if (!url.endsWith("/")) url += "/";
result.add(url + relPath);
}
else {
VirtualFile file = virtualFile.findFileByRelativePath(relPath);
if (file != null) result.add(file.getUrl());
}
}
}
return result.isEmpty() ? null : result;
}
private static String quote(String x) {
if (ourToQuote.matcher(x).find()) {
return "\\" + x;
}
return x;
}
public static String fixupText(String docText) {
Matcher fixupMatcher = ourLtFixupPattern.matcher(docText);
LinkedList<String> secondSymbols = new LinkedList<String>();
while (fixupMatcher.find()) {
String s = fixupMatcher.group(1);
//[db] that's workaround to avoid internal bug
if (!s.equals("\\") && !secondSymbols.contains(s)) {
secondSymbols.addFirst(s);
}
}
for (String s : secondSymbols) {
String pattern = "<" + quote(s);
try {
docText = Pattern.compile(pattern).matcher(docText).replaceAll(LT_ENTITY + pattern);
}
catch (PatternSyntaxException e) {
LOG.error("Pattern syntax exception on " + pattern);
}
}
return docText;
}
}
@@ -112,37 +112,41 @@ public class CompletionAutoPopupHandler extends TypedHandlerDelegate {
if (ApplicationManager.getApplication().isWriteAccessAllowed()) return; //it will fail anyway
if (DumbService.getInstance(project).isDumb()) return;
new CodeCompletionHandlerBase(CompletionType.BASIC, false, true).invoke(project, editor);
final AutoPopupState state = new AutoPopupState(project, editor);
editor.putUserData(STATE_KEY, state);
final Lookup lookup = LookupManager.getActiveLookup(editor);
if (lookup != null) {
lookup.addLookupListener(new LookupAdapter() {
@Override
public void itemSelected(LookupEvent event) {
final AutoPopupState state = getAutoPopupState(editor);
if (state != null) {
state.stopAutoPopup();
}
}
@Override
public void lookupCanceled(LookupEvent event) {
final AutoPopupState state = getAutoPopupState(editor);
if (event.isCanceledExplicitly() && state != null) {
state.stopAutoPopup();
}
}
});
}
invokeAutoPopupCompletion(project, editor);
}
};
AutoPopupController.getInstance(project).invokeAutoPopupRunnable(request, CodeInsightSettings.getInstance().AUTO_LOOKUP_DELAY);
return Result.STOP;
}
public static void invokeAutoPopupCompletion(Project project, final Editor editor) {
new CodeCompletionHandlerBase(CompletionType.BASIC, false, true).invoke(project, editor);
final AutoPopupState state = new AutoPopupState(project, editor);
editor.putUserData(STATE_KEY, state);
final Lookup lookup = LookupManager.getActiveLookup(editor);
if (lookup != null) {
lookup.addLookupListener(new LookupAdapter() {
@Override
public void itemSelected(LookupEvent event) {
final AutoPopupState state = getAutoPopupState(editor);
if (state != null) {
state.stopAutoPopup();
}
}
@Override
public void lookupCanceled(LookupEvent event) {
final AutoPopupState state = getAutoPopupState(editor);
if (event.isCanceledExplicitly() && state != null) {
state.stopAutoPopup();
}
}
});
}
}
@Nullable
private static AutoPopupState getAutoPopupState(Editor editor) {
return editor.getUserData(STATE_KEY);
@@ -25,6 +25,7 @@ import com.intellij.codeInsight.completion.InsertionContext;
import com.intellij.codeInsight.lookup.impl.ElementLookupRenderer;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.util.ClassConditionKey;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.util.containers.ContainerUtil;
@@ -42,6 +43,8 @@ import java.util.Set;
* This class represents an item of a lookup list.
*/
public class LookupItem<T> extends MutableLookupElement<T> implements Comparable {
public static final ClassConditionKey<LookupItem> CLASS_CONDITION_KEY = ClassConditionKey.create(LookupItem.class);
public static final Object HIGHLIGHTED_ATTR = Key.create("highlighted");
public static final Object ICON_ATTR = Key.create("icon");
public static final Object TYPE_TEXT_ATTR = Key.create("typeText");
@@ -358,24 +361,8 @@ public class LookupItem<T> extends MutableLookupElement<T> implements Comparable
return myAllLookupStrings;
}
public void copyAttributes(final LookupItem item) {
if (myAttributes == null) {
if (item.myAttributes == null) return;
myAttributes = new HashMap<Object, Object>(5);
}
myAttributes.putAll(item.myAttributes);
}
@Override
public boolean isCaseSensitive() {
return !Boolean.TRUE.equals(getAttribute(CASE_INSENSITIVE));
}
public static @Nullable LookupItem from(LookupElement lookupElement) {
if (lookupElement instanceof LookupElementDecorator) {
lookupElement = ((LookupElementDecorator)lookupElement).getDelegate();
}
if (lookupElement instanceof LookupItem) return (LookupItem)lookupElement;
return null;
}
}
@@ -46,7 +46,7 @@ public abstract class TailTypeDecorator<T extends LookupElement> extends LookupE
final LookupElement delegate = getDelegate();
final TailType tailType = computeTailType(context);
final LookupItem lookupItem = delegate.as(LookupItem.class);
final LookupItem lookupItem = delegate.as(LookupItem.CLASS_CONDITION_KEY);
if (lookupItem != null && tailType != null) {
lookupItem.setTailType(TailType.UNKNOWN);
}
@@ -16,9 +16,8 @@
package com.intellij.codeInsight.lookup.impl;
import com.intellij.codeInsight.completion.CompletionProcess;
import com.intellij.codeInsight.completion.CompletionProgressIndicator;
import com.intellij.codeInsight.completion.CompletionService;
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
@@ -45,14 +44,14 @@ public class BackspaceHandler extends EditorActionHandler {
}
});
if (lookup.truncatePrefix()) {
final CompletionProgressIndicator process = CompletionServiceImpl.getCompletionService().getCurrentCompletion();
if (lookup.truncatePrefix(process == null || !process.isAutopopupCompletion())) {
return;
}
if (lookup.getLookupStart() < editor.getCaretModel().getOffset()) {
final CompletionProcess process = CompletionService.getCompletionService().getCurrentCompletion();
if (process instanceof CompletionProgressIndicator) {
((CompletionProgressIndicator)process).scheduleRestart();
if (process != null) {
process.scheduleRestart();
return;
}
}
@@ -317,11 +317,13 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
ListScrollingUtil.ensureIndexIsVisible(myList, myList.getSelectedIndex(), 1);
}
public boolean truncatePrefix() {
public boolean truncatePrefix(boolean preserveSelection) {
final int len = myAdditionalPrefix.length();
if (len == 0) return false;
markSelectionTouched();
if (preserveSelection) {
markSelectionTouched();
}
myAdditionalPrefix = myAdditionalPrefix.substring(0, len - 1);
myInitialPrefix = null;
@@ -593,8 +595,8 @@ public class LookupImpl extends LightweightHint implements Lookup, Disposable {
if (item == null ||
item instanceof EmptyLookupItem ||
item.getObject() instanceof DeferredUserLookupValue &&
item.as(LookupItem.class) != null &&
!((DeferredUserLookupValue)item.getObject()).handleUserSelection(item.as(LookupItem.class), myProject)) {
item.as(LookupItem.CLASS_CONDITION_KEY) != null &&
!((DeferredUserLookupValue)item.getObject()).handleUserSelection(item.as(LookupItem.CLASS_CONDITION_KEY), myProject)) {
fireItemSelected(null, completionChar);
return;
}
@@ -32,6 +32,7 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.pom.Navigatable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.ElementBase;
import com.intellij.psi.search.PsiElementProcessor;
import com.intellij.ui.components.JBList;
import org.jetbrains.annotations.NotNull;
@@ -89,11 +90,20 @@ public final class NavigationUtil {
}
public static void activateFileWithPsiElement(@NotNull PsiElement elt) {
if (!activatePsiElementIfOpen(elt)) {
boolean openAsNative = false;
if (elt instanceof PsiFile) {
VirtualFile virtualFile = ((PsiFile)elt).getVirtualFile();
if (virtualFile != null) {
openAsNative = ElementBase.isNativeFileType(virtualFile.getFileType());
}
}
if (openAsNative || !activatePsiElementIfOpen(elt)) {
((NavigationItem)elt).navigate(true);
}
}
private static boolean activatePsiElementIfOpen(@NotNull PsiElement elt) {
if (!elt.isValid()) return false;
elt = elt.getNavigationElement();
@@ -23,6 +23,8 @@ import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
/**
* @author Rustam Vishnyakov
*/
@@ -44,5 +46,11 @@ public abstract class LangScriptingContextProvider {
@Nullable
public abstract String getDefaultDocUrl(VirtualFile file);
@Nullable
public abstract String getOfflineDocUrl(String defaultDocUrl);
@Nullable
public abstract String downloadOfflineDoc(Project project, String offlineDocUrl, JComponent parent);
}
@@ -91,7 +91,7 @@
</hspacer>
</children>
</grid>
<grid id="2a02c" layout-manager="GridLayoutManager" row-count="4" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="2a02c" layout-manager="GridLayoutManager" row-count="5" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@@ -109,7 +109,7 @@
</component>
<component id="2c3dd" class="javax.swing.JButton" binding="myRemoveDocUrlButton">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="messages/IdeBundle" key="scripting.lib.docUrl.remove"/>
@@ -117,7 +117,7 @@
</component>
<scrollpane id="2e869" class="com.intellij.ui.components.JBScrollPane">
<constraints>
<grid row="0" column="0" row-span="3" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
<grid row="0" column="0" row-span="4" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false">
<minimum-size width="400" height="-1"/>
</grid>
</constraints>
@@ -136,14 +136,22 @@
</scrollpane>
<vspacer id="6b5fa">
<constraints>
<grid row="2" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<hspacer id="128aa">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="4" column="0" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<component id="31a1" class="javax.swing.JButton" binding="myDownloadButton">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Download"/>
</properties>
</component>
</children>
</grid>
</children>
@@ -65,6 +65,7 @@ public class EditLibraryDialog extends DialogWrapper {
private JButton myAddDocUrlButton;
private JButton myRemoveDocUrlButton;
private JBList myDocUrlList;
private JButton myDownloadButton;
private Project myProject;
private FileTableModel myFileTableModel;
private VirtualFile mySelectedFile;
@@ -110,6 +111,7 @@ public class EditLibraryDialog extends DialogWrapper {
@Override
public void intervalAdded(ListDataEvent e) {
myRemoveDocUrlButton.setEnabled(true);
checkDownloadOfflineDocEnabled();
}
@Override
@@ -117,6 +119,7 @@ public class EditLibraryDialog extends DialogWrapper {
Object source = e.getSource();
if (source instanceof MyDocUrlListModel && ((MyDocUrlListModel)source).getDocUrls().length == 0) {
myRemoveDocUrlButton.setEnabled(false);
checkDownloadOfflineDocEnabled();
}
}
@@ -133,6 +136,14 @@ public class EditLibraryDialog extends DialogWrapper {
}
});
myDownloadButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
downloadDocumentation();
}
});
myDownloadButton.setVisible(false); //TODO<rv> Remove
myRemoveDocUrlButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
@@ -161,6 +172,28 @@ public class EditLibraryDialog extends DialogWrapper {
if (docUrls.length > 0) {
myRemoveDocUrlButton.setEnabled(true);
}
checkDownloadOfflineDocEnabled();
}
private void checkDownloadOfflineDocEnabled() {
for (String url : getDocUrls()) {
if (myProvider.getOfflineDocUrl(url) != null) {
myDownloadButton.setEnabled(true);
return;
}
}
myDownloadButton.setEnabled(false);
}
private void downloadDocumentation() {
for (String url : getDocUrls()) {
String offlineDocUrl = myProvider.getOfflineDocUrl(url);
if (offlineDocUrl != null) {
String targetFile = myProvider.downloadOfflineDoc(myProject, offlineDocUrl, getRootPane());
myDocUrlListModel.addUrl(targetFile);
return;
}
}
}
private class MyTableCellRenderer extends DefaultTableCellRenderer {
@@ -454,10 +487,13 @@ public class EditLibraryDialog extends DialogWrapper {
}
public int addUrl(String url) {
myDocUrls.add(url);
int newIndex = myDocUrls.indexOf(url);
fireIntervalAdded(this, newIndex, newIndex);
return newIndex;
if (!myDocUrls.contains(url)) {
myDocUrls.add(url);
int newIndex = myDocUrls.indexOf(url);
fireIntervalAdded(this, newIndex, newIndex);
return newIndex;
}
return myDocUrls.indexOf(url);
}
public int indexOf(String url) {
@@ -491,6 +527,7 @@ public class EditLibraryDialog extends DialogWrapper {
int index = myDocUrlListModel.addUrl(url);
myDocUrlList.ensureIndexIsVisible(index);
myDocUrlList.setSelectedIndex(index);
checkDownloadOfflineDocEnabled();
}
}
@@ -17,8 +17,6 @@
package com.intellij.openapi.fileTypes.impl;
import com.intellij.ide.FileIconProvider;
import com.intellij.openapi.fileTypes.NativeFileType;
import com.intellij.openapi.fileTypes.UnknownFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.vfs.VirtualFile;
@@ -23,6 +23,7 @@ import com.intellij.history.utils.LocalHistoryLog;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.util.Clock;
import com.intellij.util.Consumer;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.TestOnly;
import java.util.ArrayList;
@@ -114,6 +115,8 @@ public class ChangeList {
return new Iterable<ChangeSet>() {
public Iterator<ChangeSet> iterator() {
return new Iterator<ChangeSet>() {
private final TIntHashSet recursionGuard = new TIntHashSet(1000);
private ChangeSetHolder currentBlock;
private ChangeSet next = fetchNext();
@@ -134,13 +137,13 @@ public class ChangeList {
currentBlock = new ChangeSetHolder(-1, myCurrentChangeSet);
}
else {
currentBlock = myStorage.readPrevious(-1);
currentBlock = myStorage.readPrevious(-1, recursionGuard);
}
}
}
else {
synchronized (ChangeList.this) {
currentBlock = myStorage.readPrevious(currentBlock.id);
currentBlock = myStorage.readPrevious(currentBlock.id, recursionGuard);
}
}
if (currentBlock == null) return null;
@@ -18,6 +18,7 @@ package com.intellij.history.core;
import com.intellij.history.core.changes.ChangeSet;
import com.intellij.util.Consumer;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.Nullable;
public interface ChangeListStorage {
@@ -26,7 +27,7 @@ public interface ChangeListStorage {
long nextId();
@Nullable
ChangeSetHolder readPrevious(int id);
ChangeSetHolder readPrevious(int id, TIntHashSet recursionGuard);
void purge(long period, int intervalBetweenActivities, Consumer<ChangeSet> processor);
@@ -18,12 +18,20 @@ package com.intellij.history.core;
import com.intellij.history.core.changes.ChangeSet;
import com.intellij.history.utils.LocalHistoryLog;
import com.intellij.ide.BrowserUtil;
import com.intellij.ide.actions.ShowFilePathAction;
import com.intellij.notification.*;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.newvfs.ManagingFS;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.util.Consumer;
import com.intellij.util.io.storage.AbstractStorage;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.event.HyperlinkEvent;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
@@ -33,19 +41,19 @@ public class ChangeListStorageImpl implements ChangeListStorage {
private static final int VERSION = 5;
private static final String STORAGE_FILE = "changes";
private final LocalHistoryStorage myStorage;
private final File myStorageDir;
private LocalHistoryStorage myStorage;
public ChangeListStorageImpl(File storageDir) {
try {
myStorage = createStorage(storageDir);
}
catch (IOException e) {
throw handleError(e);
}
private boolean isCompletelyBroken = false;
public ChangeListStorageImpl(File storageDir) throws IOException {
myStorageDir = storageDir;
myStorage = createStorage(myStorageDir);
}
private static LocalHistoryStorage createStorage(File storageDir) throws IOException {
String path = storageDir.getPath() + "/" + STORAGE_FILE;
LocalHistoryStorage result = new LocalHistoryStorage(path);
long fsTimestamp = getVFSTimestamp();
@@ -74,26 +82,63 @@ public class ChangeListStorageImpl implements ChangeListStorage {
return ((PersistentFS)ManagingFS.getInstance()).getCreationTimestamp();
}
private RuntimeException handleError(Throwable e) {
private void handleError(Throwable e) {
long storageTimestamp = -1;
try {
if (myStorage != null) {
myStorage.setVersion(-1);
myStorage.force();
storageTimestamp = myStorage.getFSTimestamp();
}
long vfsTimestamp = getVFSTimestamp();
long timestamp = System.currentTimeMillis();
try {
storageTimestamp = myStorage.getFSTimestamp();
}
catch (Exception ex) {
LocalHistoryLog.LOG.warn("cannot read storage timestamp", ex);
}
LocalHistoryLog.LOG.warn("Local history is broken" +
"(version:" + VERSION +
",current timestamp:" + timestamp +
",storage timestamp:" + storageTimestamp +
",vfs timestamp:" + vfsTimestamp + ")", e);
myStorage.dispose();
try {
FileUtil.delete(myStorageDir);
myStorage = createStorage(myStorageDir);
}
catch (Throwable ex) {
LocalHistoryLog.LOG.error("cannot mark storage as broken", ex);
LocalHistoryLog.LOG.warn("cannot recreate storage", ex);
isCompletelyBroken = true;
}
long vfsTimestamp = getVFSTimestamp();
long timestamp = System.currentTimeMillis() ;
throw new RuntimeException("Local history is broken and will be rebuilt after restart " +
"(version:" + VERSION +
",current timestamp:" + timestamp +
",storage timestamp:" + storageTimestamp +
",vfs timestamp:" + vfsTimestamp+ ")", e);
notifyUser("Local History storage file has become corrupted and was rebuilt.");
}
public static void notifyUser(String message) {
final String logFile = PathManager.getLogPath();
Notifications.Bus.notify(new Notification(Notifications.SYSTEM_MESSAGES_GROUP_ID,
"Local History is broken",
message + "<br>" +
"<br>" +
"Please create a <a href=\"url\">YouTrack issue</><br>" +
"and attach log files from <a href=\"file\">" + logFile,
NotificationType.ERROR,
new NotificationListener() {
@Override
public void hyperlinkUpdate(@NotNull Notification notification,
@NotNull HyperlinkEvent event) {
if ("url".equals(event.getDescription())) {
BrowserUtil.launchBrowser("http://youtrack.jetbrains.net/issues/#newissue=yes");
}
else {
File file = new File(logFile);
ShowFilePathAction.open(file, new File(logFile));
}
}
}),
NotificationDisplayType.STICKY_BALLOON,
null);
}
public synchronized void close() {
@@ -101,32 +146,47 @@ public class ChangeListStorageImpl implements ChangeListStorage {
}
public synchronized long nextId() {
return myStorage.nextId();
}
if (isCompletelyBroken) return 0;
public synchronized ChangeSetHolder readPrevious(int id) {
int prevId = id == -1 ? myStorage.getLastRecord() : myStorage.getPrevRecord(id);
if (prevId == 0) return null;
return doReadBlock(prevId);
}
private ChangeSetHolder doReadBlock(int id) {
try {
DataInputStream in = myStorage.readStream(id);
try {
return new ChangeSetHolder(id, new ChangeSet(in));
}
finally {
in.close();
}
return myStorage.nextId();
}
catch (Throwable e) {
throw handleError(e);
handleError(e);
return myStorage.nextId();
}
}
@Nullable
public synchronized ChangeSetHolder readPrevious(int id, TIntHashSet recursionGuard) {
if (isCompletelyBroken) return null;
try {
int prevId = id == -1 ? myStorage.getLastRecord() : doReadPrevSafely(id, recursionGuard);
if (prevId == 0) return null;
return doReadBlock(prevId);
}
catch (Throwable e) {
handleError(e);
return null;
}
}
@NotNull
private ChangeSetHolder doReadBlock(int id) throws IOException {
DataInputStream in = myStorage.readStream(id);
try {
return new ChangeSetHolder(id, new ChangeSet(in));
}
finally {
in.close();
}
}
public synchronized void writeNextSet(ChangeSet changeSet) {
if (isCompletelyBroken) return;
try {
int id = myStorage.createNextRecord();
AbstractStorage.StorageDataOutput out = myStorage.writeStream(id);
@@ -139,27 +199,32 @@ public class ChangeListStorageImpl implements ChangeListStorage {
myStorage.force();
}
catch (IOException e) {
throw handleError(e);
handleError(e);
}
}
public synchronized void purge(long period, int intervalBetweenActivities, Consumer<ChangeSet> processor) {
int eachBlockId = findFirstObsoleteBlock(period, intervalBetweenActivities);
if (isCompletelyBroken) return;
TIntHashSet recursionGuard = new TIntHashSet(1000);
try {
int eachBlockId = findFirstObsoleteBlock(period, intervalBetweenActivities, recursionGuard);
while (eachBlockId != 0) {
processor.consume(doReadBlock(eachBlockId).changeSet);
int toDelete = eachBlockId;
eachBlockId = myStorage.getPrevRecord(eachBlockId);
eachBlockId = doReadPrevSafely(eachBlockId, recursionGuard);
myStorage.deleteRecord(toDelete);
}
myStorage.force();
}
catch (IOException e) {
throw handleError(e);
handleError(e);
}
}
private int findFirstObsoleteBlock(long period, int intervalBetweenActivities) {
private int findFirstObsoleteBlock(long period, int intervalBetweenActivities, TIntHashSet recursionGuard) throws IOException {
long prevTimestamp = 0;
long length = 0;
@@ -176,9 +241,16 @@ public class ChangeListStorageImpl implements ChangeListStorage {
if (length >= period) return last;
last = myStorage.getPrevRecord(last);
last = doReadPrevSafely(last, recursionGuard);
}
return 0;
}
private int doReadPrevSafely(int id, TIntHashSet recursionGuard) throws IOException {
recursionGuard.add(id);
int prev = myStorage.getPrevRecord(id);
if (!recursionGuard.add(prev)) throw new IOException("Recursive records found");
return prev;
}
}
@@ -17,6 +17,8 @@ package com.intellij.history.core;
import com.intellij.history.core.changes.ChangeSet;
import com.intellij.util.Consumer;
import gnu.trove.TIntHashSet;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
@@ -35,7 +37,8 @@ public class InMemoryChangeListStorage implements ChangeListStorage {
}
@Override
public ChangeSetHolder readPrevious(int id) {
@Nullable
public ChangeSetHolder readPrevious(int id, TIntHashSet recursionGuard) {
if (mySets.isEmpty()) return null;
if (id == -1) return new ChangeSetHolder(mySets.size() - 1, mySets.get(mySets.size() - 1));
return id == 0 ? null : new ChangeSetHolder(id -1, mySets.get(id - 1));
@@ -48,6 +51,5 @@ public class InMemoryChangeListStorage implements ChangeListStorage {
@Override
public void purge(long period, int intervalBetweenActivities, Consumer<ChangeSet> processor) {
throw new UnsupportedOperationException();
}
}
@@ -70,7 +70,16 @@ public class LocalHistoryImpl extends LocalHistory implements ApplicationCompone
}
protected void initHistory() {
myChangeList = new ChangeList(new ChangeListStorageImpl(getStorageDir()));
ChangeListStorage storage;
try {
storage = new ChangeListStorageImpl(getStorageDir());
}
catch (Throwable e) {
LocalHistoryLog.LOG.warn("cannot create storage, in-memory implementation will be used", e);
storage = new InMemoryChangeListStorage();
ChangeListStorageImpl.notifyUser("Local History storage file cannot be created. In-memory storage will be used.");
}
myChangeList = new ChangeList(storage);
myVcs = new LocalHistoryFacade(myChangeList);
myGateway = new IdeaGateway();
@@ -467,7 +467,7 @@ public abstract class HistoryDialog<T extends HistoryDialogModel> extends FrameW
return;
}
CreatePatchConfigurationPanel p = new CreatePatchConfigurationPanel();
CreatePatchConfigurationPanel p = new CreatePatchConfigurationPanel(myProject);
p.setFileName(getDefaultPatchFile());
if (!showAsDialog(p)) return;
myModel.createPatch(p.getFileName(), p.isReversePatch());
@@ -16,6 +16,7 @@
package com.intellij.notification;
import com.intellij.ide.FrameStateManager;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.startup.StartupManager;
@@ -68,8 +69,9 @@ public interface Notifications {
FrameStateManager.getInstance().getApplicationActive().doWhenDone(new Runnable() {
@Override
public void run() {
Application app = ApplicationManager.getApplication();
final MessageBus bus =
project == null ? ApplicationManager.getApplication().getMessageBus() : (project.isDisposed() ? null : project.getMessageBus());
project == null ? (app.isDisposed() ? null : app.getMessageBus()) : (project.isDisposed() ? null : project.getMessageBus());
if (bus != null) {
_notify(notification, defaultDisplayType, bus);
}
@@ -22,6 +22,7 @@ import com.intellij.openapi.actionSystem.DataKey;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.INativeFileType;
import com.intellij.openapi.fileTypes.NativeFileType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
@@ -119,7 +120,7 @@ public class OpenFileDescriptor implements Navigatable {
FileType type = FileTypeManager.getInstance().getKnownFileTypeOrAssociate(myFile);
if (type == null || !myFile.isValid()) return false;
if (type instanceof NativeFileType) {
if (type instanceof INativeFileType) {
return NativeFileType.openAssociatedApplication(myFile);
}
@@ -0,0 +1,4 @@
package com.intellij.openapi.fileTypes;
public interface INativeFileType extends FileType {
}
@@ -29,7 +29,7 @@ import java.util.List;
/**
* @author yole
*/
public class NativeFileType implements FileType {
public class NativeFileType implements INativeFileType {
private static final Icon ICON = IconLoader.getIcon("/fileTypes/custom.png");
private NativeFileType() { }
@@ -0,0 +1,44 @@
/*
* Copyright 2000-2011 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.openapi.util;
import com.intellij.util.InstanceofCheckerGenerator;
/**
* @author peter
*/
public class ClassConditionKey<T> {
private final Condition<Object> myCondition;
private final Class<T> myConditionClass;
private ClassConditionKey(Class<T> aClass) {
myCondition = InstanceofCheckerGenerator.getInstance().getInstanceofChecker(aClass);
myConditionClass = aClass;
}
public static <T> ClassConditionKey<T> create(Class<T> aClass) {
return new ClassConditionKey<T>(aClass);
}
public boolean isInstance(Object o) {
return myCondition.value(o);
}
@Override
public String toString() {
return myConditionClass.getName();
}
}
@@ -16,6 +16,7 @@
package com.intellij.ui.switcher;
import com.intellij.ide.DataManager;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.AnActionListener;
import com.intellij.openapi.components.ProjectComponent;
@@ -32,24 +33,24 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.awt.event.InputEvent;
import java.awt.event.KeyEvent;
import java.util.HashSet;
import java.util.Set;
public class SwitchManager implements ProjectComponent, KeyEventDispatcher, AnActionListener {
private Project myProject;
private final Project myProject;
private QuickAccessSettings myQa;
private SwitchingSession mySession;
private boolean myWaitingForAutoInitSession;
private Alarm myInitSessionAlarm = new Alarm();
private final Alarm myInitSessionAlarm = new Alarm();
private KeyEvent myAutoInitSessionEvent;
private Set<AnAction> mySwitchActions = new HashSet<AnAction>();
private final Set<AnAction> mySwitchActions = new HashSet<AnAction>();
private Set<SwitchingSession> myFadingWay = new HashSet<SwitchingSession>();
private final Set<SwitchingSession> myFadingAway = new HashSet<SwitchingSession>();
public SwitchManager(Project project, QuickAccessSettings quickAccess, ActionManager actionManager) {
myProject = project;
@@ -62,6 +63,14 @@ public class SwitchManager implements ProjectComponent, KeyEventDispatcher, AnAc
mySwitchActions.add(actionManager.getAction(QuickAccessSettings.SWITCH_LEFT));
mySwitchActions.add(actionManager.getAction(QuickAccessSettings.SWITCH_RIGHT));
mySwitchActions.add(actionManager.getAction(QuickAccessSettings.SWITCH_APPLY));
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
Disposer.register(project, new Disposable() {
@Override
public void dispose() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(SwitchManager.this);
}
});
}
public void beforeActionPerformed(AnAction action, DataContext dataContext, AnActionEvent event) {
@@ -77,7 +86,7 @@ public class SwitchManager implements ProjectComponent, KeyEventDispatcher, AnAc
}
public boolean dispatchKeyEvent(KeyEvent e) {
if (!myQa.isEnabled()) return false;
if (!myQa.isEnabled()) return false;
if (mySession != null && !mySession.isFinished()) return false;
@@ -109,13 +118,15 @@ public class SwitchManager implements ProjectComponent, KeyEventDispatcher, AnAc
});
}
};
if (myFadingWay.size() == 0) {
if (myFadingAway.isEmpty()) {
myInitSessionAlarm.addRequest(initRunnable, Registry.intValue("actionSystem.keyGestureHoldTime"));
} else {
}
else {
initRunnable.run();
}
}
} else {
}
else {
if (myWaitingForAutoInitSession) {
cancelWaitingForAutoInit();
}
@@ -147,33 +158,30 @@ public class SwitchManager implements ProjectComponent, KeyEventDispatcher, AnAc
int mask = 0;
for (Integer each : modifierCodes) {
if (each == KeyEvent.VK_SHIFT) {
mask |= KeyEvent.SHIFT_MASK;
mask |= InputEvent.SHIFT_MASK;
}
if (each == KeyEvent.VK_CONTROL) {
mask |= KeyEvent.CTRL_MASK;
mask |= InputEvent.CTRL_MASK;
}
if (each == KeyEvent.VK_META) {
mask |= KeyEvent.META_MASK;
mask |= InputEvent.META_MASK;
}
if (each == KeyEvent.VK_ALT) {
mask |= KeyEvent.ALT_MASK;
mask |= InputEvent.ALT_MASK;
}
}
return (modifiers ^ mask) == 0;
}
public void initComponent() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().addKeyEventDispatcher(this);
}
public void disposeComponent() {
KeyboardFocusManager.getCurrentKeyboardFocusManager().removeKeyEventDispatcher(this);
myQa = null;
}
@@ -234,7 +242,8 @@ public class SwitchManager implements ProjectComponent, KeyEventDispatcher, AnAc
});
}
});
} else {
}
else {
result.setDone();
}
@@ -246,15 +255,14 @@ public class SwitchManager implements ProjectComponent, KeyEventDispatcher, AnAc
}
public boolean isSelectionWasMoved() {
if (!isSessionActive()) return false;
return mySession.isSelectionWasMoved();
return isSessionActive() && mySession.isSelectionWasMoved();
}
public void addFadingAway(SwitchingSession session) {
myFadingWay.add(session);
myFadingAway.add(session);
}
public void removeFadingAway(SwitchingSession session) {
myFadingWay.remove(session);
myFadingAway.remove(session);
}
}
@@ -41,7 +41,8 @@ public class VMOptions {
@NonNls private static final Pattern XMX_PATTERN = Pattern.compile(XMX_OPTION + MEM_SIZE_EXPR);
@NonNls private static final Pattern PERM_GEN_PATTERN = Pattern.compile(PERM_GEN_OPTION + MEM_SIZE_EXPR);
@NonNls private static final Pattern MAC_OS_VM_OPTIONS_PATTERN = Pattern.compile("(<key>VMOptions</key>(?:(?:\\s*)(?:<!--(?:.*)-->(?:\\s*))*)<string>)(.*)(</string>)");
@NonNls public static final String MAC_ARCH_VMOPTIONS = SystemInfo.is64Bit ? "VMOptions.x86_64" : "VMOptions.i386";
@NonNls private static final Pattern MAC_OS_VM_OPTIONS_PATTERN = Pattern.compile("(<key>" + MAC_ARCH_VMOPTIONS + "</key>(?:(?:\\s*)(?:<!--(?:.*)-->(?:\\s*))*)<string>)(.*)(</string>)");
@NonNls private static final String INFO_PLIST = "/Contents/Info.plist";
@@ -36,9 +36,7 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.LightVirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.PatternUtil;
import com.intellij.util.PlatformUtils;
import com.intellij.util.containers.ConcurrentHashSet;
import com.intellij.util.messages.MessageBus;
import com.intellij.util.messages.MessageBusConnection;
import gnu.trove.THashMap;
@@ -52,7 +50,6 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.io.File;
import java.util.*;
import java.util.regex.Pattern;
/**
* @author Yura Cangea
@@ -63,12 +60,9 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
private final Set<FileType> myDefaultTypes = new THashSet<FileType>();
private final ArrayList<FileTypeIdentifiableByVirtualFile> mySpecialFileTypes = new ArrayList<FileTypeIdentifiableByVirtualFile>();
private final ArrayList<Pattern> myIgnorePatterns = new ArrayList<Pattern>();
private FileTypeAssocTable<FileType> myPatternsTable = new FileTypeAssocTable<FileType>();
private final Set<String> myIgnoredFileMasksSet = new LinkedHashSet<String>();
private final Set<String> myNotIgnoredFiles = new ConcurrentHashSet<String>();
private final Set<String> myIgnoredFiles = new ConcurrentHashSet<String>();
private final IgnoredPatternSet myIgnoredPatterns = new IgnoredPatternSet();
private final FileTypeAssocTable<FileType> myInitialAssociations = new FileTypeAssocTable<FileType>();
private final Map<FileNameMatcher, String> myUnresolvedMappings = new THashMap<FileNameMatcher, String>();
private final Map<FileNameMatcher, String> myUnresolvedRemovedMappings = new THashMap<FileNameMatcher, String>();
@@ -352,67 +346,31 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
@NotNull
public String getIgnoredFilesList() {
StringBuilder sb = new StringBuilder();
for (String ignoreMask : myIgnoredFileMasksSet) {
sb.append(ignoreMask);
sb.append(';');
final Set<String> masks = myIgnoredPatterns.getIgnoreMasks();
if (masks.isEmpty()) {
return "";
}
return sb.toString();
return StringUtil.join(masks, ";") + ";";
}
public void setIgnoredFilesList(@NotNull String list) {
fireBeforeFileTypesChanged();
setIgnoredFilesListWithoutNotification(list);
myIgnoredPatterns.setIgnoreMasks(list);
fireFileTypesChanged();
}
private void setIgnoredFilesListWithoutNotification(String list) {
myIgnoredFileMasksSet.clear();
myIgnorePatterns.clear();
StringTokenizer tokenizer = new StringTokenizer(list, ";");
while (tokenizer.hasMoreTokens()) {
String ignoredFile = tokenizer.nextToken();
if (ignoredFile != null && !myIgnoredFileMasksSet.contains(ignoredFile)) {
if (!myIgnoredFileMasksSet.contains(ignoredFile)) {
myIgnorePatterns.add(PatternUtil.fromMask(ignoredFile));
}
myIgnoredFileMasksSet.add(ignoredFile);
}
}
//[mike]
//To make async delete work. See FileUtil.asyncDelete.
//Quite a hack, but still we need to have some name, which
//won't be catched by VF for sure.
//noinspection HardCodedStringLiteral
Pattern p = Pattern.compile(".*\\.__del__");
myIgnorePatterns.add(p);
}
public boolean isIgnoredFilesListEqualToCurrent(String list) {
Set<String> tempSet = new THashSet<String>();
StringTokenizer tokenizer = new StringTokenizer(list, ";");
while (tokenizer.hasMoreTokens()) {
tempSet.add(tokenizer.nextToken());
}
return tempSet.equals(myIgnoredFileMasksSet);
return tempSet.equals(myIgnoredPatterns.getIgnoreMasks());
}
public boolean isFileIgnored(@NotNull String name) {
if (myNotIgnoredFiles.contains(name)) return false;
if (myIgnoredFiles.contains(name)) return true;
for (Pattern pattern : myIgnorePatterns) {
if (pattern.matcher(name).matches()) {
myIgnoredFiles.add(name);
return true;
}
}
myNotIgnoredFiles.add(name);
return false;
return myIgnoredPatterns.isIgnored(name);
}
@Override
@@ -453,11 +411,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
}
public void fireFileTypesChanged() {
myNotIgnoredFiles.clear();
myIgnoredFiles.clear();
final FileTypeEvent event = new FileTypeEvent(this);
myMessageBus.syncPublisher(AppTopics.FILE_TYPES).fileTypesChanged(event);
myMessageBus.syncPublisher(AppTopics.FILE_TYPES).fileTypesChanged(new FileTypeEvent(this));
}
private final Map<FileTypeListener, MessageBusConnection> myAdapters = new HashMap<FileTypeListener, MessageBusConnection>();
@@ -504,7 +458,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
}
}
else if (ELEMENT_IGNOREFILES.equals(e.getName())) {
setIgnoredFilesListWithoutNotification(e.getAttributeValue(ATTRIBUTE_LIST));
myIgnoredPatterns.setIgnoreMasks(e.getAttributeValue(ATTRIBUTE_LIST));
}
else if (AbstractFileType.ELEMENT_EXTENSIONMAP.equals(e.getName())) {
readGlobalMappings(e);
@@ -583,10 +537,7 @@ public class FileTypeManagerImpl extends FileTypeManagerEx implements NamedJDOME
}
private void addIgnore(@NonNls final String ignoreMask) {
if (!myIgnoredFileMasksSet.contains(ignoreMask)) {
myIgnorePatterns.add(PatternUtil.fromMask(ignoreMask));
myIgnoredFileMasksSet.add(ignoreMask);
}
myIgnoredPatterns.addIgnoreMask(ignoreMask);
}
private void restoreStandardFileExtensions() {
@@ -0,0 +1,72 @@
/*
* Copyright 2000-2011 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.openapi.fileTypes.impl;
import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.util.io.FileUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.StringTokenizer;
/**
* @author peter
*/
public class IgnoredPatternSet {
private final Set<String> myMasks = new LinkedHashSet<String>();
private final FileTypeAssocTable<Boolean> myIgnorePatterns = new FileTypeAssocTable<Boolean>().copy();
Set<String> getIgnoreMasks() {
return Collections.unmodifiableSet(myMasks);
}
void setIgnoreMasks(@NotNull String list) {
clearPatterns();
StringTokenizer tokenizer = new StringTokenizer(list, ";");
while (tokenizer.hasMoreTokens()) {
String ignoredFile = tokenizer.nextToken();
if (ignoredFile != null) {
addIgnoreMask(ignoredFile);
}
}
}
void addIgnoreMask(@NotNull String ignoredFile) {
if (myIgnorePatterns.findAssociatedFileType(ignoredFile) == null) {
myMasks.add(ignoredFile);
myIgnorePatterns.addAssociation(FileTypeManager.parseFromString(ignoredFile), Boolean.TRUE);
}
}
boolean isIgnored(@NotNull String fileName) {
if (myIgnorePatterns.findAssociatedFileType(fileName) == Boolean.TRUE) {
return true;
}
//Quite a hack, but still we need to have some name, which
//won't be catched by VFS for sure.
return fileName.endsWith(FileUtil.ASYNC_DELETE_EXTENSION);
}
void clearPatterns() {
myMasks.clear();
myIgnorePatterns.removeAllAssociations(Boolean.TRUE);
}
}
@@ -19,8 +19,7 @@ package com.intellij.openapi.project.impl;
* @author peter
*/
public class DefaultProject extends ProjectImpl {
protected DefaultProject(ProjectManagerImpl manager, String filePath, boolean isOptimiseTestLoadSpeed,
String projectName) {
protected DefaultProject(ProjectManagerImpl manager, String filePath, boolean isOptimiseTestLoadSpeed, String projectName) {
super(manager, filePath, isOptimiseTestLoadSpeed, projectName);
}
@@ -272,7 +272,7 @@ commit.dialog.failed.commit.template=Failed commit: {0}
commit.dialog.completed.successfully=Completed successfully
commit.dialog.refresh.files=Synchronizing files...
commit.dialog.rejected.commit.template=Rejected commit: {0}
commit.dialog.changelist.label=Change list:
commit.dialog.changelist.label=Change lis&t:
commit.dialog.changed.files.label=Changed &Files
commit.wait.util.synced.message=Please wait until VCS synchronization is finished.
commit.wait.util.synced.title=Finishing VCS refresh
@@ -548,3 +548,4 @@ line.annotation.aspect.author=Author
line.annotation.aspect.date=Date
line.annotation.aspect.revision=Revision
annotation.commit.number=Commit number
create.patch.file.path=&Patch file:
@@ -112,4 +112,5 @@
<extensionPoint name="statistics.usagesCollector" interface="com.intellij.internal.statistic.UsagesCollector"/>
<extensionPoint name="xmlRpcHandler" beanClass="com.intellij.ide.XmlRpcHandlerBean"/>
</extensionPoints>
@@ -62,6 +62,12 @@
<add-to-group group-id="NewGroup" anchor="before" relative-to-action="NewFromTemplate"/>
</group>
<action id="HtmlNavigatePopupAction"
class = "com.intellij.ide.actions.NavigateToRelatedFileAction"
text = "Related files..." description="Navigate to related file">
<add-to-group group-id="GoToMenu" relative-to-action="GotoLine" anchor="after"/>
</action>
<group id="NewXmlDescriptor" class="com.intellij.ide.actions.NonEmptyActionGroup" text="XML Configuration File" popup="true" icon="/fileTypes/xml.png">
<add-to-group group-id="NewGroup" anchor="last"/>
</group>
@@ -43,6 +43,8 @@
<extensionPoint name="xml.zenCodingGenerator" interface="com.intellij.codeInsight.template.zencoding.generators.ZenCodingGenerator"/>
<extensionPoint name="xml.zenCodingFilter" interface="com.intellij.codeInsight.template.zencoding.filters.ZenCodingFilter"/>
<extensionPoint name="xml.relatedFilesContributor" interface="com.intellij.navigation.RelatedFilesContributor"/>
</extensionPoints>
<extensions defaultExtensionNs="com.intellij">
@@ -37,8 +37,8 @@ public class _LastInSuiteTest extends TestCase {
}.execute().throwException();
final Application application = ApplicationManager.getApplication();
LeakHunter.checkProjectLeak(application);
// disposes default project too
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
@@ -51,6 +51,7 @@ public class _LastInSuiteTest extends TestCase {
}
});
LeakHunter.checkProjectLeak(application);
Disposer.assertIsEmpty();
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
<orderEntry type="module" module-name="xdebugger-impl" scope="RUNTIME" />
<orderEntry type="module" module-name="resources-en" scope="RUNTIME" />
<orderEntry type="module" module-name="community-resources" scope="RUNTIME" />
<orderEntry type="library" exported="" name="Mocks" level="project" />
<orderEntry type="library" exported="" scope="TEST" name="Mocks" level="project" />
</component>
</module>
@@ -53,6 +53,7 @@ public class FileUtil {
// do not use channels to copy files larger than 5 Mb because of possible MapFailed error
private static final long CHANNELS_COPYING_LIMIT = 5L * 1024L * 1024L;
private static String ourCanonicalTempPathCache = null;
public static final String ASYNC_DELETE_EXTENSION = ".__del__";
@Nullable
public static String getRelativePath(File base, File file) {
@@ -488,7 +489,7 @@ public class FileUtil {
private static File getTempFile(String originalFileName, File parent) {
int randomSuffix = (int)(System.currentTimeMillis() % 1000);
for (int i = randomSuffix; ; i++) {
@NonNls String name = "___" + originalFileName + i + ".__del__";
@NonNls String name = "___" + originalFileName + i + ASYNC_DELETE_EXTENSION;
File tempFile = new File(parent, name);
if (!tempFile.exists()) return tempFile;
}
@@ -0,0 +1,25 @@
/*
* Copyright 2000-2011 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.util;
/**
* @author irengrig
* Date: 2/4/11
* Time: 3:36 PM
*/
public enum TreeNodeState {
SELECTED,CLEAR,HAVE_SELECTED_ABOVE,HAVE_SELECTED_BELOW
}
@@ -112,7 +112,7 @@ public class CreatePatchCommitExecutor implements CommitExecutorWithHelp, Projec
}
private class CreatePatchCommitSession implements CommitSession {
private final CreatePatchConfigurationPanel myPanel = new CreatePatchConfigurationPanel();
private final CreatePatchConfigurationPanel myPanel = new CreatePatchConfigurationPanel(myProject);
@Nullable
public JComponent getAdditionalConfigurationUI() {
@@ -14,7 +14,7 @@
</constraints>
<properties>
<labelFor value="e6922"/>
<text resource-bundle="messages/VcsBundle" key="create.patch.file.name.field"/>
<text resource-bundle="messages/VcsBundle" key="create.patch.file.path"/>
</properties>
</component>
<vspacer id="86590">
@@ -22,7 +22,17 @@
*/
package com.intellij.openapi.vcs.changes.patch;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserFactory;
import com.intellij.openapi.fileChooser.FileSaverDescriptor;
import com.intellij.openapi.fileChooser.FileSaverDialog;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileWrapper;
import com.intellij.util.Consumer;
import javax.swing.*;
@@ -37,15 +47,22 @@ public class CreatePatchConfigurationPanel {
private JLabel myErrorLabel;
private Consumer<Boolean> myOkEnabledListener;
public CreatePatchConfigurationPanel() {
public CreatePatchConfigurationPanel(final Project project) {
myFileNameField.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setSelectedFile(new File(myFileNameField.getText()));
if (fileChooser.showSaveDialog(myFileNameField) != JFileChooser.APPROVE_OPTION) {
return;
final FileSaverDialog dialog =
FileChooserFactory.getInstance().createSaveFileDialog(
new FileSaverDescriptor("Save patch to", ""), myPanel);
final String path = FileUtil.toSystemIndependentName(myFileNameField.getText().trim());
final int idx = path.lastIndexOf("/");
VirtualFile baseDir = idx == -1 ? project.getBaseDir() :
(LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(path.substring(0, idx))));
baseDir = baseDir == null ? project.getBaseDir() : baseDir;
final String name = idx == -1 ? path : path.substring(idx + 1);
final VirtualFileWrapper fileWrapper = dialog.save(baseDir, name);
if (fileWrapper != null) {
myFileNameField.setText(fileWrapper.getFile().getPath());
}
myFileNameField.setText(fileChooser.getSelectedFile().getPath());
}
});
@@ -53,6 +70,7 @@ public class CreatePatchConfigurationPanel {
public void inputMethodTextChanged(final InputMethodEvent event) {
checkName();
}
public void caretPositionChanged(final InputMethodEvent event) {
}
});
@@ -60,9 +78,11 @@ public class CreatePatchConfigurationPanel {
public void keyTyped(final KeyEvent e) {
checkName();
}
public void keyPressed(final KeyEvent e) {
checkName();
}
public void keyReleased(final KeyEvent e) {
checkName();
}
@@ -260,7 +260,6 @@ public class MultipleChangeListBrowser extends ChangesBrowser {
add(myChooser, BorderLayout.CENTER);
JLabel label = new JLabel(VcsBundle.message("commit.dialog.changelist.label"));
label.setDisplayedMnemonic('l');
label.setLabelFor(myChooser);
add(label, BorderLayout.WEST);
}
@@ -0,0 +1,94 @@
/*
* Copyright 2000-2011 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.util.treeWithCheckedNodes;
import com.intellij.util.Processor;
import com.intellij.util.TreeNodeState;
import com.intellij.util.containers.SLRUMap;
import com.intellij.util.containers.hash.HashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
/**
* @author irengrig
* Date: 2/7/11
* Time: 10:40 AM
*
* We can have only limited number of nodes selected in a tree;
* and children of selected nodes (any level) cannot change their state
* used together with {@link SelectionManager}
*/
public class SelectedState<T> {
private final Set<T> mySelected;
private final SLRUMap<T, TreeNodeState> myCache;
private final int mySelectedSize;
public SelectedState(final int selectedSize, final int queueSize) {
mySelectedSize = selectedSize;
assert queueSize > 0;
mySelected = new HashSet<T>();
myCache = new SLRUMap<T, TreeNodeState>(queueSize,queueSize);
}
@Nullable
public TreeNodeState get(final T node) {
if (mySelected.contains(node)) return TreeNodeState.SELECTED;
return myCache.get(node);
}
public void clear(final T node) {
myCache.remove(node);
mySelected.remove(node);
}
public void clearAllCachedMatching(final Processor<T> processor) {
final Set<Map.Entry<T, TreeNodeState>> entries = myCache.entrySet();
for (Map.Entry<T, TreeNodeState> entry: entries){
if(processor.process(entry.getKey())) {
myCache.remove(entry.getKey());
}
}
}
public void remove(final T node) {
mySelected.remove(node);
myCache.remove(node);
}
@NotNull
public TreeNodeState putAndPass(final T node, @NotNull final TreeNodeState state) {
if (TreeNodeState.SELECTED.equals(state)) {
mySelected.add(node);
myCache.remove(node);
} else {
mySelected.remove(node);
myCache.put(node, state);
}
return state;
}
public boolean canAddSelection() {
return mySelected.size() < mySelectedSize;
}
public Set<T> getSelected() {
return Collections.unmodifiableSet(mySelected);
}
}
@@ -0,0 +1,151 @@
/*
* Copyright 2000-2011 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.util.treeWithCheckedNodes;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.PairProcessor;
import com.intellij.util.Processor;
import com.intellij.util.TreeNodeState;
import com.intellij.util.containers.Convertor;
import javax.swing.tree.DefaultMutableTreeNode;
/**
* @author irengrig
* Date: 2/7/11
* Time: 10:43 AM
*
* see {@link SelectedState}
*/
public class SelectionManager {
private final SelectedState<VirtualFile> myState;
private final Convertor<DefaultMutableTreeNode, VirtualFile> myNodeConvertor;
public SelectionManager(int selectedSize, int queueSize, final Convertor<DefaultMutableTreeNode, VirtualFile> nodeConvertor) {
myNodeConvertor = nodeConvertor;
myState = new SelectedState<VirtualFile>(selectedSize, queueSize);
}
public void toggleSelection(final DefaultMutableTreeNode node) {
final StateWorker stateWorker = new StateWorker(node, myNodeConvertor);
if (stateWorker.getVf() == null) return;
final TreeNodeState state = getStateImpl(stateWorker);
if (TreeNodeState.HAVE_SELECTED_ABOVE.equals(state)) return;
if (TreeNodeState.CLEAR.equals(state) && (! myState.canAddSelection())) return;
final TreeNodeState futureState =
myState.putAndPass(stateWorker.getVf(), TreeNodeState.SELECTED.equals(state) ? TreeNodeState.CLEAR : TreeNodeState.SELECTED);
// for those possibly duplicate nodes (i.e. when we have root for module and root for VCS root, each file is shown twice in a tree ->
// clear all suspicious cached)
if (! TreeNodeState.SELECTED.equals(futureState)) {
myState.clearAllCachedMatching(new Processor<VirtualFile>() {
@Override
public boolean process(VirtualFile virtualFile) {
return VfsUtil.isAncestor(virtualFile, stateWorker.getVf(), false);
}
});
}
stateWorker.iterateParents(myState, new PairProcessor<VirtualFile, TreeNodeState>() {
@Override
public boolean process(VirtualFile virtualFile, TreeNodeState state) {
if (TreeNodeState.SELECTED.equals(futureState)) {
myState.putAndPass(virtualFile, TreeNodeState.HAVE_SELECTED_BELOW);
} else {
myState.remove(virtualFile);
}
return true;
}
});
myState.clearAllCachedMatching(new Processor<VirtualFile>() {
@Override
public boolean process(VirtualFile vf) {
return VfsUtil.isAncestor(stateWorker.getVf(), vf, false);
}
});
for (VirtualFile selected : myState.getSelected()) {
if (VfsUtil.isAncestor(stateWorker.getVf(), selected, true)) {
myState.remove(selected);
}
}
}
public TreeNodeState getState(final DefaultMutableTreeNode node) {
return getStateImpl(new StateWorker(node, myNodeConvertor));
}
private TreeNodeState getStateImpl(final StateWorker stateWorker) {
if (stateWorker.getVf() == null) return TreeNodeState.CLEAR;
final TreeNodeState stateSelf = myState.get(stateWorker.getVf());
if (stateSelf != null) return stateSelf;
final Ref<TreeNodeState> result = new Ref<TreeNodeState>();
stateWorker.iterateParents(myState, new PairProcessor<VirtualFile, TreeNodeState>() {
@Override
public boolean process(VirtualFile virtualFile, TreeNodeState state) {
if (state != null) {
if (TreeNodeState.SELECTED.equals(state) || TreeNodeState.HAVE_SELECTED_ABOVE.equals(state)) {
result.set(myState.putAndPass(stateWorker.getVf(), TreeNodeState.HAVE_SELECTED_ABOVE));
}
return false; // exit
}
return true;
}
});
if (! result.isNull()) return result.get();
for (VirtualFile selected : myState.getSelected()) {
if (VfsUtil.isAncestor(stateWorker.getVf(), selected, true)) {
return myState.putAndPass(stateWorker.getVf(), TreeNodeState.HAVE_SELECTED_BELOW);
}
}
return TreeNodeState.CLEAR;
}
private static class StateWorker {
private final DefaultMutableTreeNode myNode;
private final Convertor<DefaultMutableTreeNode, VirtualFile> myConvertor;
private VirtualFile myVf;
private StateWorker(DefaultMutableTreeNode node, final Convertor<DefaultMutableTreeNode, VirtualFile> convertor) {
myNode = node;
myConvertor = convertor;
myVf = myConvertor.convert(node);
}
public VirtualFile getVf() {
return myVf;
}
public void iterateParents(final SelectedState<VirtualFile> states, final PairProcessor<VirtualFile, TreeNodeState> parentsProcessor) {
DefaultMutableTreeNode current = (DefaultMutableTreeNode) myNode.getParent();
// up cycle
while (current != null) {
final VirtualFile file = myConvertor.convert(current);
if (file == null) return;
final TreeNodeState state = states.get(file);
if (! parentsProcessor.process(file, state)) return;
current = (DefaultMutableTreeNode)current.getParent();
}
}
}
}
@@ -628,7 +628,7 @@ manual.array.copy.display.name=Manual array copy
manual.array.to.collection.copy.display.name=Manual array to collection copy
long.literals.ending.with.lowercase.l.display.name='long' literal ending with 'l' instead of 'L'
overly.complex.arithmetic.expression.display.name=Overly complex arithmetic expression
j.unit.abstract.test.class.naming.convention.display.name=JUnit abstract test class naming convention
junit.abstract.test.class.naming.convention.display.name=JUnit abstract test class naming convention
unnecessary.parentheses.display.name=Unnecessary parentheses
test.case.in.product.code.display.name=JUnit TestCase in product source
test.method.in.product.code.display.name=JUnit test method in product source
@@ -805,7 +805,7 @@ class.in.top.level.package.display.name=Class without package statement
confusing.else.display.name=Confusing 'else' branch
public.field.accessed.in.synchronized.context.display.name=Non-private field accessed in synchronized context
string.replaceable.by.string.buffer.display.name=Non-constant String should be StringBuilder
j.unit.test.class.naming.convention.display.name=JUnit test class naming convention
junit.test.class.naming.convention.display.name=JUnit test class naming convention
method.coupling.display.name=Overly coupled method
collections.must.have.initial.capacity.display.name=Collection without initial capacity
anonymous.inner.class.display.name=Anonymous inner class
@@ -1131,12 +1131,12 @@ instance.variable.name.convention.problem.descriptor.regex.mismatch=Instance fie
interface.name.convention.problem.descriptor.short=Interface name <code>#ref</code> is too short #loc
interface.name.convention.problem.descriptor.long=Interface name <code>#ref</code> is too long #loc
interface.name.convention.problem.descriptor.regex.mismatch=Interface name <code>#ref</code> doesn''t match regex ''{0}'' #loc
j.unit.abstract.test.class.naming.convention.problem.descriptor.short=Abstract JUnit test class name <code>#ref</code> is too short #loc
j.unit.abstract.test.class.naming.convention.problem.descriptor.long=Abstract JUnit test class name <code>#ref</code> is too long #loc
j.unit.abstract.test.class.naming.convention.problem.descriptor.regex.mismatch=Abstract JUnit test class name <code>#ref</code> doesn''t match regex ''{0}'' #loc
j.unit.test.class.naming.convention.problem.descriptor.short=JUnit test class name <code>#ref</code> is too short #loc
j.unit.test.class.naming.convention.problem.descriptor.long=JUnit test class name <code>#ref</code> is too long #loc
j.unit.test.class.naming.convention.problem.descriptor.regex.mismatch=JUnit test class name <code>#ref</code> doesn''t match regex ''{0}'' #loc
junit.abstract.test.class.naming.convention.problem.descriptor.short=Abstract JUnit test class name <code>#ref</code> is too short #loc
junit.abstract.test.class.naming.convention.problem.descriptor.long=Abstract JUnit test class name <code>#ref</code> is too long #loc
junit.abstract.test.class.naming.convention.problem.descriptor.regex.mismatch=Abstract JUnit test class name <code>#ref</code> doesn''t match regex ''{0}'' #loc
junit.test.class.naming.convention.problem.descriptor.short=JUnit test class name <code>#ref</code> is too short #loc
junit.test.class.naming.convention.problem.descriptor.long=JUnit test class name <code>#ref</code> is too long #loc
junit.test.class.naming.convention.problem.descriptor.regex.mismatch=JUnit test class name <code>#ref</code> doesn''t match regex ''{0}'' #loc
local.variable.naming.convention.problem.descriptor.short=Local variable name <code>#ref</code> is too short #loc
local.variable.naming.convention.problem.descriptor.long=Local variable name <code>#ref</code> is too long #loc
local.variable.naming.convention.problem.descriptor.regex.mismatch=Local variable name <code>#ref</code> doesn''t match regex ''{0}'' #loc
@@ -1182,7 +1182,7 @@ unnecessary.boxing.remove.quickfix=Remove boxing
unnecessary.unboxing.remove.quickfix=Remove unboxing
misordered.assert.equals.parameters.flip.quickfix=Flip compared parameters
setup.calls.super.setup.add.quickfix=Add call to 'super.setUp()'
simplify.j.unit.assertion.simplify.quickfix=Simplify assertion
simplify.junit.assertion.simplify.quickfix=Simplify assertion
teardown.calls.super.teardown.add.quickfix=Add call to 'super.tearDown()'
test.method.is.public.void.no.arg.problem.descriptor1=Test method <code>#ref()</code> should probably not have parameters #loc
test.method.is.public.void.no.arg.problem.descriptor2=Test method <code>#ref()</code> is not declared 'public void' #loc
@@ -1831,4 +1831,7 @@ shift.out.of.range.quickfix=Replace ''{0}'' with ''{1}''
boxing.boxed.value.display.name=Boxing of already boxed value
boxing.boxed.value.problem.descriptor=Boxing of already boxed <code>#ref</code>
boxing.boxed.value.quickfix=Remove unnecessary boxing
unnecessary.javadoc.link.option=Ignore inline links to super methods
unnecessary.javadoc.link.option=Ignore inline links to super methods
constant.junit.assert.argument.display.name=Constant JUnit assert argument
constant.junit.assert.argument.problem.descriptor=Argument <code>#ref</code> is constant
test.case.with.no.test.methods.option=Ignore test cases which have super classes with test methods
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2008 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@ package com.siyeh.ig;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
public abstract class BaseInspectionVisitor extends JavaElementVisitor{
@@ -49,7 +50,8 @@ public abstract class BaseInspectionVisitor extends JavaElementVisitor{
}
protected final void registerMethodCallError(
@NotNull PsiMethodCallExpression expression, Object... infos) {
@NotNull PsiMethodCallExpression expression,
@NonNls Object... infos) {
final PsiReferenceExpression methodExpression =
expression.getMethodExpression();
final PsiElement nameToken = methodExpression.getReferenceNameElement();
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,10 @@
package com.siyeh.ig.bugs;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.EquivalenceChecker;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -91,9 +91,9 @@ public class CollectionAddedToSelfInspection extends BaseInspection {
if(qualifierClass == null){
return;
}
if(!ClassUtils.isSubclass(qualifierClass,
if(!InheritanceUtil.isInheritor(qualifierClass,
CommonClassNames.JAVA_UTIL_COLLECTION) &&
!ClassUtils.isSubclass(qualifierClass,
!InheritanceUtil.isInheritor(qualifierClass,
CommonClassNames.JAVA_UTIL_MAP)) {
return;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -22,12 +22,12 @@ import com.intellij.codeInspection.ui.RemoveAction;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.LibraryUtil;
import com.siyeh.ig.ui.*;
import com.siyeh.ig.ui.ToggleAction;
import org.jdom.Element;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -154,7 +154,7 @@ public class IgnoreResultOfCallInspection extends BaseInspection {
continue;
}
final String className = classNames.get(i);
if (!ClassUtils.isSubclass(aClass, className)) {
if (!InheritanceUtil.isInheritor(aClass, className)) {
continue;
}
registerMethodCallError(call, aClass);
@@ -198,7 +198,6 @@ public class IgnoreResultOfCallInspection extends BaseInspection {
JCheckBox nonLibraryCheckbox;
Form(){
super();
addButton.setAction(new AddAction(table));
removeButton.setAction(new RemoveAction(table));
nonLibraryCheckbox.setAction(new ToggleAction(
@@ -1,5 +1,5 @@
/*
* Copyright 2007-2010 Bas Leijdekkers
* Copyright 2007-2011 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,12 +18,12 @@ package com.siyeh.ig.bugs;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -120,7 +120,7 @@ public class NewStringBufferWithCharArgumentInspection extends BaseInspection {
return;
}
final PsiClass aClass = constructor.getContainingClass();
if (!ClassUtils.isSubclass(aClass,
if (!InheritanceUtil.isInheritor(aClass,
CommonClassNames.JAVA_LANG_ABSTRACT_STRING_BUILDER)) {
return;
}
@@ -18,13 +18,13 @@ package com.siyeh.ig.bugs;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import com.intellij.util.IncorrectOperationException;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NonNls;
@@ -224,7 +224,8 @@ public class StringConcatenationInMessageFormatCallInspection
return false;
}
final PsiClass aClass = (PsiClass) target;
return ClassUtils.isSubclass(aClass, "java.text.MessageFormat");
return InheritanceUtil.isInheritor(aClass,
"java.text.MessageFormat");
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2005-2010 Bas Leijdekkers
* Copyright 2005-2011 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,10 +16,10 @@
package com.siyeh.ig.bugs;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
@@ -76,7 +76,7 @@ public class SuspiciousToArrayCallInspection extends BaseInspection {
final PsiClassType classType = (PsiClassType)type;
final PsiClass aClass = classType.resolve();
if (aClass == null ||
!ClassUtils.isSubclass(aClass,
!InheritanceUtil.isInheritor(aClass,
CommonClassNames.JAVA_UTIL_COLLECTION)) {
return;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2008 Bas Leijdekkers
* Copyright 2008-2011 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,24 +17,26 @@ package com.siyeh.ig.bugs;
import com.intellij.psi.*;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.Query;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.TypeUtils;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.InspectionGadgetsBundle;
import org.jetbrains.annotations.NotNull;
public class ThrowableResultOfMethodCallIgnoredInspection
extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"throwable.result.of.method.call.ignored.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
@@ -46,6 +48,7 @@ public class ThrowableResultOfMethodCallIgnoredInspection
return true;
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new ThrowableResultOfMethodCallIgnoredVisitor();
}
@@ -75,7 +78,7 @@ public class ThrowableResultOfMethodCallIgnoredInspection
}
if (!method.hasModifierProperty(PsiModifier.STATIC)) {
final PsiClass containingClass = method.getContainingClass();
if (ClassUtils.isSubclass(containingClass,
if (InheritanceUtil.isInheritor(containingClass,
CommonClassNames.JAVA_LANG_THROWABLE)) {
return;
}
@@ -117,11 +120,9 @@ public class ThrowableResultOfMethodCallIgnoredInspection
while (usageParent instanceof PsiParenthesizedExpression) {
usageParent = usageParent.getParent();
}
if (usageParent instanceof PsiThrowStatement) {
return;
} else if (usageParent instanceof PsiReturnStatement) {
return;
} else if (usageParent instanceof PsiExpressionList) {
if (usageParent instanceof PsiThrowStatement ||
usageParent instanceof PsiReturnStatement ||
usageParent instanceof PsiExpressionList) {
return;
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,11 @@
package com.siyeh.ig.bugs;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NotNull;
@@ -65,7 +65,8 @@ public class UseOfPropertiesAsHashtableInspection extends BaseInspection {
if(containingClass == null){
return;
}
if(!ClassUtils.isSubclass(containingClass, "java.util.Hashtable")){
if(!InheritanceUtil.isInheritor(containingClass,
"java.util.Hashtable")){
return;
}
final PsiExpression qualifier =
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2011 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.
@@ -218,8 +218,8 @@ public class MissingOverrideAnnotationInspection extends BaseInspection {
final List<PsiMethod> toExclude = new SmartList<PsiMethod>();
for (PsiMethod superMethod : superMethods) {
final PsiClass superClass = superMethod.getContainingClass();
if (!InheritanceUtil.isCorrectDescendant(methodClass,
superClass, true)) {
if (!InheritanceUtil.isInheritorOrSelf(methodClass, superClass,
true)) {
toExclude.add(superMethod);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,13 +15,13 @@
*/
package com.siyeh.ig.controlflow;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.HardcodedMethodConstants;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -144,7 +144,7 @@ public class ForLoopWithMissingComponentInspection extends BaseInspection {
if(declaredClass == null){
continue;
}
if(!ClassUtils.isSubclass(declaredClass,
if(!InheritanceUtil.isInheritor(declaredClass,
CommonClassNames.JAVA_UTIL_ITERATOR)){
continue;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,10 +17,10 @@ package com.siyeh.ig.errorhandling;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiClass;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
public class CheckedExceptionClassInspection extends BaseInspection {
@@ -47,11 +47,11 @@ public class CheckedExceptionClassInspection extends BaseInspection {
private static class CheckedExceptionClassVisitor
extends BaseInspectionVisitor {
@Override public void visitClass(@NotNull PsiClass aClass) {
if (!ClassUtils.isSubclass(aClass,
if (!InheritanceUtil.isInheritor(aClass,
CommonClassNames.JAVA_LANG_THROWABLE)) {
return;
}
if (ClassUtils.isSubclass(aClass,
if (InheritanceUtil.isInheritor(aClass,
CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION)) {
return;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -16,11 +16,11 @@
package com.siyeh.ig.errorhandling;
import com.intellij.psi.*;
import com.intellij.psi.util.InheritanceUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import com.siyeh.ig.psiutils.TypeUtils;
import org.jetbrains.annotations.NotNull;
@@ -73,7 +73,7 @@ public class ErrorRethrownInspection extends BaseInspection {
if (aClass == null) {
return;
}
if (!ClassUtils.isSubclass(aClass,
if (!InheritanceUtil.isInheritor(aClass,
CommonClassNames.JAVA_LANG_ERROR)) {
return;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,12 +19,12 @@ import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.InspectionGadgetsFix;
import com.siyeh.ig.fixes.MakeFieldFinalFix;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -69,7 +69,7 @@ public class NonFinalFieldOfExceptionInspection extends BaseInspection {
if (containingClass == null) {
return;
}
if (!ClassUtils.isSubclass(containingClass,
if (!InheritanceUtil.isInheritor(containingClass,
CommonClassNames.JAVA_LANG_EXCEPTION)) {
return;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2010 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -17,10 +17,10 @@ package com.siyeh.ig.errorhandling;
import com.intellij.psi.CommonClassNames;
import com.intellij.psi.PsiClass;
import com.intellij.psi.util.InheritanceUtil;
import com.siyeh.InspectionGadgetsBundle;
import com.siyeh.ig.BaseInspection;
import com.siyeh.ig.BaseInspectionVisitor;
import com.siyeh.ig.psiutils.ClassUtils;
import org.jetbrains.annotations.NotNull;
public class UncheckedExceptionClassInspection extends BaseInspection {
@@ -48,13 +48,13 @@ public class UncheckedExceptionClassInspection extends BaseInspection {
extends BaseInspectionVisitor {
@Override public void visitClass(@NotNull PsiClass aClass) {
if (!ClassUtils.isSubclass(aClass,
if (!InheritanceUtil.isInheritor(aClass,
CommonClassNames.JAVA_LANG_THROWABLE)) {
return;
}
if (ClassUtils.isSubclass(aClass,
if (InheritanceUtil.isInheritor(aClass,
CommonClassNames.JAVA_LANG_EXCEPTION) &&
!ClassUtils.isSubclass(aClass,
!InheritanceUtil.isInheritor(aClass,
CommonClassNames.JAVA_LANG_RUNTIME_EXCEPTION)) {
return;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2008-2009 Bas Leijdekkers
* Copyright 2008-2011 Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,11 +18,11 @@ package com.siyeh.ig.fixes;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.search.searches.ReferencesSearch;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.Query;
import com.siyeh.InspectionGadgetsBundle;
@@ -74,9 +74,8 @@ public class ExtractParameterAsLocalVariableFix
if (body == null) {
return;
}
final PsiManager manager = PsiManager.getInstance(project);
final CodeStyleManager codeStyleManager =
manager.getCodeStyleManager();
CodeStyleManager.getInstance(project);
final String parameterName = parameterReference.getText();
final JavaCodeStyleManager javaCodeStyleManager =
JavaCodeStyleManager.getInstance(project);
@@ -192,7 +191,7 @@ public class ExtractParameterAsLocalVariableFix
(PsiAssignmentExpression)parent;
final IElementType tokenType =
assignmentExpression.getOperationTokenType();
if (tokenType != JavaTokenType.EQ) {
if (!JavaTokenType.EQ.equals(tokenType)) {
return false;
}
final PsiExpression lExpression =
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -29,18 +29,21 @@ import org.jetbrains.annotations.NotNull;
public class OverriddenMethodCallDuringObjectConstructionInspection
extends BaseInspection{
@Override
@NotNull
public String getDisplayName(){
return InspectionGadgetsBundle.message(
"overridden.method.call.in.constructor.display.name");
}
@Override
@NotNull
public String buildErrorString(Object... infos){
return InspectionGadgetsBundle.message(
"overridden.method.call.in.constructor.problem.descriptor");
}
@Override
public BaseInspectionVisitor buildVisitor(){
return new OverriddenMethodCallInConstructorVisitor();
}
@@ -90,7 +93,7 @@ public class OverriddenMethodCallDuringObjectConstructionInspection
}
final PsiClass calledMethodClass =
calledMethod.getContainingClass();
if(!InheritanceUtil.isCorrectDescendant(containingClass,
if(!InheritanceUtil.isInheritorOrSelf(containingClass,
calledMethodClass, true)){
return;
}
@@ -1,5 +1,5 @@
/*
* Copyright 2003-2007 Dave Griffith, Bas Leijdekkers
* Copyright 2003-2011 Dave Griffith, Bas Leijdekkers
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -28,18 +28,21 @@ import org.jetbrains.annotations.NotNull;
public class ClassWithoutConstructorInspection extends BaseInspection {
@Override
@NotNull
public String getDisplayName() {
return InspectionGadgetsBundle.message(
"class.without.constructor.display.name");
}
@Override
@NotNull
protected String buildErrorString(Object... infos) {
return InspectionGadgetsBundle.message(
"class.without.constructor.problem.descriptor");
}
@Override
protected InspectionGadgetsFix buildFix(Object... infos) {
return new ClassWithoutConstructorFix();
}
@@ -53,12 +56,13 @@ public class ClassWithoutConstructorInspection extends BaseInspection {
"class.without.constructor.create.quickfix");
}
@Override
public void doFix(Project project, ProblemDescriptor descriptor)
throws IncorrectOperationException {
final PsiElement classIdentifier = descriptor.getPsiElement();
final PsiClass aClass = (PsiClass)classIdentifier.getParent();
final PsiManager psiManager = PsiManager.getInstance(project);
final PsiElementFactory factory = JavaPsiFacade.getInstance(psiManager.getProject()).getElementFactory();
final PsiElementFactory factory =
JavaPsiFacade.getElementFactory(project);
final PsiMethod constructor = factory.createConstructor();
final PsiModifierList modifierList = constructor.getModifierList();
if (aClass == null) {
@@ -78,11 +82,12 @@ public class ClassWithoutConstructorInspection extends BaseInspection {
}
aClass.add(constructor);
final CodeStyleManager styleManager =
psiManager.getCodeStyleManager();
CodeStyleManager.getInstance(project);
styleManager.reformat(constructor);
}
}
@Override
public BaseInspectionVisitor buildVisitor() {
return new ClassWithoutConstructorVisitor();
}

Some files were not shown because too many files have changed in this diff Show More