diff --git a/build/scripts/libLicenses.gant b/build/scripts/libLicenses.gant index 2449222cde3a..a1eed990ad33 100644 --- a/build/scripts/libLicenses.gant +++ b/build/scripts/libLicenses.gant @@ -103,20 +103,27 @@ libraryLicense(name: "Ant", version: "1.7", license: "Apache 2.0", url: "http:// libraryLicense(name: "ASM Bytecode Manipulation Framework", libraryName: "asm", version: "3.3", license: "BSD", url: "http://asm.objectweb.org/", licenseUrl: "http://asm.objectweb.org/license.html") libraryLicense(name: "Axis", libraryName: "axis-1.4", version: "1.4", license: "Apache 2.0", url: "http://ws.apache.org/axis/", licenseUrl: "http://svn.jetbrains.org/idea/Trunk/bundled/WebServices/resources/lib/axis-1.4.0/axis.LICENSE") libraryLicense(name: "CGLib", libraryName: "CGLIB", version: "2.2", license: "Apache", url: "http://cglib.sourceforge.net/", licenseUrl: "http://www.apache.org/foundation/licence-FAQ.html") +libraryLicense(name: "classworlds", libraryName: "classworlds-1.1.jar", version: "1.1", license: "codehaus", url: "http://classworlds.codehaus.org/", licenseUrl: "http://classworlds.codehaus.org/license.html") +libraryLicense(name: "Apache Commons BeanUtils", libraryName: "commons-beanutils.jar", version: "1.6", license: "Apache 2.0", url: "http://commons.apache.org/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  (with patch by JetBrains)", license: "Apache 2.0", url: "http://hc.apache.org/httpclient-3.x") 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/", licenseUrl: "http://svn.jetbrains.org/idea/Trunk/bundled/WebServices/resources/lib/axis-1.4.0/commons-logging-1.0.4.LICENSE") +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: "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/") +libraryLicense(name: "Gson", libraryName: "gson-1.3.jar", license: "Apache 2.0", url: "http://code.google.com/p/google-gson/") +libraryLicense(name: "ISO RELAX", libraryName: "isorelax.jar", license: "MIT License", url: "http://sourceforge.net/projects/iso-relax/", licenseUrl: "http://www.opensource.org/licenses/mit-license.html") libraryLicense(name: "JavaCVS", version: "no version number available (with patches by JetBrains)", license: "Sun Public License", url: "http://javacvs.netbeans.org/library/", licenseUrl: "http://www.netbeans.org/about/legal/spl.html") +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: "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") @@ -130,6 +137,8 @@ libraryLicense(name: "NanoXML", version: "2.2.3", license: "zlib/libpng", url: " libraryLicense(name: "Eclipse JDT Core", libraryName: "Eclipse", version: "3.3", license: "CPL 1.0", url: "http://www.eclipse.org/jdt/core/index.php") libraryLicense(name: "Jakarta ORO", libraryName: "OroMatcher", version: "2.0.8", license: "Apache", url: "http://jakarta.apache.org/oro/", licenseUrl: "http://svn.apache.org/repos/asf/jakarta/oro/trunk/LICENSE") libraryLicense(name: "PicoContainer", libraryName: "picocontainer", version: "1.2", license: "BSD", url: "http://www.picocontainer.org/", licenseUrl: "http://docs.codehaus.org/display/PICO/License") +libraryLicense(name: "Plexus Utils", libraryName: "plexus-utils-1.5.5.jar", version: "1.5.5", license: "Apache 2.0", url: "http://plexus.codehaus.org/plexus-utils") +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/") diff --git a/java/compiler/impl/compiler-impl.iml b/java/compiler/impl/compiler-impl.iml index a65d7e10171d..a247d6b5abef 100644 --- a/java/compiler/impl/compiler-impl.iml +++ b/java/compiler/impl/compiler-impl.iml @@ -18,15 +18,6 @@ - - - - - - - - - diff --git a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java index 731956ee956d..6022b512656a 100644 --- a/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/highlighting/HighlightSuppressedWarningsHandler.java @@ -108,7 +108,9 @@ public class HighlightSuppressedWarningsHandler extends HighlightUsagesHandlerBa public void computeUsages(List targets) { final Project project = myTarget.getProject(); final PsiElement parent = myTarget.getParent().getParent(); - final LocalInspectionsPass pass = new LocalInspectionsPass(myFile, myFile.getViewProvider().getDocument(), parent.getTextRange().getStartOffset(), parent.getTextRange().getEndOffset()); + final LocalInspectionsPass pass = new LocalInspectionsPass(myFile, myFile.getViewProvider().getDocument(), + parent.getTextRange().getStartOffset(), parent.getTextRange().getEndOffset(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, + false); final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(project).getInspectionProfile(); for (PsiLiteralExpression target : targets) { @@ -128,7 +130,7 @@ public class HighlightSuppressedWarningsHandler extends HighlightUsagesHandlerBa ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator(); Runnable inspect = new Runnable() { public void run() { - pass.doInspectInBatch(managerEx, Collections.singletonList(tool), false); + pass.doInspectInBatch(managerEx, Collections.singletonList(tool)); } }; if (indicator == null) { diff --git a/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java b/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java index 32785e7a44c3..06f3f70cd596 100644 --- a/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java +++ b/java/java-impl/src/com/intellij/util/xml/PsiClassConverter.java @@ -17,13 +17,18 @@ package com.intellij.util.xml; import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.resolve.reference.impl.providers.JavaClassReferenceProvider; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.ClassKind; +import com.intellij.psi.xml.XmlElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -97,7 +102,16 @@ public class PsiClassConverter extends Converter implements CustomRefe @Nullable protected GlobalSearchScope getScope(final GenericDomValue domValue) { final Module module = domValue.getModule(); - return module == null ? null : GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false); + if (module == null) return null; + XmlElement element = domValue.getXmlElement(); + if (element == null) return null; + PsiFile file = element.getContainingFile(); + if (file == null) return null; + file = file.getOriginalFile(); + VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile == null) return null; + ProjectFileIndex fileIndex = ProjectRootManager.getInstance(file.getProject()).getFileIndex(); + return GlobalSearchScope.moduleRuntimeScope(module, fileIndex.isInTestSourceContent(virtualFile)); } public static class AnnotationType extends PsiClassConverter { diff --git a/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java b/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java index ca98d5d046bd..996af38a3a63 100644 --- a/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java +++ b/java/openapi/src/com/intellij/util/xml/DomJavaUtil.java @@ -16,6 +16,9 @@ package com.intellij.util.xml; import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.ProjectFileIndex; +import com.intellij.openapi.roots.ProjectRootManager; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiFile; @@ -32,7 +35,7 @@ public class DomJavaUtil { } @Nullable - public static PsiClass findClass(@Nullable String name, @NotNull final PsiFile file, @Nullable final Module module, @Nullable final GlobalSearchScope searchScope) { + public static PsiClass findClass(@Nullable String name, @NotNull PsiFile file, @Nullable final Module module, @Nullable final GlobalSearchScope searchScope) { if (name == null) return null; if (name.indexOf('$')>=0) name = name.replace('$', '.'); @@ -40,7 +43,15 @@ public class DomJavaUtil { if (searchScope == null) { if (module != null) { - scope = GlobalSearchScope.moduleWithDependenciesAndLibrariesScope(module, false); + file = file.getOriginalFile(); + VirtualFile virtualFile = file.getVirtualFile(); + if (virtualFile == null) { + scope = GlobalSearchScope.moduleRuntimeScope(module, true); + } + else { + ProjectFileIndex fileIndex = ProjectRootManager.getInstance(file.getProject()).getFileIndex(); + scope = GlobalSearchScope.moduleRuntimeScope(module, fileIndex.isInTestSourceContent(virtualFile)); + } } else { scope = file.getResolveScope(); diff --git a/lib/dev/compilerapi.jar b/lib/dev/compilerapi.jar deleted file mode 100644 index b5bf1f3d8ed7..000000000000 Binary files a/lib/dev/compilerapi.jar and /dev/null differ diff --git a/platform/extensions/extensions.iml b/platform/extensions/extensions.iml index 8648132b4918..40f44967ffeb 100644 --- a/platform/extensions/extensions.iml +++ b/platform/extensions/extensions.iml @@ -16,7 +16,7 @@ - + diff --git a/platform/lang-api/src/com/intellij/facet/frameworks/LibrariesDownloadConnectionService.java b/platform/lang-api/src/com/intellij/facet/frameworks/LibrariesDownloadConnectionService.java index 4c43bcccab22..2d5a3ddc9685 100644 --- a/platform/lang-api/src/com/intellij/facet/frameworks/LibrariesDownloadConnectionService.java +++ b/platform/lang-api/src/com/intellij/facet/frameworks/LibrariesDownloadConnectionService.java @@ -15,72 +15,16 @@ */ package com.intellij.facet.frameworks; -import com.intellij.openapi.diagnostic.Logger; -import com.intellij.openapi.util.JDOMUtil; -import com.intellij.openapi.util.text.StringUtil; -import org.jdom.Document; -import org.jdom.Element; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.io.InputStream; -import java.net.HttpURLConnection; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLConnection; - -public class LibrariesDownloadConnectionService { - private static final Logger LOG = Logger.getInstance("com.intellij.facet.frameworks.LibrariesDownloadConnectionService"); - - private static final String DOWNLOAD_SERVICE_SETTINGS_URL = "http://jetbrains.com/idea/download-assistant.xml "; - private static final String SERVICE_URL_ATTR_NAME = "url"; - - private static final String myAgentID = "IntelliJ IDEA"; +public class LibrariesDownloadConnectionService extends SettingsConnectionService { private static final LibrariesDownloadConnectionService myInstance = new LibrariesDownloadConnectionService(); - private String myServiceUrl; public static LibrariesDownloadConnectionService getInstance() { return myInstance; } private LibrariesDownloadConnectionService() { + super("http://jetbrains.com/idea/download-assistant.xml", "http://frameworks.jetbrains.com"); } - private static String readServiceUrl() { - try { - final URL url = new URL(DOWNLOAD_SERVICE_SETTINGS_URL); - final InputStream is = getStream(url); - final Document document = JDOMUtil.loadDocument(is); - final Element root = document.getRootElement(); - return StringUtil.notNullize(root.getAttributeValue(SERVICE_URL_ATTR_NAME), ""); - } - catch (MalformedURLException e) { - LOG.error(e); - } - catch (IOException e) { - // no route to host, unknown host, etc. - } - catch (Exception e) { - LOG.error(e); - } - // default - return "http://frameworks.jetbrains.com"; - } - - private static InputStream getStream(URL url) throws IOException { - final URLConnection connection = url.openConnection(); - if (connection instanceof HttpURLConnection) { - connection.setRequestProperty("User-agent", myAgentID); - } - return connection.getInputStream(); - } - - @Nullable - public String getServiceUrl() { - if (myServiceUrl == null) { - myServiceUrl = readServiceUrl(); - } - return myServiceUrl; - } } diff --git a/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java new file mode 100644 index 000000000000..cd638d426536 --- /dev/null +++ b/platform/lang-api/src/com/intellij/facet/frameworks/SettingsConnectionService.java @@ -0,0 +1,112 @@ +/* + * 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.facet.frameworks; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.JDOMUtil; +import com.intellij.util.containers.hash.HashMap; +import org.jdom.Document; +import org.jdom.Element; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.io.InputStream; +import java.net.HttpURLConnection; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Map; + +public abstract class SettingsConnectionService { + private static final Logger LOG = Logger.getInstance("com.intellij.facet.frameworks.SettingsConnectionService"); + + protected static final String SERVICE_URL_ATTR_NAME = "url"; + + private static final String myAgentID = "IntelliJ IDEA"; + + private Map myAttributesMap; + + @NotNull + protected String[] getAttributeNames() { + return new String[] {SERVICE_URL_ATTR_NAME}; + } + + private String mySettingsUrl; + @Nullable private String myDefaultServiceUrl; + + protected SettingsConnectionService(@NotNull String settingsUrl, @Nullable String defaultServiceUrl) { + mySettingsUrl = settingsUrl; + myDefaultServiceUrl = defaultServiceUrl; + } + + public String getSettingsUrl() { + return mySettingsUrl; + } + + @Nullable + public String getDefaultServiceUrl() { + return myDefaultServiceUrl; + } + + @Nullable + private Map readSettings(String... attributes) { + Map settings = new HashMap(); + try { + final URL url = new URL(getSettingsUrl()); + final InputStream is = getStream(url); + final Document document = JDOMUtil.loadDocument(is); + final Element root = document.getRootElement(); + for (String s : attributes) { + settings.put(s, root.getAttributeValue(s)); + } + } + catch (MalformedURLException e) { + LOG.error(e); + } + catch (IOException e) { + // no route to host, unknown host, etc. + } + catch (Exception e) { + LOG.error(e); + } + + return settings; + } + + private static InputStream getStream(URL url) throws IOException { + final URLConnection connection = url.openConnection(); + if (connection instanceof HttpURLConnection) { + connection.setRequestProperty("User-agent", myAgentID); + } + return connection.getInputStream(); + } + + @Nullable + public String getServiceUrl() { + final String serviceUrl = getSettingValue(SERVICE_URL_ATTR_NAME); + + return serviceUrl == null ? getDefaultServiceUrl() : serviceUrl; + } + + @Nullable + protected String getSettingValue(@NotNull String attributeValue) { + if (myAttributesMap == null) { + myAttributesMap = readSettings(getAttributeNames()); + } + return myAttributesMap != null ? myAttributesMap.get(attributeValue) : null; + } +} diff --git a/platform/lang-api/src/com/intellij/openapi/roots/ContentEntry.java b/platform/lang-api/src/com/intellij/openapi/roots/ContentEntry.java index de4f462f57a8..a7802c4fcb62 100644 --- a/platform/lang-api/src/com/intellij/openapi/roots/ContentEntry.java +++ b/platform/lang-api/src/com/intellij/openapi/roots/ContentEntry.java @@ -21,9 +21,12 @@ import org.jetbrains.annotations.Nullable; /** * Represents a module content root. + * You can get existing entries with {@link com.intellij.openapi.roots.ModuleRootModel#getContentEntries()} or + * create a new one with {@link ModifiableRootModel#addContentEntry(com.intellij.openapi.vfs.VirtualFile)}. * * @author dsl * @see ModuleRootModel#getContentEntries() + * @see ModifiableRootModel#addContentEntry(com.intellij.openapi.vfs.VirtualFile) */ public interface ContentEntry extends Synthetic { /** diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java index 832fb318eab1..8a665afa2fa4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/DaemonCodeAnalyzerImpl.java @@ -159,7 +159,8 @@ public class DaemonCodeAnalyzerImpl extends DaemonCodeAnalyzer implements JDOMEx List result = new ArrayList(); result.addAll(action1.getHighlights()); - LocalInspectionsPass action3 = new LocalInspectionsPass(psiFile, document, 0, psiFile.getTextLength()); + LocalInspectionsPass action3 = new LocalInspectionsPass(psiFile, document, 0, + psiFile.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true); action3.doCollectInformation(progress); result.addAll(action3.getHighlights()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java index 503cd00a3c53..76a6ce8f008b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPass.java @@ -46,7 +46,6 @@ import com.intellij.openapi.progress.ProgressIndicator; import com.intellij.openapi.progress.ProgressManager; import com.intellij.openapi.project.DumbAware; import com.intellij.openapi.project.DumbService; -import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.Trinity; import com.intellij.openapi.util.text.StringUtil; @@ -58,7 +57,7 @@ import com.intellij.util.ConcurrencyUtil; import com.intellij.util.Function; import com.intellij.util.Processor; import com.intellij.util.containers.ConcurrentHashMap; -import com.intellij.util.ui.UIUtil; +import com.intellij.util.containers.TransferToEDTQueue; import com.intellij.xml.util.XmlStringUtil; import gnu.trove.THashMap; import gnu.trove.THashSet; @@ -67,9 +66,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.atomic.AtomicBoolean; /** * @author max @@ -77,9 +74,11 @@ import java.util.concurrent.atomic.AtomicBoolean; public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass implements DumbAware { private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.daemon.impl.LocalInspectionsPass"); private static final int NUM_ELEMENTS_PER_CHECK_CANCELLED = 5; + public static final TextRange EMPTY_PRIORITY_RANGE = new TextRange(0, 0); private final int myStartOffset; private final int myEndOffset; private final TextRange myPriorityRange; + private final boolean myIgnoreSuppressed; private final ConcurrentMap> result = new ConcurrentHashMap>(); static final String PRESENTABLE_NAME = DaemonBundle.message("pass.inspection"); private volatile List myInfos = Collections.emptyList(); @@ -88,14 +87,17 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass private final InspectionProfileWrapper myProfileWrapper; private boolean myFailFastOnAcquireReadAction; - public LocalInspectionsPass(@NotNull PsiFile file, @Nullable Document document, int startOffset, int endOffset) { - this(file, document, startOffset, endOffset, new TextRange(0, 0)); - } - public LocalInspectionsPass(@NotNull PsiFile file, @Nullable Document document, int startOffset, int endOffset, @NotNull TextRange priorityRange) { + public LocalInspectionsPass(@NotNull PsiFile file, + @Nullable Document document, + int startOffset, + int endOffset, + @NotNull TextRange priorityRange, + boolean ignoreSuppressed) { super(file.getProject(), document, PRESENTABLE_NAME, file, true); myStartOffset = startOffset; myEndOffset = endOffset; myPriorityRange = priorityRange; + myIgnoreSuppressed = ignoreSuppressed; setId(Pass.LOCAL_INSPECTIONS); final KeymapManager keymapManager = KeymapManager.getInstance(); @@ -113,7 +115,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass if (customizationStrategy != null) { profileToUse = customizationStrategy.fun(profileToUse); } - + myProfileWrapper = profileToUse; mySeverityRegistrar = ((SeverityProvider)myProfileWrapper.getInspectionProfile().getProfileManager()).getSeverityRegistrar(); LOG.assertTrue(mySeverityRegistrar != null); @@ -128,7 +130,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass final InspectionManagerEx iManager = (InspectionManagerEx)InspectionManager.getInstance(myProject); final InspectionProfileWrapper profile = myProfileWrapper; final List tools = DumbService.getInstance(myProject).filterByDumbAwareness(getInspectionTools(profile)); - inspect(tools, iManager, true, true, true, progress); + inspect(tools, iManager, true, true, progress); } finally { disposeDescriptors(); @@ -146,7 +148,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass result.clear(); } - public void doInspectInBatch(final InspectionManagerEx iManager, List toolWrappers, boolean ignoreSuppressed) { + public void doInspectInBatch(final InspectionManagerEx iManager, List toolWrappers) { Map tool2Wrapper = new THashMap(toolWrappers.size()); for (InspectionProfileEntry toolWrapper : toolWrappers) { tool2Wrapper.put(((LocalInspectionToolWrapper)toolWrapper).getTool(), (LocalInspectionToolWrapper)toolWrapper); @@ -154,7 +156,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass List tools = new ArrayList(tool2Wrapper.keySet()); ProgressIndicator progress = ProgressManager.getInstance().getProgressIndicator(); - inspect(tools, iManager, false, ignoreSuppressed, false, progress); + inspect(tools, iManager, false, false, progress); addDescriptorsFromInjectedResults(tool2Wrapper, iManager); List resultList = result.get(myFile); if (resultList == null) return; @@ -163,7 +165,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass LocalInspectionToolWrapper toolWrapper = tool2Wrapper.get(tool); if (toolWrapper == null) continue; for (ProblemDescriptor descriptor : inspectionResult.foundProblems) { - toolWrapper.addProblemDescriptors(Collections.singletonList(descriptor), ignoreSuppressed); + toolWrapper.addProblemDescriptors(Collections.singletonList(descriptor), myIgnoreSuppressed); } } } @@ -214,7 +216,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass private void inspect(final List tools, final InspectionManagerEx iManager, final boolean isOnTheFly, - final boolean ignoreSuppressed, boolean failFastOnAcquireReadAction, @NotNull final ProgressIndicator indicator) { myFailFastOnAcquireReadAction = failFastOnAcquireReadAction; @@ -231,8 +232,8 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass List> init = new ArrayList>(); boolean finished = false; try { - visitPriorityElementsAndInit(tools, iManager, isOnTheFly, ignoreSuppressed, indicator, inside, session, init); - visitRestElementsAndCleanup(tools,iManager,isOnTheFly,ignoreSuppressed, indicator, outside, session, init); + visitPriorityElementsAndInit(tools, iManager, isOnTheFly, indicator, inside, session, init); + visitRestElementsAndCleanup(tools,iManager,isOnTheFly, indicator, outside, session, init); finished = true; } finally { @@ -253,13 +254,12 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass indicator.checkCanceled(); myInfos = new ArrayList(); - addHighlightsFromResults(myInfos, ignoreSuppressed); + addHighlightsFromResults(myInfos); } private void visitPriorityElementsAndInit(@NotNull List tools, @NotNull final InspectionManagerEx iManager, final boolean isOnTheFly, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator, @NotNull final List elements, @NotNull final LocalInspectionToolSession session, @@ -276,7 +276,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass public void registerProblem(@NotNull ProblemDescriptor descriptor) { super.registerProblem(descriptor); if (applyIncrementally[0]) { - addDescriptorIncrementally(descriptor, tool, ignoreSuppressed, indicator); + addDescriptorIncrementally(descriptor, tool, indicator); } } }; @@ -295,7 +295,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } }, myFailFastOnAcquireReadAction, indicator); if (!result) throw new ProcessCanceledException(); - inspectInjectedPsi(elements, tools, isOnTheFly, ignoreSuppressed, indicator, iManager, true); + inspectInjectedPsi(elements, tools, isOnTheFly, indicator, iManager, true); } private static PsiElementVisitor createVisitorAndAcceptElements(@NotNull LocalInspectionTool tool, @@ -324,7 +324,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass private void visitRestElementsAndCleanup(@NotNull List tools, @NotNull InspectionManagerEx iManager, final boolean isOnTheFly, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator, @NotNull final List elements, @NotNull final LocalInspectionToolSession session, @@ -341,7 +340,8 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass ProblemsHolder holder = trinity.second; PsiElementVisitor elementVisitor = trinity.third; for (int i = 0, elementsSize = elements.size(); i < elementsSize; i++) { - elements.get(i).accept(elementVisitor); + PsiElement element = elements.get(i); + element.accept(elementVisitor); if (i % NUM_ELEMENTS_PER_CHECK_CANCELLED == 0) indicator.checkCanceled(); } @@ -359,13 +359,12 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass if (!result) { throw new ProcessCanceledException(); } - inspectInjectedPsi(elements, tools, isOnTheFly, ignoreSuppressed, indicator, iManager, false); + inspectInjectedPsi(elements, tools, isOnTheFly, indicator, iManager, false); } private void inspectInjectedPsi(@NotNull final List elements, @NotNull final List tools, final boolean onTheFly, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator, @NotNull final InspectionManagerEx iManager, final boolean inVisibleRange) { @@ -380,7 +379,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass if (injected.isEmpty()) return; if (!JobUtil.invokeConcurrentlyUnderProgress(new ArrayList(injected), new Processor() { public boolean process(final PsiFile injectedPsi) { - doInspectInjectedPsi(injectedPsi, tools, onTheFly, ignoreSuppressed, indicator, iManager, inVisibleRange); + doInspectInjectedPsi(injectedPsi, tools, onTheFly, indicator, iManager, inVisibleRange); return true; } }, myFailFastOnAcquireReadAction, indicator)) throw new ProcessCanceledException(); @@ -389,7 +388,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass public Collection getHighlights() { List highlights = new ArrayList(); - addHighlightsFromResults(highlights, true); + addHighlightsFromResults(highlights); return highlights; } @@ -410,56 +409,52 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass severity, problemDescriptor.isAfterEndOfLine(), null, isFileLevel); } - private final AtomicBoolean haveInfosToProcess = new AtomicBoolean(); - private final ConcurrentLinkedQueue> infosToAdd = new ConcurrentLinkedQueue>(); + private final TransferToEDTQueue> myTransferToEDTQueue; + { + myTransferToEDTQueue = + new TransferToEDTQueue>(new Processor>() { + private final InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); + private final InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject); + private final List infos = new ArrayList(2); + private final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); + @Override + public boolean process(Trinity trinity) { + ProgressIndicator indicator = trinity.getThird(); + if (indicator.isCanceled()) { + return false; + } + + ProblemDescriptor descriptor = trinity.first; + LocalInspectionTool tool = trinity.second; + PsiElement psiElement = descriptor.getPsiElement(); + if (psiElement == null) return true; + PsiFile file = psiElement.getContainingFile(); + Document thisDocument = documentManager.getDocument(file); + + HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); + + infos.clear(); + createHighlightsForDescriptor(infos, emptyActionRegistered, ilManager, file, thisDocument, tool, severity, descriptor); + for (HighlightInfo info : infos) { + final EditorColorsScheme colorsScheme = getColorsScheme(); + UpdateHighlightersUtil.addHighlighterToEditorIncrementally(myProject, myDocument, myFile, myStartOffset, myEndOffset, + info, colorsScheme, getId()); + } + + return true; + } + }, myProject.getDisposed()); + } + private final Set emptyActionRegistered = Collections.synchronizedSet(new HashSet()); private void addDescriptorIncrementally(@NotNull final ProblemDescriptor descriptor, @NotNull final LocalInspectionTool tool, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator) { - if (ignoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(descriptor.getPsiElement(), tool)) { + if (myIgnoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(descriptor.getPsiElement(), tool)) { return; } - - infosToAdd.offer(Pair.create(descriptor, tool)); - if (haveInfosToProcess.getAndSet(true)) return; - final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); - // extra invoke later is harmless, missing invoke is not - UIUtil.invokeLaterIfNeeded(new Runnable() { - public void run() { - if (myProject.isDisposed()) return; - InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); - InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject); - List infos = new ArrayList(2); - while (haveInfosToProcess.compareAndSet(true, false)) { - for (Pair pair = infosToAdd.poll(); pair != null; pair = infosToAdd.poll()) { - if (indicator.isCanceled()) { - infosToAdd.clear(); - return; - } - - ProblemDescriptor descriptor = pair.first; - LocalInspectionTool tool = pair.second; - PsiElement psiElement = descriptor.getPsiElement(); - if (psiElement == null) continue; - PsiFile file = psiElement.getContainingFile(); - Document thisDocument = documentManager.getDocument(file); - - HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); - - infos.clear(); - createHighlightsForDescriptor(infos, emptyActionRegistered, ilManager, file, thisDocument, tool, severity, descriptor, ignoreSuppressed); - for (HighlightInfo info : infos) { - final EditorColorsScheme colorsScheme = getColorsScheme(); - - UpdateHighlightersUtil.addHighlighterToEditorIncrementally(myProject, myDocument, myFile, myStartOffset, myEndOffset, - info, colorsScheme, getId()); - } - } - } - } - }); + myTransferToEDTQueue.offer(Trinity.create(descriptor, tool, indicator)); } private void appendDescriptors(PsiFile file, List descriptors, LocalInspectionTool tool) { @@ -519,7 +514,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass UpdateHighlightersUtil.setHighlightersToEditor(myProject, myDocument, myStartOffset, myEndOffset, myInfos, getColorsScheme(), getId()); } - private void addHighlightsFromResults(final List outInfos, boolean ignoreSuppressed) { + private void addHighlightsFromResults(final List outInfos) { InspectionProfile inspectionProfile = InspectionProjectProfileManager.getInstance(myProject).getInspectionProfile(); PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject); InjectedLanguageManager ilManager = InjectedLanguageManager.getInstance(myProject); @@ -534,8 +529,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass LocalInspectionTool tool = inspectionResult.tool; HighlightSeverity severity = inspectionProfile.getErrorLevel(HighlightDisplayKey.find(tool.getShortName()), file).getSeverity(); for (ProblemDescriptor descriptor : inspectionResult.foundProblems) { - createHighlightsForDescriptor(outInfos, emptyActionRegistered, ilManager, file, documentRange, tool, severity, descriptor, - ignoreSuppressed); + createHighlightsForDescriptor(outInfos, emptyActionRegistered, ilManager, file, documentRange, tool, severity, descriptor); } } } @@ -548,10 +542,10 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass Document documentRange, LocalInspectionTool tool, HighlightSeverity severity, - ProblemDescriptor descriptor, boolean ignoreSuppressed) { + ProblemDescriptor descriptor) { PsiElement psiElement = descriptor.getPsiElement(); if (psiElement == null) return; - if (ignoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(psiElement, tool)) return; + if (myIgnoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(psiElement, tool)) return; HighlightInfoType level = highlightTypeFromDescriptor(descriptor, severity); HighlightInfo info = createHighlightInfo(descriptor, tool, level, emptyActionRegistered); if (info == null) return; @@ -677,7 +671,6 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass private void doInspectInjectedPsi(@NotNull PsiFile injectedPsi, @NotNull List tools, final boolean isOnTheFly, - final boolean ignoreSuppressed, @NotNull final ProgressIndicator indicator, @NotNull InspectionManagerEx iManager, final boolean inVisibleRange) { @@ -689,7 +682,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass } for (final LocalInspectionTool tool : tools) { indicator.checkCanceled(); - if (host != null && ignoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(host, tool)) { + if (host != null && myIgnoreSuppressed && InspectionManagerEx.inspectionResultSuppressed(host, tool)) { continue; } ProblemsHolder holder = new ProblemsHolder(iManager, injectedPsi, isOnTheFly) { @@ -697,7 +690,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass public void registerProblem(@NotNull ProblemDescriptor descriptor) { super.registerProblem(descriptor); if (isOnTheFly && inVisibleRange) { - addDescriptorIncrementally(descriptor, tool, ignoreSuppressed, indicator); + addDescriptorIncrementally(descriptor, tool, indicator); } } }; diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPassFactory.java index 327772a905a3..368be146dd9b 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPassFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/LocalInspectionsPassFactory.java @@ -55,7 +55,7 @@ public class LocalInspectionsPassFactory extends AbstractProjectComponent implem if (textRange == null) return new ProgressableTextEditorHighlightingPass.EmptyPass(myProject, editor.getDocument() ); TextRange visibleRange = VisibleHighlightingPassFactory.calculateVisibleRange(editor); - return new LocalInspectionsPass(file, editor.getDocument(), textRange.getStartOffset(), textRange.getEndOffset(), visibleRange){ + return new LocalInspectionsPass(file, editor.getDocument(), textRange.getStartOffset(), textRange.getEndOffset(), visibleRange, true){ List getInspectionTools(InspectionProfileWrapper profile) { List tools = super.getInspectionTools(profile); List result = new ArrayList(tools.size()); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java index c77f7236f3e3..2216b24dcbcf 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/daemon/impl/WholeFileLocalInspectionsPassFactory.java @@ -90,7 +90,7 @@ public class WholeFileLocalInspectionsPassFactory extends AbstractProjectCompone public TextEditorHighlightingPass createHighlightingPass(@NotNull final PsiFile file, @NotNull final Editor editor) { TextRange textRange = FileStatusMap.getDirtyTextRange(editor, Pass.LOCAL_INSPECTIONS); if (textRange == null || myFileTools.containsKey(file) && !myFileTools.get(file)) return null; - return new LocalInspectionsPass(file, editor.getDocument(), 0, file.getTextLength()) { + return new LocalInspectionsPass(file, editor.getDocument(), 0, file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true) { List getInspectionTools(InspectionProfileWrapper profile) { List tools = super.getInspectionTools(profile); List result = new ArrayList(); diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java index 904372541275..c4aa0f10e9e4 100644 --- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java +++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/EnterHandler.java @@ -49,6 +49,7 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtilBase; import com.intellij.util.IncorrectOperationException; import com.intellij.util.text.CharArrayUtil; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public class EnterHandler extends BaseEnterHandler { @@ -196,6 +197,9 @@ public class EnterHandler extends BaseEnterHandler { lexer.advance(); continue; } + else if (isInvalidPsi(comment)) { + return false; + } return lexer.getTokenEnd() - lexer.getTokenStart() == 1; } if (tokenType == commenter.getDocumentationCommentTokenType() || tokenType == commenter.getBlockCommentTokenType()) { @@ -205,6 +209,48 @@ public class EnterHandler extends BaseEnterHandler { } } + /** + * There is a following possible use-case: + *
+   * 
    + *
  • + * Particular document has valid text: + *
    +   *       [caret]
    +   *       class A {
    +   *           int foo() {
    +   *             return 1 */*comment*/ 1;
    +   *           }
    +   *       }
    +   *     
    + *
  • + *
  • + * The user starts comment (inserts comment start symbols): + *
    +   *       /**[caret]
    +   *       class A {
    +   *           int foo() {
    +   *             return 1 */*comment*/ 1;
    +   *           }
    +   *       }
    +   *     
    + *
  • + *
  • The user presses 'enter';
  • + *
+ *
+ * We want to understand that doc comment is incomplete now, i.e. don't want to consider '*/' before + * '*comment*/ 1;' as comment end. Current approach is to check if next PSI sibling to the current PSI comment is invalid. + * This method allows to perform such an examination. + */ + private static boolean isInvalidPsi(@NotNull PsiElement base) { + for (PsiElement current = base.getNextSibling(); current != null; current = current.getNextSibling()) { + if (current.getTextLength() != 0) { + return current instanceof PsiErrorElement; + } + } + return false; + } + private static boolean isDocComment(final PsiElement element, final CodeDocumentationAwareCommenter commenter) { if (!(element instanceof PsiComment)) return false; PsiComment comment = (PsiComment) element; @@ -259,8 +305,8 @@ public class EnterHandler extends BaseEnterHandler { final PsiElement parent = element.getParent(); if (text.equals(commentContext.commenter.getDocumentationCommentPrefix()) && isDocComment(parent, commentContext.commenter) || - text.startsWith(commentContext.commenter.getDocumentationCommentPrefix()) && element instanceof PsiComment - ) { + text.startsWith(commentContext.commenter.getDocumentationCommentPrefix()) && element instanceof PsiComment) + { PsiComment comment = isDocComment(parent, commentContext.commenter) ? (PsiComment)parent:(PsiComment)element; int commentEnd = comment.getTextRange().getEndOffset(); @@ -321,7 +367,7 @@ public class EnterHandler extends BaseEnterHandler { String indentInsideJavadoc = null; int line = myDocument.getLineNumber(myOffset); - if (line > 0) { + if (line > 0 && (commentContext.docAsterisk || commentContext.docStart)) { indentInsideJavadoc = CodeDocumentationUtil.getIndentInsideJavadoc(myDocument, myDocument.getLineStartOffset(line - 1)); } diff --git a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java index 731cc9c3faf9..639610151560 100644 --- a/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java +++ b/platform/lang-impl/src/com/intellij/codeInspection/ex/GlobalInspectionContextImpl.java @@ -537,7 +537,8 @@ public class GlobalInspectionContextImpl implements GlobalInspectionContext { final FileViewProvider viewProvider = psiManager.findViewProvider(virtualFile); final com.intellij.openapi.editor.Document document = viewProvider == null ? null : viewProvider.getDocument(); if (document == null || virtualFile.getFileType().isBinary()) return; //do not inspect binary files - final LocalInspectionsPass pass = new LocalInspectionsPass(file, document, 0, file.getTextLength()); + final LocalInspectionsPass pass = new LocalInspectionsPass(file, document, 0, + file.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true); try { final List lTools = new ArrayList(); for (Tools tool : localTools) { @@ -546,7 +547,7 @@ public class GlobalInspectionContextImpl implements GlobalInspectionContext { lTools.add(enabledTool); } } - pass.doInspectInBatch((InspectionManagerEx)manager, lTools, true); + pass.doInspectInBatch((InspectionManagerEx)manager, lTools); } catch (ProcessCanceledException e) { throw e; diff --git a/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkStatisticsPersistence.java b/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkStatisticsPersistence.java index e26ed8fb5932..b1d9a0894c75 100644 --- a/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkStatisticsPersistence.java +++ b/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkStatisticsPersistence.java @@ -17,7 +17,7 @@ package com.intellij.facet.impl.statistics; import com.intellij.openapi.project.Project; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; diff --git a/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkStatisticsPersistenceComponent.java b/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkStatisticsPersistenceComponent.java index 0c18a17355b7..717dabff6e15 100644 --- a/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkStatisticsPersistenceComponent.java +++ b/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkStatisticsPersistenceComponent.java @@ -16,6 +16,7 @@ package com.intellij.facet.impl.statistics; +import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.PathManager; import com.intellij.openapi.components.ApplicationComponent; @@ -25,7 +26,6 @@ import com.intellij.openapi.components.Storage; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerListener; -import com.intellij.statistic.beans.UsageDescriptor; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.Function; import com.intellij.util.containers.HashSet; @@ -70,7 +70,7 @@ public class FrameworkStatisticsPersistenceComponent extends FrameworkStatistics if (!StringUtil.isEmptyOrSpaces(projectId) && !StringUtil.isEmptyOrSpaces(frameworks)) { Set frameworkDescriptors = new HashSet(); for (String key : StringUtil.split(frameworks, TOKENIZER)) { - frameworkDescriptors.add(new UsageDescriptor(FrameworkUsagesCollector.getGroupId(), key, 1)); + frameworkDescriptors.add(new UsageDescriptor(FrameworkUsagesCollector.getGroupDescriptor(), key, 1)); } getFrameworks().put(projectId, frameworkDescriptors); } diff --git a/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkUsagesCollector.java b/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkUsagesCollector.java index 15e24c38ed6c..abad35157269 100644 --- a/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkUsagesCollector.java +++ b/platform/lang-impl/src/com/intellij/facet/impl/statistics/FrameworkUsagesCollector.java @@ -20,9 +20,9 @@ import com.intellij.facet.FacetManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; -import com.intellij.statistic.UsagesCollector; -import com.intellij.statistic.beans.GroupDescriptor; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.UsagesCollector; +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.HashSet; @@ -34,7 +34,7 @@ import java.util.Map; import java.util.Set; public class FrameworkUsagesCollector extends UsagesCollector { - private static final String GROUP_ID = "frameworks"; + public static final String GROUP_ID = "frameworks"; public static void persistProjectUsages(@NotNull Project project) { persistProjectUsages(project, getProjectUsages(project)); @@ -51,12 +51,12 @@ public class FrameworkUsagesCollector extends UsagesCollector { } @NotNull - public static Set getApplicationUsages() { + public Set getApplicationUsages() { return getApplicationUsages(FrameworkStatisticsPersistenceComponent.getInstance()); } @NotNull - public static Set getApplicationUsages(@NotNull final FrameworkStatisticsPersistence persistence) { + public Set getApplicationUsages(@NotNull final FrameworkStatisticsPersistence persistence) { final Map facets = new HashMap(); for (Set frameworks : persistence.getFrameworks().values()) { @@ -70,12 +70,18 @@ public class FrameworkUsagesCollector extends UsagesCollector { return ContainerUtil.map2Set(facets.entrySet(), new Function, UsageDescriptor>() { @Override public UsageDescriptor fun(Map.Entry facet) { - return new UsageDescriptor(getGroupId(), facet.getKey(), facet.getValue()); + return new UsageDescriptor(getGroupDescriptor(), facet.getKey(), facet.getValue()); } }); } - public static GroupDescriptor getGroupId() { + @NotNull + @Override + public String getGroupId() { + return GROUP_ID; + } + + public static GroupDescriptor getGroupDescriptor() { return GroupDescriptor.create(GROUP_ID, GroupDescriptor.HIGHER_PRIORITY); } @@ -92,14 +98,14 @@ public class FrameworkUsagesCollector extends UsagesCollector { final Set facets = new HashSet(); for (Module module : ModuleManager.getInstance(project).getModules()) { for (Facet facet : FacetManager.getInstance(module).getAllFacets()) { - facets.add(facet.getName()); + facets.add(facet.getType().getStringId()); } } return ContainerUtil.map2Set(facets, new Function() { @Override public UsageDescriptor fun(String facet) { - return new UsageDescriptor(getGroupId(), facet, 1); + return new UsageDescriptor(getGroupDescriptor(), facet, 1); } }); } diff --git a/platform/platform-impl/platform-impl.iml b/platform/platform-impl/platform-impl.iml index 68fc2731b7bd..e2ea144cc57b 100644 --- a/platform/platform-impl/platform-impl.iml +++ b/platform/platform-impl/platform-impl.iml @@ -27,6 +27,7 @@ +
diff --git a/platform/platform-impl/src/com/intellij/featureStatistics/FeaturesUsageCollector.java b/platform/platform-impl/src/com/intellij/featureStatistics/FeaturesUsageCollector.java index 7d8707e88b5c..fcbf518cda18 100644 --- a/platform/platform-impl/src/com/intellij/featureStatistics/FeaturesUsageCollector.java +++ b/platform/platform-impl/src/com/intellij/featureStatistics/FeaturesUsageCollector.java @@ -16,9 +16,9 @@ package com.intellij.featureStatistics; import com.intellij.openapi.project.Project; -import com.intellij.statistic.UsagesCollector; -import com.intellij.statistic.beans.*; -import com.intellij.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.UsagesCollector; +import com.intellij.internal.statistic.beans.*; +import com.intellij.internal.statistic.beans.GroupDescriptor; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,6 +27,12 @@ import java.util.Set; public class FeaturesUsageCollector extends UsagesCollector { + @NotNull + @Override + public String getGroupId() { + return "productivity"; + } + @NotNull @Override public Set getUsages(@Nullable Project project) { @@ -37,7 +43,7 @@ public class FeaturesUsageCollector extends UsagesCollector { final FeatureDescriptor featureDescriptor = registry.getFeatureDescriptor(featureId); if (featureDescriptor != null) { usages.add(new UsageDescriptor( - GroupDescriptor.create("productivity", GroupDescriptor.LOWER_PRIORITY), featureId, featureDescriptor.getUsageCount())); + GroupDescriptor.create(getGroupId(), GroupDescriptor.LOWER_PRIORITY), featureId, featureDescriptor.getUsageCount())); } } diff --git a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsUsagesCollector.java b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsUsagesCollector.java index 560fac29c488..006b58967ada 100644 --- a/platform/platform-impl/src/com/intellij/ide/plugins/PluginsUsagesCollector.java +++ b/platform/platform-impl/src/com/intellij/ide/plugins/PluginsUsagesCollector.java @@ -16,9 +16,9 @@ package com.intellij.ide.plugins; import com.intellij.openapi.project.Project; -import com.intellij.statistic.UsagesCollector; -import com.intellij.statistic.beans.GroupDescriptor; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.UsagesCollector; +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; @@ -27,18 +27,19 @@ import org.jetbrains.annotations.Nullable; import java.util.Set; public class PluginsUsagesCollector extends UsagesCollector { - private static final String GROUP_ID = "plugins"; + private static final String GROUP_ID = "disabled-plugins"; - public static GroupDescriptor getGroupId() { - return GroupDescriptor.create(GROUP_ID, GroupDescriptor.HIGHER_PRIORITY); + @NotNull + public String getGroupId() { + return GROUP_ID; } @NotNull public Set getUsages(@Nullable Project project) { - return ContainerUtil.map2Set(PluginManager.getPlugins(), new Function() { + return ContainerUtil.map2Set(PluginManager.getDisabledPlugins(), new Function() { @Override - public UsageDescriptor fun(IdeaPluginDescriptor descriptor) { - return new UsageDescriptor(getGroupId(), descriptor.getName(), 1); + public UsageDescriptor fun(String descriptor) { + return new UsageDescriptor(GroupDescriptor.create(getGroupId(), GroupDescriptor.HIGHER_PRIORITY), descriptor, 1); } }); } diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/StatisticsUploadAssistant.java b/platform/platform-impl/src/com/intellij/internal/statistic/StatisticsUploadAssistant.java new file mode 100644 index 000000000000..a8fe0a736cec --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/StatisticsUploadAssistant.java @@ -0,0 +1,168 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.internal.statistic; + +import com.intellij.internal.statistic.beans.ConvertUsagesUtil; +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.PatchedUsage; +import com.intellij.internal.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.persistence.SentUsagesPersistence; +import com.intellij.internal.statistic.persistence.SentUsagesPersistenceComponent; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.project.ProjectManager; +import com.intellij.openapi.util.Condition; +import com.intellij.openapi.util.Pair; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.HashSet; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public class StatisticsUploadAssistant { + + public String getData() { + return getData(Collections.emptySet()); + } + + public String getData(@NotNull Set disabledGroups) { + return getStringPatch(disabledGroups, ProjectManager.getInstance().getOpenProjects()); + } + + public void persistSentPatch(@NotNull String patchStr) { + persistSentPatch(patchStr, SentUsagesPersistenceComponent.getInstance()); + } + + public static void persistSentPatch(@NotNull String patchStr, @NotNull SentUsagesPersistence persistenceComponent) { + Set patchedUsages = + ContainerUtil.map2Set(ConvertUsagesUtil.convertString(patchStr), new Function() { + @Override + public PatchedUsage fun(UsageDescriptor usageDescriptor) { + return new PatchedUsage(usageDescriptor); + } + }); + + if (patchedUsages.size() > 0) persistenceComponent.persistPatch(patchedUsages); + } + + @NotNull + public static String getStringPatch(@NotNull Set disabledGroups, Project... project) { + return getStringPatch(disabledGroups, project, SentUsagesPersistenceComponent.getInstance(), 0); + } + + @NotNull + public static String getStringPatch(@NotNull Set disabledGroups, + @NotNull Project[] projects, + @NotNull SentUsagesPersistence usagesPersistence, + int maxSize) { + final Set patchedUsages = getPatchedUsages(disabledGroups, projects, usagesPersistence); + + return getStringPatch(patchedUsages, maxSize); + } + + public static String getStringPatch(@NotNull Set patchedUsages, int maxSize) { + if (patchedUsages.size() == 0) return ""; + + String patchStr = ConvertUsagesUtil.convertUsages(patchedUsages); + if (maxSize > 0 && patchStr.getBytes().length > maxSize) { + patchStr = ConvertUsagesUtil.cutPatchString(patchStr, maxSize); + } + + return patchStr; + } + + @NotNull + public static Set getPatchedUsages(@NotNull Set disabledGroups, + @NotNull Project[] projects, + @NotNull SentUsagesPersistence usagesPersistence) { + Set usages = new HashSet(); + + for (Project project : projects) { + usages.addAll(getPatchedUsages(getAllUsages(project, disabledGroups), usagesPersistence.getSentUsages())); + } + return usages; + } + + @NotNull + public static Set getPatchedUsages(@NotNull final Set allUsages, + @NotNull SentUsagesPersistence usagesPersistence) { + return getPatchedUsages(allUsages, usagesPersistence.getSentUsages()); + } + + @NotNull + public static Set getPatchedUsages(@NotNull final Set allUsages, final Set sentUsages) { + final Set patchedUsages = ContainerUtil.map2Set(allUsages, new Function() { + @Override + public PatchedUsage fun(UsageDescriptor usageDescriptor) { + return new PatchedUsage(usageDescriptor); + } + }); + + for (UsageDescriptor sentUsage : sentUsages) { + final PatchedUsage descriptor = findDescriptor(patchedUsages, Pair.create(sentUsage.getGroup(), sentUsage.getKey())); + if (descriptor == null) { + patchedUsages.add(new PatchedUsage(sentUsage.getGroup(), sentUsage.getKey(), -sentUsage.getValue())); + } + else { + descriptor.subValue(sentUsage.getValue()); + } + } + + return packCollection(patchedUsages, new Condition() { + @Override + public boolean value(PatchedUsage patchedUsage) { + return patchedUsage.getDelta() != 0; + } + }); + } + + @NotNull + private static Set packCollection(@NotNull Collection set, @NotNull Condition condition) { + final Set result = new LinkedHashSet(); + for (T t : set) { + if (condition.value(t)) { + result.add(t); + } + } + return result; + } + + @Nullable + public static T findDescriptor(@NotNull Set descriptors, + @NotNull final Pair id) { + return ContainerUtil.find(descriptors, new Condition() { + @Override + public boolean value(T t) { + return id.getFirst().equals(t.getGroup()) && id.getSecond().equals(t.getKey()); + } + }); + } + + @NotNull + public static Set getAllUsages(@Nullable Project project, @NotNull Set disabledGroups) { + final Set usageDescriptors = new TreeSet(); + + for (UsagesCollector usagesCollector : Extensions.getExtensions(UsagesCollector.EP_NAME)) { + if (!disabledGroups.contains(usagesCollector.getGroupId())) { + usageDescriptors.addAll(usagesCollector.getUsages(project)); + } + } + + return usageDescriptors; + } +} diff --git a/platform/platform-impl/src/com/intellij/statistic/UsagesCollector.java b/platform/platform-impl/src/com/intellij/internal/statistic/UsagesCollector.java similarity index 87% rename from platform/platform-impl/src/com/intellij/statistic/UsagesCollector.java rename to platform/platform-impl/src/com/intellij/internal/statistic/UsagesCollector.java index e0320bc0b2ca..e07246e0556a 100644 --- a/platform/platform-impl/src/com/intellij/statistic/UsagesCollector.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/UsagesCollector.java @@ -13,11 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.statistic; +package com.intellij.internal.statistic; import com.intellij.openapi.extensions.ExtensionPointName; import com.intellij.openapi.project.Project; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,4 +27,6 @@ public abstract class UsagesCollector { public static ExtensionPointName EP_NAME = ExtensionPointName.create("com.intellij.statistics.usagesCollector"); public abstract @NotNull Set getUsages(@Nullable Project project); + + public abstract @NotNull String getGroupId(); } diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/beans/ConvertUsagesUtil.java b/platform/platform-impl/src/com/intellij/internal/statistic/beans/ConvertUsagesUtil.java new file mode 100644 index 000000000000..8fd58411e437 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/beans/ConvertUsagesUtil.java @@ -0,0 +1,164 @@ +/* + * 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.internal.statistic.beans; + + +import java.util.*; + +public class ConvertUsagesUtil { + private static final Character GROUP_SEPARATOR = ':'; + private static final Character GROUPS_SEPARATOR = ';'; + private static final Character GROUP_VALUE_SEPARATOR = ','; + + private ConvertUsagesUtil() { + } + + // @NotNull + public static String convertUsages(Set descriptors) { + assert descriptors != null; + final Map> descriptorGroups = groupDescriptors(descriptors); + + return convertUsages(descriptorGroups); + } + + // @NotNull + public static String convertUsages(Map> map) { + assert map != null; + StringBuffer buffer = new StringBuffer(); + for (Map.Entry> entry : map.entrySet()) { + buffer.append(entry.getKey().getId()); + buffer.append(GROUP_SEPARATOR); + buffer.append(convertValueMap(entry.getValue())); + buffer.append(GROUPS_SEPARATOR); + } + + return buffer.toString(); + } + + //@NotNull + public static String convertValueMap(Set descriptors) { + assert descriptors != null; + final StringBuffer buffer = new StringBuffer(); + for (UsageDescriptor usageDescriptor : descriptors) { + buffer.append(usageDescriptor.getKey()); + buffer.append("="); + buffer.append(usageDescriptor.getValue()); + buffer.append(GROUP_VALUE_SEPARATOR); + } + buffer.deleteCharAt(buffer.length() - 1); + + return buffer.toString(); + } + + //@NotNull + public static String cutPatchString(String patchStr, int maxSize) { + assert patchStr != null; + for (int i = maxSize - 1; i >= 0; i--) { + final char c = patchStr.charAt(i); + if (c == GROUPS_SEPARATOR || c == GROUP_VALUE_SEPARATOR) { + return patchStr.substring(0, i); + } + } + return ""; + } + + //@NotNull + public static Set convertString(String usages) { + assert usages != null; + Set descriptors = new LinkedHashSet(); + for (String groupStr : usages.split(GROUPS_SEPARATOR.toString())) { + if (!isEmptyOrSpaces(groupStr)) { + final StringPair group = getPair(groupStr, GROUP_SEPARATOR.toString()); + if (group != null) { + descriptors.addAll(convertValueString(GroupDescriptor.create(group.first), group.second)); + } + } + } + return descriptors; + } + + //@NotNull + public static Set convertValueString(GroupDescriptor groupId, String valueData) { + assert groupId != null; + final Set descriptors = new LinkedHashSet(); + for (String value : valueData.split(GROUP_VALUE_SEPARATOR.toString())) { + if (!isEmptyOrSpaces(value)) { + final StringPair pair = getPair(value, "="); + if (pair != null) { + final String count = pair.second; + if (!isEmptyOrSpaces(count)) { + try { + final int i = Integer.parseInt(count); + descriptors.add(new UsageDescriptor(groupId, pair.first, i)); + } catch (NumberFormatException ignored) { + } + } + } + } + } + + return descriptors; + } + + //@Nullable + public static StringPair getPair(String str, String separator) { + assert str != null; + assert separator != null; + final int i = str.indexOf(separator); + if (i > 0 && i < str.length() - 1) { + String key = str.substring(0, i).trim(); + String value = str.substring(i + 1).trim(); + if (!isEmptyOrSpaces(key) && !isEmptyOrSpaces(value)) { + return new StringPair(key, value); + } + } + return null; + } + + //@NotNull + public static Map> groupDescriptors(Set descriptors) { + assert descriptors != null; + final SortedMap> map = new TreeMap>(new Comparator() { + public int compare(GroupDescriptor g1, GroupDescriptor g2) { + final int priority = (int) (g2.getPriority() - g1.getPriority()); + return priority == 0 ? g1.getId().compareTo(g2.getId()) : priority; + } + }); + + for (UsageDescriptor descriptor : descriptors) { + final GroupDescriptor group = descriptor.getGroup(); + if (!map.containsKey(group)) { + map.put(group, new HashSet()); + } + map.get(group).add(descriptor); + } + return map; + } + + private static class StringPair { + public final String first; + public final String second; + + public StringPair(String first, String second) { + this.first = first; + this.second = second; + } + } + + public static boolean isEmptyOrSpaces(final String s) { + return s == null || s.trim().length() == 0; + } +} diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/beans/GroupDescriptor.java b/platform/platform-impl/src/com/intellij/internal/statistic/beans/GroupDescriptor.java new file mode 100644 index 000000000000..fcbff6c4f6a2 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/beans/GroupDescriptor.java @@ -0,0 +1,81 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.internal.statistic.beans; + +public class GroupDescriptor implements Comparable { + public static final double DEFAULT_PRIORITY = 0.0; + public static final double HIGHER_PRIORITY = 100.0; + public static final double LOWER_PRIORITY = -100.0; + + private final String myId; + private double myPriority; + + public static GroupDescriptor create(String id) { + assert id != null; + return new GroupDescriptor(id); + } + + public static GroupDescriptor create(String id, double priority) { + assert id != null; + return new GroupDescriptor(id, priority); + } + + private GroupDescriptor(String id) { + this(id, DEFAULT_PRIORITY); + } + + private GroupDescriptor(String id, double priority) { + assert id != null; + myId = id; + myPriority = priority; + } + + + public String getId() { + return myId; + } + + public double getPriority() { + return myPriority; + } + + public void setPriority(double priority) { + myPriority = priority; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof GroupDescriptor)) return false; + + GroupDescriptor that = (GroupDescriptor) o; + + if (myId != null ? !myId.equals(that.myId) : that.myId != null) return false; + + return true; + } + + @Override + public int hashCode() { + return myId != null ? myId.hashCode() : 0; + } + + public int compareTo(GroupDescriptor gd) { + final int priority = (int) (this.getPriority() - gd.getPriority()); + return priority == 0 ? gd.getId().compareTo(gd.getId()) : priority; + } +} + diff --git a/platform/platform-impl/src/com/intellij/statistic/beans/PatchedUsage.java b/platform/platform-impl/src/com/intellij/internal/statistic/beans/PatchedUsage.java similarity index 80% rename from platform/platform-impl/src/com/intellij/statistic/beans/PatchedUsage.java rename to platform/platform-impl/src/com/intellij/internal/statistic/beans/PatchedUsage.java index d5c0ea3c53ec..f91433e4b6bb 100644 --- a/platform/platform-impl/src/com/intellij/statistic/beans/PatchedUsage.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/beans/PatchedUsage.java @@ -13,17 +13,15 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.intellij.statistic.beans; - -import org.jetbrains.annotations.NotNull; +package com.intellij.internal.statistic.beans; public class PatchedUsage extends UsageDescriptor { - public PatchedUsage(@NotNull UsageDescriptor descriptor) { + public PatchedUsage(UsageDescriptor descriptor) { super(descriptor.getGroup(), descriptor.getKey(), descriptor.getValue()); } - public PatchedUsage(@NotNull GroupDescriptor group, @NotNull String key, int value) { + public PatchedUsage(GroupDescriptor group, String key, int value) { super(group, key, value); } diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/beans/UsageDescriptor.java b/platform/platform-impl/src/com/intellij/internal/statistic/beans/UsageDescriptor.java new file mode 100644 index 000000000000..2ec188afa17d --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/beans/UsageDescriptor.java @@ -0,0 +1,73 @@ +/* + * Copyright 2000-2010 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.intellij.internal.statistic.beans; +public class UsageDescriptor implements Comparable { + + private final GroupDescriptor myGroup; + private final String myKey; + private int myValue; + + public UsageDescriptor(GroupDescriptor group, String key, int value) { + assert group != null; + assert key != null; + + myGroup = group; + myKey = key; + myValue = value; + } + + public String getKey() { + return myKey; + } + + public GroupDescriptor getGroup() { + return myGroup; + } + + public int getValue() { + return myValue; + } + + public void setValue(int i) { + myValue = i; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof UsageDescriptor)) return false; + + UsageDescriptor that = (UsageDescriptor) o; + + if (!myGroup.equals(that.myGroup)) return false; + if (!myKey.equals(that.myKey)) return false; + + return true; + } + + @Override + public int hashCode() { + int result = myGroup.hashCode(); + result = 31 * result + myKey.hashCode(); + return result; + } + + public int compareTo(UsageDescriptor ud) { + final int byGroup = this.getGroup().compareTo(ud.getGroup()); + + return byGroup == 0 ? this.getKey().compareTo(ud.myKey) : byGroup; + } +} diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/connect/RemotelyConfigurableStatisticsService.java b/platform/platform-impl/src/com/intellij/internal/statistic/connect/RemotelyConfigurableStatisticsService.java new file mode 100644 index 000000000000..90877592027f --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/connect/RemotelyConfigurableStatisticsService.java @@ -0,0 +1,48 @@ +package com.intellij.internal.statistic.connect; + +import com.intellij.internal.statistic.StatisticsUploadAssistant; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; + +public class RemotelyConfigurableStatisticsService implements StatisticsService { + + private StatisticsConnectionService myConnectionService; + private StatisticsDataSender sender; + private StatisticsUploadAssistant myAssistant; + + public RemotelyConfigurableStatisticsService(@NotNull StatisticsConnectionService connectionService, + @NotNull StatisticsDataSender sender, + @NotNull StatisticsUploadAssistant assistant) { + myConnectionService = connectionService; + this.sender = sender; + myAssistant = assistant; + } + + public StatisticsResult send() { + final String serviceUrl = myConnectionService.getServiceUrl(); + + if (serviceUrl == null) { + return new StatisticsResult(StatisticsResult.ResultCode.ERROR_IN_CONFIG, "ERROR"); + } + + if (!myConnectionService.isTransmissionPermitted()) { + return new StatisticsResult(StatisticsResult.ResultCode.NOT_PERMITTED, "NOT_PERMITTED"); + } + + String content = myAssistant.getData(); + + if (StringUtil.isEmptyOrSpaces(content)) { + return new StatisticsResult(StatisticsResult.ResultCode.NOTHING_TO_SEND, "NOTHING_TO_SEND"); + } + + try { + sender.send(serviceUrl, content); + myAssistant.persistSentPatch(content); + + return new StatisticsResult(StatisticsResult.ResultCode.SEND, "SUCCESS"); + } + catch (Exception e) { + return new StatisticsResult(StatisticsResult.ResultCode.SEND_WITH_ERRORS, e.getMessage() != null ? e.getMessage() : "NPE"); + } + } +} diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatServiceException.java b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatServiceException.java new file mode 100644 index 000000000000..2964db2021ce --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatServiceException.java @@ -0,0 +1,36 @@ +/* + * 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.internal.statistic.connect; + + +public class StatServiceException extends RuntimeException { + + public StatServiceException() { + super(); + } + + public StatServiceException(String s) { + super(s); + } + + public StatServiceException(String s, Throwable throwable) { + super(s, throwable); + } + + public StatServiceException(Throwable throwable) { + super(throwable); + } +} diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsConnectionService.java b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsConnectionService.java new file mode 100644 index 000000000000..6a0df42f96eb --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsConnectionService.java @@ -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.internal.statistic.connect; + +import com.intellij.facet.frameworks.SettingsConnectionService; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.ArrayUtil; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +public class StatisticsConnectionService extends SettingsConnectionService { + + private static final String SETTINGS_URL = "http://jetbrains.com/idea/statistics/stat-assistant.xml"; + private static final String DEFAULT_SERVICE_URL = "http://jetbrains.com/idea/statistics/index.jsp"; + + private static final String PERMISSION_ATTR_NAME = "permitted"; + private static final String DISABLED = "disabled"; + + public StatisticsConnectionService() { + this(SETTINGS_URL, DEFAULT_SERVICE_URL); + } + + public StatisticsConnectionService(@NotNull String settingsUrl, @Nullable String defaultServiceUrl) { + super(settingsUrl, defaultServiceUrl); + } + + @NotNull + @Override + public String[] getAttributeNames() { + return ArrayUtil.append(super.getAttributeNames(), PERMISSION_ATTR_NAME); + } + + public Boolean isTransmissionPermitted() { + final String permitted = getSettingValue(PERMISSION_ATTR_NAME); + + return permitted == null ? true : Boolean.parseBoolean(permitted); + } + + @NotNull + public Set getDisabledGroups() { + final String disabledGroupsString = getSettingValue(DISABLED); + + if (disabledGroupsString == null) return Collections.emptySet(); + + final List disabledGroupsList = StringUtil.split(disabledGroupsString, ","); + return ContainerUtil.map2Set(disabledGroupsList, new Function() { + @Override + public String fun(String s) { + return s.trim(); + } + }); + } +} diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsDataSender.java b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsDataSender.java new file mode 100644 index 000000000000..0018ce34bf8a --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsDataSender.java @@ -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.internal.statistic.connect; + + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public interface StatisticsDataSender { + + void send(@NotNull String url, @NotNull String content) throws StatServiceException; +} diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java new file mode 100644 index 000000000000..ee1971138b1d --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsHttpClientSender.java @@ -0,0 +1,62 @@ +/* + * 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.internal.statistic.connect; + +import com.intellij.openapi.updateSettings.impl.UpdateChecker; +import com.intellij.openapi.util.text.StringUtil; +import org.apache.commons.httpclient.Header; +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpStatus; +import org.apache.commons.httpclient.NameValuePair; +import org.apache.commons.httpclient.methods.PostMethod; +import org.jetbrains.annotations.NotNull; + +public class StatisticsHttpClientSender implements StatisticsDataSender { + + public void send(@NotNull String url, @NotNull String content) throws StatServiceException { + PostMethod post = null; + + try { + HttpClient httpclient = new HttpClient(); + post = new PostMethod(url); + + post.setRequestBody(new NameValuePair[]{ + new NameValuePair("content", content), + new NameValuePair("uuid", UpdateChecker.getInstallationUID())}); + + httpclient.executeMethod(post); + + if (post.getStatusCode() != HttpStatus.SC_OK) { + throw new StatServiceException("Error during data sending... Code: " + post.getStatusCode()); + } + + final Header errors = post.getResponseHeader("errors"); + if (errors != null) { + final String value = errors.getValue(); + + throw new StatServiceException("Error during updating statistics " + (!StringUtil.isEmptyOrSpaces(value) ? " : " + value : "")); + } + } + catch (Exception e) { + throw new StatServiceException("Error during data sending...", e); + } + finally { + if (post != null) { + post.releaseConnection(); + } + } + } +} diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsResult.java b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsResult.java new file mode 100644 index 000000000000..20d447e52534 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsResult.java @@ -0,0 +1,38 @@ +/* + * 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.internal.statistic.connect; + +public class StatisticsResult { + private ResultCode code; + private String description; + + public StatisticsResult(ResultCode code, String description) { + this.code = code; + this.description = description; + } + + public String getDescription() { + return description; + } + + public ResultCode getCode() { + return code; + } + + public enum ResultCode {SEND, NOT_PERMITTED, ERROR_IN_CONFIG, NOTHING_TO_SEND, SEND_WITH_ERRORS} + + +} diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsService.java b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsService.java new file mode 100644 index 000000000000..3fe21714ecf1 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/connect/StatisticsService.java @@ -0,0 +1,22 @@ +/* + * 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.internal.statistic.connect; + + +public interface StatisticsService { + + StatisticsResult send(); +} diff --git a/platform/platform-impl/src/com/intellij/statistic/persistence/BasicSentUsagesPersistenceComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/BasicSentUsagesPersistenceComponent.java similarity index 80% rename from platform/platform-impl/src/com/intellij/statistic/persistence/BasicSentUsagesPersistenceComponent.java rename to platform/platform-impl/src/com/intellij/internal/statistic/persistence/BasicSentUsagesPersistenceComponent.java index 63219377632d..a0f4d7499e57 100644 --- a/platform/platform-impl/src/com/intellij/statistic/persistence/BasicSentUsagesPersistenceComponent.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/BasicSentUsagesPersistenceComponent.java @@ -14,11 +14,12 @@ * limitations under the License. */ -package com.intellij.statistic.persistence; +package com.intellij.internal.statistic.persistence; -import com.intellij.statistic.StatisticsUploadAssistant; -import com.intellij.statistic.beans.PatchedUsage; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.StatisticsUploadAssistant; +import com.intellij.internal.statistic.beans.PatchedUsage; +import com.intellij.internal.statistic.beans.UsageDescriptor; +import com.intellij.openapi.util.Pair; import com.intellij.util.containers.HashSet; import org.jetbrains.annotations.NotNull; @@ -33,7 +34,7 @@ public class BasicSentUsagesPersistenceComponent extends SentUsagesPersistence { public void persistPatch(@NotNull Set patchedDescriptors) { for (PatchedUsage patchedUsage : patchedDescriptors) { - UsageDescriptor usageDescriptor = StatisticsUploadAssistant.findDescriptor(mySentDescriptors, patchedUsage.getId()); + UsageDescriptor usageDescriptor = StatisticsUploadAssistant.findDescriptor(mySentDescriptors, Pair.create(patchedUsage.getGroup(), patchedUsage.getKey())); if (usageDescriptor != null) { usageDescriptor.setValue(usageDescriptor.getValue() + patchedUsage.getDelta()); } diff --git a/platform/platform-impl/src/com/intellij/statistic/persistence/SentUsagesPersistence.java b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/SentUsagesPersistence.java similarity index 83% rename from platform/platform-impl/src/com/intellij/statistic/persistence/SentUsagesPersistence.java rename to platform/platform-impl/src/com/intellij/internal/statistic/persistence/SentUsagesPersistence.java index 41d490797012..9d2c55fb762a 100644 --- a/platform/platform-impl/src/com/intellij/statistic/persistence/SentUsagesPersistence.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/SentUsagesPersistence.java @@ -14,10 +14,10 @@ * limitations under the License. */ -package com.intellij.statistic.persistence; +package com.intellij.internal.statistic.persistence; -import com.intellij.statistic.beans.PatchedUsage; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.beans.PatchedUsage; +import com.intellij.internal.statistic.beans.UsageDescriptor; import org.jetbrains.annotations.NotNull; import java.util.Set; diff --git a/platform/platform-impl/src/com/intellij/statistic/persistence/SentUsagesPersistenceComponent.java b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/SentUsagesPersistenceComponent.java similarity index 86% rename from platform/platform-impl/src/com/intellij/statistic/persistence/SentUsagesPersistenceComponent.java rename to platform/platform-impl/src/com/intellij/internal/statistic/persistence/SentUsagesPersistenceComponent.java index 7e2318475c1e..114949d6632c 100644 --- a/platform/platform-impl/src/com/intellij/statistic/persistence/SentUsagesPersistenceComponent.java +++ b/platform/platform-impl/src/com/intellij/internal/statistic/persistence/SentUsagesPersistenceComponent.java @@ -14,16 +14,16 @@ * limitations under the License. */ -package com.intellij.statistic.persistence; +package com.intellij.internal.statistic.persistence; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.components.ApplicationComponent; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; -import com.intellij.statistic.StatisticsUploadAssistant; -import com.intellij.statistic.beans.GroupDescriptor; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.beans.ConvertUsagesUtil; +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.openapi.util.text.StringUtil; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -66,7 +66,7 @@ public class SentUsagesPersistenceComponent extends BasicSentUsagesPersistenceCo String valueData = groupElement.getAttributeValue(DATA_ATTR); if (!StringUtil.isEmptyOrSpaces(groupId) && !StringUtil.isEmptyOrSpaces(valueData)) { - getSentUsages().addAll(StatisticsUploadAssistant.convertValueString(GroupDescriptor.create(groupId, groupPriority), valueData)); + getSentUsages().addAll(ConvertUsagesUtil.convertValueString(GroupDescriptor.create(groupId, groupPriority), valueData)); } } } @@ -80,12 +80,12 @@ public class SentUsagesPersistenceComponent extends BasicSentUsagesPersistenceCo public Element getState() { Element element = new Element("state"); - for (Map.Entry> entry : StatisticsUploadAssistant.groupDescriptors(getSentUsages()) + for (Map.Entry> entry : ConvertUsagesUtil.groupDescriptors(getSentUsages()) .entrySet()) { Element projectElement = new Element(GROUP_TAG); projectElement.setAttribute(GROUP_ID_ATTR, entry.getKey().getId()); projectElement.setAttribute(GROUP_PRIORITY_ATTR, Double.toString(entry.getKey().getPriority())); - projectElement.setAttribute(DATA_ATTR, StatisticsUploadAssistant.convertValueMap(entry.getValue())); + projectElement.setAttribute(DATA_ATTR, ConvertUsagesUtil.convertValueMap(entry.getValue())); element.addContent(projectElement); } diff --git a/platform/platform-impl/src/com/intellij/internal/statistic/tmp/SendStatisticsAction.java b/platform/platform-impl/src/com/intellij/internal/statistic/tmp/SendStatisticsAction.java new file mode 100644 index 000000000000..eef096eadfae --- /dev/null +++ b/platform/platform-impl/src/com/intellij/internal/statistic/tmp/SendStatisticsAction.java @@ -0,0 +1,38 @@ +/* + * 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.internal.statistic.tmp; + +import com.intellij.internal.statistic.StatisticsUploadAssistant; +import com.intellij.internal.statistic.connect.StatisticsHttpClientSender; +import com.intellij.internal.statistic.connect.RemotelyConfigurableStatisticsService; +import com.intellij.internal.statistic.connect.StatisticsConnectionService; +import com.intellij.openapi.actionSystem.AnAction; +import com.intellij.openapi.actionSystem.AnActionEvent; +import com.intellij.openapi.actionSystem.PlatformDataKeys; +import com.intellij.openapi.project.Project; + +public class SendStatisticsAction extends AnAction { + + @Override + public void actionPerformed(AnActionEvent e) { + final Project project = PlatformDataKeys.PROJECT.getData(e.getDataContext()); + if (project != null) { + final RemotelyConfigurableStatisticsService service = new RemotelyConfigurableStatisticsService(new StatisticsConnectionService(), new StatisticsHttpClientSender(), new StatisticsUploadAssistant()); + + service.send(); + } + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/application/impl/TransferToPooledThreadQueue.java b/platform/platform-impl/src/com/intellij/openapi/application/impl/TransferToPooledThreadQueue.java new file mode 100644 index 000000000000..93cd04f40196 --- /dev/null +++ b/platform/platform-impl/src/com/intellij/openapi/application/impl/TransferToPooledThreadQueue.java @@ -0,0 +1,40 @@ +/* + * 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.application.impl; + +import com.intellij.concurrency.JobScheduler; +import com.intellij.openapi.util.Condition; +import com.intellij.util.Processor; +import com.intellij.util.containers.TransferToEDTQueue; +import org.jetbrains.annotations.NotNull; + +/** + * Allows to process elements in the Application pooled thread. + * Processes elements in batches, no longer than 200ms per batch, and reschedules processing later for longer batches. + * Usage: {@link #offer(Object)} } : schedules element for processing in a pooled thread + */ +public class TransferToPooledThreadQueue extends TransferToEDTQueue { + + public TransferToPooledThreadQueue(@NotNull Processor processorInEDT, @NotNull Condition shutUpCondition) { + super(processorInEDT, shutUpCondition); + } + + @Override + protected void schedule(Runnable updateRunnable) { + JobScheduler.getScheduler().execute(updateRunnable); + //ApplicationManager.getApplication().executeOnPooledThread(updateRunnable); + } +} diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java index be7eed7685b6..3d926199ca88 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/UpdateChecker.java @@ -347,21 +347,9 @@ public final class UpdateChecker { public void run() { try { HttpConfigurable.getInstance().prepareURL(url); - final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(); - String uid = ""; - if (!propertiesComponent.isValueSet(INSTALLATION_UID)) { - try { - uid = UUID.randomUUID().toString(); - } - catch (Exception ignored) { - } - catch (InternalError ignored) { - } - propertiesComponent.setValue(INSTALLATION_UID, uid); - } - else { - uid = propertiesComponent.getValue(INSTALLATION_UID); - } + + String uid = getInstallationUID(); + final URL requestUrl = new URL(url + "?build=" + ApplicationInfo.getInstance().getBuild().asString() + "&uid=" + uid + ADDITIONAL_REQUEST_OPTIONS); final InputStream inputStream = requestUrl.openStream(); try { @@ -396,6 +384,25 @@ public final class UpdateChecker { return document[0]; } + public static String getInstallationUID() { + final PropertiesComponent propertiesComponent = PropertiesComponent.getInstance(); + String uid = ""; + if (!propertiesComponent.isValueSet(INSTALLATION_UID)) { + try { + uid = UUID.randomUUID().toString(); + } + catch (Exception ignored) { + } + catch (InternalError ignored) { + } + propertiesComponent.setValue(INSTALLATION_UID, uid); + } + else { + uid = propertiesComponent.getValue(INSTALLATION_UID); + } + return uid; + } + public static void showNoUpdatesDialog(boolean enableLink, final List updatePlugins, boolean showConfirmation) { NoUpdatesDialog dialog = new NoUpdatesDialog(true, updatePlugins, enableLink); dialog.setShowConfirmation(showConfirmation); diff --git a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java index efe9acd263ff..2eaa2ddab020 100644 --- a/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/vfs/encoding/EncodingManagerImpl.java @@ -24,6 +24,7 @@ package com.intellij.openapi.vfs.encoding; import com.intellij.openapi.Disposable; import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.application.impl.TransferToPooledThreadQueue; import com.intellij.openapi.components.PersistentStateComponent; import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; @@ -44,6 +45,7 @@ import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.CharsetToolkit; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.Alarm; +import com.intellij.util.Processor; import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NonNls; @@ -54,9 +56,7 @@ import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.nio.charset.Charset; import java.util.Collection; -import java.util.Queue; import java.util.Set; -import java.util.concurrent.ConcurrentLinkedQueue; @State( @@ -72,16 +72,14 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt private final Alarm updateEncodingFromContent = new Alarm(Alarm.ThreadToUse.OWN_THREAD, this); private static final Key CACHED_CHARSET_FROM_CONTENT = Key.create("CACHED_CHARSET_FROM_CONTENT"); - private final Queue myChangedDocuments = new ConcurrentLinkedQueue(); - private final Runnable myEncodingUpdateRunnable = new Runnable() { - public void run() { - for (int i=0; i<50;i++) { - if (!pollAndHandleDocument()) return; - } - // requeue myself to handle the tail of the queue in next request - addCacheEncodingAlarm(); + + private final TransferToPooledThreadQueue myChangedDocuments = new TransferToPooledThreadQueue(new Processor() { + @Override + public boolean process(Document document) { + handleDocument(document); + return true; } - }; + }, ApplicationManager.getApplication().getDisposed()); public EncodingManagerImpl(EditorFactory editorFactory) { editorFactory.getEventMulticaster().addDocumentListener(new DocumentAdapter() { @@ -99,9 +97,8 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt } @NonNls public static final String PROP_CACHED_ENCODING_CHANGED = "cachedEncoding"; - private boolean pollAndHandleDocument() { - final Document document = myChangedDocuments.poll(); - if (document == null) return false; + + private void handleDocument(final Document document) { ApplicationManager.getApplication().runReadAction(new Runnable(){ public void run() { VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document); @@ -114,28 +111,15 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt ((EncodingManagerImpl)EncodingManager.getInstance()).firePropertyChange(PROP_CACHED_ENCODING_CHANGED, oldCached, charset); } }); - return true; } public void dispose() { updateEncodingFromContent.cancelAllRequests(); - drainDocumentQueue(); - } - - public void drainDocumentQueue() { - while (pollAndHandleDocument()) { - // loop until empty - } + clearDocumentQueue(); } public void queueUpdateEncodingFromContent(@NotNull Document document) { myChangedDocuments.offer(document); - addCacheEncodingAlarm(); - } - - private void addCacheEncodingAlarm() { - updateEncodingFromContent.cancelAllRequests(); - updateEncodingFromContent.addRequest(myEncodingUpdateRunnable, 400); } public Charset getCachedCharsetFromContent(@NotNull Document document) { @@ -172,6 +156,10 @@ public class EncodingManagerImpl extends EncodingManager implements PersistentSt return encodingManager.getEncoding(virtualFile, useParentDefaults); } + public void clearDocumentQueue() { + myChangedDocuments.stop(); + } + @Nullable private static Project guessProject(final VirtualFile virtualFile) { return ProjectLocator.getInstance().guessProjectForFile(virtualFile); diff --git a/platform/platform-impl/src/com/intellij/statistic/StatisticsUploadAssistant.java b/platform/platform-impl/src/com/intellij/statistic/StatisticsUploadAssistant.java deleted file mode 100644 index 1dc60bb6535d..000000000000 --- a/platform/platform-impl/src/com/intellij/statistic/StatisticsUploadAssistant.java +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.statistic; - -import com.intellij.openapi.extensions.Extensions; -import com.intellij.openapi.project.Project; -import com.intellij.statistic.beans.GroupDescriptor; -import com.intellij.statistic.beans.PatchedUsage; -import com.intellij.statistic.beans.UsageDescriptor; -import com.intellij.statistic.persistence.SentUsagesPersistence; -import com.intellij.statistic.persistence.SentUsagesPersistenceComponent; -import com.intellij.openapi.util.Condition; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.util.text.StringUtil; -import com.intellij.util.Function; -import com.intellij.util.containers.ContainerUtil; -import com.intellij.util.containers.HashSet; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -public class StatisticsUploadAssistant { - - private static final Character GROUP_SEPARATOR = ':'; - private static final Character GROUPS_SEPARATOR = ';'; - private static final Character GROUP_VALUE_SEPARATOR = ','; - - private StatisticsUploadAssistant() { - } - - @NotNull - public static String getStringPatch(@Nullable Project project) { - return getStringPatch(project, 0); - } - - @NotNull - public static String getStringPatch(@Nullable Project project, int maxSize) { - return getStringPatch(project, SentUsagesPersistenceComponent.getInstance(), maxSize); - } - - @NotNull - public static String getStringPatch(@Nullable Project project, @NotNull SentUsagesPersistence usagesPersistence, int maxSize) { - final Set patchedUsages = getPatchedUsages(project, usagesPersistence); - - return getStringPatch(patchedUsages, usagesPersistence, maxSize); - } - - @NotNull - public static String getStringPatch(@NotNull Set patchedUsages, - @NotNull SentUsagesPersistence usagesPersistence, - int maxSize) { - if (patchedUsages.size() == 0) return ""; - - String patchStr = convertUsages(patchedUsages); - if (maxSize > 0 && patchStr.getBytes().length > maxSize) { - patchStr = cutPatchString(patchStr, maxSize); - - patchedUsages = ContainerUtil.map2Set(convertString(patchStr), new Function() { - @Override - public PatchedUsage fun(UsageDescriptor usageDescriptor) { - return new PatchedUsage(usageDescriptor); - } - }); - } - - if (patchedUsages.size() > 0) usagesPersistence.persistPatch(patchedUsages); - - return patchStr; - } - - @NotNull - public static Set getPatchedUsages(@Nullable Project project, @NotNull SentUsagesPersistence usagesPersistence) { - return getPatchedUsages(getAllUsages(project), usagesPersistence.getSentUsages()); - } - - @NotNull - public static Set getPatchedUsages(@NotNull final Set allUsages, @NotNull SentUsagesPersistence usagesPersistence) { - return getPatchedUsages(allUsages, usagesPersistence.getSentUsages()); - } - - @NotNull - public static Set getPatchedUsages(@NotNull final Set allUsages, final Set sentUsages ) { - final Set patchedUsages = ContainerUtil.map2Set(allUsages, new Function() { - @Override - public PatchedUsage fun(UsageDescriptor usageDescriptor) { - return new PatchedUsage(usageDescriptor); - } - }); - - for (UsageDescriptor sentUsage : sentUsages) { - final PatchedUsage descriptor = findDescriptor(patchedUsages, sentUsage.getId()); - if (descriptor == null) { - patchedUsages.add(new PatchedUsage(sentUsage.getGroup(), sentUsage.getKey(), - sentUsage.getValue())); - } - else { - descriptor.subValue(sentUsage.getValue()); - } - } - - return packCollection(patchedUsages, new Condition() { - @Override - public boolean value(PatchedUsage patchedUsage) { - return patchedUsage.getDelta() != 0; - } - }); - } - - @NotNull - private static Set packCollection(@NotNull Collection set, @NotNull Condition condition) { - final Set result = new LinkedHashSet(); - for (T t : set) { - if (condition.value(t)) { - result.add(t); - } - } - return result; - } - - @NotNull - private static String cutPatchString(@NotNull String patchStr, int maxSize) { - for (int i = maxSize - 1; i >= 0; i--) { - final char c = patchStr.charAt(i); - if (c == GROUPS_SEPARATOR || c == GROUP_VALUE_SEPARATOR) { - return patchStr.substring(0, i); - } - } - return ""; - } - - @Nullable - public static T findDescriptor(@NotNull Set descriptors, - @NotNull final Pair id) { - return ContainerUtil.find(descriptors, new Condition() { - @Override - public boolean value(T t) { - return id.equals(t.getId()); - } - }); - } - - @NotNull - public static Set getAllUsages(@Nullable Project project) { - final Set usageDescriptors = new TreeSet(); - - for (UsagesCollector usagesCollector : Extensions.getExtensions(UsagesCollector.EP_NAME)) { - usageDescriptors.addAll(usagesCollector.getUsages(project)); - } - - return usageDescriptors; - } - - @NotNull - public static String convertUsages(@NotNull Set descriptors) { - final Map> descriptorGroups = groupDescriptors(descriptors); - - return convertUsages(descriptorGroups); - } - - @NotNull - public static Map> groupDescriptors(@NotNull Set descriptors) { - final SortedMap> map = new TreeMap>(new Comparator() { - @Override - public int compare(GroupDescriptor g1, GroupDescriptor g2) { - final int priority = (int)(g2.getPriority() - g1.getPriority()); - return priority == 0 ? g1.getId().compareTo(g2.getId()) : priority; - } - }); - - for (UsageDescriptor descriptor : descriptors) { - final GroupDescriptor group = descriptor.getGroup(); - if (!map.containsKey(group)) { - map.put(group, new HashSet()); - } - map.get(group).add(descriptor); - } - return map; - } - - @NotNull - private static String convertUsages(@NotNull Map> map) { - StringBuffer buffer = new StringBuffer(); - for (Map.Entry> entry : map.entrySet()) { - buffer.append(entry.getKey().getId()); - buffer.append(GROUP_SEPARATOR); - buffer.append(convertValueMap(entry.getValue())); - buffer.append(GROUPS_SEPARATOR); - } - - return buffer.toString(); - } - - @NotNull - public static Set convertString(@NotNull String usages) { - Set descriptors = new LinkedHashSet(); - for (String groupStr : StringUtil.split(usages, GROUPS_SEPARATOR.toString())) { - if (!StringUtil.isEmptyOrSpaces(groupStr)) { - final Pair group = getPair(groupStr, GROUP_SEPARATOR.toString()); - if (group != null) { - descriptors.addAll(convertValueString(GroupDescriptor.create(group.getFirst()), group.getSecond())); - } - } - } - return descriptors; - } - - @NotNull - public static String convertValueMap(@NotNull Set descriptors) { - final StringBuffer buffer = new StringBuffer(); - for (UsageDescriptor usageDescriptor : descriptors) { - buffer.append(usageDescriptor.getKey()); - buffer.append("="); - buffer.append(usageDescriptor.getValue()); - buffer.append(GROUP_VALUE_SEPARATOR); - } - buffer.deleteCharAt(buffer.length() - 1); - - return buffer.toString(); - } - - @NotNull - public static Set convertValueString(@NotNull GroupDescriptor groupId, String valueData) { - final Set descriptors = new LinkedHashSet(); - for (String value : StringUtil.split(valueData, GROUP_VALUE_SEPARATOR.toString())) { - if (!StringUtil.isEmptyOrSpaces(value)) { - final Pair pair = getPair(value, "="); - if (pair != null) { - final String count = pair.getSecond(); - if (!StringUtil.isEmptyOrSpaces(count)) { - try { - final int i = Integer.parseInt(count); - descriptors.add(new UsageDescriptor(groupId, pair.getFirst(), i)); - } catch (NumberFormatException ignored) {} - } - } - } - } - - return descriptors; - } - - @Nullable - private static Pair getPair(@NotNull String str, @NotNull String separator) { - final int i = str.indexOf(separator); - if (i > 0 && i < str.length() - 1) { - String key = str.substring(0, i).trim(); - String value = str.substring(i + 1).trim(); - if (!StringUtil.isEmptyOrSpaces(key) && !StringUtil.isEmptyOrSpaces(value)) { - return Pair.create(key, value); - } - } - return null; - } -} diff --git a/platform/platform-impl/src/com/intellij/statistic/beans/GroupDescriptor.java b/platform/platform-impl/src/com/intellij/statistic/beans/GroupDescriptor.java deleted file mode 100644 index 326769adf724..000000000000 --- a/platform/platform-impl/src/com/intellij/statistic/beans/GroupDescriptor.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.statistic.beans; - -import org.jetbrains.annotations.NotNull; - -public class GroupDescriptor implements Comparable { - public static final double DEFAULT_PRIORITY = 0.0; - public static final double HIGHER_PRIORITY = 100.0; - public static final double LOWER_PRIORITY = -100.0; - - private final String myId; - private double myPriority; - - public static GroupDescriptor create(@NotNull String id) { - return new GroupDescriptor(id); - } - - public static GroupDescriptor create(@NotNull String id, double priority) { - return new GroupDescriptor(id, priority); - } - - private GroupDescriptor(@NotNull String id) { - this(id, DEFAULT_PRIORITY); - } - - private GroupDescriptor(@NotNull String id, double priority) { - myId = id; - myPriority = priority; - } - - - public String getId() { - return myId; - } - - public double getPriority() { - return myPriority; - } - - public void setPriority(double priority) { - myPriority = priority; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof GroupDescriptor)) return false; - - GroupDescriptor that = (GroupDescriptor)o; - - if (myId != null ? !myId.equals(that.myId) : that.myId != null) return false; - - return true; - } - - @Override - public int hashCode() { - return myId != null ? myId.hashCode() : 0; - } - - @Override - public int compareTo(GroupDescriptor gd) { - final int priority = (int)(this.getPriority() - gd.getPriority()); - return priority == 0 ? gd.getId().compareTo(gd.getId()) : priority; - } -} - diff --git a/platform/platform-impl/src/com/intellij/statistic/beans/UsageDescriptor.java b/platform/platform-impl/src/com/intellij/statistic/beans/UsageDescriptor.java deleted file mode 100644 index e31a924be4f5..000000000000 --- a/platform/platform-impl/src/com/intellij/statistic/beans/UsageDescriptor.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2000-2010 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.intellij.statistic.beans; - -import com.intellij.openapi.util.Pair; -import org.jetbrains.annotations.NotNull; - -public class UsageDescriptor implements Comparable { - - private final GroupDescriptor myGroup; - private final String myKey; - private int myValue; - - public UsageDescriptor(@NotNull GroupDescriptor group, @NotNull String key, int value) { - myGroup = group; - myKey = key; - myValue = value; - } - - public Pair getId() { - return Pair.create(getGroup(), getKey()); - } - - @NotNull - public String getKey() { - return myKey; - } - - @NotNull - public GroupDescriptor getGroup() { - return myGroup; - } - - public int getValue() { - return myValue; - } - - public void setValue(int i) { - myValue = i; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof UsageDescriptor)) return false; - - UsageDescriptor that = (UsageDescriptor)o; - - if (!myGroup.equals(that.myGroup)) return false; - if (!myKey.equals(that.myKey)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = myGroup.hashCode(); - result = 31 * result + myKey.hashCode(); - return result; - } - - @Override - public int compareTo(UsageDescriptor ud) { - final int byGroup = this.getGroup().compareTo(ud.getGroup()); - - return byGroup == 0 ? this.getKey().compareTo(ud.myKey) : byGroup; - } -} diff --git a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml index 3f7291cee545..dcbdc60e0cb7 100644 --- a/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml +++ b/platform/platform-resources/src/META-INF/PlatformExtensionPoints.xml @@ -109,7 +109,7 @@ - + diff --git a/platform/platform-resources/src/componentSets/Platform.xml b/platform/platform-resources/src/componentSets/Platform.xml index a99994ac7cfd..262f9d54c624 100644 --- a/platform/platform-resources/src/componentSets/Platform.xml +++ b/platform/platform-resources/src/componentSets/Platform.xml @@ -114,8 +114,8 @@ - com.intellij.statistic.persistence.SentUsagesPersistenceComponent - com.intellij.statistic.persistence.SentUsagesPersistenceComponent + com.intellij.internal.statistic.persistence.SentUsagesPersistenceComponent + com.intellij.internal.statistic.persistence.SentUsagesPersistenceComponent diff --git a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java index e301bf877394..cd1da081ce42 100644 --- a/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java +++ b/platform/testFramework/src/com/intellij/testFramework/LightPlatformTestCase.java @@ -469,7 +469,7 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da } } EncodingManager encodingManager = EncodingManager.getInstance(); - if (encodingManager instanceof EncodingManagerImpl) ((EncodingManagerImpl)encodingManager).drainDocumentQueue(); + if (encodingManager instanceof EncodingManagerImpl) ((EncodingManagerImpl)encodingManager).clearDocumentQueue(); FileDocumentManager manager = FileDocumentManager.getInstance(); if (manager instanceof FileDocumentManagerImpl) { diff --git a/platform/usageView/testSrc/com/intellij/usages/impl/UsageViewMemoryTest.java b/platform/usageView/testSrc/com/intellij/usages/impl/UsageViewMemoryTest.java new file mode 100644 index 000000000000..7d56cc69b840 --- /dev/null +++ b/platform/usageView/testSrc/com/intellij/usages/impl/UsageViewMemoryTest.java @@ -0,0 +1,58 @@ +/* + * 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.usages.impl; + +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.util.Disposer; +import com.intellij.openapi.vfs.encoding.EncodingManager; +import com.intellij.openapi.vfs.encoding.EncodingManagerImpl; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.impl.source.PsiFileImpl; +import com.intellij.testFramework.LeakHunter; +import com.intellij.testFramework.LightPlatformCodeInsightTestCase; +import com.intellij.usageView.UsageInfo; +import com.intellij.usages.*; +import com.intellij.util.ui.UIUtil; + +/** + * User: cdr + */ +public class UsageViewMemoryTest extends LightPlatformCodeInsightTestCase{ + public void testUsageViewDoesNotHoldPsiFilesOrDocuments() throws Exception { + PsiFile psiFile = createFile("X.java", "public class X{} //iuggjhfg"); + Usage[] usages = new Usage[100]; + for (int i = 0; i < usages.length; i++) { + usages[i] = createUsage(psiFile,i); + } + + UsageView usageView = UsageViewManager.getInstance(getProject()).createUsageView(UsageTarget.EMPTY_ARRAY, usages, new UsageViewPresentation(), null); + + Disposer.register(getTestRootDisposable(), usageView); + + UIUtil.dispatchAllInvocationEvents(); + ((EncodingManagerImpl)EncodingManager.getInstance()).clearDocumentQueue(); + + LeakHunter.checkLeak(usageView, PsiFileImpl.class); + LeakHunter.checkLeak(usageView, Document.class); + } + + private static Usage createUsage(PsiFile psiFile, int offset) { + PsiElement element = psiFile.findElementAt(offset % psiFile.getTextLength()); + assertNotNull(element); + return new UsageInfo2UsageAdapter(new UsageInfo(element)); + } +} diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistence.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistence.java index 0850d38c3749..968e52aae1a8 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistence.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistence.java @@ -17,7 +17,7 @@ package com.intellij.openapi.vcs.statistics; import com.intellij.openapi.project.Project; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NotNull; diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistenceComponent.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistenceComponent.java index 3cff5584312c..1e095cd4f677 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistenceComponent.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsStatisticsPersistenceComponent.java @@ -26,7 +26,7 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectManager; import com.intellij.openapi.project.ProjectManagerListener; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.util.Function; import com.intellij.util.containers.HashSet; import org.jdom.Element; @@ -71,7 +71,7 @@ public class VcsStatisticsPersistenceComponent extends VcsStatisticsPersistence if (!StringUtil.isEmptyOrSpaces(projectId) && !StringUtil.isEmptyOrSpaces(vcs)) { Set vcsDescriptors = new HashSet(); for (String key : StringUtil.split(vcs, TOKENIZER)) { - vcsDescriptors.add(new UsageDescriptor(VcsUsagesCollector.getGroupId(), key, 1)); + vcsDescriptors.add(new UsageDescriptor(VcsUsagesCollector.createGroupDescriptor(), key, 1)); } getVcsUsageMap().put(projectId, vcsDescriptors); } diff --git a/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsUsagesCollector.java b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsUsagesCollector.java index b534312e3b82..602a62853521 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsUsagesCollector.java +++ b/platform/vcs-impl/src/com/intellij/openapi/vcs/statistics/VcsUsagesCollector.java @@ -18,9 +18,9 @@ package com.intellij.openapi.vcs.statistics; import com.intellij.openapi.project.Project; import com.intellij.openapi.vcs.ProjectLevelVcsManager; import com.intellij.openapi.vcs.impl.VcsDescriptor; -import com.intellij.statistic.UsagesCollector; -import com.intellij.statistic.beans.GroupDescriptor; -import com.intellij.statistic.beans.UsageDescriptor; +import com.intellij.internal.statistic.UsagesCollector; +import com.intellij.internal.statistic.beans.GroupDescriptor; +import com.intellij.internal.statistic.beans.UsageDescriptor; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.hash.HashMap; @@ -49,12 +49,12 @@ public class VcsUsagesCollector extends UsagesCollector { } @NotNull - public static Set getApplicationUsages() { + public Set getApplicationUsages() { return getApplicationUsages(VcsStatisticsPersistenceComponent.getInstance()); } @NotNull - public static Set getApplicationUsages(@NotNull final VcsStatisticsPersistenceComponent persistence) { + public Set getApplicationUsages(@NotNull final VcsStatisticsPersistenceComponent persistence) { final Map vcsUsagesMap = new HashMap(); for (Set descriptors : persistence.getVcsUsageMap().values()) { @@ -68,13 +68,14 @@ public class VcsUsagesCollector extends UsagesCollector { return ContainerUtil.map2Set(vcsUsagesMap.entrySet(), new Function, UsageDescriptor>() { @Override public UsageDescriptor fun(Map.Entry vcsUsage) { - return new UsageDescriptor(getGroupId(), vcsUsage.getKey(), vcsUsage.getValue()); + return new UsageDescriptor(createGroupDescriptor(), vcsUsage.getKey(), vcsUsage.getValue()); } }); } - public static GroupDescriptor getGroupId() { - return GroupDescriptor.create(GROUP_ID, GroupDescriptor.HIGHER_PRIORITY); + @NotNull + public String getGroupId() { + return GROUP_ID; } @NotNull @@ -90,9 +91,13 @@ public class VcsUsagesCollector extends UsagesCollector { return ContainerUtil.map2Set(ProjectLevelVcsManager.getInstance(project).getAllVcss(), new Function() { @Override public UsageDescriptor fun(VcsDescriptor descriptor) { - return new UsageDescriptor(getGroupId(), descriptor.getName(), 1); + return new UsageDescriptor(createGroupDescriptor(), descriptor.getName(), 1); } }); } + + public static GroupDescriptor createGroupDescriptor() { + return GroupDescriptor.create(GROUP_ID, GroupDescriptor.HIGHER_PRIORITY); + } } diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java index 69f12b130689..ea0fc190fa50 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/style/UnqualifiedFieldAccessInspection.java @@ -1,5 +1,5 @@ /* - * Copyright 2006-2010 Bas Leijdekkers + * Copyright 2006-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,6 +18,7 @@ package com.siyeh.ig.style; 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; @@ -74,18 +75,32 @@ public class UnqualifiedFieldAccessInspection extends BaseInspection { if (field == null) { return; } - final PsiClass containingClass = field.getContainingClass(); - if (containingClass == null) { + final PsiClass fieldClass = field.getContainingClass(); + if (fieldClass == null) { return; } - final PsiClass parentClass = + PsiClass containingClass = ClassUtils.getContainingClass(expression); @NonNls final String newExpression; - if (!containingClass.equals(parentClass)) { + if (InheritanceUtil.isInheritorOrSelf(containingClass, fieldClass, + true)) { + newExpression = "this." + expression.getText(); + } else { + containingClass = + ClassUtils.getContainingClass(containingClass); + if (containingClass == null) { + return; + } + while (!InheritanceUtil.isInheritorOrSelf(containingClass, + fieldClass, true)) { + containingClass = + ClassUtils.getContainingClass(containingClass); + if (containingClass == null) { + return; + } + } newExpression = containingClass.getQualifiedName() + ".this." + expression.getText(); - } else { - newExpression = "this." + expression.getText(); } replaceExpressionAndShorten(expression, newExpression); } diff --git a/plugins/maven/facade-impl/maven-facade-impl.iml b/plugins/maven/facade-impl/maven-facade-impl.iml index d6356b9cf3f3..85676062dd81 100644 --- a/plugins/maven/facade-impl/maven-facade-impl.iml +++ b/plugins/maven/facade-impl/maven-facade-impl.iml @@ -12,26 +12,9 @@ - + - - - - - - - - - - - - - - - - - @@ -41,7 +24,7 @@ - + @@ -75,23 +58,17 @@ - + + + + - - - - - - - - - @@ -101,15 +78,6 @@ - - - - - - - - - diff --git a/resources/src/idea/IdeaActions.xml b/resources/src/idea/IdeaActions.xml index 838d33b3ec5d..ab01fb606c8a 100644 --- a/resources/src/idea/IdeaActions.xml +++ b/resources/src/idea/IdeaActions.xml @@ -262,6 +262,7 @@ + diff --git a/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java b/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java index 4a241fe4550b..a03014ba0953 100644 --- a/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java +++ b/xml/dom-impl/src/com/intellij/util/xml/ui/DomUIFactoryImpl.java @@ -151,7 +151,8 @@ public class DomUIFactoryImpl extends DomUIFactory { psiDocumentManager.commitAllDocuments(); GeneralHighlightingPass ghp = new GeneralHighlightingPass(project, psiFile, document, 0, document.getTextLength(), true); - LocalInspectionsPass lip = new LocalInspectionsPass(psiFile, document, 0, document.getTextLength()); + LocalInspectionsPass lip = new LocalInspectionsPass(psiFile, document, 0, + document.getTextLength(), LocalInspectionsPass.EMPTY_PRIORITY_RANGE, true); return new HighlightingPass[]{ghp, lip}; }